192 lines
5.7 KiB
PHP
192 lines
5.7 KiB
PHP
<?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;
|
|
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);
|
|
}
|
|
}
|