diff options
Diffstat (limited to 'application/forms/Config/User')
-rw-r--r-- | application/forms/Config/User/CreateMembershipForm.php | 192 | ||||
-rw-r--r-- | application/forms/Config/User/UserForm.php | 210 |
2 files changed, 402 insertions, 0 deletions
diff --git a/application/forms/Config/User/CreateMembershipForm.php b/application/forms/Config/User/CreateMembershipForm.php new file mode 100644 index 0000000..6c74c8c --- /dev/null +++ b/application/forms/Config/User/CreateMembershipForm.php @@ -0,0 +1,192 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Forms\Config\User; + +use Exception; +use Icinga\Application\Logger; +use Icinga\Data\DataArray\ArrayDatasource; +use Icinga\Web\Form; +use Icinga\Web\Notification; + +/** + * Form for creating one or more group memberships + */ +class CreateMembershipForm extends Form +{ + /** + * The user group backends to fetch groups from + * + * Each backend must implement the Icinga\Data\Extensible and Icinga\Data\Selectable interface. + * + * @var array + */ + protected $backends; + + /** + * The username to create memberships for + * + * @var string + */ + protected $userName; + + /** + * Set the user group backends to fetch groups from + * + * @param array $backends + * + * @return $this + */ + public function setBackends($backends) + { + $this->backends = $backends; + return $this; + } + + /** + * Set the username to create memberships for + * + * @param string $userName + * + * @return $this + */ + public function setUsername($userName) + { + $this->userName = $userName; + return $this; + } + + /** + * Create and add elements to this form + * + * @param array $formData The data sent by the user + */ + public function createElements(array $formData) + { + $query = $this->createDataSource()->select()->from('group', array('group_name', 'backend_name')); + + $options = array(); + foreach ($query as $row) { + $options[$row->backend_name . ';' . $row->group_name] = $row->group_name . ' (' . $row->backend_name . ')'; + } + + $this->addElement( + 'multiselect', + 'groups', + array( + 'required' => true, + 'multiOptions' => $options, + 'label' => $this->translate('Groups'), + 'description' => sprintf( + $this->translate('Select one or more groups where to add %s as member'), + $this->userName + ), + 'class' => 'grant-permissions' + ) + ); + + $this->setTitle(sprintf($this->translate('Create memberships for %s'), $this->userName)); + $this->setSubmitLabel($this->translate('Create')); + } + + /** + * Instantly redirect back in case the user is already a member of all groups + */ + public function onRequest() + { + if ($this->createDataSource()->select()->from('group')->count() === 0) { + Notification::info(sprintf($this->translate('User %s is already a member of all groups'), $this->userName)); + $this->getResponse()->redirectAndExit($this->getRedirectUrl()); + } + } + + /** + * Create the memberships for the user + * + * @return bool + */ + public function onSuccess() + { + $backendMap = array(); + foreach ($this->backends as $backend) { + $backendMap[$backend->getName()] = $backend; + } + + $single = null; + $groupName = null; + foreach ($this->getValue('groups') as $backendAndGroup) { + list($backendName, $groupName) = explode(';', $backendAndGroup, 2); + try { + $backendMap[$backendName]->insert( + 'group_membership', + array( + 'group_name' => $groupName, + 'user_name' => $this->userName + ) + ); + } catch (Exception $e) { + Notification::error(sprintf( + $this->translate('Failed to add "%s" as group member for "%s"'), + $this->userName, + $groupName + )); + $this->error($e->getMessage()); + return false; + } + + $single = $single === null; + } + + if ($single) { + Notification::success( + sprintf($this->translate('Membership for group %s created successfully'), $groupName) + ); + } else { + Notification::success($this->translate('Memberships created successfully')); + } + + return true; + } + + /** + * Create and return a data source to fetch all groups from all backends where the user is not already a member of + * + * @return ArrayDatasource + */ + protected function createDataSource() + { + $groups = $failures = array(); + foreach ($this->backends as $backend) { + try { + $memberships = $backend + ->select() + ->from('group_membership', array('group_name')) + ->where('user_name', $this->userName) + ->fetchColumn(); + foreach ($backend->select(array('group_name')) as $row) { + if (! in_array($row->group_name, $memberships)) { // TODO(jom): Apply this as native query filter + $row->backend_name = $backend->getName(); + $groups[] = $row; + } + } + } catch (Exception $e) { + $failures[] = array($backend->getName(), $e); + } + } + + if (empty($groups) && !empty($failures)) { + // In case there are only failures, throw the very first exception again + throw $failures[0][1]; + } elseif (! empty($failures)) { + foreach ($failures as $failure) { + Logger::error($failure[1]); + Notification::warning(sprintf( + $this->translate('Failed to fetch any groups from backend %s. Please check your log'), + $failure[0] + )); + } + } + + return new ArrayDatasource($groups); + } +} diff --git a/application/forms/Config/User/UserForm.php b/application/forms/Config/User/UserForm.php new file mode 100644 index 0000000..fb2ef4d --- /dev/null +++ b/application/forms/Config/User/UserForm.php @@ -0,0 +1,210 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Forms\Config\User; + +use Icinga\Application\Hook\ConfigFormEventsHook; +use Icinga\Data\Filter\Filter; +use Icinga\Forms\RepositoryForm; +use Icinga\Web\Notification; + +class UserForm extends RepositoryForm +{ + /** + * Create and add elements to this form to insert or update a user + * + * @param array $formData The data sent by the user + */ + protected function createInsertElements(array $formData) + { + $this->addElement( + 'checkbox', + 'is_active', + array( + 'value' => true, + 'label' => $this->translate('Active'), + 'description' => $this->translate('Prevents the user from logging in if unchecked') + ) + ); + $this->addElement( + 'text', + 'user_name', + array( + 'required' => true, + 'label' => $this->translate('Username') + ) + ); + $this->addElement( + 'password', + 'password', + array( + 'required' => true, + 'label' => $this->translate('Password') + ) + ); + + $this->setTitle($this->translate('Add a new user')); + $this->setSubmitLabel($this->translate('Add')); + } + + /** + * Create and add elements to this form to update a user + * + * @param array $formData The data sent by the user + */ + protected function createUpdateElements(array $formData) + { + $this->createInsertElements($formData); + + $this->addElement( + 'password', + 'password', + array( + 'description' => $this->translate('Leave empty for not updating the user\'s password'), + 'label' => $this->translate('Password'), + ) + ); + + $this->setTitle(sprintf($this->translate('Edit user %s'), $this->getIdentifier())); + $this->setSubmitLabel($this->translate('Save')); + } + + /** + * Update a user + * + * @return bool + */ + protected function onUpdateSuccess() + { + if (parent::onUpdateSuccess()) { + if (($newName = $this->getValue('user_name')) !== $this->getIdentifier()) { + $this->getRedirectUrl()->setParam('user', $newName); + } + + return true; + } + + return false; + } + + /** + * Retrieve all form element values + * + * Strips off the password if null or the empty string. + * + * @param bool $suppressArrayNotation + * + * @return array + */ + public function getValues($suppressArrayNotation = false) + { + $values = parent::getValues($suppressArrayNotation); + // before checking if password values is empty + // we have to check that the password field is set + // otherwise an error is thrown + if (isset($values['password']) && ! $values['password']) { + unset($values['password']); + } + + return $values; + } + + /** + * Create and add elements to this form to delete a user + * + * @param array $formData The data sent by the user + */ + protected function createDeleteElements(array $formData) + { + $this->setTitle(sprintf($this->translate('Remove user %s?'), $this->getIdentifier())); + $this->setSubmitLabel($this->translate('Yes')); + $this->setAttrib('class', 'icinga-controls'); + } + + /** + * Create and return a filter to use when updating or deleting a user + * + * @return Filter + */ + protected function createFilter() + { + return Filter::where('user_name', $this->getIdentifier()); + } + + /** + * Return a notification message to use when inserting a user + * + * @param bool $success true or false, whether the operation was successful + * + * @return string + */ + protected function getInsertMessage($success) + { + if ($success) { + return $this->translate('User added successfully'); + } else { + return $this->translate('Failed to add user'); + } + } + + /** + * Return a notification message to use when updating a user + * + * @param bool $success true or false, whether the operation was successful + * + * @return string + */ + protected function getUpdateMessage($success) + { + if ($success) { + return sprintf($this->translate('User "%s" has been edited'), $this->getIdentifier()); + } else { + return sprintf($this->translate('Failed to edit user "%s"'), $this->getIdentifier()); + } + } + + /** + * Return a notification message to use when deleting a user + * + * @param bool $success true or false, whether the operation was successful + * + * @return string + */ + protected function getDeleteMessage($success) + { + if ($success) { + return sprintf($this->translate('User "%s" has been removed'), $this->getIdentifier()); + } else { + return sprintf($this->translate('Failed to remove user "%s"'), $this->getIdentifier()); + } + } + + public function isValid($formData) + { + $valid = parent::isValid($formData); + + if ($valid && ConfigFormEventsHook::runIsValid($this) === false) { + foreach (ConfigFormEventsHook::getLastErrors() as $msg) { + $this->error($msg); + } + + $valid = false; + } + + return $valid; + } + + public function onSuccess() + { + if (parent::onSuccess() === false) { + return false; + } + + if (ConfigFormEventsHook::runOnSuccess($this) === false) { + Notification::error($this->translate( + 'Configuration successfully stored. Though, one or more module hooks failed to run.' + . ' See logs for details' + )); + } + } +} |