def test_group_edge_roles_order_unchanged(): # The order of the GROUP_EDGE_ROLES tuple matters: new roles must be # appended. This test attempts exposes that information to help prevent # that from happening accidentally. assert GROUP_EDGE_ROLES.index("member") == 0 assert GROUP_EDGE_ROLES.index("manager") == 1 assert GROUP_EDGE_ROLES.index("owner") == 2 assert GROUP_EDGE_ROLES.index("np-owner") == 3
def permission_grants_for_user(self, username): # type: (str) -> List[PermissionGrant] now = datetime.utcnow() user = User.get(self.session, name=username) if not user or user.role_user or user.is_service_account or not user.enabled: return [] # Get the groups of which this user is a direct member. groups = (self.session.query(Group.id).join( GroupEdge, Group.id == GroupEdge.group_id).join( User, User.id == GroupEdge.member_pk).filter( Group.enabled == True, User.id == user.id, GroupEdge.active == True, GroupEdge.member_type == OBJ_TYPES["User"], GroupEdge._role != GROUP_EDGE_ROLES.index("np-owner"), or_(GroupEdge.expiration > now, GroupEdge.expiration == None), ).distinct()) group_ids = [g.id for g in groups] # If the user was not a member of any group, we can return early. if not group_ids: return [] # Now, get the parent groups of those groups and so forth until we run out of levels of the # tree. Use a set of seen group_ids to avoid querying the same group twice if a user is a # member of it via multiple paths. seen_group_ids = set(group_ids) while group_ids: parent_groups = (self.session.query(Group.id).join( GroupEdge, Group.id == GroupEdge.group_id).filter( GroupEdge.member_pk.in_(group_ids), Group.enabled == True, GroupEdge.active == True, GroupEdge.member_type == OBJ_TYPES["Group"], GroupEdge._role != GROUP_EDGE_ROLES.index("np-owner"), or_(GroupEdge.expiration > now, GroupEdge.expiration == None), ).distinct()) group_ids = [ g.id for g in parent_groups if g.id not in seen_group_ids ] seen_group_ids.update(group_ids) # Return the permission grants. group_permission_grants = (self.session.query( Permission.name, PermissionMap.argument).filter( Permission.id == PermissionMap.permission_id, PermissionMap.group_id.in_(seen_group_ids), ).all()) return [ PermissionGrant(g.name, g.argument) for g in group_permission_grants ]
def user_role_index(user, members): if user_is_group_admin(user.session, user): return GROUP_EDGE_ROLES.index("owner") member = members.get(("User", user.name)) if not member: return None return member.role
def _create_edge(session, group, member, role): edge, new = GroupEdge.get_or_create(session, group_id=group.id, member_type=member.member_type, member_pk=member.id) if new: # TODO(herb): this means all requests by this user to this group will # have the same role. we should probably record the role specifically # on the request and use that as the source on the UI edge._role = GROUP_EDGE_ROLES.index(role) session.flush() return edge
def add_user_to_group(self, user, group, role="member"): # type: (str, str, str) -> None self.create_user(user) self.create_group(group) user_obj = User.get(self.session, name=user) assert user_obj group_obj = Group.get(self.session, name=group) assert group_obj edge = GroupEdge( group_id=group_obj.id, member_type=OBJ_TYPES["User"], member_pk=user_obj.id, active=True, _role=GROUP_EDGE_ROLES.index(role), ) edge.add(self.session)
def add_group_to_group(self, member, group): # type: (str, str) -> None self.create_group(member) self.create_group(group) member_obj = Group.get(self.session, name=member) assert member_obj group_obj = Group.get(self.session, name=group) assert group_obj edge = GroupEdge( group_id=group_obj.id, member_type=OBJ_TYPES["Group"], member_pk=member_obj.id, active=True, _role=GROUP_EDGE_ROLES.index("member"), ) edge.add(self.session)
def _create_edge(session, group, member, role): edge, new = GroupEdge.get_or_create( session, group_id=group.id, member_type=member.member_type, member_pk=member.id ) if new: # TODO(herb): this means all requests by this user to this group will # have the same role. we should probably record the role specifically # on the request and use that as the source on the UI edge._role = GROUP_EDGE_ROLES.index(role) session.flush() return edge
def will_update_group_membership(self, session, group, member, **updates): if member.member_type != OBJ_TYPES["User"]: return check_permanent_owners = False if "role" in updates: role_idx = GROUP_EDGE_ROLES.index(updates["role"]) if role_idx not in OWNER_ROLE_INDICES: check_permanent_owners = True if updates.get("expiration"): check_permanent_owners = True if "active" in updates and not updates["active"]: check_permanent_owners = True if check_permanent_owners and _is_last_permanent_owner(session, group, member): raise PluginRejectedGroupMembershipUpdate(EXCEPTION_MESSAGE)
def groups_of_user(self, username): # type: (str) -> List[str] now = datetime.utcnow() user = User.get(self.session, name=username) if not user or user.role_user or user.is_service_account or not user.enabled: return [] groups = ( self.session.query(Group.groupname) .join(GroupEdge, Group.id == GroupEdge.group_id) .join(User, User.id == GroupEdge.member_pk) .filter( Group.enabled == True, User.id == user.id, GroupEdge.active == True, GroupEdge.member_type == OBJ_TYPES["User"], GroupEdge._role != GROUP_EDGE_ROLES.index("np-owner"), or_(GroupEdge.expiration > now, GroupEdge.expiration == None), ) .distinct() ) return [g.groupname for g in groups]