From 92fd2dbfb672d7b2b1cdfd5dd5cf89f7716b3e12 Mon Sep 17 00:00:00 2001 From: asteroide Date: Tue, 1 Sep 2015 16:03:26 +0200 Subject: Update Keystone code from official Github repository with branch Master on 09/01/2015. Change-Id: I0ff6099e6e2580f87f502002a998bbfe12673498 --- keystone-moon/keystone/assignment/backends/sql.py | 108 +++++++++++++++++++--- 1 file changed, 96 insertions(+), 12 deletions(-) (limited to 'keystone-moon/keystone/assignment/backends/sql.py') diff --git a/keystone-moon/keystone/assignment/backends/sql.py b/keystone-moon/keystone/assignment/backends/sql.py index 2de6ca60..89ff64b5 100644 --- a/keystone-moon/keystone/assignment/backends/sql.py +++ b/keystone-moon/keystone/assignment/backends/sql.py @@ -14,7 +14,6 @@ from oslo_config import cfg from oslo_log import log -import six import sqlalchemy from sqlalchemy.sql.expression import false @@ -53,10 +52,10 @@ class AssignmentType(object): class Assignment(keystone_assignment.Driver): def default_role_driver(self): - return "keystone.assignment.role_backends.sql.Role" + return 'sql' def default_resource_driver(self): - return 'keystone.resource.backends.sql.Resource' + return 'sql' def list_user_ids_for_project(self, tenant_id): with sql.transaction() as session: @@ -336,7 +335,62 @@ class Assignment(keystone_assignment.Driver): 'Cannot remove role that has not been granted, %s') % role_id) - def list_role_assignments(self): + def _get_user_assignment_types(self): + return [AssignmentType.USER_PROJECT, AssignmentType.USER_DOMAIN] + + def _get_group_assignment_types(self): + return [AssignmentType.GROUP_PROJECT, AssignmentType.GROUP_DOMAIN] + + def _get_project_assignment_types(self): + return [AssignmentType.USER_PROJECT, AssignmentType.GROUP_PROJECT] + + def _get_domain_assignment_types(self): + return [AssignmentType.USER_DOMAIN, AssignmentType.GROUP_DOMAIN] + + def _get_assignment_types(self, user, group, project, domain): + """Returns a list of role assignment types based on provided entities + + If one of user or group (the "actor") as well as one of project or + domain (the "target") are provided, the list will contain the role + assignment type for that specific pair of actor and target. + + If only an actor or target is provided, the list will contain the + role assignment types that satisfy the specified entity. + + For example, if user and project are provided, the return will be: + + [AssignmentType.USER_PROJECT] + + However, if only user was provided, the return would be: + + [AssignmentType.USER_PROJECT, AssignmentType.USER_DOMAIN] + + It is not expected that user and group (or project and domain) are + specified - but if they are, the most fine-grained value will be + chosen (i.e. user over group, project over domain). + + """ + actor_types = [] + if user: + actor_types = self._get_user_assignment_types() + elif group: + actor_types = self._get_group_assignment_types() + + target_types = [] + if project: + target_types = self._get_project_assignment_types() + elif domain: + target_types = self._get_domain_assignment_types() + + if actor_types and target_types: + return list(set(actor_types).intersection(target_types)) + + return actor_types or target_types + + def list_role_assignments(self, role_id=None, + user_id=None, group_ids=None, + domain_id=None, project_ids=None, + inherited_to_projects=None): def denormalize_role(ref): assignment = {} @@ -362,8 +416,35 @@ class Assignment(keystone_assignment.Driver): return assignment with sql.transaction() as session: - refs = session.query(RoleAssignment).all() - return [denormalize_role(ref) for ref in refs] + assignment_types = self._get_assignment_types( + user_id, group_ids, project_ids, domain_id) + + targets = None + if project_ids: + targets = project_ids + elif domain_id: + targets = [domain_id] + + actors = None + if group_ids: + actors = group_ids + elif user_id: + actors = [user_id] + + query = session.query(RoleAssignment) + + if role_id: + query = query.filter_by(role_id=role_id) + if actors: + query = query.filter(RoleAssignment.actor_id.in_(actors)) + if targets: + query = query.filter(RoleAssignment.target_id.in_(targets)) + if assignment_types: + query = query.filter(RoleAssignment.type.in_(assignment_types)) + if inherited_to_projects is not None: + query = query.filter_by(inherited=inherited_to_projects) + + return [denormalize_role(ref) for ref in query.all()] def delete_project_assignments(self, project_id): with sql.transaction() as session: @@ -377,13 +458,13 @@ class Assignment(keystone_assignment.Driver): q = q.filter_by(role_id=role_id) q.delete(False) - def delete_user(self, user_id): + def delete_user_assignments(self, user_id): with sql.transaction() as session: q = session.query(RoleAssignment) q = q.filter_by(actor_id=user_id) q.delete(False) - def delete_group(self, group_id): + def delete_group_assignments(self, group_id): with sql.transaction() as session: q = session.query(RoleAssignment) q = q.filter_by(actor_id=group_id) @@ -399,12 +480,15 @@ class RoleAssignment(sql.ModelBase, sql.DictBase): AssignmentType.USER_DOMAIN, AssignmentType.GROUP_DOMAIN, name='type'), nullable=False) - actor_id = sql.Column(sql.String(64), nullable=False, index=True) + actor_id = sql.Column(sql.String(64), nullable=False) target_id = sql.Column(sql.String(64), nullable=False) role_id = sql.Column(sql.String(64), nullable=False) inherited = sql.Column(sql.Boolean, default=False, nullable=False) - __table_args__ = (sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', - 'role_id'), {}) + __table_args__ = ( + sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id', + 'inherited'), + sql.Index('ix_actor_id', 'actor_id'), + ) def to_dict(self): """Override parent to_dict() method with a simpler implementation. @@ -412,4 +496,4 @@ class RoleAssignment(sql.ModelBase, sql.DictBase): RoleAssignment doesn't have non-indexed 'extra' attributes, so the parent implementation is not applicable. """ - return dict(six.iteritems(self)) + return dict(self.items()) -- cgit 1.2.3-korg