From ac7546d9f2f166a3bebbbb9d5941b2084c1ce00b Mon Sep 17 00:00:00 2001 From: Vladislav Ponomarev Date: Fri, 2 Oct 2015 15:40:08 +0200 Subject: [PATCH 01/16] Fix group base DN is erroneously used in place of user base DN refs #10340 refs #10367 Signed-off-by: Eric Lippmann --- .../Icinga/Authentication/UserGroup/LdapUserGroupBackend.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php index 2a737d535..f50371137 100644 --- a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php +++ b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php @@ -607,7 +607,7 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt return $this ->setGroupBaseDn($config->base_dn) - ->setUserBaseDn($config->get('user_base_dn', $this->getGroupBaseDn())) + ->setUserBaseDn($config->get('user_base_dn', $this->getUserBaseDn())) ->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)) From 21688393496467b75c568c0613e18c2d8439072d Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 13:45:43 +0200 Subject: [PATCH 02/16] user/show.phtml: Fix coding style refs #10367 --- application/views/scripts/user/show.phtml | 132 +++++++++++----------- 1 file changed, 64 insertions(+), 68 deletions(-) diff --git a/application/views/scripts/user/show.phtml b/application/views/scripts/user/show.phtml index ee3aa6809..97566a782 100644 --- a/application/views/scripts/user/show.phtml +++ b/application/views/scripts/user/show.phtml @@ -24,35 +24,35 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc ?>
compact): ?> - + -

escape($user->user_name) ?>

- - - - - - - - - - - - - -
translate('State'); ?>is_active === null ? '-' : ($user->is_active ? $this->translate('Active') : $this->translate('Inactive')); ?>
translate('Created at'); ?>created_at === null ? '-' : $this->formatDateTime($user->created_at); ?>
translate('Last modified'); ?>last_modified === null ? '-' : $this->formatDateTime($user->last_modified); ?>
-

translate('Group Memberships'); ?>

+

escape($user->user_name) ?>

+ + + + + + + + + + + + + +
translate('State'); ?>is_active === null ? '-' : ($user->is_active ? $this->translate('Active') : $this->translate('Inactive')); ?>
translate('Created at'); ?>created_at === null ? '-' : $this->formatDateTime($user->created_at); ?>
translate('Last modified'); ?>last_modified === null ? '-' : $this->formatDateTime($user->last_modified); ?>
+

translate('Group Memberships'); ?>

compact): ?> - sortBox; ?> + sortBox; ?> - limiter; ?> - paginator; ?> + limiter; ?> + paginator; ?> compact): ?> - filterEditor; ?> + filterEditor; ?>
- + qlink( $this->translate('Add User to Group') , 'user/createmembership', @@ -64,51 +64,47 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc 'title' => $this->translate('Add user to user group') ) ) ?> - - - - - - - - - - - - - - - - - - -hasResult()): ?> - -
translate('Group'); ?>translate('Cancel', 'group.membership'); ?>
- hasPermission('config/authentication/groups/show') && $membership->backend instanceof Selectable): ?> - qlink($membership->group_name, 'group/show', array( - 'backend' => $membership->backend->getName(), - 'group' => $membership->group_name - ), array( - 'title' => sprintf($this->translate('Show detailed information for group %s'), $membership->group_name) - )); ?> - - escape($membership->group_name); ?> - - - backend instanceof Reducible): ?> - setAction($this->url('group/removemember', array( - 'backend' => $membership->backend->getName(), - 'group' => $membership->group_name - ))); ?> - - - - -
- -

translate('No memberships found matching the filter'); ?>

+ +hasResult()): ?> +

translate('No memberships found matching the filter'); ?>

+ + + + + + + + + + + + + + + + + +
translate('Group'); ?>translate('Cancel', 'group.membership'); ?>
+ hasPermission('config/authentication/groups/show') && $membership->backend instanceof Selectable): ?> + qlink($membership->group_name, 'group/show', array( + 'backend' => $membership->backend->getName(), + 'group' => $membership->group_name + ), array( + 'title' => sprintf($this->translate('Show detailed information for group %s'), $membership->group_name) + )); ?> + + escape($membership->group_name); ?> + + + backend instanceof Reducible): ?> + setAction($this->url('group/removemember', array( + 'backend' => $membership->backend->getName(), + 'group' => $membership->group_name + ))); ?> + + - + +
+ \ No newline at end of file From f6e5fac23e677ff86f68bec2d1a9eeb2276d5ede Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 13:46:34 +0200 Subject: [PATCH 03/16] user/show.phtml: Pass through a user's name when creating memberships refs #10367 --- application/views/scripts/user/show.phtml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/application/views/scripts/user/show.phtml b/application/views/scripts/user/show.phtml index 97566a782..6500e9ade 100644 --- a/application/views/scripts/user/show.phtml +++ b/application/views/scripts/user/show.phtml @@ -56,7 +56,10 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc qlink( $this->translate('Add User to Group') , 'user/createmembership', - array('backend' => $backend->getName()), + array( + 'backend' => $backend->getName(), + 'user' => $user->user_name + ), array( 'class' => 'button-link', 'data-base-target' => '_next', From 4d5fde768a872111fc6c8f660af093e65108e7b2 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 14:02:14 +0200 Subject: [PATCH 04/16] user/show.phtml: Fix presentation and behaviour of the membership link * Removed base target _next, _self feels more natural * Removed obsolete link title, it has already a sufficient label * Restored previous link label, we're using the term membership everywhere else, so why should we make an exception here? refs #10367 --- application/views/scripts/user/show.phtml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/application/views/scripts/user/show.phtml b/application/views/scripts/user/show.phtml index 6500e9ade..5ad1e6865 100644 --- a/application/views/scripts/user/show.phtml +++ b/application/views/scripts/user/show.phtml @@ -54,17 +54,15 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc
qlink( - $this->translate('Add User to Group') , + $this->translate('Create New Membership') , 'user/createmembership', array( 'backend' => $backend->getName(), 'user' => $user->user_name ), array( - 'class' => 'button-link', - 'data-base-target' => '_next', - 'icon' => 'plus', - 'title' => $this->translate('Add user to user group') + 'icon' => 'plus', + 'class' => 'button-link' ) ) ?> From 635bb3eec666dc331f67faa4a0f0517f44aeb309 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 14:35:30 +0200 Subject: [PATCH 05/16] user/show.phtml: Improve layout refs #10367 --- application/controllers/UserController.php | 2 +- application/views/scripts/user/show.phtml | 24 +++++++++---------- public/css/icinga/main-content.less | 27 ---------------------- 3 files changed, 13 insertions(+), 40 deletions(-) diff --git a/application/controllers/UserController.php b/application/controllers/UserController.php index d080c1dae..9b2845758 100644 --- a/application/controllers/UserController.php +++ b/application/controllers/UserController.php @@ -140,7 +140,7 @@ class UserController extends AuthBackendController $removeForm->addElement('button', 'btn_submit', array( 'escape' => false, 'type' => 'submit', - 'class' => 'link-like spinner', + 'class' => 'link-button spinner', 'value' => 'btn_submit', 'decorators' => array('ViewHelper'), 'label' => $this->view->icon('trash'), diff --git a/application/views/scripts/user/show.phtml b/application/views/scripts/user/show.phtml index 5ad1e6865..aa440ff42 100644 --- a/application/views/scripts/user/show.phtml +++ b/application/views/scripts/user/show.phtml @@ -22,7 +22,7 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc } ?> -
+
compact): ?> @@ -41,17 +41,17 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc last_modified === null ? '-' : $this->formatDateTime($user->last_modified); ?> +compact): ?>

translate('Group Memberships'); ?>

-compact): ?> - sortBox; ?> - - limiter; ?> - paginator; ?> -compact): ?> +
+ limiter; ?> + paginator; ?> + sortBox; ?> +
filterEditor; ?>
-
+
qlink( $this->translate('Create New Membership') , @@ -75,14 +75,14 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc - - + + - - -
translate('Group'); ?>translate('Cancel', 'group.membership'); ?>translate('Group'); ?>translate('Cancel', 'group.membership'); ?>
+ hasPermission('config/authentication/groups/show') && $membership->backend instanceof Selectable): ?> qlink($membership->group_name, 'group/show', array( 'backend' => $membership->backend->getName(), @@ -94,7 +94,7 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc escape($membership->group_name); ?> + backend instanceof Reducible): ?> setAction($this->url('group/removemember', array( 'backend' => $membership->backend->getName(), diff --git a/public/css/icinga/main-content.less b/public/css/icinga/main-content.less index 54430ef60..05c41ce62 100644 --- a/public/css/icinga/main-content.less +++ b/public/css/icinga/main-content.less @@ -233,33 +233,6 @@ div.content.users { } } -div.content.memberships { - table.membership-list { - th.membership-cancel { - width: 8em; - padding-right: 0.5em; - text-align: right; - } - - td.membership-cancel { - text-align: right; - - form button.link-like { - color: inherit; - } - } - } - - p { - margin-top: 0; - } - - a.membership-create { - display: block; - margin-top: 1em; - } -} - div.content.groups { table.group-list { th.group-remove { From 34bf0c3cb0c868f882fe8deac349acc24a82e151 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 15:28:03 +0200 Subject: [PATCH 06/16] Add method getUserBackendName() to UserGroupBackendInterface refs #10367 refs #10373 --- application/views/scripts/group/show.phtml | 7 ++----- .../UserGroup/DbUserGroupBackend.php | 12 ++++++++++++ .../UserGroup/LdapUserGroupBackend.php | 15 +++++++++++++++ .../UserGroup/UserGroupBackendInterface.php | 9 +++++++++ 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/application/views/scripts/group/show.phtml b/application/views/scripts/group/show.phtml index f76ecdf3f..8d81683ee 100644 --- a/application/views/scripts/group/show.phtml +++ b/application/views/scripts/group/show.phtml @@ -2,7 +2,6 @@ use Icinga\Data\Extensible; use Icinga\Data\Updatable; -use Icinga\Data\Selectable; $extensible = $this->hasPermission('config/authentication/groups/add') && $backend instanceof Extensible; @@ -85,12 +84,10 @@ foreach ($members as $member): ?> hasPermission('config/authentication/users/show') - && method_exists($backend, 'getUserBackend') - && ($userBackend = $backend->getUserBackend()) !== null - && $userBackend instanceof Selectable + && ($userBackend = $backend->getUserBackendName($member->user_name)) !== null ): ?> qlink($member->user_name, 'user/show', array( - 'backend' => $userBackend->getName(), + 'backend' => $userBackend, 'user' => $member->user_name ), array( 'title' => sprintf($this->translate('Show detailed information about %s'), $member->user_name) diff --git a/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php b/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php index a114cc8d1..5596f18b6 100644 --- a/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php +++ b/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php @@ -217,6 +217,18 @@ class DbUserGroupBackend extends DbRepository implements UserGroupBackendInterfa return $memberships; } + /** + * Return the name of the backend that is providing the given user + * + * @param string $username Currently unused + * + * @return null|string The name of the backend or null in case this information is not available + */ + public function getUserBackendName($username) + { + return null; // TODO(10373): Store this to the database when inserting and fetch it here + } + /** * Join group into group_membership * diff --git a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php index 54ec1763b..1b1bb31d0 100644 --- a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php +++ b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php @@ -560,6 +560,21 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt return $groups; } + /** + * Return the name of the backend that is providing the given user + * + * @param string $username Unused + * + * @return null|string The name of the backend or null in case this information is not available + */ + public function getUserBackendName($username) + { + $userBackend = $this->getUserBackend(); + if ($userBackend !== null) { + return $userBackend->getName(); + } + } + /** * Apply the given configuration on this backend * diff --git a/library/Icinga/Authentication/UserGroup/UserGroupBackendInterface.php b/library/Icinga/Authentication/UserGroup/UserGroupBackendInterface.php index a567d1f0a..31dd2c50d 100644 --- a/library/Icinga/Authentication/UserGroup/UserGroupBackendInterface.php +++ b/library/Icinga/Authentication/UserGroup/UserGroupBackendInterface.php @@ -34,4 +34,13 @@ interface UserGroupBackendInterface * @return array */ public function getMemberships(User $user); + + /** + * Return the name of the backend that is providing the given user + * + * @param string $username + * + * @return null|string The name of the backend or null in case this information is not available + */ + public function getUserBackendName($username); } From 32955dea50844ab3b2eea6ab650f1afaa8fe4315 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 15:46:04 +0200 Subject: [PATCH 07/16] user/show.phtml: Fix some minor issues refs #10367 --- application/views/scripts/user/show.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/views/scripts/user/show.phtml b/application/views/scripts/user/show.phtml index aa440ff42..2fbdab551 100644 --- a/application/views/scripts/user/show.phtml +++ b/application/views/scripts/user/show.phtml @@ -54,7 +54,7 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc
qlink( - $this->translate('Create New Membership') , + $this->translate('Create New Membership'), 'user/createmembership', array( 'backend' => $backend->getName(), @@ -94,7 +94,7 @@ if ($this->hasPermission('config/authentication/users/edit') && $backend instanc escape($membership->group_name); ?>
+ backend instanceof Reducible): ?> setAction($this->url('group/removemember', array( 'backend' => $membership->backend->getName(), From 0ee73f2560af61070672fe6f077dd4a1bb06d88f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 15:47:38 +0200 Subject: [PATCH 08/16] group/show.phtml: Fix coding style, link targets, css, etc refs #10367 --- application/controllers/GroupController.php | 2 +- application/views/scripts/group/show.phtml | 140 ++++++++++---------- public/css/icinga/main-content.less | 27 ---- 3 files changed, 69 insertions(+), 100 deletions(-) diff --git a/application/controllers/GroupController.php b/application/controllers/GroupController.php index 4dd05fdef..3f14b2090 100644 --- a/application/controllers/GroupController.php +++ b/application/controllers/GroupController.php @@ -134,7 +134,7 @@ class GroupController extends AuthBackendController $removeForm->addElement('button', 'btn_submit', array( 'escape' => false, 'type' => 'submit', - 'class' => 'link-like spinner', + 'class' => 'link-button spinner', 'value' => 'btn_submit', 'decorators' => array('ViewHelper'), 'label' => $this->view->icon('trash'), diff --git a/application/views/scripts/group/show.phtml b/application/views/scripts/group/show.phtml index 8d81683ee..fb850a2a5 100644 --- a/application/views/scripts/group/show.phtml +++ b/application/views/scripts/group/show.phtml @@ -23,90 +23,86 @@ if ($this->hasPermission('config/authentication/groups/edit') && $backend instan } ?> -
- compact): ?> - - -

escape($group->group_name) ?>

- - - - - - - - - -
translate('Created at'); ?>created_at === null ? '-' : $this->formatDateTime($group->created_at); ?>
translate('Last modified'); ?>last_modified === null ? '-' : $this->formatDateTime($group->last_modified); ?>
-

translate('Members'); ?>

+
compact): ?> - sortBox; ?> + - limiter; ?> - paginator; ?> +

escape($group->group_name) ?>

+ + + + + + + + + +
translate('Created at'); ?>created_at === null ? '-' : $this->formatDateTime($group->created_at); ?>
translate('Last modified'); ?>last_modified === null ? '-' : $this->formatDateTime($group->last_modified); ?>
compact): ?> - filterEditor; ?> +

translate('Members'); ?>

+
+ limiter; ?> + paginator; ?> + sortBox; ?> +
+ filterEditor; ?>
-
+
qlink( - $this->translate('Add User to Group') , + $this->translate('Add New Member'), 'group/addmember', - null, array( - 'class' => 'button-link', - 'data-base-target' => '_next', - 'icon' => 'plus', - 'title' => $this->translate('Add user to group') + 'backend' => $backend->getName(), + 'group' => $group->group_name + ), + array( + 'icon' => 'plus', + 'class' => 'button-link' ) ) ?> - - - - - - - - - - - - - - - - - - - - - -hasResult()): ?> - -
translate('Username'); ?>translate('Remove'); ?>
- hasPermission('config/authentication/users/show') - && ($userBackend = $backend->getUserBackendName($member->user_name)) !== null - ): ?> - qlink($member->user_name, 'user/show', array( - 'backend' => $userBackend, - 'user' => $member->user_name - ), array( - 'title' => sprintf($this->translate('Show detailed information about %s'), $member->user_name) - )); ?> - - escape($member->user_name); ?> - - - getElement('user_name')->setValue($member->user_name); echo $removeForm; ?> -
- +hasResult()): ?>

translate('No group member found matching the filter'); ?>

-
+ + + + + + + + + + + + + + + + + + + + + +
translate('Username'); ?>translate('Remove'); ?>
+ hasPermission('config/authentication/users/show') + && ($userBackend = $backend->getUserBackendName($member->user_name)) !== null + ): ?> + qlink($member->user_name, 'user/show', array( + 'backend' => $userBackend, + 'user' => $member->user_name + ), array( + 'title' => sprintf($this->translate('Show detailed information about %s'), $member->user_name) + )); ?> + + escape($member->user_name); ?> + + + getElement('user_name')->setValue($member->user_name); echo $removeForm; ?> +
+
\ No newline at end of file diff --git a/public/css/icinga/main-content.less b/public/css/icinga/main-content.less index 05c41ce62..0d0e92d23 100644 --- a/public/css/icinga/main-content.less +++ b/public/css/icinga/main-content.less @@ -256,33 +256,6 @@ div.content.groups { } } -div.content.members { - table.member-list { - th.member-remove { - width: 8em; - padding-right: 0.5em; - text-align: right; - } - - td.member-remove { - text-align: right; - - form button.link-like { - color: inherit; - } - } - } - - p { - margin-top: 0; - } - - a.member-add { - display: block; - margin-top: 1em; - } -} - form.backend-selection { float: right; From 1144c869365323a773449241271c40e0b5a157f5 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 16:14:19 +0200 Subject: [PATCH 09/16] group/list.phtml: Fix coding style, link targets, css, etc refs #10367 --- application/controllers/GroupController.php | 4 +- application/views/scripts/group/list.phtml | 134 ++++++++++---------- public/css/icinga/main-content.less | 23 ---- 3 files changed, 68 insertions(+), 93 deletions(-) diff --git a/application/controllers/GroupController.php b/application/controllers/GroupController.php index 3f14b2090..21fba5ebb 100644 --- a/application/controllers/GroupController.php +++ b/application/controllers/GroupController.php @@ -44,7 +44,7 @@ class GroupController extends AuthBackendController 'backend', array( 'autosubmit' => true, - 'label' => $this->translate('Usergroup Backend'), + 'label' => $this->translate('User Group Backend'), 'multiOptions' => array_combine($backendNames, $backendNames), 'value' => $this->params->get('backend') ) @@ -66,7 +66,7 @@ class GroupController extends AuthBackendController $this->setupLimitControl(); $this->setupSortControl( array( - 'group_name' => $this->translate('Group'), + 'group_name' => $this->translate('User Group'), 'created_at' => $this->translate('Created at'), 'last_modified' => $this->translate('Last modified') ), diff --git a/application/views/scripts/group/list.phtml b/application/views/scripts/group/list.phtml index 01bf3f7dd..b2bc9b920 100644 --- a/application/views/scripts/group/list.phtml +++ b/application/views/scripts/group/list.phtml @@ -4,30 +4,24 @@ use Icinga\Data\Extensible; use Icinga\Data\Reducible; if (! $this->compact): ?> -
- tabs; ?> -
-
- limiter ?> +
+ +
+ limiter ?> + paginator ?> + sortBox ?>
-
- paginator ?> +
+ backendSelection; ?> + filterEditor; ?>
-
- sortBox ?> -
-
-
- backendSelection; ?> - filterEditor; ?> -
-
+
translate('No backend found which is able to list groups') . '
'; + echo $this->translate('No backend found which is able to list user groups') . '
'; return; } else { $extensible = $this->hasPermission('config/authentication/groups/add') && $backend instanceof Extensible; @@ -37,64 +31,68 @@ if (! isset($backend)) { qlink( - $this->translate('Add a New User Group') , + $this->translate('Add a New User Group'), 'group/add', array('backend' => $backend->getName()), array( 'class' => 'button-link', 'data-base-target' => '_next', - 'icon' => 'plus', - 'title' => $this->translate('Create a new user group') + 'icon' => 'plus' ) ) ?> - - - - - - - - - - - - - - - - - - - - - -hasResult()): ?> - -
translate('Group'); ?>translate('Remove'); ?>
qlink($group->group_name, 'group/show', array( - 'backend' => $backend->getName(), - 'group' => $group->group_name - ), array( - 'title' => sprintf($this->translate('Show detailed information for group %s'), $group->group_name) - )); ?> - qlink( - null, - 'group/remove', - array( - 'backend' => $backend->getName(), - 'group' => $group->group_name - ), - array( - 'title' => sprintf($this->translate('Remove group %s'), $group->group_name), - 'icon' => 'trash' - ) - ); ?> -
- -

translate('No groups found matching the filter'); ?>

- +hasResult()): ?> +

translate('No user groups found matching the filter'); ?>

+ + + + + + + + + + + + + + + + + + + + + +
translate('User Group'); ?>translate('Remove'); ?>
+ qlink( + $group->group_name, + 'group/show', + array( + 'backend' => $backend->getName(), + 'group' => $group->group_name + ), + array( + 'title' => sprintf( + $this->translate('Show detailed information for user group %s'), + $group->group_name + ) + ) + ); ?> + + qlink( + null, + 'group/remove', + array( + 'backend' => $backend->getName(), + 'group' => $group->group_name + ), + array( + 'title' => sprintf($this->translate('Remove user group %s'), $group->group_name), + 'icon' => 'trash' + ) + ); ?> +
+
\ No newline at end of file diff --git a/public/css/icinga/main-content.less b/public/css/icinga/main-content.less index 0d0e92d23..624b21eec 100644 --- a/public/css/icinga/main-content.less +++ b/public/css/icinga/main-content.less @@ -233,29 +233,6 @@ div.content.users { } } -div.content.groups { - table.group-list { - th.group-remove { - width: 8em; - padding-right: 0.5em; - text-align: right; - } - - td.group-remove { - text-align: right; - } - } - - p { - margin-top: 0; - } - - a.group-add { - display: block; - margin-top: 1em; - } -} - form.backend-selection { float: right; From 9ccd6cd95357f559292b3963f6bf578ed39c483f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Oct 2015 17:06:02 +0200 Subject: [PATCH 10/16] user/list.phtml: Fix coding style, link targets, css, etc refs #10367 --- application/controllers/UserController.php | 2 +- application/views/scripts/user/list.phtml | 52 +++++++++++----------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/application/controllers/UserController.php b/application/controllers/UserController.php index 9b2845758..69d4a71a5 100644 --- a/application/controllers/UserController.php +++ b/application/controllers/UserController.php @@ -44,7 +44,7 @@ class UserController extends AuthBackendController 'backend', array( 'autosubmit' => true, - 'label' => $this->translate('Authentication Backend'), + 'label' => $this->translate('User Backend'), 'multiOptions' => array_combine($backendNames, $backendNames), 'value' => $this->params->get('backend') ) diff --git a/application/views/scripts/user/list.phtml b/application/views/scripts/user/list.phtml index c89ea82e8..26114d657 100644 --- a/application/views/scripts/user/list.phtml +++ b/application/views/scripts/user/list.phtml @@ -1,20 +1,15 @@ compact): ?> -
- tabs ?> -
-
- limiter ?> -
-
- paginator ?> -
-
- sortBox ?> -
+
+ +
+ limiter ?> + paginator ?> + sortBox ?>
backendSelection ?> @@ -22,20 +17,18 @@ if (! $this->compact): ?>
-
- -

translate('No backend found which is able to list users.') ?>

-
- -hasResult()): ?> -

translate('No users found matching the filter.') ?>

-
- hasPermission('config/authentication/users/add') && $backend instanceof Extensible; -$reducible = $this->hasPermission('config/authentication/users/remove') && $backend instanceof Reducible; + +if (! isset($backend)) { + echo $this->translate('No backend found which is able to list users') . '
'; + return; +} else { + $extensible = $this->hasPermission('config/authentication/users/add') && $backend instanceof Extensible; + $reducible = $this->hasPermission('config/authentication/users/remove') && $backend instanceof Reducible; +} ?> + qlink( $this->translate('Add a New User') , @@ -44,12 +37,17 @@ $reducible = $this->hasPermission('config/authentication/users/remove') && $back array( 'class' => 'button-link', 'data-base-target' => '_next', - 'icon' => 'plus', - 'title' => $this->translate('Create a new user') + 'icon' => 'plus' ) ) ?> - + +hasResult()): ?> +

translate('No users found matching the filter') ?>

+ + + +
@@ -91,4 +89,4 @@ $reducible = $this->hasPermission('config/authentication/users/remove') && $back
translate('Username') ?>
-
+
\ No newline at end of file From 33037eebbbf06df23764897f31846af5ca0a1618 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 16 Oct 2015 10:08:14 +0200 Subject: [PATCH 11/16] Revert "Fix group base DN is erroneously used in place of user base DN" This reverts commit ac7546d9f2f166a3bebbbb9d5941b2084c1ce00b. --- .../Icinga/Authentication/UserGroup/LdapUserGroupBackend.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php index 1b1bb31d0..b9827b40b 100644 --- a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php +++ b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php @@ -622,7 +622,7 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt return $this ->setGroupBaseDn($config->base_dn) - ->setUserBaseDn($config->get('user_base_dn', $this->getUserBaseDn())) + ->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)) From 7ef76932d4af652739f149e3eb104f7b3a61bd91 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 16 Oct 2015 12:36:47 +0200 Subject: [PATCH 12/16] DbRepository: Validate the table when inserting, updating and deleting --- library/Icinga/Authentication/User/DbUserBackend.php | 2 ++ library/Icinga/Repository/DbRepository.php | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/library/Icinga/Authentication/User/DbUserBackend.php b/library/Icinga/Authentication/User/DbUserBackend.php index c0c949fd7..e004a56c0 100644 --- a/library/Icinga/Authentication/User/DbUserBackend.php +++ b/library/Icinga/Authentication/User/DbUserBackend.php @@ -130,6 +130,7 @@ class DbUserBackend extends DbRepository implements UserBackendInterface, Inspec */ public function insert($table, array $bind) { + $this->requireTable($table); $bind['created_at'] = date('Y-m-d H:i:s'); $this->ds->insert( $this->prependTablePrefix($table), @@ -150,6 +151,7 @@ class DbUserBackend extends DbRepository implements UserBackendInterface, Inspec */ public function update($table, array $bind, Filter $filter = null) { + $this->requireTable($table); $bind['last_modified'] = date('Y-m-d H:i:s'); if ($filter) { $filter = $this->requireFilter($table, $filter); diff --git a/library/Icinga/Repository/DbRepository.php b/library/Icinga/Repository/DbRepository.php index a187d76c0..90b7807fa 100644 --- a/library/Icinga/Repository/DbRepository.php +++ b/library/Icinga/Repository/DbRepository.php @@ -297,6 +297,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, */ public function insert($table, array $bind) { + $this->requireTable($table); $this->ds->insert($this->prependTablePrefix($table), $this->requireStatementColumns($table, $bind)); } @@ -309,6 +310,8 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, */ public function update($table, array $bind, Filter $filter = null) { + $this->requireTable($table); + if ($filter) { $filter = $this->requireFilter($table, $filter); } @@ -324,6 +327,8 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, */ public function delete($table, Filter $filter = null) { + $this->requireTable($table); + if ($filter) { $filter = $this->requireFilter($table, $filter); } From 1b7dc1098c0c26932ec634dfeab68dc15e4d7ce6 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 16 Oct 2015 13:10:39 +0200 Subject: [PATCH 13/16] DbUserGroupBackend: Use LEFT JOIN to join the group_membership table Fixes the issue that groups are not found if they do not have any members even though they meet the where clause --- library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php b/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php index 5596f18b6..6f5c2e9dd 100644 --- a/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php +++ b/library/Icinga/Authentication/UserGroup/DbUserGroupBackend.php @@ -250,7 +250,7 @@ class DbUserGroupBackend extends DbRepository implements UserGroupBackendInterfa */ protected function joinGroupMembership(RepositoryQuery $query) { - $query->getQuery()->join( + $query->getQuery()->joinLeft( $this->requireTable('group_membership'), 'g.id = gm.group_id', array() From 58fc87b2e56e2cd3c16d33ddf41c7cdc469b430e Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 16 Oct 2015 14:46:44 +0200 Subject: [PATCH 14/16] Repository: Ensure that we'll internally only work with virtual table names refs #10367 --- .../Authentication/User/LdapUserBackend.php | 46 +++---- .../UserGroup/LdapUserGroupBackend.php | 26 ++-- library/Icinga/Repository/DbRepository.php | 120 +++++------------- library/Icinga/Repository/RepositoryQuery.php | 5 +- 4 files changed, 74 insertions(+), 123 deletions(-) diff --git a/library/Icinga/Authentication/User/LdapUserBackend.php b/library/Icinga/Authentication/User/LdapUserBackend.php index d8ea19ca2..f3a852115 100644 --- a/library/Icinga/Authentication/User/LdapUserBackend.php +++ b/library/Icinga/Authentication/User/LdapUserBackend.php @@ -102,15 +102,13 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In /** * Set the objectClass where to look for users * - * Sets also the base table name for the underlying repository. - * * @param string $userClass * * @return $this */ public function setUserClass($userClass) { - $this->baseTable = $this->userClass = $this->getNormedAttribute($userClass); + $this->userClass = $this->getNormedAttribute($userClass); return $this; } @@ -216,13 +214,10 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In * * @return array * - * @throws ProgrammingError In case either $this->userNameAttribute or $this->userClass has not been set yet + * @throws ProgrammingError In case $this->userNameAttribute has not been set yet */ protected function initializeQueryColumns() { - if ($this->userClass === null) { - throw new ProgrammingError('It is required to set the objectClass where to look for users first'); - } if ($this->userNameAttribute === null) { throw new ProgrammingError('It is required to set a attribute name where to find a user\'s name first'); } @@ -240,7 +235,7 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In } return array( - $this->userClass => array( + 'user' => array( 'user' => $this->userNameAttribute, 'user_name' => $this->userNameAttribute, 'is_active' => $isActiveAttribute, @@ -269,15 +264,9 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In * Initialize this repository's conversion rules * * @return array - * - * @throws ProgrammingError In case $this->userClass has not been set yet */ protected function initializeConversionRules() { - if ($this->userClass === null) { - throw new ProgrammingError('It is required to set the objectClass where to look for users first'); - } - if ($this->ds->getCapabilities()->isActiveDirectory()) { $stateConverter = 'user_account_control'; } else { @@ -285,7 +274,7 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In } return array( - $this->userClass => array( + 'user' => array( 'is_active' => $stateConverter, 'created_at' => 'generalized_time', 'last_modified' => 'generalized_time' @@ -330,14 +319,26 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In } /** - - * @param Inspection $info Optional inspection to fill with diagnostic info + * Validate that the requested table exists * - * @throws AuthenticationException When authentication is not possible + * This will return $this->userClass in case $table equals "user". + * + * @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 assertAuthenticationPossible(Inspection $insp = null) + public function requireTable($table, RepositoryQuery $query = null) { + $table = parent::requireTable($table, $query); + if ($table === 'user') { + $table = $this->userClass; + } + return $table; } /** @@ -359,17 +360,16 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In ->getQuery() ->setUsePagedResults(false) ->fetchDn(); - if ($userDn === null) { return false; } - $testCredentialsResult = $this->ds->testCredentials($userDn, $password); - if ($testCredentialsResult) { + $validCredentials = $this->ds->testCredentials($userDn, $password); + if ($validCredentials) { $user->setAdditional('ldap_dn', $userDn); } - return $testCredentialsResult; + return $validCredentials; } catch (LdapException $e) { throw new AuthenticationException( 'Failed to authenticate user "%s" against backend "%s". An exception was thrown:', diff --git a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php index b9827b40b..648c6c700 100644 --- a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php +++ b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php @@ -211,15 +211,13 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt /** * 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); + $this->groupClass = $this->getNormedAttribute($groupClass); return $this; } @@ -382,16 +380,17 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt * * @return array * - * @throws ProgrammingError In case either $this->groupNameAttribute or $this->groupClass has not been set yet + * @throws ProgrammingError In case either $this->groupNameAttribute or + * $this->groupMemberAttribute 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->groupMemberAttribute === null) { + throw new ProgrammingError('It is required to set a attribute name where to find a group\'s members first'); + } if ($this->ds->getCapabilities()->isActiveDirectory()) { $createdAtAttribute = 'whenCreated'; @@ -409,7 +408,7 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt 'created_at' => $createdAtAttribute, 'last_modified' => $lastModifiedAttribute ); - return array($this->groupClass => $columns, $this->groupClass => $columns); + return array('group' => $columns, 'group_membership' => $columns); } /** @@ -432,7 +431,8 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt * * @return array * - * @throws ProgrammingError In case $this->groupClass has not been set yet + * @throws ProgrammingError In case either $this->groupClass or $this->groupMemberAttribute + * has not been set yet */ protected function initializeConversionRules() { @@ -444,13 +444,17 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt } $rules = array( - $this->groupClass => array( + 'group' => array( + 'created_at' => 'generalized_time', + 'last_modified' => 'generalized_time' + ), + 'group_membership' => array( 'created_at' => 'generalized_time', 'last_modified' => 'generalized_time' ) ); if (! $this->isAmbiguous($this->groupClass, $this->groupMemberAttribute)) { - $rules[$this->groupClass][] = 'user_name'; + $rules['group']['user_name'] = 'user_name'; } return $rules; diff --git a/library/Icinga/Repository/DbRepository.php b/library/Icinga/Repository/DbRepository.php index 90b7807fa..27144d097 100644 --- a/library/Icinga/Repository/DbRepository.php +++ b/library/Icinga/Repository/DbRepository.php @@ -473,8 +473,8 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, * This does not check whether any conversion for the given table is available if $column is not given, as it * may be possible that columns from another table where joined in which would otherwise not being converted. * - * @param array|string $table - * @param string $column + * @param string $table + * @param string $column * * @return bool */ @@ -482,10 +482,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, { if ($column !== null) { if ($this->validateQueryColumnAssociation($table, $column)) { - return parent::providesValueConversion( - $this->removeTablePrefix($this->clearTableAlias($table)), - $column - ); + return parent::providesValueConversion($table, $column); } if (($tableName = $this->findTableName($column))) { @@ -518,11 +515,9 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, protected function getConverter($table, $name, $context, RepositoryQuery $query = null) { if ( - ($query !== null && $this->validateQueryColumnAssociation($table, $name)) - || ($query === null && $this->validateStatementColumnAssociation($table, $name)) + ! ($query !== null && $this->validateQueryColumnAssociation($table, $name)) + && !($query === null && $this->validateStatementColumnAssociation($table, $name)) ) { - $table = $this->removeTablePrefix($this->clearTableAlias($table)); - } else { $table = $this->findTableName($name); if (! $table) { throw new ProgrammingError('Column name validation seems to have failed. Did you require the column?'); @@ -589,44 +584,17 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, return $filter; } - /** - * Return this repository's query columns of the given table mapped to their respective aliases - * - * @param array|string $table - * - * @return array - * - * @throws ProgrammingError In case $table does not exist - */ - public function requireAllQueryColumns($table) - { - return parent::requireAllQueryColumns($this->removeTablePrefix($this->clearTableAlias($table))); - } - - /** - * Return the query column name for the given alias or null in case the alias does not exist - * - * @param array|string $table - * @param string $alias - * - * @return string|null - */ - public function resolveQueryColumnAlias($table, $alias) - { - return parent::resolveQueryColumnAlias($this->removeTablePrefix($this->clearTableAlias($table)), $alias); - } - /** * Return the alias for the given query column name or null in case the query column name does not exist * - * @param array|string $table - * @param string $column + * @param string $table + * @param string $column * * @return string|null */ public function reassembleQueryColumnAlias($table, $column) { - $alias = parent::reassembleQueryColumnAlias($this->removeTablePrefix($this->clearTableAlias($table)), $column); + $alias = parent::reassembleQueryColumnAlias($table, $column); if ( $alias === null && !$this->validateQueryColumnAssociation($table, $column) @@ -638,29 +606,13 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, return $alias; } - /** - * Return whether the given query column name or alias is available in the given table - * - * @param array|string $table - * @param string $column - * - * @return bool - */ - public function validateQueryColumnAssociation($table, $column) - { - return parent::validateQueryColumnAssociation( - $this->removeTablePrefix($this->clearTableAlias($table)), - $column - ); - } - /** * Validate that the given column is a valid query target and return it or the actual name if it's an alias * * Attempts to join the given column from a different table if its association to the given table cannot be * verified. * - * @param array|string $table The table where to look for the column or alias + * @param string $table The table where to look for the column or alias * @param string $name The name or alias of the column to validate * @param RepositoryQuery $query An optional query to pass as context, * if not given no join will be attempted @@ -672,7 +624,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, public function requireQueryColumn($table, $name, RepositoryQuery $query = null) { if ($query === null || $this->validateQueryColumnAssociation($table, $name)) { - return parent::requireQueryColumn($this->removeTablePrefix($this->clearTableAlias($table)), $name, $query); + return parent::requireQueryColumn($table, $name, $query); } return $this->joinColumn($name, $table, $query); @@ -684,7 +636,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, * Attempts to join the given column from a different table if its association to the given table cannot be * verified. * - * @param array|string $table The table where to look for the column or alias + * @param string $table The table where to look for the column or alias * @param string $name The name or alias of the column to validate * @param RepositoryQuery $query An optional query to pass as context, * if not given the column is considered being used for a statement filter @@ -700,7 +652,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, } if ($this->validateQueryColumnAssociation($table, $name)) { - return parent::requireFilterColumn($this->removeTablePrefix($this->clearTableAlias($table)), $name, $query); + return parent::requireFilterColumn($table, $name, $query); } return $this->joinColumn($name, $table, $query); @@ -709,8 +661,8 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, /** * Return the statement column name for the given alias or null in case the alias does not exist * - * @param array|string $table - * @param string $alias + * @param string $table + * @param string $alias * * @return string|null */ @@ -721,7 +673,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, return $statementAliasColumnMap[$alias]; } - $prefixedAlias = $this->removeTablePrefix($this->clearTableAlias($table)) . '.' . $alias; + $prefixedAlias = $table . '.' . $alias; if (isset($statementAliasColumnMap[$prefixedAlias])) { return $statementAliasColumnMap[$prefixedAlias]; } @@ -730,8 +682,8 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, /** * Return the alias for the given statement column name or null in case the statement column does not exist * - * @param array|string $table - * @param string $column + * @param string $table + * @param string $column * * @return string|null */ @@ -742,7 +694,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, return $statementColumnAliasMap[$column]; } - $prefixedColumn = $this->removeTablePrefix($this->clearTableAlias($table)) . '.' . $column; + $prefixedColumn = $table . '.' . $column; if (isset($statementColumnAliasMap[$prefixedColumn])) { return $statementColumnAliasMap[$prefixedColumn]; } @@ -751,34 +703,32 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, /** * Return whether the given alias or statement column name is available in the given table * - * @param array|string $table - * @param string $alias + * @param string $table + * @param string $alias * * @return bool */ public function validateStatementColumnAssociation($table, $alias) { - $tableName = $this->removeTablePrefix($this->clearTableAlias($table)); - $statementAliasTableMap = $this->getStatementAliasTableMap(); if (isset($statementAliasTableMap[$alias])) { - return $statementAliasTableMap[$alias] === $tableName; + return $statementAliasTableMap[$alias] === $table; } $statementColumnTableMap = $this->getStatementColumnTableMap(); if (isset($statementColumnTableMap[$alias])) { - return $statementColumnTableMap[$alias] === $tableName; + return $statementColumnTableMap[$alias] === $table; } - $prefixedAlias = $tableName . '.' . $alias; + $prefixedAlias = $table . '.' . $alias; return isset($statementAliasTableMap[$prefixedAlias]) || isset($statementColumnTableMap[$prefixedAlias]); } /** * Return whether the given column name or alias of the given table is a valid statement column * - * @param array|string $table The table where to look for the column or alias - * @param string $name The column name or alias to check + * @param string $table The table where to look for the column or alias + * @param string $name The column name or alias to check * * @return bool */ @@ -789,7 +739,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, && $this->reassembleStatementColumnAlias($table, $name) === null) || !$this->validateStatementColumnAssociation($table, $name) ) { - return parent::hasStatementColumn($this->removeTablePrefix($this->clearTableAlias($table)), $name); + return parent::hasStatementColumn($table, $name); } return true; @@ -798,8 +748,8 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, /** * Validate that the given column is a valid statement column and return it or the actual name if it's an alias * - * @param array|string $table The table for which to require the column - * @param string $name The name or alias of the column to validate + * @param string $table The table for which to require the column + * @param string $name The name or alias of the column to validate * * @return string The given column's name * @@ -812,15 +762,11 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, } elseif (($alias = $this->reassembleStatementColumnAlias($table, $name)) !== null) { $column = $name; } else { - return parent::requireStatementColumn($this->removeTablePrefix($this->clearTableAlias($table)), $name); + return parent::requireStatementColumn($table, $name); } if (! $this->validateStatementColumnAssociation($table, $alias)) { - throw new StatementException( - 'Statement column "%s" not found in table "%s"', - $name, - $this->removeTablePrefix($this->clearTableAlias($table)) - ); + throw new StatementException('Statement column "%s" not found in table "%s"', $name, $table); } return $column; @@ -834,7 +780,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, * The method is called with the same parameters but in reversed order. * * @param string $name The alias or column name to join into $target - * @param array|string $target The table to join $name into + * @param string $target The table to join $name into * @param RepositoryQUery $query The query to apply the JOIN-clause on * * @return string The resolved alias or $name @@ -848,7 +794,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, throw new ProgrammingError( 'Unable to find a valid table for column "%s" to join into "%s"', $name, - $this->removeTablePrefix($this->clearTableAlias($target)) + $target ); } @@ -866,7 +812,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable, throw new ProgrammingError( 'Unable to join table "%s" into "%s". Method "%s" not found', $tableName, - $this->removeTablePrefix($this->clearTableAlias($target)), + $target, $joinMethod ); } diff --git a/library/Icinga/Repository/RepositoryQuery.php b/library/Icinga/Repository/RepositoryQuery.php index 927f4f02b..8beba988b 100644 --- a/library/Icinga/Repository/RepositoryQuery.php +++ b/library/Icinga/Repository/RepositoryQuery.php @@ -79,8 +79,9 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera */ public function from($target, array $columns = null) { - $target = $this->repository->requireTable($target, $this); - $this->query = $this->repository->getDataSource()->select()->from($target); + $this->query = $this->repository->getDataSource()->select()->from( + $this->repository->requireTable($target, $this) + ); $this->query->columns($this->prepareQueryColumns($target, $columns)); $this->target = $target; return $this; From 8ed489c637de20a3f8810362240eb0ac8174a79f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 16 Oct 2015 15:28:44 +0200 Subject: [PATCH 15/16] LdapUserGroupBackend: Add method persistUserName() refs #10367 refs #10370 --- .../UserGroup/LdapUserGroupBackend.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php index 648c6c700..1521ba119 100644 --- a/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php +++ b/library/Icinga/Authentication/UserGroup/LdapUserGroupBackend.php @@ -5,6 +5,7 @@ namespace Icinga\Authentication\UserGroup; use Icinga\Authentication\User\UserBackend; use Icinga\Authentication\User\LdapUserBackend; +use Icinga\Application\Logger; use Icinga\Data\ConfigObject; use Icinga\Exception\ConfigurationError; use Icinga\Exception\ProgrammingError; @@ -454,12 +455,48 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt ) ); if (! $this->isAmbiguous($this->groupClass, $this->groupMemberAttribute)) { + $rules['group_membership']['user_name'] = 'user_name'; + $rules['group_membership']['user'] = 'user_name'; $rules['group']['user_name'] = 'user_name'; + $rules['group']['user'] = 'user_name'; } return $rules; } + /** + * Return the distinguished name for the given uid or gid + * + * @param string $name + * + * @return string + */ + protected function persistUserName($name) + { + $userDn = $this->ds + ->select() + ->from($this->userClass, array()) + ->where($this->userNameAttribute, $name) + ->setUsePagedResults(false) + ->fetchDn(); + if ($userDn) { + return $userDn; + } + + $groupDn = $this->ds + ->select() + ->from($this->groupClass, array()) + ->where($this->groupNameAttribute, $name) + ->setUsePagedResults(false) + ->fetchDn(); + if ($groupDn) { + return $groupDn; + } + + Logger::debug('Unable to persist uid or gid "%s" in repository "%s". No DN found.', $name, $this->getName()); + return $name; + } + /** * Return the uid for the given distinguished name * From 878bd78587f088248e49f751b1808ce31d6887a1 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 16 Oct 2015 17:25:42 +0200 Subject: [PATCH 16/16] LdapUserBackend: Unfold the user_name_attribute automatically This is.. the currently easiest solution. As long as attribute unfolding is not very performance intensive this solution suffices. refs #10367 refs #10332 --- .../Authentication/User/LdapUserBackend.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/Icinga/Authentication/User/LdapUserBackend.php b/library/Icinga/Authentication/User/LdapUserBackend.php index f3a852115..b5bd51f45 100644 --- a/library/Icinga/Authentication/User/LdapUserBackend.php +++ b/library/Icinga/Authentication/User/LdapUserBackend.php @@ -341,6 +341,27 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In return $table; } + /** + * Validate that the given column is a valid query target and return it or the actual name if it's an alias + * + * @param string $table The table where to look for the column or alias + * @param string $name The name or alias of the column to validate + * @param RepositoryQuery $query An optional query to pass as context + * + * @return string The given column's name + * + * @throws QueryException In case the given column is not a valid query column + */ + public function requireQueryColumn($table, $name, RepositoryQuery $query = null) + { + $column = parent::requireQueryColumn($table, $name, $query); + if ($name === 'user_name' && $query !== null) { + $query->getQuery()->setUnfoldAttribute('user_name'); + } + + return $column; + } + /** * Authenticate the given user *