Merge branch 'master' into feature/monitoring-restrictions-9009
This commit is contained in:
commit
d5dffe9a7a
|
@ -6,3 +6,6 @@ Vagrantfile export-ignore
|
|||
|
||||
# Normalize puppet manifests' line endings to LF on checkin and prevent conversion to CRLF when the files are checked out
|
||||
.puppet* eol=lf
|
||||
|
||||
# Include version information on `git archive'
|
||||
/application/VERSION export-subst
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
$Format:%H%d %ci$
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
# namespace Icinga\Application\Controllers;
|
||||
|
||||
use Icinga\Web\Controller\ActionController;
|
||||
use Icinga\Application\Version;
|
||||
|
||||
class AboutController extends ActionController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->version = Version::get();
|
||||
}
|
||||
}
|
|
@ -28,6 +28,10 @@ class GroupController extends AuthBackendController
|
|||
function ($b) { return $b->getName(); },
|
||||
$this->loadUserGroupBackends('Icinga\Data\Selectable')
|
||||
);
|
||||
if (empty($backendNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->view->backendSelection = new Form();
|
||||
$this->view->backendSelection->setAttrib('class', 'backend-selection');
|
||||
$this->view->backendSelection->setUidDisabled();
|
||||
|
@ -100,6 +104,7 @@ class GroupController extends AuthBackendController
|
|||
|
||||
$filterEditor = Widget::create('filterEditor')
|
||||
->setQuery($members)
|
||||
->setSearchColumns(array('user'))
|
||||
->preserveParams('limit', 'sort', 'dir', 'view', 'backend', 'group')
|
||||
->ignoreParams('page')
|
||||
->handleRequest($this->getRequest());
|
||||
|
|
|
@ -28,6 +28,10 @@ class UserController extends AuthBackendController
|
|||
function ($b) { return $b->getName(); },
|
||||
$this->loadUserBackends('Icinga\Data\Selectable')
|
||||
);
|
||||
if (empty($backendNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->view->backendSelection = new Form();
|
||||
$this->view->backendSelection->setAttrib('class', 'backend-selection');
|
||||
$this->view->backendSelection->setUidDisabled();
|
||||
|
@ -99,6 +103,7 @@ class UserController extends AuthBackendController
|
|||
|
||||
$filterEditor = Widget::create('filterEditor')
|
||||
->setQuery($memberships)
|
||||
->setSearchColumns(array('group_name'))
|
||||
->preserveParams('limit', 'sort', 'dir', 'view', 'backend', 'user')
|
||||
->ignoreParams('page')
|
||||
->handleRequest($this->getRequest());
|
||||
|
|
|
@ -52,7 +52,7 @@ class UsergroupbackendController extends Controller
|
|||
$form->setIniConfig(Config::app('groups'));
|
||||
$form->setOnSuccess(function (UserGroupBackendForm $form) {
|
||||
try {
|
||||
$form->add($form->getValues());
|
||||
$form->add(array_filter($form->getValues()));
|
||||
} catch (Exception $e) {
|
||||
$form->error($e->getMessage());
|
||||
return false;
|
||||
|
@ -85,7 +85,12 @@ class UsergroupbackendController extends Controller
|
|||
$form->setIniConfig(Config::app('groups'));
|
||||
$form->setOnSuccess(function (UserGroupBackendForm $form) use ($backendName) {
|
||||
try {
|
||||
$form->edit($backendName, $form->getValues());
|
||||
$form->edit($backendName, array_map(
|
||||
function ($v) {
|
||||
return $v !== '' ? $v : null;
|
||||
},
|
||||
$form->getValues()
|
||||
));
|
||||
} catch (Exception $e) {
|
||||
$form->error($e->getMessage());
|
||||
return false;
|
||||
|
|
|
@ -8,7 +8,7 @@ use Icinga\Web\Form;
|
|||
use Icinga\Data\ConfigObject;
|
||||
use Icinga\Data\ResourceFactory;
|
||||
use Icinga\Exception\AuthenticationException;
|
||||
use Icinga\Authentication\User\LdapUserBackend;
|
||||
use Icinga\Authentication\User\UserBackend;
|
||||
|
||||
/**
|
||||
* Form class for adding/modifying LDAP user backends
|
||||
|
@ -48,6 +48,8 @@ class LdapBackendForm extends Form
|
|||
*/
|
||||
public function createElements(array $formData)
|
||||
{
|
||||
$isAd = isset($formData['type']) ? $formData['type'] === 'msldap' : false;
|
||||
|
||||
$this->addElement(
|
||||
'text',
|
||||
'name',
|
||||
|
@ -77,10 +79,13 @@ class LdapBackendForm extends Form
|
|||
'text',
|
||||
'user_class',
|
||||
array(
|
||||
'required' => true,
|
||||
'label' => $this->translate('LDAP User Object Class'),
|
||||
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
|
||||
'value' => 'inetOrgPerson'
|
||||
'preserveDefault' => true,
|
||||
'required' => ! $isAd,
|
||||
'ignore' => $isAd,
|
||||
'disabled' => $isAd ?: null,
|
||||
'label' => $this->translate('LDAP User Object Class'),
|
||||
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
|
||||
'value' => $isAd ? 'user' : 'inetOrgPerson'
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
|
@ -117,12 +122,15 @@ class LdapBackendForm extends Form
|
|||
'text',
|
||||
'user_name_attribute',
|
||||
array(
|
||||
'required' => true,
|
||||
'label' => $this->translate('LDAP User Name Attribute'),
|
||||
'description' => $this->translate(
|
||||
'preserveDefault' => true,
|
||||
'required' => ! $isAd,
|
||||
'ignore' => $isAd,
|
||||
'disabled' => $isAd ?: null,
|
||||
'label' => $this->translate('LDAP User Name Attribute'),
|
||||
'description' => $this->translate(
|
||||
'The attribute name used for storing the user name on the LDAP server.'
|
||||
),
|
||||
'value' => 'uid'
|
||||
'value' => $isAd ? 'sAMAccountName' : 'uid'
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
|
@ -130,7 +138,7 @@ class LdapBackendForm extends Form
|
|||
'backend',
|
||||
array(
|
||||
'disabled' => true,
|
||||
'value' => 'ldap'
|
||||
'value' => $isAd ? 'msldap' : 'ldap'
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
|
@ -170,8 +178,7 @@ class LdapBackendForm extends Form
|
|||
public static function isValidUserBackend(Form $form)
|
||||
{
|
||||
try {
|
||||
$ldapUserBackend = new LdapUserBackend(ResourceFactory::createResource($form->getResourceConfig()));
|
||||
$ldapUserBackend->setConfig(new ConfigObject($form->getValues()));
|
||||
$ldapUserBackend = UserBackend::create(null, new ConfigObject($form->getValues()));
|
||||
$ldapUserBackend->assertAuthenticationPossible();
|
||||
} catch (AuthenticationException $e) {
|
||||
if (($previous = $e->getPrevious()) !== null) {
|
||||
|
@ -193,6 +200,8 @@ class LdapBackendForm extends Form
|
|||
* Return the configuration for the chosen resource
|
||||
*
|
||||
* @return ConfigObject
|
||||
*
|
||||
* @todo Check whether it's possible to drop this (Or even all occurences!)
|
||||
*/
|
||||
public function getResourceConfig()
|
||||
{
|
||||
|
|
|
@ -60,16 +60,24 @@ class UserBackendConfigForm extends ConfigForm
|
|||
*/
|
||||
public function getBackendForm($type)
|
||||
{
|
||||
if ($type === 'db') {
|
||||
$form = new DbBackendForm();
|
||||
$form->setResources(isset($this->resources['db']) ? $this->resources['db'] : array());
|
||||
} elseif ($type === 'ldap') {
|
||||
$form = new LdapBackendForm();
|
||||
$form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
|
||||
} elseif ($type === 'external') {
|
||||
$form = new ExternalBackendForm();
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type));
|
||||
switch ($type)
|
||||
{
|
||||
case 'db':
|
||||
$form = new DbBackendForm();
|
||||
$form->setResources(isset($this->resources['db']) ? $this->resources['db'] : array());
|
||||
break;
|
||||
case 'ldap':
|
||||
case 'msldap':
|
||||
$form = new LdapBackendForm();
|
||||
$form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
|
||||
break;
|
||||
case 'external':
|
||||
$form = new ExternalBackendForm();
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException(
|
||||
sprintf($this->translate('Invalid backend type "%s" provided'), $type)
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
|
@ -296,6 +304,7 @@ class UserBackendConfigForm extends ConfigForm
|
|||
}
|
||||
if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) {
|
||||
$backendTypes['ldap'] = 'LDAP';
|
||||
$backendTypes['msldap'] = 'ActiveDirectory';
|
||||
}
|
||||
|
||||
$externalBackends = array_filter(
|
||||
|
|
|
@ -0,0 +1,310 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Forms\Config\UserGroup;
|
||||
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Authentication\User\UserBackend;
|
||||
use Icinga\Authentication\UserGroup\LdapUserGroupBackend;
|
||||
use Icinga\Data\ConfigObject;
|
||||
use Icinga\Data\ResourceFactory;
|
||||
use Icinga\Protocol\Ldap\Connection;
|
||||
use Icinga\Web\Form;
|
||||
use Icinga\Web\Notification;
|
||||
|
||||
/**
|
||||
* Form for managing LDAP user group backends
|
||||
*/
|
||||
class LdapUserGroupBackendForm extends Form
|
||||
{
|
||||
/**
|
||||
* Initialize this form
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->setName('form_config_ldapusergroupbackend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add elements to this form
|
||||
*
|
||||
* @param array $formData
|
||||
*/
|
||||
public function createElements(array $formData)
|
||||
{
|
||||
$resourceNames = $this->getLdapResourceNames();
|
||||
$this->addElement(
|
||||
'select',
|
||||
'resource',
|
||||
array(
|
||||
'required' => true,
|
||||
'autosubmit' => true,
|
||||
'label' => $this->translate('LDAP Connection'),
|
||||
'description' => $this->translate('The LDAP connection to use for this backend.'),
|
||||
'multiOptions' => array_combine($resourceNames, $resourceNames)
|
||||
)
|
||||
);
|
||||
$resource = ResourceFactory::create(
|
||||
isset($formData['resource']) && in_array($formData['resource'], $resourceNames)
|
||||
? $formData['resource']
|
||||
: $resourceNames[0]
|
||||
);
|
||||
|
||||
$userBackends = array('none' => $this->translate('None', 'usergroupbackend.ldap.user_backend'));
|
||||
$userBackendNames = $this->getLdapUserBackendNames($resource);
|
||||
if (! empty($userBackendNames)) {
|
||||
$userBackends = array_merge($userBackends, array_combine($userBackendNames, $userBackendNames));
|
||||
}
|
||||
$this->addElement(
|
||||
'select',
|
||||
'user_backend',
|
||||
array(
|
||||
'required' => true,
|
||||
'autosubmit' => true,
|
||||
'label' => $this->translate('User Backend'),
|
||||
'description' => $this->translate('The user backend to link with this user group backend.'),
|
||||
'multiOptions' => $userBackends
|
||||
)
|
||||
);
|
||||
|
||||
$groupBackend = new LdapUserGroupBackend($resource);
|
||||
if ($formData['type'] === 'ldap') {
|
||||
$defaults = $groupBackend->getOpenLdapDefaults();
|
||||
$groupConfigDisabled = $userConfigDisabled = null; // MUST BE null, do NOT change this to false!
|
||||
} else { // $formData['type'] === 'msldap'
|
||||
$defaults = $groupBackend->getActiveDirectoryDefaults();
|
||||
$groupConfigDisabled = $userConfigDisabled = true;
|
||||
}
|
||||
|
||||
$dnDisabled = null; // MUST BE null
|
||||
if (isset($formData['user_backend']) && $formData['user_backend'] !== 'none') {
|
||||
$userBackend = UserBackend::create($formData['user_backend']);
|
||||
$defaults->merge(array(
|
||||
'user_base_dn' => $userBackend->getBaseDn(),
|
||||
'user_class' => $userBackend->getUserClass(),
|
||||
'user_name_attribute' => $userBackend->getUserNameAttribute(),
|
||||
'user_filter' => $userBackend->getFilter()
|
||||
));
|
||||
$userConfigDisabled = $dnDisabled = true;
|
||||
}
|
||||
|
||||
$this->createGroupConfigElements($defaults, $groupConfigDisabled);
|
||||
$this->createUserConfigElements($defaults, $userConfigDisabled, $dnDisabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add all elements to this form required for the group configuration
|
||||
*
|
||||
* @param ConfigObject $defaults
|
||||
* @param null|bool $disabled
|
||||
*/
|
||||
protected function createGroupConfigElements(ConfigObject $defaults, $disabled)
|
||||
{
|
||||
$this->addElement(
|
||||
'text',
|
||||
'group_class',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'ignore' => $disabled,
|
||||
'disabled' => $disabled,
|
||||
'label' => $this->translate('LDAP Group Object Class'),
|
||||
'description' => $this->translate('The object class used for storing groups on the LDAP server.'),
|
||||
'value' => $defaults->group_class
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
'text',
|
||||
'group_filter',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'allowEmpty' => true,
|
||||
'label' => $this->translate('LDAP Group Filter'),
|
||||
'description' => $this->translate(
|
||||
'An additional filter to use when looking up groups using the specified connection. '
|
||||
. 'Leave empty to not to use any additional filter rules.'
|
||||
),
|
||||
'requirement' => $this->translate(
|
||||
'The filter needs to be expressed as standard LDAP expression, without'
|
||||
. ' outer parentheses. (e.g. &(foo=bar)(bar=foo) or foo=bar)'
|
||||
),
|
||||
'validators' => array(
|
||||
array(
|
||||
'Callback',
|
||||
false,
|
||||
array(
|
||||
'callback' => function ($v) {
|
||||
return strpos($v, '(') !== 0;
|
||||
},
|
||||
'messages' => array(
|
||||
'callbackValue' => $this->translate('The filter must not be wrapped in parantheses.')
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
'value' => $defaults->group_filter
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
'text',
|
||||
'group_name_attribute',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'ignore' => $disabled,
|
||||
'disabled' => $disabled,
|
||||
'label' => $this->translate('LDAP Group Name Attribute'),
|
||||
'description' => $this->translate(
|
||||
'The attribute name used for storing a group\'s name on the LDAP server.'
|
||||
),
|
||||
'value' => $defaults->group_name_attribute
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
'text',
|
||||
'base_dn',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'label' => $this->translate('LDAP Group Base DN'),
|
||||
'description' => $this->translate(
|
||||
'The path where groups can be found on the LDAP server. Leave ' .
|
||||
'empty to select all users available using the specified connection.'
|
||||
),
|
||||
'value' => $defaults->base_dn
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add all elements to this form required for the user configuration
|
||||
*
|
||||
* @param ConfigObject $defaults
|
||||
* @param null|bool $disabled
|
||||
* @param null|bool $dnDisabled
|
||||
*/
|
||||
protected function createUserConfigElements(ConfigObject $defaults, $disabled, $dnDisabled)
|
||||
{
|
||||
$this->addElement(
|
||||
'text',
|
||||
'user_class',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'ignore' => $disabled,
|
||||
'disabled' => $disabled,
|
||||
'label' => $this->translate('LDAP User Object Class'),
|
||||
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
|
||||
'value' => $defaults->user_class
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
'text',
|
||||
'user_filter',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'allowEmpty' => true,
|
||||
'ignore' => $dnDisabled,
|
||||
'disabled' => $dnDisabled,
|
||||
'label' => $this->translate('LDAP User Filter'),
|
||||
'description' => $this->translate(
|
||||
'An additional filter to use when looking up users using the specified connection. '
|
||||
. 'Leave empty to not to use any additional filter rules.'
|
||||
),
|
||||
'requirement' => $this->translate(
|
||||
'The filter needs to be expressed as standard LDAP expression, without'
|
||||
. ' outer parentheses. (e.g. &(foo=bar)(bar=foo) or foo=bar)'
|
||||
),
|
||||
'validators' => array(
|
||||
array(
|
||||
'Callback',
|
||||
false,
|
||||
array(
|
||||
'callback' => function ($v) {
|
||||
return strpos($v, '(') !== 0;
|
||||
},
|
||||
'messages' => array(
|
||||
'callbackValue' => $this->translate('The filter must not be wrapped in parantheses.')
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
'value' => $defaults->user_filter
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
'text',
|
||||
'user_name_attribute',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'ignore' => $disabled,
|
||||
'disabled' => $disabled,
|
||||
'label' => $this->translate('LDAP User Name Attribute'),
|
||||
'description' => $this->translate(
|
||||
'The attribute name used for storing a user\'s name on the LDAP server.'
|
||||
),
|
||||
'value' => $defaults->user_name_attribute
|
||||
)
|
||||
);
|
||||
$this->addElement(
|
||||
'text',
|
||||
'user_base_dn',
|
||||
array(
|
||||
'preserveDefault' => true,
|
||||
'ignore' => $dnDisabled,
|
||||
'disabled' => $dnDisabled,
|
||||
'label' => $this->translate('LDAP User Base DN'),
|
||||
'description' => $this->translate(
|
||||
'The path where users can be found on the LDAP server. Leave ' .
|
||||
'empty to select all users available using the specified connection.'
|
||||
),
|
||||
'value' => $defaults->user_base_dn
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the names of all configured LDAP resources
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getLdapResourceNames()
|
||||
{
|
||||
$names = array();
|
||||
foreach (ResourceFactory::getResourceConfigs() as $name => $config) {
|
||||
if (in_array(strtolower($config->type), array('ldap', 'msldap'))) {
|
||||
$names[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($names)) {
|
||||
Notification::error(
|
||||
$this->translate('No LDAP resources available. Please configure an LDAP resource first.')
|
||||
);
|
||||
$this->getResponse()->redirectAndExit('config/createresource');
|
||||
}
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the names of all configured LDAP user backends
|
||||
*
|
||||
* @param Connection $resource
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getLdapUserBackendNames(Connection $resource)
|
||||
{
|
||||
$names = array();
|
||||
foreach (Config::app('authentication') as $name => $config) {
|
||||
if (in_array(strtolower($config->backend), array('ldap', 'msldap'))) {
|
||||
$backendResource = ResourceFactory::create($config->resource);
|
||||
if (
|
||||
$backendResource->getHostname() === $resource->getHostname()
|
||||
&& $backendResource->getPort() === $resource->getPort()
|
||||
) {
|
||||
$names[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $names;
|
||||
}
|
||||
}
|
|
@ -13,6 +13,13 @@ use Icinga\Forms\ConfigForm;
|
|||
*/
|
||||
class UserGroupBackendForm extends ConfigForm
|
||||
{
|
||||
/**
|
||||
* The backend to load when displaying the form for the first time
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $backendToLoad;
|
||||
|
||||
/**
|
||||
* Initialize this form
|
||||
*/
|
||||
|
@ -31,10 +38,17 @@ class UserGroupBackendForm extends ConfigForm
|
|||
*/
|
||||
public function getBackendForm($type)
|
||||
{
|
||||
if ($type === 'db') {
|
||||
return new DbUserGroupBackendForm();
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type));
|
||||
switch ($type)
|
||||
{
|
||||
case 'db':
|
||||
return new DbUserGroupBackendForm();
|
||||
case 'ldap':
|
||||
case 'msldap':
|
||||
return new LdapUserGroupBackendForm();
|
||||
default:
|
||||
throw new InvalidArgumentException(
|
||||
sprintf($this->translate('Invalid backend type "%s" provided'), $type)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,10 +67,7 @@ class UserGroupBackendForm extends ConfigForm
|
|||
throw new NotFoundError('No user group backend called "%s" found', $name);
|
||||
}
|
||||
|
||||
$data = $this->config->getSection($name)->toArray();
|
||||
$data['type'] = $data['backend'];
|
||||
$data['name'] = $name;
|
||||
$this->populate($data);
|
||||
$this->backendToLoad = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -103,13 +114,23 @@ class UserGroupBackendForm extends ConfigForm
|
|||
}
|
||||
|
||||
$backendConfig = $this->config->getSection($name);
|
||||
if (isset($data['name']) && $data['name'] !== $name) {
|
||||
$this->config->removeSection($name);
|
||||
$name = $data['name'];
|
||||
if (isset($data['name'])) {
|
||||
if ($data['name'] !== $name) {
|
||||
$this->config->removeSection($name);
|
||||
$name = $data['name'];
|
||||
}
|
||||
|
||||
unset($data['name']);
|
||||
}
|
||||
|
||||
$this->config->setSection($name, $backendConfig->merge($data));
|
||||
$backendConfig->merge($data);
|
||||
foreach ($backendConfig->toArray() as $k => $v) {
|
||||
if ($v === null) {
|
||||
unset($backendConfig->$k);
|
||||
}
|
||||
}
|
||||
|
||||
$this->config->setSection($name, $backendConfig);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -161,7 +182,9 @@ class UserGroupBackendForm extends ConfigForm
|
|||
|
||||
// TODO(jom): We did not think about how to configure custom group backends yet!
|
||||
$backendTypes = array(
|
||||
'db' => $this->translate('Database')
|
||||
'db' => $this->translate('Database'),
|
||||
'ldap' => 'LDAP',
|
||||
'msldap' => 'ActiveDirectory'
|
||||
);
|
||||
|
||||
$backendType = isset($formData['type']) ? $formData['type'] : null;
|
||||
|
@ -191,8 +214,34 @@ class UserGroupBackendForm extends ConfigForm
|
|||
)
|
||||
);
|
||||
|
||||
$backendForm = $this->getBackendForm($backendType);
|
||||
$backendForm->createElements($formData);
|
||||
$this->addElements($backendForm->getElements());
|
||||
$this->addSubForm($this->getBackendForm($backendType)->create($formData), 'backend_form');
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the configuration of the backend to load
|
||||
*/
|
||||
public function onRequest()
|
||||
{
|
||||
if ($this->backendToLoad) {
|
||||
$data = $this->config->getSection($this->backendToLoad)->toArray();
|
||||
$data['type'] = $data['backend'];
|
||||
$data['name'] = $this->backendToLoad;
|
||||
$this->populate($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all form element values
|
||||
*
|
||||
* @param bool $suppressArrayNotation Ignored
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getValues($suppressArrayNotation = false)
|
||||
{
|
||||
$values = parent::getValues();
|
||||
$values = array_merge($values, $values['backend_form']);
|
||||
unset($values['backend_form']);
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<div class="content">
|
||||
<h1>Icinga Web 2</h1>
|
||||
<?php
|
||||
$versionInfo = array();
|
||||
if ($version !== false) {
|
||||
foreach (array(
|
||||
'appVersion' => $this->translate('Version: %s'),
|
||||
'gitCommitID' => $this->translate('Git commit ID: %s'),
|
||||
'gitCommitDate' => $this->translate('Git commit date: %s')
|
||||
) as $key => $label) {
|
||||
if (array_key_exists($key, $version) && null !== ($value = $version[$key])) {
|
||||
$versionInfo[] = sprintf($label, htmlspecialchars($value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo (
|
||||
0 === count($versionInfo)
|
||||
? '<p class="message-error">' . $this->translate(
|
||||
'Can\'t determine Icinga Web 2\'s version'
|
||||
)
|
||||
: '<p>' . nl2br(implode("\n", $versionInfo), false)
|
||||
) . '</p>';
|
||||
?>
|
||||
</div>
|
|
@ -18,7 +18,7 @@ if (! $this->compact): ?>
|
|||
<div class="content groups">
|
||||
<?php
|
||||
|
||||
if ($backend === null) {
|
||||
if (! isset($backend)) {
|
||||
echo $this->translate('No backend found which is able to list groups') . '</div>';
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<?php endif ?>
|
||||
<a data-base-target="_next" href="<?= $this->href('role/new') ?>">
|
||||
<a data-base-target="_next" href="<?= $this->href('role/add') ?>">
|
||||
<?= $this->translate('Create a New Role') ?>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,7 @@ if (! $this->compact): ?>
|
|||
<div class="content users">
|
||||
<?php
|
||||
|
||||
if ($backend === null) {
|
||||
if (! isset($backend)) {
|
||||
echo $this->translate('No backend found which is able to list users') . '</div>';
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -218,6 +218,7 @@ rm -rf %{buildroot}
|
|||
%{basedir}/application/forms
|
||||
%{basedir}/application/layouts
|
||||
%{basedir}/application/views
|
||||
%{basedir}/application/VERSION
|
||||
%{basedir}/doc
|
||||
%{basedir}/modules
|
||||
%{basedir}/public
|
||||
|
|
|
@ -59,6 +59,122 @@ class Platform
|
|||
return strtoupper(substr(self::getOperatingSystemName(), 0, 5)) === 'LINUX';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Linux distribution's name
|
||||
* or 'linux' if the name could not be found out
|
||||
* or false if the OS isn't Linux or an error occurred
|
||||
*
|
||||
* @param int $reliable
|
||||
* 3: Only parse /etc/os-release (or /usr/lib/os-release).
|
||||
* For the paranoid ones.
|
||||
* 2: If that (3) doesn't help, check /etc/*-release, too.
|
||||
* If something is unclear, return 'linux'.
|
||||
* 1: Almost equal to mode 2. The possible return values also include:
|
||||
* 'redhat' -- unclear whether RHEL/Fedora/...
|
||||
* 'suse' -- unclear whether SLES/openSUSE/...
|
||||
* 0: If even that (1) doesn't help, check /proc/version, too.
|
||||
* This may not work (as expected) on LXC containers!
|
||||
* (No reliability at all!)
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public static function getLinuxDistro($reliable = 2)
|
||||
{
|
||||
if (! self::isLinux()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (array('/etc/os-release', '/usr/lib/os-release') as $osReleaseFile) {
|
||||
if (false === ($osRelease = @file(
|
||||
$osReleaseFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
|
||||
))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($osRelease as $osInfo) {
|
||||
if (false === ($res = @preg_match('/(?<!.)[ \t]*#/ms', $osInfo))) {
|
||||
return false;
|
||||
}
|
||||
if ($res === 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
if (false === ($res = @preg_match(
|
||||
'/(?<!.)[ \t]*ID[ \t]*=[ \t]*(\'|"|)(.*?)(?:\1)[ \t]*(?!.)/msi',
|
||||
$osInfo,
|
||||
$matches
|
||||
))) {
|
||||
return false;
|
||||
}
|
||||
if (! ($res === 0 || $matches[2] === '' || $matches[2] === 'linux')) {
|
||||
return $matches[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($reliable > 2) {
|
||||
return 'linux';
|
||||
}
|
||||
|
||||
foreach (array(
|
||||
'fedora' => '/etc/fedora-release',
|
||||
'centos' => '/etc/centos-release'
|
||||
) as $distro => $releaseFile) {
|
||||
if (! (false === (
|
||||
$release = @file_get_contents($releaseFile)
|
||||
) || false === strpos(strtolower($release), $distro))) {
|
||||
return $distro;
|
||||
}
|
||||
}
|
||||
|
||||
if (false !== ($release = @file_get_contents('/etc/redhat-release'))) {
|
||||
$release = strtolower($release);
|
||||
if (false !== strpos($release, 'red hat enterprise linux')) {
|
||||
return 'rhel';
|
||||
}
|
||||
foreach (array('fedora', 'centos') as $distro) {
|
||||
if (false !== strpos($release, $distro)) {
|
||||
return $distro;
|
||||
}
|
||||
}
|
||||
return $reliable < 2 ? 'redhat' : 'linux';
|
||||
}
|
||||
|
||||
if (false !== ($release = @file_get_contents('/etc/SuSE-release'))) {
|
||||
$release = strtolower($release);
|
||||
foreach (array(
|
||||
'opensuse' => 'opensuse',
|
||||
'sles' => 'suse linux enterprise server',
|
||||
'sled' => 'suse linux enterprise desktop'
|
||||
) as $distro => $name) {
|
||||
if (false !== strpos($release, $name)) {
|
||||
return $distro;
|
||||
}
|
||||
}
|
||||
return $reliable < 2 ? 'suse' : 'linux';
|
||||
}
|
||||
|
||||
if ($reliable < 1) {
|
||||
if (false === ($procVersion = @file_get_contents('/proc/version'))) {
|
||||
return false;
|
||||
}
|
||||
$procVersion = strtolower($procVersion);
|
||||
foreach (array(
|
||||
'redhat' => 'red hat',
|
||||
'suse' => 'suse linux',
|
||||
'ubuntu' => 'ubuntu',
|
||||
'debian' => 'debian'
|
||||
) as $distro => $name) {
|
||||
if (false !== strpos($procVersion, $name)) {
|
||||
return $distro;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 'linux';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of CLI environment
|
||||
*
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Application;
|
||||
|
||||
class Version
|
||||
{
|
||||
/**
|
||||
* Get the version of this instance of Icinga Web 2
|
||||
*
|
||||
* @return array|bool array on success, false otherwise
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
if (false === ($appVersion = @file_get_contents(
|
||||
Icinga::app()->getApplicationDir() . DIRECTORY_SEPARATOR . 'VERSION'
|
||||
))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
if (false === ($res = preg_match(
|
||||
'/(?<!.)\s*(?P<gitCommitID>\w+)(?:\s*\(.*?(?:(?<=[\(,])\s*tag\s*:\s*v(?P<appVersion>.+?)\s*(?=[\),]).*?)?\))?\s*(?P<gitCommitDate>\S+)/ms',
|
||||
$appVersion,
|
||||
$matches
|
||||
)) || $res === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($matches as $key => $value) {
|
||||
if (is_int($key) || $value === '') {
|
||||
unset($matches[$key]);
|
||||
}
|
||||
}
|
||||
return $matches;
|
||||
}
|
||||
}
|
|
@ -4,17 +4,16 @@
|
|||
namespace Icinga\Authentication\User;
|
||||
|
||||
use DateTime;
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Data\ConfigObject;
|
||||
use Icinga\Exception\AuthenticationException;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Repository\Repository;
|
||||
use Icinga\Repository\LdapRepository;
|
||||
use Icinga\Repository\RepositoryQuery;
|
||||
use Icinga\Protocol\Ldap\Exception as LdapException;
|
||||
use Icinga\Protocol\Ldap\Expression;
|
||||
use Icinga\User;
|
||||
|
||||
class LdapUserBackend extends Repository implements UserBackendInterface
|
||||
class LdapUserBackend extends LdapRepository implements UserBackendInterface
|
||||
{
|
||||
/**
|
||||
* The base DN to use for a query
|
||||
|
@ -65,20 +64,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||
)
|
||||
);
|
||||
|
||||
protected $groupOptions;
|
||||
|
||||
/**
|
||||
* Normed attribute names based on known LDAP environments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $normedAttributes = array(
|
||||
'uid' => 'uid',
|
||||
'user' => 'user',
|
||||
'inetorgperson' => 'inetOrgPerson',
|
||||
'samaccountname' => 'sAMAccountName'
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the base DN to use for a query
|
||||
*
|
||||
|
@ -179,34 +164,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||
return $this->filter;
|
||||
}
|
||||
|
||||
public function setGroupOptions(array $options)
|
||||
{
|
||||
$this->groupOptions = $options;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGroupOptions()
|
||||
{
|
||||
return $this->groupOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given attribute name normed to known LDAP enviroments, if possible
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getNormedAttribute($name)
|
||||
{
|
||||
$loweredName = strtolower($name);
|
||||
if (array_key_exists($loweredName, $this->normedAttributes)) {
|
||||
return $this->normedAttributes[$loweredName];
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given configuration to this backend
|
||||
*
|
||||
|
@ -325,37 +282,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||
return ((int) $value & $ADS_UF_ACCOUNTDISABLE) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given value based on the ASN.1 standard (GeneralizedTime) and return its timestamp representation
|
||||
*
|
||||
* @param string|null $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function retrieveGeneralizedTime($value)
|
||||
{
|
||||
if ($value === null) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (
|
||||
($dateTime = DateTime::createFromFormat('YmdHis.uO', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHis.uZ', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHis.u', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHis', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHi', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdH', $value)) !== false
|
||||
) {
|
||||
return $dateTime->getTimeStamp();
|
||||
} else {
|
||||
Logger::debug(sprintf(
|
||||
'Failed to parse "%s" based on the ASN.1 standard (GeneralizedTime) for user backend "%s".',
|
||||
$value,
|
||||
$this->getName()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given shadowExpire value defines that a user is permitted to login
|
||||
*
|
||||
|
@ -413,41 +339,6 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the user groups
|
||||
*
|
||||
* @TODO: Subject to change, see #7343
|
||||
*
|
||||
* @param string $dn
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGroups($dn)
|
||||
{
|
||||
if (empty($this->groupOptions) || ! isset($this->groupOptions['group_base_dn'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$result = $this->ds->select()
|
||||
->setBase($this->groupOptions['group_base_dn'])
|
||||
->from(
|
||||
$this->groupOptions['group_class'],
|
||||
array($this->groupOptions['group_attribute'])
|
||||
)
|
||||
->where(
|
||||
$this->groupOptions['group_member_attribute'],
|
||||
$dn
|
||||
)
|
||||
->fetchAll();
|
||||
|
||||
$groups = array();
|
||||
foreach ($result as $group) {
|
||||
$groups[] = $group->{$this->groupOptions['group_attribute']};
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the given user
|
||||
*
|
||||
|
@ -472,15 +363,7 @@ class LdapUserBackend extends Repository implements UserBackendInterface
|
|||
return false;
|
||||
}
|
||||
|
||||
$authenticated = $this->ds->testCredentials($userDn, $password);
|
||||
if ($authenticated) {
|
||||
$groups = $this->getGroups($userDn);
|
||||
if ($groups !== null) {
|
||||
$user->setGroups($groups);
|
||||
}
|
||||
}
|
||||
|
||||
return $authenticated;
|
||||
return $this->ds->testCredentials($userDn, $password);
|
||||
} catch (LdapException $e) {
|
||||
throw new AuthenticationException(
|
||||
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace Icinga\Authentication\User;
|
||||
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Data\ConfigObject;
|
||||
|
@ -106,8 +107,17 @@ class UserBackend
|
|||
*
|
||||
* @throws ConfigurationError
|
||||
*/
|
||||
public static function create($name, ConfigObject $backendConfig)
|
||||
public static function create($name, ConfigObject $backendConfig = null)
|
||||
{
|
||||
if ($backendConfig === null) {
|
||||
$authConfig = Config::app('authentication');
|
||||
if ($authConfig->hasSection($name)) {
|
||||
$backendConfig = $authConfig->getSection($name);
|
||||
} else {
|
||||
throw new ConfigurationError('User backend "%s" does not exist', $name);
|
||||
}
|
||||
}
|
||||
|
||||
if ($backendConfig->name !== null) {
|
||||
$name = $backendConfig->name;
|
||||
}
|
||||
|
@ -165,12 +175,6 @@ class UserBackend
|
|||
$backend->setUserClass($backendConfig->get('user_class', 'user'));
|
||||
$backend->setUserNameAttribute($backendConfig->get('user_name_attribute', 'sAMAccountName'));
|
||||
$backend->setFilter($backendConfig->filter);
|
||||
$backend->setGroupOptions(array(
|
||||
'group_base_dn' => $backendConfig->get('group_base_dn', $resource->getDN()),
|
||||
'group_attribute' => $backendConfig->get('group_attribute', 'sAMAccountName'),
|
||||
'group_member_attribute' => $backendConfig->get('group_member_attribute', 'member'),
|
||||
'group_class' => $backendConfig->get('group_class', 'group')
|
||||
));
|
||||
break;
|
||||
case 'ldap':
|
||||
$backend = new LdapUserBackend($resource);
|
||||
|
@ -178,12 +182,6 @@ class UserBackend
|
|||
$backend->setUserClass($backendConfig->get('user_class', 'inetOrgPerson'));
|
||||
$backend->setUserNameAttribute($backendConfig->get('user_name_attribute', 'uid'));
|
||||
$backend->setFilter($backendConfig->filter);
|
||||
$backend->setGroupOptions(array(
|
||||
'group_base_dn' => $backendConfig->group_base_dn,
|
||||
'group_attribute' => $backendConfig->group_attribute,
|
||||
'group_member_attribute' => $backendConfig->group_member_attribute,
|
||||
'group_class' => $backendConfig->group_class
|
||||
));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,627 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Authentication\UserGroup;
|
||||
|
||||
use Icinga\Authentication\User\UserBackend;
|
||||
use Icinga\Authentication\User\LdapUserBackend;
|
||||
use Icinga\Data\ConfigObject;
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Protocol\Ldap\Expression;
|
||||
use Icinga\Repository\LdapRepository;
|
||||
use Icinga\Repository\RepositoryQuery;
|
||||
use Icinga\User;
|
||||
|
||||
class LdapUserGroupBackend /*extends LdapRepository*/ implements UserGroupBackendInterface
|
||||
{
|
||||
/**
|
||||
* The base DN to use for a user query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $userBaseDn;
|
||||
|
||||
/**
|
||||
* The base DN to use for a group query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $groupBaseDn;
|
||||
|
||||
/**
|
||||
* The objectClass where look for users
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $userClass;
|
||||
|
||||
/**
|
||||
* The objectClass where look for groups
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $groupClass;
|
||||
|
||||
/**
|
||||
* The attribute name where to find a user's name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $userNameAttribute;
|
||||
|
||||
/**
|
||||
* The attribute name where to find a group's name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $groupNameAttribute;
|
||||
|
||||
/**
|
||||
* The attribute name where to find a group's member
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $groupMemberAttribute;
|
||||
|
||||
/**
|
||||
* The custom LDAP filter to apply on a user query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $userFilter;
|
||||
|
||||
/**
|
||||
* The custom LDAP filter to apply on a group query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $groupFilter;
|
||||
|
||||
/**
|
||||
* The columns which are not permitted to be queried
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $filterColumns = array('group', 'user');
|
||||
|
||||
/**
|
||||
* The default sort rules to be applied on a query
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sortRules = array(
|
||||
'group_name' => array(
|
||||
'order' => 'asc'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Normed attribute names based on known LDAP environments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $normedAttributes = array(
|
||||
'uid' => 'uid',
|
||||
'gid' => 'gid',
|
||||
'user' => 'user',
|
||||
'group' => 'group',
|
||||
'member' => 'member',
|
||||
'inetorgperson' => 'inetOrgPerson',
|
||||
'samaccountname' => 'sAMAccountName'
|
||||
);
|
||||
|
||||
/**
|
||||
* The name of this repository
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* The datasource being used
|
||||
*
|
||||
* @var Connection
|
||||
*/
|
||||
protected $ds;
|
||||
|
||||
/**
|
||||
* Create a new LDAP repository object
|
||||
*
|
||||
* @param Connection $ds The data source to use
|
||||
*/
|
||||
public function __construct($ds)
|
||||
{
|
||||
$this->ds = $ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given attribute name normed to known LDAP enviroments, if possible
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getNormedAttribute($name)
|
||||
{
|
||||
$loweredName = strtolower($name);
|
||||
if (array_key_exists($loweredName, $this->normedAttributes)) {
|
||||
return $this->normedAttributes[$loweredName];
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this repository's name
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this repository's name
|
||||
*
|
||||
* In case no name has been explicitly set yet, the class name is returned.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base DN to use for a user query
|
||||
*
|
||||
* @param string $baseDn
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUserBaseDn($baseDn)
|
||||
{
|
||||
if (($baseDn = trim($baseDn))) {
|
||||
$this->userBaseDn = $baseDn;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base DN to use for a user query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserBaseDn()
|
||||
{
|
||||
return $this->userBaseDn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base DN to use for a group query
|
||||
*
|
||||
* @param string $baseDn
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroupBaseDn($baseDn)
|
||||
{
|
||||
if (($baseDn = trim($baseDn))) {
|
||||
$this->groupBaseDn = $baseDn;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base DN to use for a group query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGroupBaseDn()
|
||||
{
|
||||
return $this->groupBaseDn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the objectClass where to look for users
|
||||
*
|
||||
* @param string $userClass
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUserClass($userClass)
|
||||
{
|
||||
$this->userClass = $this->getNormedAttribute($userClass);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the objectClass where to look for users
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserClass()
|
||||
{
|
||||
return $this->userClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the objectClass where to look for groups
|
||||
*
|
||||
* Sets also the base table name for the underlying repository.
|
||||
*
|
||||
* @param string $groupClass
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroupClass($groupClass)
|
||||
{
|
||||
$this->baseTable = $this->groupClass = $this->getNormedAttribute($groupClass);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the objectClass where to look for groups
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGroupClass()
|
||||
{
|
||||
return $this->groupClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attribute name where to find a user's name
|
||||
*
|
||||
* @param string $userNameAttribute
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUserNameAttribute($userNameAttribute)
|
||||
{
|
||||
$this->userNameAttribute = $this->getNormedAttribute($userNameAttribute);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the attribute name where to find a user's name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserNameAttribute()
|
||||
{
|
||||
return $this->userNameAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attribute name where to find a group's name
|
||||
*
|
||||
* @param string $groupNameAttribute
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroupNameAttribute($groupNameAttribute)
|
||||
{
|
||||
$this->groupNameAttribute = $this->getNormedAttribute($groupNameAttribute);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the attribute name where to find a group's name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGroupNameAttribute()
|
||||
{
|
||||
return $this->groupNameAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attribute name where to find a group's member
|
||||
*
|
||||
* @param string $groupMemberAttribute
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroupMemberAttribute($groupMemberAttribute)
|
||||
{
|
||||
$this->groupMemberAttribute = $this->getNormedAttribute($groupMemberAttribute);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the attribute name where to find a group's member
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGroupMemberAttribute()
|
||||
{
|
||||
return $this->groupMemberAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom LDAP filter to apply on a user query
|
||||
*
|
||||
* @param string $filter
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUserFilter($filter)
|
||||
{
|
||||
if (($filter = trim($filter))) {
|
||||
$this->userFilter = $filter;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the custom LDAP filter to apply on a user query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserFilter()
|
||||
{
|
||||
return $this->userFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom LDAP filter to apply on a group query
|
||||
*
|
||||
* @param string $filter
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroupFilter($filter)
|
||||
{
|
||||
if (($filter = trim($filter))) {
|
||||
$this->groupFilter = $filter;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the custom LDAP filter to apply on a group query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGroupFilter()
|
||||
{
|
||||
return $this->groupFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new query for the given columns
|
||||
*
|
||||
* @param array $columns The desired columns, if null all columns will be queried
|
||||
*
|
||||
* @return RepositoryQuery
|
||||
*/
|
||||
public function select(array $columns = null)
|
||||
{
|
||||
$query = parent::select($columns);
|
||||
$query->getQuery()->setBase($this->groupBaseDn);
|
||||
if ($this->groupFilter) {
|
||||
// TODO(jom): This should differentiate between groups and their memberships
|
||||
$query->getQuery()->where(new Expression($this->groupFilter));
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this repository's query columns
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws ProgrammingError In case either $this->groupNameAttribute or $this->groupClass has not been set yet
|
||||
*/
|
||||
protected function initializeQueryColumns()
|
||||
{
|
||||
if ($this->groupClass === null) {
|
||||
throw new ProgrammingError('It is required to set the objectClass where to look for groups first');
|
||||
}
|
||||
if ($this->groupNameAttribute === null) {
|
||||
throw new ProgrammingError('It is required to set a attribute name where to find a group\'s name first');
|
||||
}
|
||||
|
||||
if ($this->ds->getCapabilities()->hasAdOid()) {
|
||||
$createdAtAttribute = 'whenCreated';
|
||||
$lastModifiedAttribute = 'whenChanged';
|
||||
} else {
|
||||
$createdAtAttribute = 'createTimestamp';
|
||||
$lastModifiedAttribute = 'modifyTimestamp';
|
||||
}
|
||||
|
||||
// TODO(jom): Fetching memberships does not work currently, we'll need some aggregate functionality!
|
||||
$columns = array(
|
||||
'group' => $this->groupNameAttribute,
|
||||
'group_name' => $this->groupNameAttribute,
|
||||
'user' => $this->groupMemberAttribute,
|
||||
'user_name' => $this->groupMemberAttribute,
|
||||
'created_at' => $createdAtAttribute,
|
||||
'last_modified' => $lastModifiedAttribute
|
||||
);
|
||||
return array('group' => $columns, 'group_membership' => $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this repository's conversion rules
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws ProgrammingError In case $this->groupClass has not been set yet
|
||||
*/
|
||||
protected function initializeConversionRules()
|
||||
{
|
||||
if ($this->groupClass === null) {
|
||||
throw new ProgrammingError('It is required to set the objectClass where to look for groups first');
|
||||
}
|
||||
|
||||
return array(
|
||||
$this->groupClass => array(
|
||||
'created_at' => 'generalized_time',
|
||||
'last_modified' => 'generalized_time'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the requested table exists
|
||||
*
|
||||
* This will return $this->groupClass in case $table equals "group" or "group_membership".
|
||||
*
|
||||
* @param string $table The table to validate
|
||||
* @param RepositoryQuery $query An optional query to pass as context
|
||||
* (unused by the base implementation)
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws ProgrammingError In case the given table does not exist
|
||||
*/
|
||||
public function requireTable($table, RepositoryQuery $query = null)
|
||||
{
|
||||
$table = parent::requireTable($table, $query);
|
||||
if ($table === 'group' || $table === 'group_membership') {
|
||||
$table = $this->groupClass;
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the groups the given user is a member of
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMemberships(User $user)
|
||||
{
|
||||
$userQuery = $this->ds
|
||||
->select()
|
||||
->from($this->userClass)
|
||||
->where($this->userNameAttribute, $user->getUsername())
|
||||
->setBase($this->userBaseDn)
|
||||
->setUsePagedResults(false);
|
||||
if ($this->userFilter) {
|
||||
$userQuery->where(new Expression($this->userFilter));
|
||||
}
|
||||
|
||||
if (($userDn = $userQuery->fetchDn()) === null) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$groupQuery = $this->ds
|
||||
->select()
|
||||
->from($this->groupClass, array($this->groupNameAttribute))
|
||||
->where($this->groupMemberAttribute, $userDn)
|
||||
->setBase($this->groupBaseDn);
|
||||
if ($this->groupFilter) {
|
||||
$groupQuery->where(new Expression($this->groupFilter));
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
foreach ($groupQuery as $row) {
|
||||
$groups[] = $row->{$this->groupNameAttribute};
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given configuration on this backend
|
||||
*
|
||||
* @param ConfigObject $config
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws ConfigurationError In case a linked user backend does not exist or is invalid
|
||||
*/
|
||||
public function setConfig(ConfigObject $config)
|
||||
{
|
||||
if ($config->backend === 'ldap') {
|
||||
$defaults = $this->getOpenLdapDefaults();
|
||||
} elseif ($config->backend === 'msldap') {
|
||||
$defaults = $this->getActiveDirectoryDefaults();
|
||||
} else {
|
||||
$defaults = new ConfigObject();
|
||||
}
|
||||
|
||||
if ($config->user_backend && $config->user_backend !== 'none') {
|
||||
$userBackend = UserBackend::create($config->user_backend);
|
||||
if (! $userBackend instanceof LdapUserBackend) {
|
||||
throw new ConfigurationError('User backend "%s" is not of type LDAP', $config->user_backend);
|
||||
}
|
||||
|
||||
if (
|
||||
$this->ds->getHostname() !== $userBackend->getDataSource()->getHostname()
|
||||
|| $this->ds->getPort() !== $userBackend->getDataSource()->getPort()
|
||||
) {
|
||||
// TODO(jom): Elaborate whether it makes sense to link directories on different hosts
|
||||
throw new ConfigurationError(
|
||||
'It is required that a linked user backend refers to the '
|
||||
. 'same directory as it\'s user group backend counterpart'
|
||||
);
|
||||
}
|
||||
|
||||
$defaults->merge(array(
|
||||
'user_base_dn' => $userBackend->getBaseDn(),
|
||||
'user_class' => $userBackend->getUserClass(),
|
||||
'user_name_attribute' => $userBackend->getUserNameAttribute(),
|
||||
'user_filter' => $userBackend->getFilter()
|
||||
));
|
||||
}
|
||||
|
||||
return $this
|
||||
->setGroupBaseDn($config->base_dn)
|
||||
->setUserBaseDn($config->get('user_base_dn', $this->getGroupBaseDn()))
|
||||
->setGroupClass($config->get('group_class', $defaults->group_class))
|
||||
->setUserClass($config->get('user_class', $defaults->user_class))
|
||||
->setGroupNameAttribute($config->get('group_name_attribute', $defaults->group_name_attribute))
|
||||
->setUserNameAttribute($config->get('user_name_attribute', $defaults->user_name_attribute))
|
||||
->setGroupMemberAttribute($config->get('group_member_attribute', $defaults->group_member_attribute))
|
||||
->setGroupFilter($config->filter)
|
||||
->setUserFilter($config->user_filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configuration defaults for an OpenLDAP environment
|
||||
*
|
||||
* @return ConfigObject
|
||||
*/
|
||||
public function getOpenLdapDefaults()
|
||||
{
|
||||
return new ConfigObject(array(
|
||||
'group_class' => 'group',
|
||||
'user_class' => 'inetOrgPerson',
|
||||
'group_name_attribute' => 'gid',
|
||||
'user_name_attribute' => 'uid',
|
||||
'group_member_attribute' => 'member'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configuration defaults for an ActiveDirectory environment
|
||||
*
|
||||
* @return ConfigObject
|
||||
*/
|
||||
public function getActiveDirectoryDefaults()
|
||||
{
|
||||
return new ConfigObject(array(
|
||||
'group_class' => 'group',
|
||||
'user_class' => 'user',
|
||||
'group_name_attribute' => 'sAMAccountName',
|
||||
'user_name_attribute' => 'sAMAccountName',
|
||||
'group_member_attribute' => 'member'
|
||||
));
|
||||
}
|
||||
}
|
|
@ -21,6 +21,8 @@ class UserGroupBackend
|
|||
*/
|
||||
protected static $defaultBackends = array(
|
||||
'db',
|
||||
'ldap',
|
||||
'msldap',
|
||||
//'ini'
|
||||
);
|
||||
|
||||
|
@ -156,6 +158,11 @@ class UserGroupBackend
|
|||
case 'ini':
|
||||
$backend = new IniUserGroupBackend($resource);
|
||||
break;
|
||||
case 'ldap':
|
||||
case 'msldap':
|
||||
$backend = new LdapUserGroupBackend($resource);
|
||||
$backend->setConfig($backendConfig);
|
||||
break;
|
||||
}
|
||||
|
||||
$backend->setName($name);
|
||||
|
|
|
@ -313,14 +313,19 @@ class IniEditor
|
|||
*/
|
||||
public function getText()
|
||||
{
|
||||
$this->cleanUpWhitespaces();
|
||||
return rtrim(implode(PHP_EOL, $this->text)) . PHP_EOL;
|
||||
$this->normalizeSectionSpacing();
|
||||
|
||||
// trim leading and trailing whitespaces from generated file
|
||||
$txt = trim(implode(PHP_EOL, $this->text)) . PHP_EOL;
|
||||
|
||||
// replace linebreaks, unless they preceed a comment or a section
|
||||
return preg_replace("/\n[\n]*([^;\[])/", "\n$1", $txt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all unneeded line breaks between sections
|
||||
* normalize section spacing according to the current settings
|
||||
*/
|
||||
private function cleanUpWhitespaces()
|
||||
private function normalizeSectionSpacing()
|
||||
{
|
||||
$i = count($this->text) - 1;
|
||||
for (; $i > 0; $i--) {
|
||||
|
@ -328,24 +333,18 @@ class IniEditor
|
|||
if ($this->isSectionDeclaration($line) && $i > 0) {
|
||||
$i--;
|
||||
$line = $this->text[$i];
|
||||
/*
|
||||
* Ignore comments that are glued to the section declaration
|
||||
*/
|
||||
// ignore comments that are glued to the section declaration
|
||||
while ($i > 0 && $this->isComment($line)) {
|
||||
$i--;
|
||||
$line = $this->text[$i];
|
||||
}
|
||||
/*
|
||||
* Remove whitespaces between the sections
|
||||
*/
|
||||
// remove whitespaces between the sections
|
||||
while ($i > 0 && preg_match('/^\s*$/', $line) === 1) {
|
||||
$this->deleteLine($i);
|
||||
$i--;
|
||||
$line = $this->text[$i];
|
||||
}
|
||||
/*
|
||||
* Refresh section separators
|
||||
*/
|
||||
// refresh section separators
|
||||
if ($i !== 0 && $this->sectionSeparators > 0) {
|
||||
$this->insertAtLine($i + 1, str_repeat(PHP_EOL, $this->sectionSeparators - 1));
|
||||
}
|
||||
|
@ -621,6 +620,6 @@ class IniEditor
|
|||
|
||||
private function sanitize($value)
|
||||
{
|
||||
return str_replace('\n', '', $value);
|
||||
return str_replace("\n", '', $value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
|
|||
{
|
||||
if (file_exists($this->_filename)) {
|
||||
$oldconfig = new Zend_Config_Ini($this->_filename);
|
||||
$content = file_get_contents($this->_filename);
|
||||
$content = trim(file_get_contents($this->_filename));
|
||||
} else {
|
||||
$oldconfig = new Zend_Config(array());
|
||||
$content = '';
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Repository;
|
||||
|
||||
use Icinga\Protocol\Ldap\Connection;
|
||||
|
||||
/**
|
||||
* Abstract base class for concrete LDAP repository implementations
|
||||
*
|
||||
* Additionally provided features:
|
||||
* <ul>
|
||||
* <li>Attribute name normalization</li>
|
||||
* </ul>
|
||||
*/
|
||||
abstract class LdapRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* The datasource being used
|
||||
*
|
||||
* @var Connection
|
||||
*/
|
||||
protected $ds;
|
||||
|
||||
/**
|
||||
* Normed attribute names based on known LDAP environments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $normedAttributes = array(
|
||||
'uid' => 'uid',
|
||||
'gid' => 'gid',
|
||||
'user' => 'user',
|
||||
'group' => 'group',
|
||||
'member' => 'member',
|
||||
'inetorgperson' => 'inetOrgPerson',
|
||||
'samaccountname' => 'sAMAccountName'
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a new LDAP repository object
|
||||
*
|
||||
* @param Connection $ds The data source to use
|
||||
*/
|
||||
public function __construct(Connection $ds)
|
||||
{
|
||||
parent::__construct($ds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given attribute name normed to known LDAP enviroments, if possible
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getNormedAttribute($name)
|
||||
{
|
||||
$loweredName = strtolower($name);
|
||||
if (array_key_exists($loweredName, $this->normedAttributes)) {
|
||||
return $this->normedAttributes[$loweredName];
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
|
@ -599,6 +599,37 @@ abstract class Repository implements Selectable
|
|||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given value based on the ASN.1 standard (GeneralizedTime) and return its timestamp representation
|
||||
*
|
||||
* @param string|null $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function retrieveGeneralizedTime($value)
|
||||
{
|
||||
if ($value === null) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (
|
||||
($dateTime = DateTime::createFromFormat('YmdHis.uO', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHis.uZ', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHis.u', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHis', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdHi', $value)) !== false
|
||||
|| ($dateTime = DateTime::createFromFormat('YmdH', $value)) !== false
|
||||
) {
|
||||
return $dateTime->getTimeStamp();
|
||||
} else {
|
||||
Logger::debug(sprintf(
|
||||
'Failed to parse "%s" based on the ASN.1 standard (GeneralizedTime) in repository "%s".',
|
||||
$value,
|
||||
$this->getName()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the requested table exists
|
||||
*
|
||||
|
|
|
@ -855,8 +855,19 @@ class Form extends Zend_Form
|
|||
public function populate(array $defaults)
|
||||
{
|
||||
$this->create($defaults);
|
||||
$this->preserveDefaults($this, $defaults);
|
||||
return parent::populate($defaults);
|
||||
}
|
||||
|
||||
foreach ($this->getElements() as $name => $_) {
|
||||
/**
|
||||
* Recurse the given form and unset all unchanged default values
|
||||
*
|
||||
* @param Zend_Form $form
|
||||
* @param array $defaults
|
||||
*/
|
||||
protected function preserveDefaults(Zend_Form $form, array & $defaults)
|
||||
{
|
||||
foreach ($form->getElements() as $name => $_) {
|
||||
if (
|
||||
array_key_exists($name, $defaults)
|
||||
&& array_key_exists($name . static::DEFAULT_SUFFIX, $defaults)
|
||||
|
@ -866,7 +877,9 @@ class Form extends Zend_Form
|
|||
}
|
||||
}
|
||||
|
||||
return parent::populate($defaults);
|
||||
foreach ($form->getSubForms() as $_ => $subForm) {
|
||||
$this->preserveDefaults($subForm, $defaults);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -279,6 +279,11 @@ class Menu implements RecursiveIterator
|
|||
'priority' => 990,
|
||||
'renderer' => 'ForeignMenuItemRenderer'
|
||||
));
|
||||
|
||||
$this->add(t('About'), array(
|
||||
'url' => 'about',
|
||||
'priority' => 1000
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,12 @@ $this->addHelperFunction('url', function ($path = null, $params = null) {
|
|||
} else {
|
||||
$url = Url::fromPath($path);
|
||||
}
|
||||
|
||||
if ($params !== null) {
|
||||
if ($url === $path) {
|
||||
$url = clone $url;
|
||||
}
|
||||
|
||||
$url->overwriteParams($params);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div class="content">
|
||||
<?php foreach (/** @var \Icinga\Module\Doc\Renderer\DocSearchRenderer[] $searches */ $searches as $title => $search): ?>
|
||||
<?php if (! $search->isEmpty()): ?>
|
||||
<h1><?= $this->escape($title) ?></h1>
|
||||
<?= $search ?>
|
||||
<?php endif ?>
|
||||
<h2><?= $this->escape($title) ?></h2>
|
||||
<?= $search->isEmpty()
|
||||
? $this->translate('No documentation found matching the filter')
|
||||
: $search ?>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
|
|
@ -132,8 +132,8 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g
|
|||
<?php endforeach ?>
|
||||
<a aria-hidden="true" id="end" href="<?= Url::fromRequest()->remove(
|
||||
array(
|
||||
'raw_timestamp<',
|
||||
'raw_timestamp>'
|
||||
'timestamp<',
|
||||
'timestamp>'
|
||||
)
|
||||
)->overwriteParams(
|
||||
array(
|
||||
|
|
|
@ -10,6 +10,39 @@ $configDir = Icinga::app()->getConfigDir();
|
|||
$setupTokenPath = rtrim($configDir, '/') . '/setup.token';
|
||||
$cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');
|
||||
|
||||
$groupadd = null;
|
||||
$usermod = null;
|
||||
if (! (false === ($distro = Platform::getLinuxDistro(1)) || $distro === 'linux')) {
|
||||
foreach (array(
|
||||
'groupadd -r icingaweb2' => array(
|
||||
'redhat', 'rhel', 'centos', 'fedora',
|
||||
'suse', 'sles', 'sled', 'opensuse'
|
||||
),
|
||||
'addgroup --system icingaweb2' => array('debian', 'ubuntu')
|
||||
) as $groupadd_ => $distros) {
|
||||
if (in_array($distro, $distros)) {
|
||||
$groupadd = $groupadd_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array(
|
||||
'usermod -a -G icingaweb2 apache' => array(
|
||||
'redhat', 'rhel', 'centos', 'fedora'
|
||||
),
|
||||
'usermod -A icingaweb2 wwwrun' => array(
|
||||
'suse', 'sles', 'sled', 'opensuse'
|
||||
),
|
||||
'usermod -a -G icingaweb2 www-data' => array(
|
||||
'debian', 'ubuntu'
|
||||
)
|
||||
) as $usermod_ => $distros) {
|
||||
if (in_array($distro, $distros)) {
|
||||
$usermod = $usermod_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div class="welcome-page">
|
||||
<h2><?= $this->translate('Welcome to the configuration of Icinga Web 2!') ?></h2>
|
||||
|
@ -51,6 +84,12 @@ $cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');
|
|||
<li><?= $this->translate('Your webserver\'s user is a member of the system group "icingaweb2"'); ?></li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<?php if (! ($groupadd === null || $usermod === null)) { ?>
|
||||
<div class="code">
|
||||
<span><?= $this->escape($groupadd . ';') ?></span>
|
||||
<span><?= $this->escape($usermod . ';') ?></span>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<p><?= $this->translate('If you\'ve got the IcingaCLI installed you can do the following:'); ?></p>
|
||||
<div class="code">
|
||||
<span><?= $cliPath ? $cliPath : 'icingacli'; ?> setup config directory --group icingaweb2<?= $configDir !== '/etc/icingaweb2' ? ' --config ' . $configDir : ''; ?>;</span>
|
||||
|
|
|
@ -331,8 +331,7 @@ html {
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
/* TODO: replace this with .error */
|
||||
.fileNotReadable {
|
||||
.message-error {
|
||||
padding: 0.5em;
|
||||
background-color: @colorCritical;
|
||||
font-weight: bold;
|
||||
|
|
|
@ -27,10 +27,9 @@ class LdapBackendFormTest extends BaseTestCase
|
|||
*/
|
||||
public function testValidBackendIsValid()
|
||||
{
|
||||
$this->setUpResourceFactoryMock();
|
||||
Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend')
|
||||
->shouldReceive('assertAuthenticationPossible')->andReturnNull()
|
||||
->shouldReceive('setConfig')->andReturnNull();
|
||||
$ldapUserBackendMock = Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend');
|
||||
$ldapUserBackendMock->shouldReceive('assertAuthenticationPossible')->andReturnNull();
|
||||
$this->setUpUserBackendMock($ldapUserBackendMock);
|
||||
|
||||
// Passing array(null) is required to make Mockery call the constructor...
|
||||
$form = Mockery::mock('Icinga\Forms\Config\UserBackend\LdapBackendForm[getView]', array(null));
|
||||
|
@ -53,9 +52,9 @@ class LdapBackendFormTest extends BaseTestCase
|
|||
*/
|
||||
public function testInvalidBackendIsNotValid()
|
||||
{
|
||||
$this->setUpResourceFactoryMock();
|
||||
Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend')
|
||||
->shouldReceive('assertAuthenticationPossible')->andThrow(new AuthenticationException);
|
||||
$ldapUserBackendMock = Mockery::mock('overload:Icinga\Authentication\User\LdapUserBackend');
|
||||
$ldapUserBackendMock->shouldReceive('assertAuthenticationPossible')->andThrow(new AuthenticationException);
|
||||
$this->setUpUserBackendMock($ldapUserBackendMock);
|
||||
|
||||
// Passing array(null) is required to make Mockery call the constructor...
|
||||
$form = Mockery::mock('Icinga\Forms\Config\UserBackend\LdapBackendForm[getView]', array(null));
|
||||
|
@ -72,12 +71,10 @@ class LdapBackendFormTest extends BaseTestCase
|
|||
);
|
||||
}
|
||||
|
||||
protected function setUpResourceFactoryMock()
|
||||
protected function setUpUserBackendMock($ldapUserBackendMock)
|
||||
{
|
||||
Mockery::mock('alias:Icinga\Data\ResourceFactory')
|
||||
->shouldReceive('createResource')
|
||||
->andReturn(Mockery::mock('Icinga\Protocol\Ldap\Connection'))
|
||||
->shouldReceive('getResourceConfig')
|
||||
->andReturn(new ConfigObject());
|
||||
Mockery::mock('alias:Icinga\Authentication\User\UserBackend')
|
||||
->shouldReceive('create')
|
||||
->andReturn($ldapUserBackendMock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -719,6 +719,34 @@ EOD;
|
|||
);
|
||||
}
|
||||
|
||||
public function testWhetherLinebreaksAreRemoved()
|
||||
{
|
||||
$target = $this->writeConfigToTemporaryFile('');
|
||||
$writer = new IniWriter(
|
||||
array(
|
||||
'config' => Config::fromArray(
|
||||
array(
|
||||
'section' => array(
|
||||
'foo' => 'linebreak
|
||||
in line',
|
||||
'linebreak
|
||||
inkey' => 'blarg'
|
||||
)
|
||||
)
|
||||
),
|
||||
'filename' => $target
|
||||
)
|
||||
);
|
||||
|
||||
$rendered = $writer->render();
|
||||
var_dump($rendered);
|
||||
$this->assertEquals(
|
||||
count(explode("\n", $rendered)),
|
||||
4,
|
||||
'generated config should not contain more than three line breaks'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a INI-configuration string to a temporary file and return its path
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue