]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch 'statusnetworkapi' into 1.0.x
authorEvan Prodromou <evan@status.net>
Fri, 10 Jun 2011 20:50:15 +0000 (16:50 -0400)
committerEvan Prodromou <evan@status.net>
Fri, 10 Jun 2011 20:50:15 +0000 (16:50 -0400)
actions/recoverpassword.php
classes/User.php
plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php
plugins/DomainStatusNetwork/actions/globallogin.php [new file with mode: 0644]
plugins/DomainStatusNetwork/actions/globalrecover.php [new file with mode: 0644]
plugins/DomainStatusNetwork/actions/globalregister.php [new file with mode: 0644]
plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php [deleted file]
plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php [new file with mode: 0644]
plugins/DomainStatusNetwork/lib/globalapiaction.php [new file with mode: 0644]
plugins/DomainStatusNetwork/scripts/installforemail.php

index 47a947dc0c786dc77df89581262fdaf149f1830c..8d731cb871cb3fbe9d11f2e0ca8334ef25aca19b 100644 (file)
@@ -273,109 +273,25 @@ class RecoverpasswordAction extends Action
     function recoverPassword()
     {
         $nore = $this->trimmed('nicknameoremail');
+
         if (!$nore) {
             // TRANS: Form instructions for password recovery form.
             $this->showForm(_('Enter a nickname or email address.'));
             return;
         }
 
-        $user = User::staticGet('email', common_canonical_email($nore));
-
-        if (!$user) {
-            try {
-                $user = User::staticGet('nickname', common_canonical_nickname($nore));
-            } catch (NicknameException $e) {
-                // invalid
-            }
-        }
-
-        // See if it's an unconfirmed email address
-
-        if (!$user) {
-            // Warning: it may actually be legit to have multiple folks
-            // who have claimed, but not yet confirmed, the same address.
-            // We'll only send to the first one that comes up.
-            $confirm_email = new Confirm_address();
-            $confirm_email->address = common_canonical_email($nore);
-            $confirm_email->address_type = 'email';
-            $confirm_email->find();
-            if ($confirm_email->fetch()) {
-                $user = User::staticGet($confirm_email->user_id);
-            } else {
-                $confirm_email = null;
-            }
-        } else {
-            $confirm_email = null;
-        }
-
-        if (!$user) {
-            // TRANS: Information on password recovery form if no known username or e-mail address was specified.
-            $this->showForm(_('No user with that email address or username.'));
-            return;
-        }
-
-        // Try to get an unconfirmed email address if they used a user name
-
-        if (!$user->email && !$confirm_email) {
-            $confirm_email = new Confirm_address();
-            $confirm_email->user_id = $user->id;
-            $confirm_email->address_type = 'email';
-            $confirm_email->find();
-            if (!$confirm_email->fetch()) {
-                $confirm_email = null;
-            }
-        }
-
-        if (!$user->email && !$confirm_email) {
-            // TRANS: Client error displayed on password recovery form if a user does not have a registered e-mail address.
-            $this->clientError(_('No registered email address for that user.'));
-            return;
+        try {
+            User::recoverPassword($nore);
+            $this->mode = 'sent';
+            // TRANS: User notification after an e-mail with instructions was sent from the password recovery form.
+            $this->msg = _('Instructions for recovering your password ' .
+                           'have been sent to the email address registered to your ' .
+                           'account.');
+            $this->success = true;
+            $this->showPage();
+        } catch (Exception $e) {
+            $this->success = false;
         }
-
-        // Success! We have a valid user and a confirmed or unconfirmed email address
-
-        $confirm = new Confirm_address();
-        $confirm->code = common_confirmation_code(128);
-        $confirm->address_type = 'recover';
-        $confirm->user_id = $user->id;
-        $confirm->address = (!empty($user->email)) ? $user->email : $confirm_email->address;
-
-        if (!$confirm->insert()) {
-            common_log_db_error($confirm, 'INSERT', __FILE__);
-            // TRANS: Server error displayed if e-mail address confirmation fails in the database on the password recovery form.
-            $this->serverError(_('Error saving address confirmation.'));
-            return;
-        }
-
-         // @todo FIXME: needs i18n.
-        $body = "Hey, $user->nickname.";
-        $body .= "\n\n";
-        $body .= 'Someone just asked for a new password ' .
-                 'for this account on ' . common_config('site', 'name') . '.';
-        $body .= "\n\n";
-        $body .= 'If it was you, and you want to confirm, use the URL below:';
-        $body .= "\n\n";
-        $body .= "\t".common_local_url('recoverpassword',
-                                   array('code' => $confirm->code));
-        $body .= "\n\n";
-        $body .= 'If not, just ignore this message.';
-        $body .= "\n\n";
-        $body .= 'Thanks for your time, ';
-        $body .= "\n";
-        $body .= common_config('site', 'name');
-        $body .= "\n";
-
-        $headers = _mail_prepare_headers('recoverpassword', $user->nickname, $user->nickname);
-        // TRANS: Subject for password recovery e-mail.
-        mail_to_user($user, _('Password recovery requested'), $body, $headers, $confirm->address);
-
-        $this->mode = 'sent';
-        // TRANS: User notification after an e-mail with instructions was sent from the password recovery form.
-        $this->msg = _('Instructions for recovering your password ' .
-                          'have been sent to the email address registered to your ' .
-                          'account.');
-        $this->success = true;
-        $this->showPage();
     }
 
     function resetPassword()
index 9f7954932738909aabe3c4f64600605744cb1b5d..2d1253b7f7ad19f362bee8b2f22c007e4c74fe9c 100644 (file)
@@ -1008,4 +1008,97 @@ class User extends Memcached_DataObject
         $skip = array('_profile');
         return array_diff($vars, $skip);
     }
+
+    static function recoverPassword($nore)
+    {
+        $user = User::staticGet('email', common_canonical_email($nore));
+
+        if (!$user) {
+            try {
+                $user = User::staticGet('nickname', common_canonical_nickname($nore));
+            } catch (NicknameException $e) {
+                // invalid
+            }
+        }
+
+        // See if it's an unconfirmed email address
+
+        if (!$user) {
+            // Warning: it may actually be legit to have multiple folks
+            // who have claimed, but not yet confirmed, the same address.
+            // We'll only send to the first one that comes up.
+            $confirm_email = new Confirm_address();
+            $confirm_email->address = common_canonical_email($nore);
+            $confirm_email->address_type = 'email';
+            $confirm_email->find();
+            if ($confirm_email->fetch()) {
+                $user = User::staticGet($confirm_email->user_id);
+            } else {
+                $confirm_email = null;
+            }
+        } else {
+            $confirm_email = null;
+        }
+
+        if (!$user) {
+            // TRANS: Information on password recovery form if no known username or e-mail address was specified.
+            throw new ClientError(_('No user with that email address or username.'));
+            return;
+        }
+
+        // Try to get an unconfirmed email address if they used a user name
+
+        if (!$user->email && !$confirm_email) {
+            $confirm_email = new Confirm_address();
+            $confirm_email->user_id = $user->id;
+            $confirm_email->address_type = 'email';
+            $confirm_email->find();
+            if (!$confirm_email->fetch()) {
+                $confirm_email = null;
+            }
+        }
+
+        if (!$user->email && !$confirm_email) {
+            // TRANS: Client error displayed on password recovery form if a user does not have a registered e-mail address.
+            throw new ClientException(_('No registered email address for that user.'));
+            return;
+        }
+
+        // Success! We have a valid user and a confirmed or unconfirmed email address
+
+        $confirm = new Confirm_address();
+        $confirm->code = common_confirmation_code(128);
+        $confirm->address_type = 'recover';
+        $confirm->user_id = $user->id;
+        $confirm->address = (!empty($user->email)) ? $user->email : $confirm_email->address;
+
+        if (!$confirm->insert()) {
+            common_log_db_error($confirm, 'INSERT', __FILE__);
+            // TRANS: Server error displayed if e-mail address confirmation fails in the database on the password recovery form.
+            throw new ServerException(_('Error saving address confirmation.'));
+            return;
+        }
+
+         // @todo FIXME: needs i18n.
+        $body = "Hey, $user->nickname.";
+        $body .= "\n\n";
+        $body .= 'Someone just asked for a new password ' .
+                 'for this account on ' . common_config('site', 'name') . '.';
+        $body .= "\n\n";
+        $body .= 'If it was you, and you want to confirm, use the URL below:';
+        $body .= "\n\n";
+        $body .= "\t".common_local_url('recoverpassword',
+                                   array('code' => $confirm->code));
+        $body .= "\n\n";
+        $body .= 'If not, just ignore this message.';
+        $body .= "\n\n";
+        $body .= 'Thanks for your time, ';
+        $body .= "\n";
+        $body .= common_config('site', 'name');
+        $body .= "\n";
+
+        $headers = _mail_prepare_headers('recoverpassword', $user->nickname, $user->nickname);
+        // TRANS: Subject for password recovery e-mail.
+        mail_to_user($user, _('Password recovery requested'), $body, $headers, $confirm->address);
+    }
 }
index 9390a6e08353b3cdf441af4d9a3a5092251cbde2..a923ac4c30fd352ad64583f1ec6052f321c73f64 100644 (file)
@@ -97,8 +97,16 @@ class DomainStatusNetworkPlugin extends Plugin
 
         switch ($cls)
         {
+        case 'GlobalregisterAction':
+        case 'GloballoginAction':
+        case 'GlobalrecoverAction':
+            include_once $dir . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
+            return false;
         case 'DomainStatusNetworkInstaller':
-            include_once $dir . '/' . strtolower($cls) . '.php';
+            include_once $dir . '/lib/' . strtolower($cls) . '.php';
+            return false;
+        case 'GlobalApiAction':
+            include_once $dir . '/lib/' . strtolower($cls) . '.php';
             return false;
         default:
             return true;
@@ -138,6 +146,26 @@ class DomainStatusNetworkPlugin extends Plugin
         return true;
     }
 
+    function onRouterInitialized($m)
+    {
+        if (common_config('globalapi', 'enabled')) {
+            foreach (array('register', 'login', 'recover') as $method) {
+                $m->connect('api/statusnet/global/'.$method,
+                            array('action' => 'global'.$method));
+            }
+        }
+        return true;
+    }
+
+    function onLoginAction($action, &$login) {
+        $this->debug($action);
+        if (in_array($action, array('globalregister', 'globallogin', 'globalrecover'))) {
+            $login = true;
+            return false;
+        }
+        return true;
+    }
+
     static function nicknameForDomain($domain)
     {
         $registered = self::registeredDomain($domain);
@@ -195,6 +223,103 @@ class DomainStatusNetworkPlugin extends Plugin
                             _m('A plugin that maps a single status_network to an email domain.'));
         return true;
     }
+
+    static function userExists($email)
+    {
+        $domain = self::toDomain($email);
+
+        $sn = self::siteForDomain($domain);
+
+        if (empty($sn)) {
+            return false;
+        }
+
+        StatusNet::switchSite($sn->nickname);
+
+        $user = User::staticGet('email', $email);
+
+        return !empty($user);
+    }
+
+    static function registerEmail($email, $sendWelcome, $template)
+    {
+        $domain = self::toDomain($email);
+
+        $sn = self::siteForDomain($domain);
+
+        if (empty($sn)) {
+            $installer = new DomainStatusNetworkInstaller($domain);
+
+            // Do the thing
+            $installer->main();
+
+            $sn = $installer->getStatusNetwork();
+
+            $config = $installer->getConfig();
+
+            Status_network::$wildcard = $config['WILDCARD'];
+        }
+
+        StatusNet::switchSite($sn->nickname);
+
+        $confirm = EmailRegistrationPlugin::registerEmail($email);
+
+        return $confirm;
+    }
+
+    static function login($email, $password)
+    {
+        $domain = self::toDomain($email);
+
+        $sn = self::siteForDomain($domain);
+
+        if (empty($sn)) {
+            throw new ClientException(_("No such site."));
+        }
+
+        StatusNet::switchSite($sn->nickname);
+
+        $user = common_check_user($email, $password);
+
+        if (empty($user)) {
+            // TRANS: Form validation error displayed when trying to log in with incorrect credentials.
+            throw new ClientException(_('Incorrect username or password.'));
+        }
+
+        $loginToken = Login_token::makeNew($user);
+
+        if (empty($loginToken)) {
+            throw new ServerException(sprintf(_('Could not create new login token for user %s'), $user->nickname));
+        }
+
+        $url = common_local_url('otp', array('user_id' => $loginToken->user_id,
+                                             'token' => $loginToken->token));
+
+        if (empty($url)) {
+            throw new ServerException(sprintf(_('Could not create new OTP URL for user %s'), $user->nickname));
+        }
+
+        return $url;
+    }
+
+    static function recoverPassword($email)
+    {
+        $domain = self::toDomain($email);
+
+        $sn = self::siteForDomain($domain);
+
+        if (empty($sn)) {
+            throw new NoSuchUserException(array('email' => $email));
+        }
+
+        StatusNet::switchSite($sn->nickname);
+
+        $user = User::staticGet('email', $email);
+        
+        if (empty($user)) {
+            throw new ClientException(_('No such user.'));
+        }
+    }
 }
 
 // The way addPlugin() works, this global variable gets disappeared.
diff --git a/plugins/DomainStatusNetwork/actions/globallogin.php b/plugins/DomainStatusNetwork/actions/globallogin.php
new file mode 100644 (file)
index 0000000..f843392
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Log into a site globally
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Login to a site
+ *
+ * @category  Action
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GloballoginAction extends GlobalApiAction
+{
+    var $password;
+
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+
+    function prepare($argarray)
+    {
+        parent::prepare($argarray);
+
+        $password = $this->trimmed('password');
+
+        if (empty($password)) {
+            throw new ClientException(_('No password.'));
+        }
+
+        $this->password = $password;
+
+        return true;
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+
+    function handle($argarray=null)
+    {
+        try {
+            $url = DomainStatusNetworkPlugin::login($email, $password);
+            $this->showSuccess(array('url' => $url));
+        } catch (ClientException $ce) {
+            $this->showError($ce->getMessage());
+        } catch (Exception $e) {
+            common_log(LOG_ERR, $e->getMessage());
+            $this->showError(_('An internal error occurred.'));
+        }
+        return;
+    }
+}
diff --git a/plugins/DomainStatusNetwork/actions/globalrecover.php b/plugins/DomainStatusNetwork/actions/globalrecover.php
new file mode 100644 (file)
index 0000000..9b688cb
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Recover a password
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Recover a password
+ *
+ * @category  Action
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GlobalrecoverAction extends GlobalApiAction
+{
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+
+    function prepare($argarray)
+    {
+        parent::prepare($argarray);
+        return true;
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+
+    function handle($argarray=null)
+    {
+        try {
+            DomainStatusNetworkPlugin::recoverPassword($email);
+            $this->showSuccess();
+        } catch (ClientException $ce) {
+            $this->showError($ce->getMessage());
+        } catch (Exception $e) {
+            common_log(LOG_ERR, $e->getMessage());
+            $this->showError(_('An internal error occurred.'));
+        }
+        return;
+    }
+}
diff --git a/plugins/DomainStatusNetwork/actions/globalregister.php b/plugins/DomainStatusNetwork/actions/globalregister.php
new file mode 100644 (file)
index 0000000..ed9bfc3
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Register a user to a site by their email address
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * An action to globally register a new user
+ *
+ * @category  Action
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GlobalregisterAction extends GlobalApiAction
+{
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+
+    function prepare($argarray)
+    {
+        try {
+            parent::prepare($argarray);
+            return true;
+        } catch (ClientException $e) {
+            $this->showError($e->getMessage(), $e->getCode());
+            return false;
+        } catch (Exception $e) {
+            common_log(LOG_ERR, $e->getMessage());
+            $this->showError(_('An internal error occurred.'), 500);
+            return false;
+        }
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+
+    function handle($argarray=null)
+    {
+        try {
+            DomainStatusNetworkPlugin::registerEmail($this->email, true);
+            $this->showSuccess();
+        } catch (ClientException $e) {
+            $this->showError($e->getMessage(), $e->getCode());
+        } catch (Exception $e) {
+            common_log(LOG_ERR, $e->getMessage());
+            $this->showError(_('An internal error occurred.'), 500);
+        }
+
+        return;
+    }
+}
diff --git a/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php b/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php
deleted file mode 100644 (file)
index b2e988b..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2011, StatusNet, Inc.
- *
- * Installer class for domain-based multi-homing systems
- *
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  DomainStatusNetwork
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2011 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Installer class for domain-based multi-homing systems
- *
- * @category  DomainStatusNetwork
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2011 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-class DomainStatusNetworkInstaller extends Installer
-{
-    protected $domain   = null;
-    protected $rootname = null;
-    protected $sitedb   = null;
-    protected $rootpass = null;
-    protected $nickname = null;
-    protected $sn       = null;
-
-    public $verbose     = false;
-
-    function __construct($domain)
-    {
-        $this->domain = $domain;
-    }
-
-    /**
-     * Go for it!
-     * @return boolean success
-     */
-    function main()
-    {
-        // We don't check prereqs. Check 'em before setting up a
-        // multi-home system, kthxbi
-        if ($this->prepare()) {
-            return $this->handle();
-        } else {
-            $this->showHelp();
-            return false;
-        }
-    }
-
-    /**
-     * Get our input parameters...
-     * @return boolean success
-     */
-    function prepare()
-    {
-        $config = $this->getConfig();
-
-        $this->nickname = DomainStatusNetworkPlugin::nicknameForDomain($this->domain);
-
-        // XXX make this configurable
-
-        $this->sitename = sprintf('The %s Status Network', $this->domain);
-
-        $this->server   = $this->nickname.'.'.$config['WILDCARD'];
-        $this->path     = null;
-        $this->fancy    = true;
-
-        $datanick = $this->databaseize($this->nickname);
-
-        $this->host     = $config['DBHOSTNAME'];
-        $this->database = $datanick.$config['DBBASE'];
-        $this->dbtype   = 'mysql'; // XXX: support others... someday
-        $this->username = $datanick.$config['USERBASE'];
-
-        // Max size for MySQL
-
-        if (strlen($this->username) > 16) {
-            $this->username = sprintf('%s%08x', substr($this->username, 0, 8), crc32($this->username));
-        }
-
-        $pwgen = $config['PWDGEN'];
-
-        $password = `$pwgen`;
-
-        $this->password = trim($password);
-
-        // For setting up the database
-
-        $this->rootname = $config['ADMIN'];
-        $this->rootpass = $config['ADMINPASS'];
-        $this->sitehost = $config['DBHOST'];
-        $this->sitedb   = $config['SITEDB'];
-
-        $tagstr = $config['TAGS'];
-
-        if (!empty($tagstr)) {
-            $this->tags = preg_split('/[\s,]+/', $tagstr);
-        } else {
-            $this->tags = array();
-        }
-
-        // Explicitly empty
-
-        $this->adminNick    = null;
-        $this->adminPass    = null;
-        $this->adminEmail   = null;
-        $this->adminUpdates = null;
-
-        /** Should we skip writing the configuration file? */
-        $this->skipConfig = true;
-
-        if (!$this->validateDb()) {
-            return false;
-        }
-
-        return true;
-    }
-
-    function handle()
-    {
-        return $this->doInstall();
-    }
-
-    function setupDatabase()
-    {
-        $this->updateStatus('Creating database...');
-        $this->createDatabase();
-        parent::setupDatabase();
-        $this->updateStatus('Creating file directories...');
-        $this->createDirectories();
-        $this->updateStatus('Saving status network...');
-        $this->saveStatusNetwork();
-        $this->updateStatus('Checking schema for plugins...');
-        $this->checkSchema();
-    }
-
-    function saveStatusNetwork()
-    {
-        Status_network::setupDB($this->sitehost,
-                                $this->rootname,
-                                $this->rootpass,
-                                $this->sitedb, array());
-
-        $sn = new Status_network();
-
-        $sn->nickname = $this->nickname;
-        $sn->dbhost   = $this->host;
-        $sn->dbuser   = $this->username;
-        $sn->dbpass   = $this->password;
-        $sn->dbname   = $this->database;
-        $sn->sitename = $this->sitename;
-
-        $result = $sn->insert();
-
-        if (!$result) {
-            throw new ServerException("Could not create status_network: " . print_r($sn, true));
-        }
-
-        // Re-fetch; stupid auto-increment integer isn't working
-
-        $sn = Status_network::staticGet('nickname', $sn->nickname);
-
-        if (empty($sn)) {
-            throw new ServerException("Created {$this->nickname} status_network and could not find it again.");
-        }
-
-        // Set default tags
-
-        $tags = $this->tags;
-
-        // Add domain tag
-
-        $tags[] = 'domain='.$this->domain;
-
-        $sn->setTags($tags);
-
-        $this->sn = $sn;
-    }
-
-    function checkSchema()
-    {
-        $config = $this->getConfig();
-
-        Status_network::$wildcard = $config['WILDCARD'];
-
-        StatusNet::switchSite($this->nickname);
-
-        // We need to initialize the schema_version stuff to make later setup easier
-
-        $schema = array();
-        require INSTALLDIR.'/db/core.php';
-        $tableDefs = $schema;
-
-        $schema = Schema::get();
-        $schemaUpdater = new SchemaUpdater($schema);
-
-        foreach ($tableDefs as $table => $def) {
-            $schemaUpdater->register($table, $def);
-        }
-
-        $schemaUpdater->checkSchema();
-
-        Event::handle('CheckSchema');
-    }
-
-    function getStatusNetwork()
-    {
-        return $this->sn;
-    }
-
-    function createDirectories()
-    {
-        $config = $this->getConfig();
-
-        foreach (array('AVATARBASE', 'BACKGROUNDBASE', 'FILEBASE') as $key) {
-            $base = $config[$key];
-            $dirname = $base.'/'.$this->nickname;
-
-            // Make sure our bits are set
-            $mask = umask(0);
-            mkdir($dirname, 0770, true);
-            umask($mask);
-
-            // If you set the setuid bit on your base dirs this should be
-            // unnecessary, but just in case. You must be root for this
-            // to work.
-
-            if (array_key_exists('WEBUSER', $config)) {
-                chown($dirname, $config['WEBUSER']);
-            }
-            if (array_key_exists('WEBGROUP', $config)) {
-                chgrp($dirname, $config['WEBGROUP']);
-            }
-        }
-    }
-
-    function createDatabase()
-    {
-        // Create the New DB
-        $res = mysql_connect($this->host, $this->rootname, $this->rootpass);
-        if (!$res) {
-            throw new ServerException("Cannot connect to {$this->host} as {$this->rootname}.");
-        }
-
-        mysql_query("CREATE DATABASE ". mysql_real_escape_string($this->database), $res);
-
-        $return = mysql_select_db($this->database, $res);
-
-        if (!$return) {
-            throw new ServerException("Unable to connect to {$this->database} on {$this->host}.");
-        }
-
-        foreach (array('localhost', '%') as $src) {
-            mysql_query("GRANT ALL ON " .
-                        mysql_real_escape_string($this->database).".* TO '" .
-                        $this->username . "'@'".$src."' ".
-                        "IDENTIFIED BY '".$this->password."'", $res);
-        }
-
-        mysql_close($res);
-    }
-
-    function getConfig()
-    {
-        static $config;
-
-        $cfg_file = "/etc/statusnet/setup.cfg";
-
-        if (empty($config)) {
-            $result = parse_ini_file($cfg_file);
-
-            $config = array();
-            foreach ($result as $key => $value) {
-                $key = str_replace('export ', '', $key);
-                $config[$key] = $value;
-            }
-        }
-
-        return $config;
-    }
-
-    function showHelp()
-    {
-    }
-
-    function warning($message, $submessage='')
-    {
-        print $this->html2text($message) . "\n";
-        if ($submessage != '') {
-            print "  " . $this->html2text($submessage) . "\n";
-        }
-        print "\n";
-    }
-
-    function updateStatus($status, $error=false)
-    {
-        if ($this->verbose || $error) {
-            if ($error) {
-                print "ERROR: ";
-            }
-            print $this->html2text($status);
-            print "\n";
-        }
-    }
-
-    private function html2text($html)
-    {
-        // break out any links for text legibility
-        $breakout = preg_replace('/<a[^>+]\bhref="(.*)"[^>]*>(.*)<\/a>/',
-                                 '\2 &lt;\1&gt;',
-                                 $html);
-        return html_entity_decode(strip_tags($breakout), ENT_QUOTES, 'UTF-8');
-    }
-
-    function databaseize($nickname)
-    {
-        $nickname = str_replace('-', '_', $nickname);
-        return $nickname;
-    }
-}
diff --git a/plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php b/plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php
new file mode 100644 (file)
index 0000000..b2e988b
--- /dev/null
@@ -0,0 +1,349 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Installer class for domain-based multi-homing systems
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Installer class for domain-based multi-homing systems
+ *
+ * @category  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+class DomainStatusNetworkInstaller extends Installer
+{
+    protected $domain   = null;
+    protected $rootname = null;
+    protected $sitedb   = null;
+    protected $rootpass = null;
+    protected $nickname = null;
+    protected $sn       = null;
+
+    public $verbose     = false;
+
+    function __construct($domain)
+    {
+        $this->domain = $domain;
+    }
+
+    /**
+     * Go for it!
+     * @return boolean success
+     */
+    function main()
+    {
+        // We don't check prereqs. Check 'em before setting up a
+        // multi-home system, kthxbi
+        if ($this->prepare()) {
+            return $this->handle();
+        } else {
+            $this->showHelp();
+            return false;
+        }
+    }
+
+    /**
+     * Get our input parameters...
+     * @return boolean success
+     */
+    function prepare()
+    {
+        $config = $this->getConfig();
+
+        $this->nickname = DomainStatusNetworkPlugin::nicknameForDomain($this->domain);
+
+        // XXX make this configurable
+
+        $this->sitename = sprintf('The %s Status Network', $this->domain);
+
+        $this->server   = $this->nickname.'.'.$config['WILDCARD'];
+        $this->path     = null;
+        $this->fancy    = true;
+
+        $datanick = $this->databaseize($this->nickname);
+
+        $this->host     = $config['DBHOSTNAME'];
+        $this->database = $datanick.$config['DBBASE'];
+        $this->dbtype   = 'mysql'; // XXX: support others... someday
+        $this->username = $datanick.$config['USERBASE'];
+
+        // Max size for MySQL
+
+        if (strlen($this->username) > 16) {
+            $this->username = sprintf('%s%08x', substr($this->username, 0, 8), crc32($this->username));
+        }
+
+        $pwgen = $config['PWDGEN'];
+
+        $password = `$pwgen`;
+
+        $this->password = trim($password);
+
+        // For setting up the database
+
+        $this->rootname = $config['ADMIN'];
+        $this->rootpass = $config['ADMINPASS'];
+        $this->sitehost = $config['DBHOST'];
+        $this->sitedb   = $config['SITEDB'];
+
+        $tagstr = $config['TAGS'];
+
+        if (!empty($tagstr)) {
+            $this->tags = preg_split('/[\s,]+/', $tagstr);
+        } else {
+            $this->tags = array();
+        }
+
+        // Explicitly empty
+
+        $this->adminNick    = null;
+        $this->adminPass    = null;
+        $this->adminEmail   = null;
+        $this->adminUpdates = null;
+
+        /** Should we skip writing the configuration file? */
+        $this->skipConfig = true;
+
+        if (!$this->validateDb()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    function handle()
+    {
+        return $this->doInstall();
+    }
+
+    function setupDatabase()
+    {
+        $this->updateStatus('Creating database...');
+        $this->createDatabase();
+        parent::setupDatabase();
+        $this->updateStatus('Creating file directories...');
+        $this->createDirectories();
+        $this->updateStatus('Saving status network...');
+        $this->saveStatusNetwork();
+        $this->updateStatus('Checking schema for plugins...');
+        $this->checkSchema();
+    }
+
+    function saveStatusNetwork()
+    {
+        Status_network::setupDB($this->sitehost,
+                                $this->rootname,
+                                $this->rootpass,
+                                $this->sitedb, array());
+
+        $sn = new Status_network();
+
+        $sn->nickname = $this->nickname;
+        $sn->dbhost   = $this->host;
+        $sn->dbuser   = $this->username;
+        $sn->dbpass   = $this->password;
+        $sn->dbname   = $this->database;
+        $sn->sitename = $this->sitename;
+
+        $result = $sn->insert();
+
+        if (!$result) {
+            throw new ServerException("Could not create status_network: " . print_r($sn, true));
+        }
+
+        // Re-fetch; stupid auto-increment integer isn't working
+
+        $sn = Status_network::staticGet('nickname', $sn->nickname);
+
+        if (empty($sn)) {
+            throw new ServerException("Created {$this->nickname} status_network and could not find it again.");
+        }
+
+        // Set default tags
+
+        $tags = $this->tags;
+
+        // Add domain tag
+
+        $tags[] = 'domain='.$this->domain;
+
+        $sn->setTags($tags);
+
+        $this->sn = $sn;
+    }
+
+    function checkSchema()
+    {
+        $config = $this->getConfig();
+
+        Status_network::$wildcard = $config['WILDCARD'];
+
+        StatusNet::switchSite($this->nickname);
+
+        // We need to initialize the schema_version stuff to make later setup easier
+
+        $schema = array();
+        require INSTALLDIR.'/db/core.php';
+        $tableDefs = $schema;
+
+        $schema = Schema::get();
+        $schemaUpdater = new SchemaUpdater($schema);
+
+        foreach ($tableDefs as $table => $def) {
+            $schemaUpdater->register($table, $def);
+        }
+
+        $schemaUpdater->checkSchema();
+
+        Event::handle('CheckSchema');
+    }
+
+    function getStatusNetwork()
+    {
+        return $this->sn;
+    }
+
+    function createDirectories()
+    {
+        $config = $this->getConfig();
+
+        foreach (array('AVATARBASE', 'BACKGROUNDBASE', 'FILEBASE') as $key) {
+            $base = $config[$key];
+            $dirname = $base.'/'.$this->nickname;
+
+            // Make sure our bits are set
+            $mask = umask(0);
+            mkdir($dirname, 0770, true);
+            umask($mask);
+
+            // If you set the setuid bit on your base dirs this should be
+            // unnecessary, but just in case. You must be root for this
+            // to work.
+
+            if (array_key_exists('WEBUSER', $config)) {
+                chown($dirname, $config['WEBUSER']);
+            }
+            if (array_key_exists('WEBGROUP', $config)) {
+                chgrp($dirname, $config['WEBGROUP']);
+            }
+        }
+    }
+
+    function createDatabase()
+    {
+        // Create the New DB
+        $res = mysql_connect($this->host, $this->rootname, $this->rootpass);
+        if (!$res) {
+            throw new ServerException("Cannot connect to {$this->host} as {$this->rootname}.");
+        }
+
+        mysql_query("CREATE DATABASE ". mysql_real_escape_string($this->database), $res);
+
+        $return = mysql_select_db($this->database, $res);
+
+        if (!$return) {
+            throw new ServerException("Unable to connect to {$this->database} on {$this->host}.");
+        }
+
+        foreach (array('localhost', '%') as $src) {
+            mysql_query("GRANT ALL ON " .
+                        mysql_real_escape_string($this->database).".* TO '" .
+                        $this->username . "'@'".$src."' ".
+                        "IDENTIFIED BY '".$this->password."'", $res);
+        }
+
+        mysql_close($res);
+    }
+
+    function getConfig()
+    {
+        static $config;
+
+        $cfg_file = "/etc/statusnet/setup.cfg";
+
+        if (empty($config)) {
+            $result = parse_ini_file($cfg_file);
+
+            $config = array();
+            foreach ($result as $key => $value) {
+                $key = str_replace('export ', '', $key);
+                $config[$key] = $value;
+            }
+        }
+
+        return $config;
+    }
+
+    function showHelp()
+    {
+    }
+
+    function warning($message, $submessage='')
+    {
+        print $this->html2text($message) . "\n";
+        if ($submessage != '') {
+            print "  " . $this->html2text($submessage) . "\n";
+        }
+        print "\n";
+    }
+
+    function updateStatus($status, $error=false)
+    {
+        if ($this->verbose || $error) {
+            if ($error) {
+                print "ERROR: ";
+            }
+            print $this->html2text($status);
+            print "\n";
+        }
+    }
+
+    private function html2text($html)
+    {
+        // break out any links for text legibility
+        $breakout = preg_replace('/<a[^>+]\bhref="(.*)"[^>]*>(.*)<\/a>/',
+                                 '\2 &lt;\1&gt;',
+                                 $html);
+        return html_entity_decode(strip_tags($breakout), ENT_QUOTES, 'UTF-8');
+    }
+
+    function databaseize($nickname)
+    {
+        $nickname = str_replace('-', '_', $nickname);
+        return $nickname;
+    }
+}
diff --git a/plugins/DomainStatusNetwork/lib/globalapiaction.php b/plugins/DomainStatusNetwork/lib/globalapiaction.php
new file mode 100644 (file)
index 0000000..cd0c7f9
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * An action that requires an API key
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * An action that requires an API key
+ *
+ * @category  General
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GlobalApiAction extends Action
+{
+    var $email;
+
+    /**
+     * Check for an API key, and throw an exception if it's not set
+     *
+     * @param array $args URL and POST params
+     *
+     * @return boolean continuation flag
+     */
+
+    function prepare($args)
+    {
+        StatusNet::setApi(true); // reduce exception reports to aid in debugging
+
+        parent::prepare($args);
+
+        if (!common_config('globalapi', 'enabled')) {
+            throw new ClientException(_('Global API not enabled.'), 403);
+        }
+
+        $apikey = $this->trimmed('apikey');
+
+        if (empty($apikey)) {
+            throw new ClientException(_('No API key.'), 403);
+        }
+
+        $expected = common_config('globalapi', 'key');
+
+        if ($expected != $apikey) {
+            // FIXME: increment a counter by IP address to prevent brute-force
+            // attacks on the key.
+            throw new ClientException(_('Bad API key.'), 403);
+        }
+
+        $email = common_canonical_email($this->trimmed('email'));
+
+        if (empty($email)) {
+            throw new ClientException(_('No email address.'));
+        }
+
+        if (!Validate::email($email, common_config('email', 'check_domain'))) {
+            throw new ClientException(_('Invalid email address.'));
+        }
+
+        $this->email = $email;
+
+        return true;
+    }
+
+    function showError($message, $code=400)
+    {
+        $this->showOutput(array('error' => $message), $code);
+    }
+
+    function showSuccess($values=null, $code=200)
+    {
+        if (empty($values)) {
+            $values = array();
+        }
+        $values['success'] = 1;
+        $this->showOutput($values, $code);
+    }
+
+    function showOutput($values, $code)
+    {
+        if (array_key_exists($code, ClientErrorAction::$status)) {
+            $status_string = ClientErrorAction::$status[$code];
+        } else if (array_key_exists($code, ServerErrorAction::$status)) {
+            $status_string = ServerErrorAction::$status[$code];
+        } else {
+            // bad code!
+            $code = 500;
+            $status_string = ServerErrorAction::$status[$code];
+        }
+
+        header('HTTP/1.1 '.$code.' '.$status_string);
+
+        header('Content-Type: application/json; charset=utf-8');
+        print(json_encode($values));
+        print("\n");
+    }
+}
index 98ce620c28cb24fcfa1fd50d7cf145eacaf32a8c..f773094a74c426e9ccc023b43468d08e5a61cef2 100644 (file)
@@ -39,39 +39,24 @@ require_once INSTALLDIR.'/scripts/commandline.inc';
 
 $email = $args[0];
 
-$domain = DomainStatusNetworkPlugin::toDomain($email);
+$sendWelcome = have_option('w', 'welcome');
 
-$sn = DomainStatusNetworkPlugin::siteForDomain($domain);
-
-if (empty($sn)) {
-    $installer = new DomainStatusNetworkInstaller($domain);
-
-    $installer->verbose = have_option('v', 'verbose');
-
-    // Do the thing
-    $installer->main();
-
-    $sn = $installer->getStatusNetwork();
-
-    $config = $installer->getConfig();
-
-    Status_network::$wildcard = $config['WILDCARD'];
+if ($sendWelcome && have_option('t', 'template')) {
+    $template = get_option_value('t', 'template');
 }
 
-StatusNet::switchSite($sn->nickname);
+try {
 
-$confirm = EmailRegistrationPlugin::registerEmail($email);
+    $confirm = DomainStatusNetworkPlugin::registerEmail($email);
 
-if (have_option('w', 'welcome')) {
-    if (have_option('t', 'template')) {
-        // use the provided template
-        EmailRegistrationPlugin::sendConfirmEmail($confirm, get_option_value('t', 'template'));
-    } else {
-        // use the default template
-        EmailRegistrationPlugin::sendConfirmEmail($confirm);
+    if ($sendWelcome) {
+        EmailRegistrationPlugin::sendConfirmEmail($confirm, $template);
     }
-}
 
-$confirmUrl = common_local_url('register', array('code' => $confirm->code));
+    $confirmUrl = common_local_url('register', array('code' => $confirm->code));
 
-print $confirmUrl."\n";
+    print $confirmUrl."\n";
+
+} catch (Exception $e) {
+    print "ERROR: " . $e->getMessage() . "\n";
+}