From 337b1aaaa16bde80b42a9902ebeb299f8f13a226 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 14:32:14 -0800 Subject: Site-wide notice text admin panel --- lib/router.php | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/router.php') diff --git a/lib/router.php b/lib/router.php index abbce041d..7e8e22a7d 100644 --- a/lib/router.php +++ b/lib/router.php @@ -649,6 +649,7 @@ class Router $m->connect('admin/access', array('action' => 'accessadminpanel')); $m->connect('admin/paths', array('action' => 'pathsadminpanel')); $m->connect('admin/sessions', array('action' => 'sessionsadminpanel')); + $m->connect('admin/sitenotice', array('action' => 'sitenoticeadminpanel')); $m->connect('getfile/:filename', array('action' => 'getfile'), -- cgit v1.2.3-54-g00ecf From 4a2511139eaafcbe93a2e720e0c6f170ecb00d77 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 15:43:49 -0800 Subject: Initial user role controls on profile pages, for owner to add/remove administrator and moderator options. Buttons need to be themed. --- actions/grantrole.php | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ actions/revokerole.php | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ classes/Profile.php | 4 ++ classes/Profile_role.php | 17 +++++++++ lib/grantroleform.php | 93 +++++++++++++++++++++++++++++++++++++++++++++ lib/revokeroleform.php | 93 +++++++++++++++++++++++++++++++++++++++++++++ lib/right.php | 2 + lib/router.php | 1 + lib/userprofile.php | 26 +++++++++++++ 9 files changed, 434 insertions(+) create mode 100644 actions/grantrole.php create mode 100644 actions/revokerole.php create mode 100644 lib/grantroleform.php create mode 100644 lib/revokeroleform.php (limited to 'lib/router.php') diff --git a/actions/grantrole.php b/actions/grantrole.php new file mode 100644 index 000000000..cd6bd4d79 --- /dev/null +++ b/actions/grantrole.php @@ -0,0 +1,99 @@ +. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @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); +} + +/** + * Sandbox a user. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class GrantRoleAction extends ProfileFormAction +{ + /** + * Check parameters + * + * @param array $args action arguments (URL, GET, POST) + * + * @return boolean success flag + */ + + function prepare($args) + { + if (!parent::prepare($args)) { + return false; + } + + $this->role = $this->arg('role'); + if (!Profile_role::isValid($this->role)) { + $this->clientError(_("Invalid role.")); + return false; + } + if (!Profile_role::isSettable($this->role)) { + $this->clientError(_("This role is reserved and cannot be set.")); + return false; + } + + $cur = common_current_user(); + + assert(!empty($cur)); // checked by parent + + if (!$cur->hasRight(Right::GRANTROLE)) { + $this->clientError(_("You cannot grant user roles on this site.")); + return false; + } + + assert(!empty($this->profile)); // checked by parent + + if ($this->profile->hasRole($this->role)) { + $this->clientError(_("User already has this role.")); + return false; + } + + return true; + } + + /** + * Sandbox a user. + * + * @return void + */ + + function handlePost() + { + $this->profile->grantRole($this->role); + } +} diff --git a/actions/revokerole.php b/actions/revokerole.php new file mode 100644 index 000000000..b78c1c25a --- /dev/null +++ b/actions/revokerole.php @@ -0,0 +1,99 @@ +. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @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); +} + +/** + * Sandbox a user. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class RevokeRoleAction extends ProfileFormAction +{ + /** + * Check parameters + * + * @param array $args action arguments (URL, GET, POST) + * + * @return boolean success flag + */ + + function prepare($args) + { + if (!parent::prepare($args)) { + return false; + } + + $this->role = $this->arg('role'); + if (!Profile_role::isValid($this->role)) { + $this->clientError(_("Invalid role.")); + return false; + } + if (!Profile_role::isSettable($this->role)) { + $this->clientError(_("This role is reserved and cannot be set.")); + return false; + } + + $cur = common_current_user(); + + assert(!empty($cur)); // checked by parent + + if (!$cur->hasRight(Right::REVOKEROLE)) { + $this->clientError(_("You cannot revoke user roles on this site.")); + return false; + } + + assert(!empty($this->profile)); // checked by parent + + if (!$this->profile->hasRole($this->role)) { + $this->clientError(_("User doesn't have this role.")); + return false; + } + + return true; + } + + /** + * Sandbox a user. + * + * @return void + */ + + function handlePost() + { + $this->profile->revokeRole($this->role); + } +} diff --git a/classes/Profile.php b/classes/Profile.php index 9c2fa7a0c..0322c9358 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -743,6 +743,10 @@ class Profile extends Memcached_DataObject case Right::CONFIGURESITE: $result = $this->hasRole(Profile_role::ADMINISTRATOR); break; + case Right::GRANTROLE: + case Right::REVOKEROLE: + $result = $this->hasRole(Profile_role::OWNER); + break; case Right::NEWNOTICE: case Right::NEWMESSAGE: case Right::SUBSCRIBE: diff --git a/classes/Profile_role.php b/classes/Profile_role.php index bf2c453ed..d0a0b31f0 100644 --- a/classes/Profile_role.php +++ b/classes/Profile_role.php @@ -53,4 +53,21 @@ class Profile_role extends Memcached_DataObject const ADMINISTRATOR = 'administrator'; const SANDBOXED = 'sandboxed'; const SILENCED = 'silenced'; + + public static function isValid($role) + { + // @fixme could probably pull this from class constants + $known = array(self::OWNER, + self::MODERATOR, + self::ADMINISTRATOR, + self::SANDBOXED, + self::SILENCED); + return in_array($role, $known); + } + + public static function isSettable($role) + { + $allowedRoles = array('administrator', 'moderator'); + return self::isValid($role) && in_array($role, $allowedRoles); + } } diff --git a/lib/grantroleform.php b/lib/grantroleform.php new file mode 100644 index 000000000..b5f952746 --- /dev/null +++ b/lib/grantroleform.php @@ -0,0 +1,93 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou , Brion Vibber + * @copyright 2009-2010 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); +} + +/** + * Form for sandboxing a user + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see UnSandboxForm + */ + +class GrantRoleForm extends ProfileActionForm +{ + function __construct($role, $label, $writer, $profile, $r2args) + { + parent::__construct($writer, $profile, $r2args); + $this->role = $role; + $this->label = $label; + } + + /** + * Action this form provides + * + * @return string Name of the action, lowercased. + */ + + function target() + { + return 'grantrole'; + } + + /** + * Title of the form + * + * @return string Title of the form, internationalized + */ + + function title() + { + return $this->label; + } + + function formData() + { + parent::formData(); + $this->out->hidden('role', $this->role); + } + + /** + * Description of the form + * + * @return string description of the form, internationalized + */ + + function description() + { + return sprintf(_('Grant this user the "%s" role'), $this->label); + } +} diff --git a/lib/revokeroleform.php b/lib/revokeroleform.php new file mode 100644 index 000000000..ec24b9910 --- /dev/null +++ b/lib/revokeroleform.php @@ -0,0 +1,93 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou , Brion Vibber + * @copyright 2009-2010 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); +} + +/** + * Form for sandboxing a user + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see UnSandboxForm + */ + +class RevokeRoleForm extends ProfileActionForm +{ + function __construct($role, $label, $writer, $profile, $r2args) + { + parent::__construct($writer, $profile, $r2args); + $this->role = $role; + $this->label = $label; + } + + /** + * Action this form provides + * + * @return string Name of the action, lowercased. + */ + + function target() + { + return 'revokerole'; + } + + /** + * Title of the form + * + * @return string Title of the form, internationalized + */ + + function title() + { + return $this->label; + } + + function formData() + { + parent::formData(); + $this->out->hidden('role', $this->role); + } + + /** + * Description of the form + * + * @return string description of the form, internationalized + */ + + function description() + { + return sprintf(_('Revoke the "%s" role from this user'), $this->label); + } +} diff --git a/lib/right.php b/lib/right.php index 4e9c5a918..deb451fde 100644 --- a/lib/right.php +++ b/lib/right.php @@ -58,5 +58,7 @@ class Right const EMAILONSUBSCRIBE = 'emailonsubscribe'; const EMAILONFAVE = 'emailonfave'; const MAKEGROUPADMIN = 'makegroupadmin'; + const GRANTROLE = 'grantrole'; + const REVOKEROLE = 'revokerole'; } diff --git a/lib/router.php b/lib/router.php index 7e8e22a7d..15f88c959 100644 --- a/lib/router.php +++ b/lib/router.php @@ -98,6 +98,7 @@ class Router 'groupblock', 'groupunblock', 'sandbox', 'unsandbox', 'silence', 'unsilence', + 'grantrole', 'revokerole', 'repeat', 'deleteuser', 'geocode', diff --git a/lib/userprofile.php b/lib/userprofile.php index 43dfd05be..8464c2446 100644 --- a/lib/userprofile.php +++ b/lib/userprofile.php @@ -346,6 +346,16 @@ class UserProfile extends Widget $this->out->elementEnd('ul'); $this->out->elementEnd('li'); } + + if ($cur->hasRight(Right::GRANTROLE)) { + $this->out->elementStart('li', 'entity_role'); + $this->out->element('p', null, _('User role')); + $this->out->elementStart('ul'); + $this->roleButton('administrator', _m('role', 'Administrator')); + $this->roleButton('moderator', _m('role', 'Moderator')); + $this->out->elementEnd('ul'); + $this->out->elementEnd('li'); + } } } @@ -359,6 +369,22 @@ class UserProfile extends Widget } } + function roleButton($role, $label) + { + list($action, $r2args) = $this->out->returnToArgs(); + $r2args['action'] = $action; + + $this->out->elementStart('li', "entity_role_$role"); + if ($this->user->hasRole($role)) { + $rf = new RevokeRoleForm($role, $label, $this->out, $this->profile, $r2args); + $rf->show(); + } else { + $rf = new GrantRoleForm($role, $label, $this->out, $this->profile, $r2args); + $rf->show(); + } + $this->out->elementEnd('li'); + } + function showRemoteSubscribeLink() { $url = common_local_url('remotesubscribe', -- cgit v1.2.3-54-g00ecf From 61de37ec7bfb620288d3bc3b1fcdfb66725f0f99 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 16:47:27 -0800 Subject: Move snapshot configuration to its own admin panel Turn on with: $config['admin']['panels'][] = 'snapshot'; --- actions/siteadminpanel.php | 56 +-------- actions/snapshotadminpanel.php | 251 +++++++++++++++++++++++++++++++++++++++++ lib/adminpanelaction.php | 5 + lib/router.php | 1 + 4 files changed, 263 insertions(+), 50 deletions(-) create mode 100644 actions/snapshotadminpanel.php (limited to 'lib/router.php') diff --git a/actions/siteadminpanel.php b/actions/siteadminpanel.php index 4b29819b7..cb3c2e8fd 100644 --- a/actions/siteadminpanel.php +++ b/actions/siteadminpanel.php @@ -66,7 +66,7 @@ class SiteadminpanelAction extends AdminPanelAction function getInstructions() { - return _('Basic settings for this StatusNet site.'); + return _('Basic settings for this StatusNet site'); } /** @@ -90,10 +90,11 @@ class SiteadminpanelAction extends AdminPanelAction function saveSettings() { - static $settings = array('site' => array('name', 'broughtby', 'broughtbyurl', - 'email', 'timezone', 'language', - 'site', 'textlimit', 'dupelimit'), - 'snapshot' => array('run', 'reporturl', 'frequency')); + static $settings = array( + 'site' => array('name', 'broughtby', 'broughtbyurl', + 'email', 'timezone', 'language', + 'site', 'textlimit', 'dupelimit'), + ); $values = array(); @@ -158,25 +159,6 @@ class SiteadminpanelAction extends AdminPanelAction $this->clientError(sprintf(_('Unknown language "%s".'), $values['site']['language'])); } - // Validate report URL - - if (!is_null($values['snapshot']['reporturl']) && - !Validate::uri($values['snapshot']['reporturl'], array('allowed_schemes' => array('http', 'https')))) { - $this->clientError(_("Invalid snapshot report URL.")); - } - - // Validate snapshot run value - - if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) { - $this->clientError(_("Invalid snapshot run value.")); - } - - // Validate snapshot run value - - if (!Validate::number($values['snapshot']['frequency'])) { - $this->clientError(_("Snapshot frequency must be a number.")); - } - // Validate text limit if (!Validate::number($values['site']['textlimit'], array('min' => 140))) { @@ -285,32 +267,6 @@ class SiteAdminPanelForm extends AdminForm $this->out->elementEnd('ul'); $this->out->elementEnd('fieldset'); - $this->out->elementStart('fieldset', array('id' => 'settings_admin_snapshots')); - $this->out->element('legend', null, _('Snapshots')); - $this->out->elementStart('ul', 'form_data'); - $this->li(); - $snapshot = array('web' => _('Randomly during Web hit'), - 'cron' => _('In a scheduled job'), - 'never' => _('Never')); - $this->out->dropdown('run', _('Data snapshots'), - $snapshot, _('When to send statistical data to status.net servers'), - false, $this->value('run', 'snapshot')); - $this->unli(); - - $this->li(); - $this->input('frequency', _('Frequency'), - _('Snapshots will be sent once every N web hits'), - 'snapshot'); - $this->unli(); - - $this->li(); - $this->input('reporturl', _('Report URL'), - _('Snapshots will be sent to this URL'), - 'snapshot'); - $this->unli(); - $this->out->elementEnd('ul'); - $this->out->elementEnd('fieldset'); - $this->out->elementStart('fieldset', array('id' => 'settings_admin_limits')); $this->out->element('legend', null, _('Limits')); $this->out->elementStart('ul', 'form_data'); diff --git a/actions/snapshotadminpanel.php b/actions/snapshotadminpanel.php new file mode 100644 index 000000000..a0c2315bc --- /dev/null +++ b/actions/snapshotadminpanel.php @@ -0,0 +1,251 @@ +. + * + * @category Settings + * @package StatusNet + * @author Zach Copley + * @copyright 2010 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); +} + +/** + * Manage snapshots + * + * @category Admin + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class SnapshotadminpanelAction extends AdminPanelAction +{ + /** + * Returns the page title + * + * @return string page title + */ + + function title() + { + return _('Snapshots'); + } + + /** + * Instructions for using this form. + * + * @return string instructions + */ + + function getInstructions() + { + return _('Manage snapshot configuration'); + } + + /** + * Show the snapshots admin panel form + * + * @return void + */ + + function showForm() + { + $form = new SnapshotAdminPanelForm($this); + $form->show(); + return; + } + + /** + * Save settings from the form + * + * @return void + */ + + function saveSettings() + { + static $settings = array( + 'snapshot' => array('run', 'reporturl', 'frequency') + ); + + $values = array(); + + foreach ($settings as $section => $parts) { + foreach ($parts as $setting) { + $values[$section][$setting] = $this->trimmed($setting); + } + } + + // This throws an exception on validation errors + + $this->validate($values); + + // assert(all values are valid); + + $config = new Config(); + + $config->query('BEGIN'); + + foreach ($settings as $section => $parts) { + foreach ($parts as $setting) { + Config::save($section, $setting, $values[$section][$setting]); + } + } + + $config->query('COMMIT'); + + return; + } + + function validate(&$values) + { + // Validate snapshot run value + + if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) { + $this->clientError(_("Invalid snapshot run value.")); + } + + // Validate snapshot frequency value + + if (!Validate::number($values['snapshot']['frequency'])) { + $this->clientError(_("Snapshot frequency must be a number.")); + } + + // Validate report URL + + if (!is_null($values['snapshot']['reporturl']) + && !Validate::uri( + $values['snapshot']['reporturl'], + array('allowed_schemes' => array('http', 'https') + ) + )) { + $this->clientError(_("Invalid snapshot report URL.")); + } + } +} + +class SnapshotAdminPanelForm extends AdminForm +{ + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + return 'form_snapshot_admin_panel'; + } + + /** + * class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_settings'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('snapshotadminpanel'); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->elementStart( + 'fieldset', + array('id' => 'settings_admin_snapshots') + ); + $this->out->element('legend', null, _('Snapshots')); + $this->out->elementStart('ul', 'form_data'); + $this->li(); + $snapshot = array( + 'web' => _('Randomly during Web hit'), + 'cron' => _('In a scheduled job'), + 'never' => _('Never') + ); + $this->out->dropdown( + 'run', + _('Data snapshots'), + $snapshot, + _('When to send statistical data to status.net servers'), + false, + $this->value('run', 'snapshot') + ); + $this->unli(); + + $this->li(); + $this->input( + 'frequency', + _('Frequency'), + _('Snapshots will be sent once every N web hits'), + 'snapshot' + ); + $this->unli(); + + $this->li(); + $this->input( + 'reporturl', + _('Report URL'), + _('Snapshots will be sent to this URL'), + 'snapshot' + ); + $this->unli(); + $this->out->elementEnd('ul'); + $this->out->elementEnd('fieldset'); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit( + 'submit', + _('Save'), + 'submit', + null, + _('Save snapshot settings') + ); + } +} diff --git a/lib/adminpanelaction.php b/lib/adminpanelaction.php index eb622871e..d1aab3dfc 100644 --- a/lib/adminpanelaction.php +++ b/lib/adminpanelaction.php @@ -381,6 +381,11 @@ class AdminPanelNav extends Widget _('Edit site notice'), $action_name == 'sitenoticeadminpanel', 'nav_sitenotice_admin_panel'); } + if (AdminPanelAction::canAdmin('snapshot')) { + $this->out->menuItem(common_local_url('snapshotadminpanel'), _('Snapshots'), + _('Snapshots configuration'), $action_name == 'snapshotadminpanel', 'nav_snapshot_admin_panel'); + } + Event::handle('EndAdminPanelNav', array($this)); } $this->action->elementEnd('ul'); diff --git a/lib/router.php b/lib/router.php index 15f88c959..706120e0b 100644 --- a/lib/router.php +++ b/lib/router.php @@ -651,6 +651,7 @@ class Router $m->connect('admin/paths', array('action' => 'pathsadminpanel')); $m->connect('admin/sessions', array('action' => 'sessionsadminpanel')); $m->connect('admin/sitenotice', array('action' => 'sitenoticeadminpanel')); + $m->connect('admin/snapshot', array('action' => 'snapshotadminpanel')); $m->connect('getfile/:filename', array('action' => 'getfile'), -- cgit v1.2.3-54-g00ecf