From 2d72a64841ebaae889b723d5e259095cdc1b6389 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 10 Jun 2011 15:51:30 -0400 Subject: [PATCH] First pass at complete global API --- .../DomainStatusNetworkPlugin.php | 33 ++++- .../actions/globallogin.php | 24 +++- .../actions/globalrecover.php | 85 +++++++++++++ .../actions/globalregister.php | 56 ++------- .../domainstatusnetworkinstaller.php | 0 .../lib/globalapiaction.php | 118 ++++++++++++++++++ 6 files changed, 268 insertions(+), 48 deletions(-) create mode 100644 plugins/DomainStatusNetwork/actions/globalrecover.php rename plugins/DomainStatusNetwork/{ => lib}/domainstatusnetworkinstaller.php (100%) create mode 100644 plugins/DomainStatusNetwork/lib/globalapiaction.php diff --git a/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php b/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php index 876443aa3f..efb1aae4d8 100644 --- a/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php +++ b/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php @@ -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,17 @@ 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; + } + static function nicknameForDomain($domain) { $registered = self::registeredDomain($domain); @@ -261,12 +280,16 @@ class DomainStatusNetworkPlugin extends Plugin $loginToken = Login_token::makeNew($user); if (empty($loginToken)) { - throw new ServerException(_('Cannot log in.')); + 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; } @@ -282,6 +305,12 @@ class DomainStatusNetworkPlugin extends Plugin 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 index 034d719a2f..f843392f44 100644 --- a/plugins/DomainStatusNetwork/actions/globallogin.php +++ b/plugins/DomainStatusNetwork/actions/globallogin.php @@ -35,7 +35,7 @@ if (!defined('STATUSNET')) { } /** - * Class comment + * Login to a site * * @category Action * @package StatusNet @@ -45,8 +45,10 @@ if (!defined('STATUSNET')) { * @link http://status.net/ */ -class GlobalLoginAction extends Action +class GloballoginAction extends GlobalApiAction { + var $password; + /** * For initializing members of the class. * @@ -58,6 +60,15 @@ class GlobalLoginAction extends Action function prepare($argarray) { parent::prepare($argarray); + + $password = $this->trimmed('password'); + + if (empty($password)) { + throw new ClientException(_('No password.')); + } + + $this->password = $password; + return true; } @@ -71,6 +82,15 @@ class GlobalLoginAction extends Action 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 index 0000000000..9b688cbe70 --- /dev/null +++ b/plugins/DomainStatusNetwork/actions/globalrecover.php @@ -0,0 +1,85 @@ +. + * + * @category DomainStatusNetwork + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index ad223808ff..42dd207f4e 100644 --- a/plugins/DomainStatusNetwork/actions/globalregister.php +++ b/plugins/DomainStatusNetwork/actions/globalregister.php @@ -35,7 +35,7 @@ if (!defined('STATUSNET')) { } /** - * Class comment + * An action to globally register a new user * * @category Action * @package StatusNet @@ -45,7 +45,7 @@ if (!defined('STATUSNET')) { * @link http://status.net/ */ -class GlobalRegisterAction extends Action +class GlobalregisterAction extends GlobalApiAction { /** * For initializing members of the class. @@ -71,48 +71,16 @@ class GlobalRegisterAction extends Action function handle($argarray=null) { + try { + DomainStatusNetworkPlugin::registerEmail($this->email, true); + $this->showSuccess(); + } catch (ClientException $e) { + $this->showError($e->getMessage()); + } catch (Exception $e) { + common_log(LOG_ERR, $e->getMessage()); + $this->showError(_('An internal error occurred.')); + } + return; } - - /** - * Return true if read only. - * - * MAY override - * - * @param array $args other arguments - * - * @return boolean is read only action? - */ - - function isReadOnly($args) - { - return false; - } - - /** - * Return last modified, if applicable. - * - * MAY override - * - * @return string last modified http header - */ - function lastModified() - { - // For comparison with If-Last-Modified - // If not applicable, return null - return null; - } - - /** - * Return etag, if applicable. - * - * MAY override - * - * @return string etag http header - */ - - function etag() - { - return null; - } } diff --git a/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php b/plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php similarity index 100% rename from plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php rename to plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php diff --git a/plugins/DomainStatusNetwork/lib/globalapiaction.php b/plugins/DomainStatusNetwork/lib/globalapiaction.php new file mode 100644 index 0000000000..ef77d89cfe --- /dev/null +++ b/plugins/DomainStatusNetwork/lib/globalapiaction.php @@ -0,0 +1,118 @@ +. + * + * @category DomainStatusNetwork + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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.')); + } + + $apikey = $this->trimmed('apikey'); + + if (empty($apikey)) { + throw new ClientException(_('No API key.')); + } + + $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.')); + } + + $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) + { + $this->showOutput(array('error' => $message)); + } + + function showSuccess($values=null) + { + if (empty($values)) { + $values = array(); + } + $values['success'] = 1; + $this->showOutput($values); + } + + function showOutput($values) + { + header('Content-Type: application/json; charset=utf-8'); + print(json_encode($values)); + } +}