Merge branch '0.9.x' of git@gitorious.org:statusnet/mainline into 0.9.x

This commit is contained in:
Evan Prodromou 2009-11-11 00:22:29 -05:00
commit 093857c582
13 changed files with 938 additions and 65 deletions

View File

@ -162,6 +162,42 @@ StartAccountSettingsNav: Before showing the account settings menu
EndAccountSettingsNav: After showing the account settings menu EndAccountSettingsNav: After showing the account settings menu
- $action: the current action - $action: the current action
StartAccountSettingsProfileMenuItem: Before showing the Profile menu item
- $widget: AccountSettingsNav instance being shown
EndAccountSettingsProfileMenuItem: After showing the Profile menu item
- $widget: AccountSettingsNav instance being shown
StartAccountSettingsAvatarMenuItem: Before showing the Avatar menu item
- $widget: AccountSettingsNav instance being shown
EndAccountSettingsAvatarMenuItem: After showing the Avatar menu item
- $widget: AccountSettingsNav instance being shown
StartAccountSettingsPasswordMenuItem: Before showing the Password menu item
- $widget: AccountSettingsNav instance being shown
EndAccountSettingsPasswordMenuItem: After showing the Password menu item
- $widget: AccountSettingsNav instance being shown
StartAccountSettingsEmailMenuItem: Before showing the Email menu item
- $widget: AccountSettingsNav instance being shown
EndAccountSettingsEmailMenuItem: After showing the Email menu item
- $widget: AccountSettingsNav instance being shown
StartAccountSettingsDesignMenuItem: Before showing the Design menu item
- $widget: AccountSettingsNav instance being shown
EndAccountSettingsDesignMenuItem: After showing the Design menu item
- $widget: AccountSettingsNav instance being shown
StartAccountSettingsOtherMenuItem: Before showing the Other menu item
- $widget: AccountSettingsNav instance being shown
EndAccountSettingsOtherMenuItem: After showing the Other menu item
- $widget: AccountSettingsNav instance being shown
Autoload: When trying to autoload a class Autoload: When trying to autoload a class
- $cls: the class being sought. A plugin might require_once the file for the class. - $cls: the class being sought. A plugin might require_once the file for the class.
@ -499,10 +535,6 @@ StartChangePassword: Before changing a password
EndChangePassword: After changing a password EndChangePassword: After changing a password
- $nickname: user's nickname - $nickname: user's nickname
CanUserChangeField: Determines if a user is allowed to change a specific profile field
- $nickname: nickname of the user who would like to know which of their profile fields are mutable
- $field: name of the field the user wants to change (nickname, fullname, password, avatar, etc)
UserDeleteRelated: Specify additional tables to delete entries from when deleting users UserDeleteRelated: Specify additional tables to delete entries from when deleting users
- $user: User object - $user: User object
- &$related: array of DB_DataObject class names to delete entries on matching user_id. - &$related: array of DB_DataObject class names to delete entries on matching user_id.

View File

@ -67,7 +67,7 @@ class ApiAccountRateLimitStatusAction extends ApiBareAuthAction
if (!in_array($this->format, array('xml', 'json'))) { if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError( $this->clientError(
_('API method not found!'), _('API method not found.'),
404, 404,
$this->format $this->format
); );

View File

@ -0,0 +1,157 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Update the authenticating user notification channels
*
* PHP version 5
*
* LICENCE: 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 API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Sets which channel (device) StatusNet delivers updates to for
* the authenticating user. Sending none as the device parameter
* will disable IM and/or SMS updates.
*
* @category API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class ApiAccountUpdateDeliveryDeviceAction extends ApiAuthAction
{
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*
*/
function prepare($args)
{
parent::prepare($args);
$this->user = $this->auth_user;
$this->device = $this->trimmed('device');
return true;
}
/**
* Handle the request
*
* See which request params have been set, and update the user settings
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
_('This method requires a POST.'),
400, $this->format
);
return;
}
if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(
_('API method not found.'),
404,
$this->format
);
return;
}
// Note: Twitter no longer supports IM
if (!in_array(strtolower($this->device), array('sms', 'im', 'none'))) {
$this->clientError(
_(
'You must specify a parameter named ' .
'\'device\' with a value of one of: sms, im, none'
)
);
return;
}
if (empty($this->user)) {
$this->clientError(_('No such user.'), 404, $this->format);
return;
}
$original = clone($this->user);
if (strtolower($this->device) == 'sms') {
$this->user->smsnotify = true;
} elseif (strtolower($this->device) == 'im') {
$this->user->jabbernotify = true;
} elseif (strtolower($this->device == 'none')) {
$this->user->smsnotify = false;
$this->user->jabbernotify = false;
}
$result = $this->user->update($original);
if ($result === false) {
common_log_db_error($this->user, 'UPDATE', __FILE__);
$this->serverError(_('Could not update user.'));
return;
}
$profile = $this->user->getProfile();
$twitter_user = $this->twitterUserArray($profile, true);
// Note: this Twitter API method is retarded because it doesn't give
// any success/failure information. Twitter's docs claim that the
// notification field will change to reflect notification choice,
// but that's not true; notification> is used to indicate
// whether the auth user is following the user in question.
if ($this->format == 'xml') {
$this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user);
$this->endDocument('xml');
} elseif ($this->format == 'json') {
$this->initDocument('json');
$this->showJsonObjects($twitter_user);
$this->endDocument('json');
}
}
}

View File

@ -0,0 +1,166 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Update the authenticating user's profile
*
* PHP version 5
*
* LICENCE: 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 API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* API analog to the profile settings page
* Only the parameters specified will be updated.
*
* @category API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class ApiAccountUpdateProfileAction extends ApiAuthAction
{
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*
*/
function prepare($args)
{
parent::prepare($args);
$this->user = $this->auth_user;
$this->name = $this->trimmed('name');
$this->url = $this->trimmed('url');
$this->location = $this->trimmed('location');
$this->description = $this->trimmed('description');
return true;
}
/**
* Handle the request
*
* See which request params have been set, and update the profile
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
_('This method requires a POST.'),
400, $this->format
);
return;
}
if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(
_('API method not found.'),
404,
$this->format
);
return;
}
if (empty($this->user)) {
$this->clientError(_('No such user.'), 404, $this->format);
return;
}
$profile = $this->user->getProfile();
if (empty($profile)) {
$this->clientError(_('User has no profile.'));
return;
}
$original = clone($profile);
if (empty($this->name)) {
$profile->fullname = $this->name;
}
if (empty($this->url)) {
$profile->homepage = $this->url;
}
if (!empty($this->description)) {
$profile->bio = $this->description;
}
if (!empty($this->location)) {
$profile->location = $this->location;
$loc = Location::fromName($location);
if (!empty($loc)) {
$profile->lat = $loc->lat;
$profile->lon = $loc->lon;
$profile->location_id = $loc->location_id;
$profile->location_ns = $loc->location_ns;
}
}
$result = $profile->update($original);
if (!$result) {
common_log_db_error($profile, 'UPDATE', __FILE__);
$this->serverError(_('Could not save profile.'));
return;
}
common_broadcast_profile($profile);
$twitter_user = $this->twitterUserArray($profile, true);
if ($this->format == 'xml') {
$this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user);
$this->endDocument('xml');
} elseif ($this->format == 'json') {
$this->initDocument('json');
$this->showJsonObjects($twitter_user);
$this->endDocument('json');
}
}
}

View File

@ -0,0 +1,211 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Update the authenticating user's profile background image
*
* PHP version 5
*
* LICENCE: 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 API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Update the authenticating user's profile background image
*
* @category API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class ApiAccountUpdateProfileBackgroundImageAction extends ApiAuthAction
{
var $tile = false;
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*
*/
function prepare($args)
{
parent::prepare($args);
$this->user = $this->auth_user;
$this->tile = $this->arg('tile');
return true;
}
/**
* Handle the request
*
* Check whether the credentials are valid and output the result
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
_('This method requires a POST.'),
400, $this->format
);
return;
}
if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(
_('API method not found.'),
404,
$this->format
);
return;
}
// Workaround for PHP returning empty $_POST and $_FILES when POST
// length > post_max_size in php.ini
if (empty($_FILES)
&& empty($_POST)
&& ($_SERVER['CONTENT_LENGTH'] > 0)
) {
$msg = _('The server was unable to handle that much POST ' .
'data (%s bytes) due to its current configuration.');
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
return;
}
if (empty($this->user)) {
$this->clientError(_('No such user.'), 404, $this->format);
return;
}
$design = $this->user->getDesign();
// XXX: This is kinda gross, but before we can add a background
// img we have to make sure there's a Design because design ID
// is part of the img filename.
if (empty($design)) {
$this->user->query('BEGIN');
// save new design
$design = new Design();
$id = $design->insert();
if (empty($id)) {
common_log_db_error($id, 'INSERT', __FILE__);
$this->clientError(_('Unable to save your design settings.'));
return;
}
$original = clone($this->user);
$this->user->design_id = $id;
$result = $this->user->update($original);
if (empty($result)) {
common_log_db_error($original, 'UPDATE', __FILE__);
$this->clientError(_('Unable to save your design settings.'));
$this->user->query('ROLLBACK');
return;
}
$this->user->query('COMMIT');
}
// Okay, now get the image and add it to the design
try {
$imagefile = ImageFile::fromUpload('image');
} catch (Exception $e) {
$this->clientError($e->getMessage(), 400, $this->format);
return;
}
$filename = Design::filename(
$design->id,
image_type_to_extension($imagefile->type),
common_timestamp()
);
$filepath = Design::path($filename);
move_uploaded_file($imagefile->filepath, $filepath);
// delete any old backround img laying around
if (isset($design->backgroundimage)) {
@unlink(Design::path($design->backgroundimage));
}
$original = clone($design);
$design->backgroundimage = $filename;
$design->setDisposition(true, false, ($this->tile == 'true'));
$result = $design->update($original);
if ($result === false) {
common_log_db_error($design, 'UPDATE', __FILE__);
$this->showForm(_('Could not update your design.'));
return;
}
$profile = $this->user->getProfile();
if (empty($profile)) {
$this->clientError(_('User has no profile.'));
return;
}
$twitter_user = $this->twitterUserArray($profile, true);
if ($this->format == 'xml') {
$this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user);
$this->endDocument('xml');
} elseif ($this->format == 'json') {
$this->initDocument('json');
$this->showJsonObjects($twitter_user);
$this->endDocument('json');
}
}
}

View File

@ -0,0 +1,246 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Update a user's design colors
*
* PHP version 5
*
* LICENCE: 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 API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Sets one or more hex values that control the color scheme of the
* authenticating user's design
*
* @category API
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class ApiAccountUpdateProfileColorsAction extends ApiAuthAction
{
var $profile_background_color = null;
var $profile_text_color = null;
var $profile_link_color = null;
var $profile_sidebar_fill_color = null;
var $profile_sidebar_border_color = null;
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*
*/
function prepare($args)
{
parent::prepare($args);
$this->user = $this->auth_user;
$this->profile_background_color
= $this->trimmed('profile_background_color');
$this->profile_text_color
= $this->trimmed('profile_text_color');
$this->profile_link_color
= $this->trimmed('profile_link_color');
$this->profile_sidebar_fill_color
= $this->trimmed('profile_sidebar_fill_color');
// XXX: we don't support changing the sidebar border color
// in our designs.
$this->profile_sidebar_border_color
= $this->trimmed('profile_sidebar_border_color');
// XXX: Unlike Twitter, we do allow people to change the 'content color'
$this->profile_content_color = $this->trimmed('profile_content_color');
return true;
}
/**
* Handle the request
*
* Try to save the user's colors in her design. Create a new design
* if the user doesn't already have one.
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
_('This method requires a POST.'),
400, $this->format
);
return;
}
if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(
_('API method not found.'),
404,
$this->format
);
return;
}
$design = $this->user->getDesign();
if (!empty($design)) {
$original = clone($design);
try {
$this->setColors($design);
} catch (WebColorException $e) {
$this->clientError($e->getMessage());
return false;
}
$result = $design->update($original);
if ($result === false) {
common_log_db_error($design, 'UPDATE', __FILE__);
$this->clientError(_('Could not update your design.'));
return;
}
} else {
$this->user->query('BEGIN');
// save new design
$design = new Design();
try {
$this->setColors($design);
} catch (WebColorException $e) {
$this->clientError($e->getMessage());
return false;
}
$id = $design->insert();
if (empty($id)) {
common_log_db_error($id, 'INSERT', __FILE__);
$this->clientError(_('Unable to save your design settings.'));
return;
}
$original = clone($this->user);
$this->user->design_id = $id;
$result = $this->user->update($original);
if (empty($result)) {
common_log_db_error($original, 'UPDATE', __FILE__);
$this->clientError(_('Unable to save your design settings.'));
$this->user->query('ROLLBACK');
return;
}
$this->user->query('COMMIT');
}
$profile = $this->user->getProfile();
if (empty($profile)) {
$this->clientError(_('User has no profile.'));
return;
}
$twitter_user = $this->twitterUserArray($profile, true);
if ($this->format == 'xml') {
$this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user);
$this->endDocument('xml');
} elseif ($this->format == 'json') {
$this->initDocument('json');
$this->showJsonObjects($twitter_user);
$this->endDocument('json');
}
}
/**
* Sets the user's design colors based on the request parameters
*
* @param Design $design the user's Design
*
* @return void
*/
function setColors($design)
{
$bgcolor = empty($this->profile_background_color) ?
null : new WebColor($this->profile_background_color);
$tcolor = empty($this->profile_text_color) ?
null : new WebColor($this->profile_text_color);
$sbcolor = empty($this->profile_sidebar_fill_color) ?
null : new WebColor($this->profile_sidebar_fill_color);
$lcolor = empty($this->profile_link_color) ?
null : new WebColor($this->profile_link_color);
$ccolor = empty($this->profile_content_color) ?
null : new WebColor($this->profile_content_color);
if (!empty($bgcolor)) {
$design->backgroundcolor = $bgcolor->intValue();
}
if (!empty($ccolor)) {
$design->contentcolor = $ccolor->intValue();
}
if (!empty($sbcolor)) {
$design->sidebarcolor = $sbcolor->intValue();
}
if (!empty($tcolor)) {
$design->textcolor = $tcolor->intValue();
}
if (!empty($lcolor)) {
$design->linkcolor = $lcolor->intValue();
}
return true;
}
}

View File

@ -135,7 +135,7 @@ class ApiAccountUpdateProfileImageAction extends ApiAuthAction
common_broadcast_profile($profile); common_broadcast_profile($profile);
$twitter_user = $this->twitterUserArray($this->user->getProfile(), true); $twitter_user = $this->twitterUserArray($profile, true);
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');

View File

@ -104,35 +104,29 @@ class AccountSettingsNav extends Widget
if (Event::handle('StartAccountSettingsNav', array(&$this->action))) { if (Event::handle('StartAccountSettingsNav', array(&$this->action))) {
$user = common_current_user(); $user = common_current_user();
$menu = array(); if(Event::handle('StartAccountSettingsProfileMenuItem', array($this, &$menu))){
$menu['profilesettings'] = $this->showMenuItem('profilesettings',_('Profile'),_('Change your profile settings'));
array(_('Profile'), Event::handle('EndAccountSettingsProfileMenuItem', array($this, &$menu));
_('Change your profile settings'));
if(Event::handle('CanUserChangeField', array($user->nickname, 'avatar'))){
$menu['avatarsettings'] =
array(_('Avatar'),
_('Upload an avatar'));
} }
if(Event::handle('CanUserChangeField', array($user->nickname, 'password'))){ if(Event::handle('StartAccountSettingsAvatarMenuItem', array($this, &$menu))){
$menu['passwordsettings'] = $this->showMenuItem('avatarsettings',_('Avatar'),_('Upload an avatar'));
array(_('Password'), Event::handle('EndAccountSettingsAvatarMenuItem', array($this, &$menu));
_('Change your password'));
} }
$menu['emailsettings'] = if(Event::handle('StartAccountSettingsPasswordMenuItem', array($this, &$menu))){
array(_('Email'), $this->showMenuItem('passwordsettings',_('Password'),_('Change your password'));
_('Change email handling')); Event::handle('EndAccountSettingsPasswordMenuItem', array($this, &$menu));
$menu['userdesignsettings'] = }
array(_('Design'), if(Event::handle('StartAccountSettingsEmailMenuItem', array($this, &$menu))){
_('Design your profile')); $this->showMenuItem('emailsettings',_('Email'),_('Change email handling'));
$menu['othersettings'] = Event::handle('EndAccountSettingsEmailMenuItem', array($this, &$menu));
array(_('Other'), }
_('Other options')); if(Event::handle('StartAccountSettingsDesignMenuItem', array($this, &$menu))){
$this->showMenuItem('userdesignsettings',_('Design'),_('Design your profile'));
foreach ($menu as $menuaction => $menudesc) { Event::handle('EndAccountSettingsDesignMenuItem', array($this, &$menu));
$this->action->menuItem(common_local_url($menuaction), }
$menudesc[0], if(Event::handle('StartAccountSettingsOtherMenuItem', array($this, &$menu))){
$menudesc[1], $this->showMenuItem('othersettings',_('Other'),_('Other options'));
$action_name === $menuaction); Event::handle('EndAccountSettingsOtherMenuItem', array($this, &$menu));
} }
Event::handle('EndAccountSettingsNav', array(&$this->action)); Event::handle('EndAccountSettingsNav', array(&$this->action));
@ -140,4 +134,13 @@ class AccountSettingsNav extends Widget
$this->action->elementEnd('ul'); $this->action->elementEnd('ul');
} }
function showMenuItem($menuaction, $desc1, $desc2)
{
$action_name = $this->action->trimmed('action');
$this->action->menuItem(common_local_url($menuaction),
$desc1,
$desc2,
$action_name === $menuaction);
}
} }

View File

@ -176,9 +176,14 @@ class ApiAction extends Action
$twitter_user['utc_offset'] = $t->format('Z'); $twitter_user['utc_offset'] = $t->format('Z');
$twitter_user['time_zone'] = $timezone; $twitter_user['time_zone'] = $timezone;
// To be supported some day, perhaps $twitter_user['profile_background_image_url']
$twitter_user['profile_background_image_url'] = ''; = empty($design->backgroundimage)
$twitter_user['profile_background_tile'] = false; ? '' : ($design->disposition & BACKGROUND_ON)
? Design::url($design->backgroundimage) : '';
$twitter_user['profile_background_tile']
= empty($design->disposition)
? '' : ($design->disposition & BACKGROUND_TILE) ? 'true' : 'false';
$twitter_user['statuses_count'] = $profile->noticeCount(); $twitter_user['statuses_count'] = $profile->noticeCount();

View File

@ -428,9 +428,21 @@ class Router
$m->connect('api/account/verify_credentials.:format', $m->connect('api/account/verify_credentials.:format',
array('action' => 'ApiAccountVerifyCredentials')); array('action' => 'ApiAccountVerifyCredentials'));
$m->connect('api/account/update_profile.:format',
array('action' => 'ApiAccountUpdateProfile'));
$m->connect('api/account/update_profile_image.:format', $m->connect('api/account/update_profile_image.:format',
array('action' => 'ApiAccountUpdateProfileImage')); array('action' => 'ApiAccountUpdateProfileImage'));
$m->connect('api/account/update_profile_background_image.:format',
array('action' => 'ApiAccountUpdateProfileBackgroundImage'));
$m->connect('api/account/update_profile_colors.:format',
array('action' => 'ApiAccountUpdateProfileColors'));
$m->connect('api/account/update_delivery_device.:format',
array('action' => 'ApiAccountUpdateDeliveryDevice'));
// special case where verify_credentials is called w/out a format // special case where verify_credentials is called w/out a format
$m->connect('api/account/verify_credentials', $m->connect('api/account/verify_credentials',

View File

@ -43,11 +43,17 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
abstract class AuthPlugin extends Plugin abstract class AuthPlugin extends Plugin
{ {
//is this plugin authoritative for authentication? //is this plugin authoritative for authentication?
protected $authn_authoritative = false; public $authn_authoritative = false;
//should accounts be automatically created after a successful login attempt? //should accounts be automatically created after a successful login attempt?
protected $autoregistration = false; public $autoregistration = false;
//can the user change their email address
public $email_changeable=true;
//can the user change their email address
public $password_changeable=true;
//------------Auth plugin should implement some (or all) of these methods------------\\ //------------Auth plugin should implement some (or all) of these methods------------\\
/** /**
* Check if a nickname/password combination is valid * Check if a nickname/password combination is valid
@ -102,44 +108,65 @@ abstract class AuthPlugin extends Plugin
} }
function StartCheckPassword($nickname, $password, &$authenticatedUser){ function StartCheckPassword($nickname, $password, &$authenticatedUser){
$authenticated = $this->checkPassword($nickname, $password); if($this->password_changeable){
if($authenticated){ $authenticated = $this->checkPassword($nickname, $password);
$authenticatedUser = User::staticGet('nickname', $nickname); if($authenticated){
if(!$authenticatedUser && $this->autoregistration){ $authenticatedUser = User::staticGet('nickname', $nickname);
if($this->autoregister($nickname)){ if(!$authenticatedUser && $this->autoregistration){
$authenticatedUser = User::staticGet('nickname', $nickname); if($this->autoregister($nickname)){
$authenticatedUser = User::staticGet('nickname', $nickname);
}
}
return false;
}else{
if($this->authn_authoritative){
return false;
} }
} }
return false; //we're not authoritative, so let other handlers try
}else{ }else{
if($this->authn_authoritative){ if($this->authn_authoritative){
return false; //since we're authoritative, no other plugin could do this
throw new Exception(_('Password changing is not allowed'));
} }
} }
//we're not authoritative, so let other handlers try
} }
function onStartChangePassword($nickname,$oldpassword,$newpassword) function onStartChangePassword($nickname,$oldpassword,$newpassword)
{ {
$authenticated = $this->checkPassword($nickname, $oldpassword); if($this->password_changeable){
if($authenticated){ $authenticated = $this->checkPassword($nickname, $oldpassword);
$result = $this->changePassword($nickname,$oldpassword,$newpassword); if($authenticated){
if($result){ $result = $this->changePassword($nickname,$oldpassword,$newpassword);
//stop handling of other handlers, because what was requested was done if($result){
return false; //stop handling of other handlers, because what was requested was done
return false;
}else{
throw new Exception(_('Password changing failed'));
}
}else{ }else{
throw new Exception(_('Password changing failed')); if($this->authn_authoritative){
//since we're authoritative, no other plugin could do this
throw new Exception(_('Password changing failed'));
}else{
//let another handler try
return null;
}
} }
}else{ }else{
if($this->authn_authoritative){ if($this->authn_authoritative){
//since we're authoritative, no other plugin could do this //since we're authoritative, no other plugin could do this
throw new Exception(_('Password changing failed')); throw new Exception(_('Password changing is not allowed'));
}else{
//let another handler try
return null;
} }
} }
}
function onStartAccountSettingsPasswordMenuItem($widget)
{
if($this->authn_authoritative && !$this->password_changeable){
//since we're authoritative, no other plugin could change passwords, so do render the menu item
return false;
}
} }
} }

View File

@ -36,6 +36,17 @@ require_once 'Net/LDAP2.php';
class LdapPlugin extends AuthPlugin class LdapPlugin extends AuthPlugin
{ {
public $host=null;
public $port=null;
public $version=null;
public $starttls=null;
public $binddn=null;
public $bindpw=null;
public $basedn=null;
public $options=null;
public $filter=null;
public $scope=null;
public $attributes=array();
function __construct() function __construct()
{ {
@ -125,7 +136,7 @@ class LdapPlugin extends AuthPlugin
$keys = array('host','port','version','starttls','binddn','bindpw','basedn','options','filter','scope'); $keys = array('host','port','version','starttls','binddn','bindpw','basedn','options','filter','scope');
foreach($keys as $key){ foreach($keys as $key){
$value = $this->$key; $value = $this->$key;
if($value!==false){ if($value!==null){
$config[$key]=$value; $config[$key]=$value;
} }
} }

View File

@ -4,12 +4,12 @@ Installation
============ ============
add "addPlugin('ldap', array('setting'=>'value', 'setting2'=>'value2', ...);" to the bottom of your config.php add "addPlugin('ldap', array('setting'=>'value', 'setting2'=>'value2', ...);" to the bottom of your config.php
Settings Settings
======== ========
authn_authoritative: Set to true if LDAP's responses are authoritative (meaning if LDAP fails, do check the any other plugins or the internal password database). authn_authoritative (false): Set to true if LDAP's responses are authoritative (meaning if LDAP fails, do check the any other plugins or the internal password database).
autoregistration: Set to true if users should be automatically created when they attempt to login. autoregistration (false): Set to true if users should be automatically created when they attempt to login.
email_changeable (true): Are users allowed to change their email address? (true or false)
password_changeable (true): Are users allowed to change their passwords? (true or false)
host*: LDAP server name to connect to. You can provide several hosts in an array in which case the hosts are tried from left to right.. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php host*: LDAP server name to connect to. You can provide several hosts in an array in which case the hosts are tried from left to right.. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php
port: Port on the server. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php port: Port on the server. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php
@ -30,12 +30,15 @@ attributes: an array with the key being the StatusNet user attribute name, and t
location location
* required * required
default values are in (parenthesis)
Example Example
======= =======
Here's an example of an LDAP plugin configuration that connects to Microsoft Active Directory. Here's an example of an LDAP plugin configuration that connects to Microsoft Active Directory.
addPlugin('ldap', array( addPlugin('ldap', array(
'authn_authoritative'=>true,
'autoregistration'=>true,
'binddn'=>'username', 'binddn'=>'username',
'bindpw'=>'password', 'bindpw'=>'password',
'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc', 'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc',