Perforce Chronicle 2012.2/486814
API Documentation
|
Manages user operations (e.g. More...
Public Member Functions | |
addAction () | |
Add a new user. | |
deleteAction () | |
Delete user entry. | |
editAction () | |
Edit an existing user entry. | |
indexAction () | |
List all users. | |
init () | |
Use management layout for all actions. | |
loginAction () | |
Handle user logins. | |
logoutAction () | |
Log the user out (clear identity). | |
Public Attributes | |
$contexts | |
const | LOGIN_FAILED_MAX_DELAY = 2000000 |
const | LOGIN_FAILED_MIN_DELAY = 1000000 |
Protected Member Functions | |
_authenticate ($login, $password) | |
Authenticate the user. | |
_getLoginForm () | |
Get the login form. | |
_isSystemUser ($userId) | |
Check if the given user is the system user. |
Manages user operations (e.g.
login/logout).
User_IndexController::_authenticate | ( | $ | login, |
$ | password | ||
) | [protected] |
Authenticate the user.
Return true if success, otherwise false.
string | $login | user's id |
string | $password | user's password |
{ // construct user instance to authenticate against. $user = new P4Cms_User; $user->setId($login) ->setPassword($password); // authenticate return Zend_Auth::getInstance()->authenticate($user); }
User_IndexController::_getLoginForm | ( | ) | [protected] |
Get the login form.
{ // grab current acl. $acl = $this->acl->getAcl(); $form = new User_Form_Login( array( 'action' => $this->view->url( array( 'module' => 'user', 'controller' => 'index', 'action' => 'login' ) ), 'acl' => $acl ) ); // for context switched requests, prefix form ids with context // to ensure ids are unique if they appear twice on the page. $context = $this->contextSwitch->getCurrentContext(); if ($context) { $form->setIdPrefix($context . "-"); } return $form; }
User_IndexController::_isSystemUser | ( | $ | userId | ) | [protected] |
Check if the given user is the system user.
string | $userId | the user id to compare against the system user id. |
{ return $userId == $this->getInvokeArg('bootstrap')->getResource('perforce')->getUser(); }
User_IndexController::addAction | ( | ) |
Add a new user.
{ // enforce permissions $this->acl->check('users', 'add'); $request = $this->getRequest(); $activeUser = P4Cms_User::fetchActive(); $form = new User_Form_Add; // deny if adding user is disabled if (!$activeUser->isAdministrator() && !P4_User::isAutoUserCreationEnabled()) { throw new P4Cms_AccessDeniedException( "You don't have permission to add users." ); } // set up view $view = $this->view; $view->form = $form; $view->headTitle()->set('Add User'); // prepare default roles $defaultRoles = P4Cms_Acl_Role::exists(P4Cms_Acl_Role::ROLE_MEMBER) ? array(P4Cms_Acl_Role::ROLE_MEMBER) : array(); // set default roles if no post if (!$request->isPost()) { $request->setParam('roles', $defaultRoles); } // populate form from request $form->populate($request->getParams()); // if posted, validate form and save user. if ($request->isPost()) { // if form is invalid, set response code and exit if (!$form->isValid($request->getParams())) { $this->getResponse()->setHttpResponseCode(400); $view->errors = $form->getMessages(); return; } // create the user entry. $user = new P4Cms_User; $user->setValues($form->getValues()) ->save(); // set roles // - if active user is not administrator, use site storage adapter // - if user has permission, take roles from request, otherwise use defaults $adapter = $activeUser->isAdministrator() ? $activeUser->getPersonalAdapter() : P4Cms_Site::fetchActive()->getStorageAdapter(); $roles = $form->getElement('roles') && $this->acl->isAllowed('users', 'manage-roles') ? $form->getValue('roles') : $defaultRoles; P4Cms_Acl_Role::setUserRoles($user, $roles, $adapter); // if active user is anonymous, log in as newly created user if (P4Cms_User::fetchActive()->isAnonymous()) { $result = $this->_authenticate($user->getId(), $form->getValue('password')); if ($result->isValid()) { P4Cms_Notifications::add( "You have been logged in as '{$user->getId()}'", P4Cms_Notifications::SEVERITY_SUCCESS ); } } // set notification message $view->message = "User '{$user->getId()}' has been successfuly added."; // for traditional requests, add notification message and redirect if (!$this->contextSwitch->getCurrentContext()) { P4Cms_Notifications::add( $view->message, P4Cms_Notifications::SEVERITY_SUCCESS ); $this->redirector->gotoUrl($request->getBaseUrl()); } } }
User_IndexController::deleteAction | ( | ) |
Delete user entry.
User account can be removed only via post.
{ // deny if not accessed via post $request = $this->getRequest(); if (!$request->isPost()) { throw new P4Cms_AccessDeniedException( "Deleting users is not permitted in this context." ); } $activeUser = P4Cms_User::fetchActive(); $userId = $request->getPost('id'); $deleteActiveUser = $userId === $activeUser->getId(); if (!$deleteActiveUser) { $this->acl->check('users', 'manage'); } // deny if attempting to delete system user if ($this->_isSystemUser($userId)) { throw new P4Cms_AccessDeniedException( "You don't have permission to delete this user." ); } // get user to delete $user = $deleteActiveUser ? $activeUser : P4Cms_User::fetch($userId); // deleted user should have the same adapter as active user personal adapter $user->setAdapter($activeUser->getPersonalAdapter()); // deny if deleted user is the only administrator if ($user->isAdministrator() && count(P4Cms_Acl_Role::fetch(P4Cms_Acl_Role::ROLE_ADMINISTRATOR)->getUsers()) == 1 ) { throw new P4Cms_AccessDeniedException( "The only administrator cannot be deleted." ); } // remove user references from the roles that user is associated with // use personal adapter if user is admin, otherwise use site adapter. $adapter = $activeUser->isAdministrator() ? $activeUser->getPersonalAdapter() : P4Cms_Site::fetchActive()->getStorageAdapter(); P4Cms_Acl_Role::setUserRoles($user, array(), $adapter); // do the actual delete $user->delete(); // clear any cache entries related to this user P4Cms_Cache::clean('all', 'p4cms_user_' . md5($user->getId())); // add notification if active user was deleted or // if we are in traditional context $context = $this->contextSwitch->getCurrentContext(); if (!$context || $deleteActiveUser) { P4Cms_Notifications::add( "User '$userId' has been deleted.", P4Cms_Notifications::SEVERITY_SUCCESS ); } // redirect for traditional requests if (!$context) { $this->redirector->gotoUrl($request->getBaseUrl()); } $this->view->userId = $userId; $this->view->deleteActiveUser = $deleteActiveUser; }
User_IndexController::editAction | ( | ) |
Edit an existing user entry.
{ $request = $this->getRequest(); $activeUser = P4Cms_User::fetchActive(); $userId = $request->getParam('id', $activeUser->getId()); // ensure user id is set in the request $request->setParam('id', $userId); // enforce permissions if ($userId !== $activeUser->getId()) { $this->acl->check('users', 'manage'); } // deny if user id is null or attempted to edit system user if ($userId === null || $this->_isSystemUser($userId)) { throw new P4Cms_AccessDeniedException( "You don't have permission to edit this user." ); } // determine whether old password input is neccessary when setting up new password $formOptions = array( 'needOldPassword' => !$activeUser->isAdministrator() || ($activeUser->getId() === $userId) ); // determine whether the user is the last administrator $admins = P4Cms_Acl_Role::fetch(P4Cms_Acl_Role::ROLE_ADMINISTRATOR)->getRealUsers(); $formOptions['requireAdministrator'] = count($admins) == 1 && in_array($userId, $admins); // redirect to page not found if user doesn't exist if (!P4Cms_User::exists($userId)) { return $this->_forward('page-not-found', 'index', 'error'); } $user = P4Cms_User::fetch($userId); // set up view $form = new User_Form_Edit($formOptions); $view = $this->view; $view->form = $form; $view->user = $user; $view->headTitle()->set('Edit User'); // set roles from storage if no post, or not permitted. if (!$request->isPost() || !$this->acl->isAllowed('users', 'manage-roles')) { $request->setParam('roles', $user->getRoles()->invoke('getId')); } // populate form from request if posted, otherwise from storage. $form->populate( $request->isPost() ? $request->getParams() : $request->getParams() + $user->getValues() ); // if change password unchecked, disable 'password' group. if (!$form->getValue('changePassword')) { $group = $form->getDisplayGroup('passwords'); $group->setAttrib('class', $group->getAttrib('class') . ' disabled'); } // if posted, validate form and save user. if ($request->isPost()) { // if form is invalid, set response code and exit if (!$form->isValid($request->getParams())) { $this->getResponse()->setHttpResponseCode(400); $view->errors = $form->getMessages(); return; } $user->setValues($form->getValues()); // if current password given, must set password explicitly. if ($form->getValue('currentPassword')) { $user->setPassword( $form->getValue('password'), $form->getValue('currentPassword') ); } $user->save(); // if user has permission to manage roles, set roles from request if ($form->getElement('roles') && $this->acl->isAllowed('users', 'manage-roles')) { P4Cms_Acl_Role::setUserRoles($user, $form->getValue('roles')); } // if current user changed the password, re-authenticate to get updated ticket if ($activeUser->getId() === $userId && $form->getValue('changePassword')) { $result = $this->_authenticate($userId, $form->getValue('password')); } // set notification message $view->message = "User '{$user->getId()}' has been successfuly updated."; // clear any cache entries related to this user P4Cms_Cache::clean('all', 'p4cms_user_' . md5($user->getId())); // for traditional requests, add notification message and redirect if (!$this->contextSwitch->getCurrentContext()) { P4Cms_Notifications::add( $view->message, P4Cms_Notifications::SEVERITY_SUCCESS ); $this->redirector->gotoUrl($request->getBaseUrl()); } } }
User_IndexController::indexAction | ( | ) |
List all users.
p4cms.user.grid.actions Modify the passed menu (add/modify/delete items) to influence the actions shown on entries in the Manage Users grid. P4Cms_Navigation $actions A menu to hold grid actions.
p4cms.user.grid.data.item Return the passed item after applying any modifications (add properties, change values, etc.) to influence the row values sent to the Manage Users grid. array $item The item to potentially modify. mixed $model The original object/array that was used to make the item. Ui_View_Helper_DataGrid $helper The view helper that broadcast this topic.
p4cms.user.grid.data Adjust the passed data (add properties, modify values, etc.) to influence the row values sent to the Manage Users grid. Zend_Dojo_Data $data The data to be filtered. Ui_View_Helper_DataGrid $helper The view helper that broadcast this topic.
p4cms.user.grid.populate Adjust the passed iterator (possibly based on values in the passed form) to filter which users will be shown on the Manage Users grid. P4Cms_Model_Iterator $users An Iterator of User_Model_User objects. P4Cms_Form_PubSubForm $form A form containing filter options.
p4cms.user.grid.render Make adjustments to the datagrid helper's options pre-render (e.g. change options to add columns) for the Manage Users grid. Ui_View_Helper_DataGrid $helper The view helper that broadcast this topic.
p4cms.user.grid.form Make arbitrary modifications to the Manage Users filters form. P4Cms_Form_PubSubForm $form The form that published this event.
p4cms.user.grid.form.subForms Return a Form (or array of Forms) to have them added to the Manage Users filters form. The returned form(s) should have a 'name' set on them to allow them to be uniquely identified. P4Cms_Form_PubSubForm $form The form that published this event.
p4cms.user.grid.form.preValidate Allows subscribers to adjust the Manage Users filters form prior to validation of the passed data. For example, modify element values based on related selections to permit proper validation. P4Cms_Form_PubSubForm $form The form that published this event. array $values An associative array of form values.
p4cms.user.grid.form.validate Return false to indicate the Manage Users filters form is invalid. Return true to indicate your custom checks were satisfied, so form validity should be unchanged. P4Cms_Form_PubSubForm $form The form that published this event. array $values An associative array of form values.
p4cms.user.grid.form.populate Allows subscribers to adjust the Manage Users filters form after it has been populated with the passed data. P4Cms_Form_PubSubForm $form The form that published this event. array $values The values passed to the populate method.
{ // enforce permissions $this->acl->check('users', 'manage'); // setup list options form. $request = $this->getRequest(); $gridNamespace = 'p4cms.user.grid'; $form = new Ui_Form_GridOptions( array( 'namespace' => $gridNamespace ) ); $form->populate($request->getParams()); // setup view. $view = $this->view; $view->form = $form; $view->pageSize = $request->getParam('count', 100); $view->rowOffset = $request->getParam('start', 0); $view->pageOffset = round($view->rowOffset / $view->pageSize, 0) + 1; $view->showAddLink = $this->acl->isAllowed('users', 'add'); $view->headTitle()->set('Manage Users'); // set DataGrid view helper namespace $helper = $view->dataGrid(); $helper->setNamespace($gridNamespace); // collect the actions from interested parties $actions = new P4Cms_Navigation; P4Cms_PubSub::publish($gridNamespace . '.actions', $actions); $view->actions = $actions; // early exit for standard requests (ie. not json) if (!$this->contextSwitch->getCurrentContext()) { return; } // fetch users - allow third-parties to influence list $users = P4Cms_User::fetchAll(); try { P4Cms_PubSub::publish($gridNamespace . '.populate', $users, $form); } catch (Exception $e) { P4Cms_Log::logException("Error building user list.", $e); } // prepare sorting options $sortKey = $request->getParam('sort', 'id'); $sortFlags = array( P4Cms_Model_Iterator::SORT_NATURAL, P4Cms_Model_Iterator::SORT_NO_CASE ); if (substr($sortKey, 0, 1) == '-') { $sortKey = substr($sortKey, 1); $sortFlags[] = P4Cms_Model_Iterator::SORT_DESCENDING; } else { $sortFlags[] = P4Cms_Model_Iterator::SORT_ASCENDING; } // apply sorting options. $users->sortBy($sortKey, $sortFlags); // add users to the view. $view->users = $users; }
User_IndexController::init | ( | ) |
Use management layout for all actions.
{
$this->_helper->layout->setLayout('manage-layout');
}
User_IndexController::loginAction | ( | ) |
Handle user logins.
If not posted, presents form; otherwise, authenticates.
{ $request = $this->getRequest(); $form = $this->_getLoginForm(); $form->setAction($this->_helper->url('login')); // set up view $view = $this->view; $view->form = $form; $view->headTitle()->set('User Login'); // if posted, validate form and authenticate user. if ($request->isPost()) { // if form is invalid, set response code and exit if (!$form->isValid($request->getPost())) { $this->getResponse()->setHttpResponseCode(400); return; } $login = $form->getValue('user'); // silently clear login if it is does not look like // a valid p4 username or email address. $userValidator = new P4_Validate_UserName; $emailValidator = new Zend_Validate_EmailAddress; if (!$userValidator->isValid($login) && !$emailValidator->isValid($login)) { $login = null; } // if login is an email address, lookup corresponding usernames. if (strpos($login, '@')) { $found = array(); // list with users matching the email address foreach (P4Cms_User::fetchAll() as $user) { if ($user->getEmail() !== $login) { continue; } $found[] = $user->getId(); } $login = $found ?: null; } if (!is_array($login)) { $login = array($login); } // loop through all login candidates $errorMessage = 'Login failed. Invalid user or password.'; foreach ($login as $loginCandidate) { // try to authenticate with given password $result = $this->_authenticate($loginCandidate, $form->getValue('password')); if (!$result->isValid()) { // don't allow successful auth without priveleges, and report correct error if ($result->getCode() === Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS) { $errorMessage = 'You do not have permission to access this site.'; break; } continue; } // don't allow login as system user if ($this->_isSystemUser($loginCandidate)) { Zend_Auth::getInstance()->clearIdentity(); $errorMessage = 'Login failed. Cannot login as the system user.'; break; } // auth data in session shouldn't influence page caching; add ourselves to the ignore list if (P4Cms_Cache::canCache('page')) { P4Cms_Cache::getCache('page')->addIgnoredSessionVariable( Zend_Auth::getInstance()->getStorage()->getNamespace() ); } // protect against session fixation Zend_Session::regenerateId(); // login successful P4Cms_Notifications::add( 'Login successful.', P4Cms_Notifications::SEVERITY_SUCCESS ); // redirect for traditional contexts if (!$this->contextSwitch->getCurrentContext()) { $this->redirector->gotoUrl($request->getBaseUrl()); } return; } // login failed, add random 1-2 second delay. $delay = mt_rand(self::LOGIN_FAILED_MIN_DELAY, self::LOGIN_FAILED_MAX_DELAY); usleep($delay); // authentication failed - add error to form. if (!$this->contextSwitch->getCurrentContext()) { P4Cms_Notifications::add($errorMessage, P4Cms_Notifications::SEVERITY_ERROR); } $form->addError($errorMessage); $this->getResponse()->setHttpResponseCode(400); } }
User_IndexController::logoutAction | ( | ) |
Log the user out (clear identity).
{ Zend_Auth::getInstance()->clearIdentity(); P4Cms_Notifications::add('Logout completed.', P4Cms_Notifications::SEVERITY_SUCCESS); $this->redirector->gotoUrl($this->getRequest()->getBaseUrl()); }
User_IndexController::$contexts |
array( 'login' => array('partial', 'json'), 'add' => array('partial', 'json'), 'edit' => array('partial', 'json'), 'index' => array('json'), 'delete' => array('json'), )
const User_IndexController::LOGIN_FAILED_MAX_DELAY = 2000000 |
const User_IndexController::LOGIN_FAILED_MIN_DELAY = 1000000 |