Fix list users by name
When attempting to filter users by name, it works for local users, but doesn't work for federated users. This patch fixed this error. Change-Id: I1bee51c2be81dbddd9d849731ab53728c86b2765 Closes-bug: #1738895
This commit is contained in:
parent
f4ac7b7a5f
commit
e7a4d43ece
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
"""Main entry point into the Identity service."""
|
"""Main entry point into the Identity service."""
|
||||||
|
|
||||||
|
import copy
|
||||||
import functools
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
import operator
|
import operator
|
||||||
@ -1025,12 +1026,23 @@ class Manager(manager.Manager):
|
|||||||
raise exception.InvalidOperatorError(op)
|
raise exception.InvalidOperatorError(op)
|
||||||
return hints
|
return hints
|
||||||
|
|
||||||
def _handle_federated_attributes_in_hints(self, driver, hints):
|
def _handle_shadow_and_local_users(self, driver, hints):
|
||||||
federated_attributes = ['idp_id', 'protocol_id', 'unique_id']
|
federated_attributes = ['idp_id', 'protocol_id', 'unique_id']
|
||||||
for filter_ in hints.filters:
|
for filter_ in hints.filters:
|
||||||
if filter_['name'] in federated_attributes:
|
if filter_['name'] in federated_attributes:
|
||||||
return PROVIDERS.shadow_users_api.get_federated_users(hints)
|
return PROVIDERS.shadow_users_api.get_federated_users(hints)
|
||||||
return driver.list_users(hints)
|
fed_hints = copy.deepcopy(hints)
|
||||||
|
res = driver.list_users(hints)
|
||||||
|
|
||||||
|
# Note: If the filters contain 'name', we should get the user from both
|
||||||
|
# local user and shadow user backend.
|
||||||
|
for filter_ in fed_hints.filters:
|
||||||
|
if filter_['name'] == 'name':
|
||||||
|
fed_res = PROVIDERS.shadow_users_api.get_federated_users(
|
||||||
|
fed_hints)
|
||||||
|
res += fed_res
|
||||||
|
break
|
||||||
|
return res
|
||||||
|
|
||||||
@domains_configured
|
@domains_configured
|
||||||
@exception_translated('user')
|
@exception_translated('user')
|
||||||
@ -1047,7 +1059,7 @@ class Manager(manager.Manager):
|
|||||||
# driver selection, so remove any such filter.
|
# driver selection, so remove any such filter.
|
||||||
self._mark_domain_id_filter_satisfied(hints)
|
self._mark_domain_id_filter_satisfied(hints)
|
||||||
hints = self._translate_expired_password_hints(hints)
|
hints = self._translate_expired_password_hints(hints)
|
||||||
ref_list = self._handle_federated_attributes_in_hints(driver, hints)
|
ref_list = self._handle_shadow_and_local_users(driver, hints)
|
||||||
return self._set_domain_id_and_mapping(
|
return self._set_domain_id_and_mapping(
|
||||||
ref_list, domain_scope, driver, mapping.EntityType.USER)
|
ref_list, domain_scope, driver, mapping.EntityType.USER)
|
||||||
|
|
||||||
|
@ -67,9 +67,20 @@ class ShadowUsers(base.ShadowUsersDriverBase):
|
|||||||
|
|
||||||
def get_federated_users(self, hints):
|
def get_federated_users(self, hints):
|
||||||
with sql.session_for_read() as session:
|
with sql.session_for_read() as session:
|
||||||
query = session.query(model.User).outerjoin(model.LocalUser)
|
query = session.query(model.User).outerjoin(
|
||||||
|
model.LocalUser).outerjoin(model.FederatedUser)
|
||||||
query = query.filter(model.User.id == model.FederatedUser.user_id)
|
query = query.filter(model.User.id == model.FederatedUser.user_id)
|
||||||
query = self._update_query_with_federated_statements(hints, query)
|
query = self._update_query_with_federated_statements(hints, query)
|
||||||
|
name_filter = None
|
||||||
|
for filter_ in hints.filters:
|
||||||
|
if filter_['name'] == 'name':
|
||||||
|
name_filter = filter_
|
||||||
|
query = query.filter(
|
||||||
|
model.FederatedUser.display_name == name_filter[
|
||||||
|
'value'])
|
||||||
|
break
|
||||||
|
if name_filter:
|
||||||
|
hints.filters.remove(name_filter)
|
||||||
user_refs = sql.filter_limit_query(model.User, query, hints)
|
user_refs = sql.filter_limit_query(model.User, query, hints)
|
||||||
return [identity_base.filter_user(x.to_dict()) for x in user_refs]
|
return [identity_base.filter_user(x.to_dict()) for x in user_refs]
|
||||||
|
|
||||||
|
@ -529,6 +529,29 @@ class IdentityTests(object):
|
|||||||
filters = ['unique_id', 'idp_id', 'protocol_id']
|
filters = ['unique_id', 'idp_id', 'protocol_id']
|
||||||
self._test_list_users_with_attribute(filters, federated_dict)
|
self._test_list_users_with_attribute(filters, federated_dict)
|
||||||
|
|
||||||
|
def test_list_users_with_name(self):
|
||||||
|
federated_dict = unit.new_federated_user_ref(
|
||||||
|
display_name='test@federation.org')
|
||||||
|
domain = self._get_domain_fixture()
|
||||||
|
|
||||||
|
hints = driver_hints.Hints()
|
||||||
|
hints.add_filter('name', 'test@federation.org')
|
||||||
|
users = self.identity_api.list_users(hints=hints)
|
||||||
|
self.assertEqual(0, len(users))
|
||||||
|
|
||||||
|
self.shadow_users_api.create_federated_user(domain['id'],
|
||||||
|
federated_dict)
|
||||||
|
hints = driver_hints.Hints()
|
||||||
|
hints.add_filter('name', 'test@federation.org')
|
||||||
|
users = self.identity_api.list_users(hints=hints)
|
||||||
|
self.assertEqual(1, len(users))
|
||||||
|
|
||||||
|
hints = driver_hints.Hints()
|
||||||
|
hints.add_filter('name', 'test@federation.org')
|
||||||
|
hints.add_filter('idp_id', 'ORG_IDP')
|
||||||
|
users = self.identity_api.list_users(hints=hints)
|
||||||
|
self.assertEqual(1, len(users))
|
||||||
|
|
||||||
def test_list_groups(self):
|
def test_list_groups(self):
|
||||||
group1 = unit.new_group_ref(domain_id=CONF.identity.default_domain_id)
|
group1 = unit.new_group_ref(domain_id=CONF.identity.default_domain_id)
|
||||||
group2 = unit.new_group_ref(domain_id=CONF.identity.default_domain_id)
|
group2 = unit.new_group_ref(domain_id=CONF.identity.default_domain_id)
|
||||||
|
7
releasenotes/notes/bug-1738895-342864cd0285bc42.yaml
Normal file
7
releasenotes/notes/bug-1738895-342864cd0285bc42.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
[`bug 1738895 <https://bugs.launchpad.net/keystone/+bug/1738895>`_]
|
||||||
|
Fixed the bug that federated users can't be listed by `name` filter. Now
|
||||||
|
when list users by `name`, Keystone will query both local user backend and
|
||||||
|
shadow user backend.
|
Loading…
x
Reference in New Issue
Block a user