def can_approve_request(session, request, owner, group_ids=None, owners_by_arg_by_perm=None): owner_arg_list = get_owner_arg_list(session, request.permission, request.argument, owners_by_arg_by_perm) if group_ids is None: group_ids = {g.id for g, _ in get_groups_by_user(session, owner)} return group_ids.intersection([o.id for o, arg in owner_arg_list])
def _build_form(self, data): # type: (Optional[int]) -> Tuple[PermissionRequestForm, Dict[str, List[str]]] """Build the permission request form given the request and POST data. Normally all fields of the form will be editable. But if the URL locks down a specific value for the group, permission, or argument, then the specified fields will display those values and will be grayed out and not editable. """ session = self.session current_user = self.current_user def pairs(seq): # type: (Iterable[str]) -> List[Tuple[str, str]] return [(item, item) for item in seq] form = PermissionRequestForm(data) group_names = { g.groupname for g, e in get_groups_by_user(session, current_user) } args_by_perm = get_grantable_permissions( session, settings().restricted_ownership_permissions) permission_names = {p for p in args_by_perm} group_param = self.get_argument("group", None) if group_param is not None: if group_param not in group_names: raise HTTPError( status_code=404, reason="the group name in the URL is not one you belong to" ) form.group_name.choices = pairs([group_param]) form.group_name.render_kw = {"readonly": "readonly"} form.group_name.data = group_param else: form.group_name.choices = pairs([""] + sorted(group_names)) permission_param = self.get_argument("permission", None) if permission_param is not None: if permission_param not in permission_names: raise HTTPError( status_code=404, reason="an unrecognized permission is specified in the URL" ) form.permission.choices = pairs([permission_param]) form.permission.render_kw = {"readonly": "readonly"} form.permission.data = permission_param else: form.permission.choices = pairs(sorted(permission_names)) argument_param = self.get_argument("argument", "") if argument_param: form.argument.render_kw = {"readonly": "readonly"} form.argument.data = argument_param return form, args_by_perm
def get_requests_by_owner(session, owner, status, limit, offset): """Load pending requests for a particular owner. Args: session(sqlalchemy.orm.session.Session): database session owner(models.User): model of user in question status(models.base.constants.REQUEST_STATUS_CHOICES): if not None, filter by particular status limit(int): how many results to return offset(int): the offset into the result set that should be applied Returns: 2-tuple of (Requests, total) where total is total result size and Requests is the namedtuple with requests and associated comments/changes. """ # get owners groups group_ids = {g.id for g, _ in get_groups_by_user(session, owner)} # get all requests all_requests = session.query(PermissionRequest) if status: all_requests = all_requests.filter(PermissionRequest.status == status) all_requests = all_requests.order_by( PermissionRequest.requested_at.desc()).all() owners_by_arg_by_perm = get_owners_by_grantable_permission(session) requests = [] for request in all_requests: if can_approve_request(session, request, owner, group_ids=group_ids, owners_by_arg_by_perm=owners_by_arg_by_perm): requests.append(request) total = len(requests) requests = requests[offset:limit] status_change_by_request_id = defaultdict(list) if not requests: comment_by_status_change_id = {} else: status_changes = session.query(PermissionRequestStatusChange).filter( PermissionRequestStatusChange.request_id.in_( [r.id for r in requests]), ).all() for sc in status_changes: status_change_by_request_id[sc.request_id].append(sc) comments = session.query(Comment).filter( Comment.obj_type == OBJ_TYPES_IDX.index( "PermissionRequestStatusChange"), Comment.obj_pk.in_([s.id for s in status_changes]), ).all() comment_by_status_change_id = {c.obj_pk: c for c in comments} return Requests(requests, status_change_by_request_id, comment_by_status_change_id), total
def get_user_view_template_vars(session, actor, user, graph): # type: (Session, User, User, GroupGraph) -> Dict[str, Any] # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} # type: Dict[str, Any] if user.is_service_account: ret["can_control"] = can_manage_service_account( session, user.service_account, actor ) or user_is_user_admin(session, actor) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["can_enable_preserving_membership"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = user.name == actor.name or user_is_user_admin(session, actor) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable_preserving_membership"] = UserEnable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access_without_membership(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests( session, status="pending", limit=1, offset=0, owner=actor ) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell_metadata = get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) ret["shell"] = shell_metadata.data_value if shell_metadata else "No shell configured" github_username = get_user_metadata_by_key(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY) ret["github_username"] = github_username.data_value if github_username else "(Unset)" ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [ {"name": g.name, "type": "Group", "role": ge._role} for g, ge in group_edge_list ] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp(permission["granted_on"]) return ret
def _get_choices(self, group: Group, member_groups: Set[str], user_is_member: bool) -> List[Tuple[str, str]]: choices = [] if not user_is_member: choice = "User: {}".format(self.current_user.name) choices.append((choice, choice)) for _group, group_edge in get_groups_by_user(self.session, self.current_user): if group.name == _group.name: # Don't add self. continue if group_edge._role not in APPROVER_ROLE_INDICES: # manager, owner, and np-owner only. continue if _group.name in member_groups: continue choice = "Group: {}".format(_group.name) choices.append((choice, choice)) # If there are some choices but the user is already a member or has a pending request, add # a blank option as the first choice to avoid the user requesting membership on behalf of a # group by mistake. if choices and user_is_member: choices.insert(0, ("", "")) return choices
def can_approve_request( session: Session, request: PermissionRequest, owner: User, group_ids: Optional[Set[int]] = None, owners_by_arg_by_perm: Optional[Dict[object, Dict[str, List[Group]]]] = None, ) -> bool: """Determine whether the given owner can approve a permission request. Args: session: Database session request: Pending permission request owner: User who may or may not be able to approve the request group_ids: If given, the IDs of the groups of which the user is a member (solely so that we can avoid another database query if this information is already available) owners_by_arg_by_perm: List of permission granters by permission and argument (solely so that we can avoid another database query if this information is already available) """ owner_arg_list = get_owner_arg_list(session, request.permission, request.argument, owners_by_arg_by_perm) if group_ids is None: group_ids = {g.id for g, _ in get_groups_by_user(session, owner)} return bool(group_ids.intersection([o.id for o, arg in owner_arg_list]))
def get_user_view_template_vars(session, actor, user, graph): # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} if user.is_service_account: ret["can_control"] = ( can_manage_service_account(session, user.service_account, actor) or user_is_user_admin(session, actor) ) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = (user.name == actor.name or user_is_user_admin(session, actor)) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests_by_owner(session, actor, status='pending', limit=1, offset=0) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = (get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured") ret["shell"] = shell ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [{'name': g.name, 'type': 'Group', 'role': ge._role} for g, ge in group_edge_list] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) for key in ret["public_keys"]: key.tags = get_public_key_tags(session, key) key.pretty_permissions = ["{} ({})".format(perm.name, perm.argument if perm.argument else "unargumented") for perm in get_public_key_permissions(session, key)] ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get('permissions', []) return ret
def get_requests_by_owner(session, owner, status, limit, offset): """Load pending requests for a particular owner. Args: session(sqlalchemy.orm.session.Session): database session owner(models.User): model of user in question status(models.base.constants.REQUEST_STATUS_CHOICES): if not None, filter by particular status limit(int): how many results to return offset(int): the offset into the result set that should be applied Returns: 2-tuple of (Requests, total) where total is total result size and Requests is the namedtuple with requests and associated comments/changes. """ # get owners groups group_ids = {g.id for g, _ in get_groups_by_user(session, owner)} # get all requests all_requests = session.query(PermissionRequest) if status: all_requests = all_requests.filter(PermissionRequest.status == status) all_requests = all_requests.order_by(PermissionRequest.requested_at.desc()).all() owners_by_arg_by_perm = get_owners_by_grantable_permission(session) requests = [] for request in all_requests: owner_arg_list = get_owner_arg_list(session, request.permission, request.argument, owners_by_arg_by_perm) if group_ids.intersection([o.id for o, arg in owner_arg_list]): requests.append(request) total = len(requests) requests = requests[offset:limit] status_change_by_request_id = defaultdict(list) if not requests: comment_by_status_change_id = {} else: status_changes = session.query(PermissionRequestStatusChange).filter( PermissionRequestStatusChange.request_id.in_([r.id for r in requests]), ).all() for sc in status_changes: status_change_by_request_id[sc.request_id].append(sc) comments = session.query(Comment).filter( Comment.obj_type == OBJ_TYPES_IDX.index("PermissionRequestStatusChange"), Comment.obj_pk.in_([s.id for s in status_changes]), ).all() comment_by_status_change_id = {c.obj_pk: c for c in comments} return Requests(requests, status_change_by_request_id, comment_by_status_change_id), total
def _build_form(self, data): # type: (Optional[int]) -> Tuple[PermissionRequestForm, Dict[Permission, List[str]]] """Build the permission request form given the request and POST data. Normally all fields of the form will be editable. But if the URL locks down a specific value for the group, permission, or argument, then the specified fields will display those values and will be grayed out and not editable. """ session = self.session current_user = self.current_user def pairs(seq): # type: (Iterable[str]) -> List[Tuple[str, str]] return [(item, item) for item in seq] form = PermissionRequestForm(data) group_names = {g.groupname for g, e in get_groups_by_user(session, current_user)} args_by_perm = get_grantable_permissions( session, settings().restricted_ownership_permissions ) permission_names = {p for p in args_by_perm} group_param = self.get_argument("group", None) if group_param is not None: if group_param not in group_names: raise HTTPError( status_code=404, reason="the group name in the URL is not one you belong to" ) form.group_name.choices = pairs([group_param]) form.group_name.render_kw = {"readonly": "readonly"} else: form.group_name.choices = pairs([""] + sorted(group_names)) permission_param = self.get_argument("permission", None) if permission_param is not None: if permission_param not in permission_names: raise HTTPError( status_code=404, reason="an unrecognized permission is specified in the URL" ) form.permission_name.choices = pairs([permission_param]) form.permission_name.render_kw = {"readonly": "readonly"} else: form.permission_name.choices = pairs([""] + sorted(permission_names)) argument_param = self.get_argument("argument", "") if argument_param: form.argument.render_kw = {"readonly": "readonly"} form.argument.data = argument_param return form, args_by_perm
def get_user_view_template_vars(session, actor, user, graph): ret = {} ret["can_control"] = (user.name == actor.name or user_is_user_admin(session, actor)) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate( session, actor).count() _, ret["num_pending_perm_requests"] = get_requests_by_owner( session, actor, status='pending', limit=1, offset=0) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = (get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured") ret["shell"] = shell ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [{ 'name': g.name, 'type': 'Group', 'role': ge._role } for g, ge in group_edge_list] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) for key in ret["public_keys"]: key.tags = get_public_key_tags(session, key) key.pretty_permissions = [ "{} ({})".format( perm.name, perm.argument if perm.argument else "unargumented") for perm in get_public_key_permissions(session, key) ] ret["permissions"] = user_md.get('permissions', []) ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens return ret
def _get_choices(self, group): choices = [] members = group.my_members() if ("User", self.current_user.name) not in members: choices.append(("User: {}".format(self.current_user.name),) * 2) for _group, group_edge in get_groups_by_user(self.session, self.current_user): if group.name == _group.name: # Don't add self. continue if group_edge._role not in APPROVER_ROLE_INDICES: # manager, owner, and np-owner only. continue if ("Group", _group.name) in members: continue choices.append(("Group: {}".format(_group.name),) * 2) return choices
def _get_choices(self, group): choices = [] members = group.my_members() if ("User", self.current_user.name) not in members: choices.append(("User: {}".format(self.current_user.name),) * 2) for _group, group_edge in get_groups_by_user(self.session, self.current_user): if group.name == _group.name: # Don't add self. continue if group_edge._role not in APPROVER_ROLE_INDICIES: # manager, owner, and np-owner only. continue if ("Group", _group.name) in members: continue choices.append(("Group: {}".format(_group.name),) * 2) return choices
def enable_user(session, user, requester, preserve_membership): """Enable a disabled user. Args: preserve_membership(bool): whether to remove user from any groups it may be a member of Returns: None """ if not preserve_membership: for group, group_edge in get_groups_by_user(session, user): group_obj = session.query(Group).filter_by( groupname=group.name ).scalar() if group_obj: group_obj.revoke_member( requester, user, "group membership stripped as part of re-enabling account." ) user.enabled = True Counter.incr(session, "updates")
def enable_user(session, user, requester, preserve_membership): """Enable a disabled user. Args: preserve_membership(bool): whether to remove user from any groups it may be a member of Returns: None """ if not preserve_membership: for group, group_edge in get_groups_by_user(session, user): group_obj = session.query(Group).filter_by( groupname=group.name).scalar() if group_obj: group_obj.revoke_member( requester, user, "group membership stripped as part of re-enabling account." ) user.enabled = True Counter.incr(session, "updates")
def _get_choices(self, group): # type: (Group) -> List[Tuple[str, ...]] # This returns List[Tuple[str, str]], but mypy is confused by the * 2 syntax. choices = [] members = group.my_members() if ("User", self.current_user.name) not in members: choices.append(("User: {}".format(self.current_user.name),) * 2) for _group, group_edge in get_groups_by_user(self.session, self.current_user): if group.name == _group.name: # Don't add self. continue if group_edge._role not in APPROVER_ROLE_INDICES: # manager, owner, and np-owner only. continue if ("Group", _group.name) in members: continue choices.append(("Group: {}".format(_group.name),) * 2) return choices
def _get_choices(self, group): # type: (Group) -> List[Tuple[str, ...]] # This returns List[Tuple[str, str]], but mypy is confused by the * 2 syntax. choices = [] members = group.my_members() if ("User", self.current_user.name) not in members: choices.append(("User: {}".format(self.current_user.name), ) * 2) for _group, group_edge in get_groups_by_user(self.session, self.current_user): if group.name == _group.name: # Don't add self. continue if group_edge._role not in APPROVER_ROLE_INDICES: # manager, owner, and np-owner only. continue if ("Group", _group.name) in members: continue choices.append(("Group: {}".format(_group.name), ) * 2) return choices
def get_user_view_template_vars(session, actor, user, graph): # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} if user.is_service_account: ret["can_control"] = can_manage_service_account( session, user.service_account, actor ) or user_is_user_admin(session, actor) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["can_enable_preserving_membership"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = user.name == actor.name or user_is_user_admin(session, actor) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable_preserving_membership"] = UserEnable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access_without_membership(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests( session, status="pending", limit=1, offset=0, owner=actor ) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = ( get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured" ) ret["shell"] = shell ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [ {"name": g.name, "type": "Group", "role": ge._role} for g, ge in group_edge_list ] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) for key in ret["public_keys"]: key.tags = get_public_key_tags(session, key) key.pretty_permissions = [ "{} ({})".format(perm.name, perm.argument if perm.argument else "unargumented") for perm in get_public_key_permissions(session, key) ] ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get("permissions", []) return ret
def get_requests( session: Session, status: str, limit: int, offset: int, owner: Optional[User] = None, requester: Optional[User] = None, owners_by_arg_by_perm: Optional[Dict[object, Dict[str, List[Group]]]] = None, ) -> Tuple[Requests, int]: """Load requests using the given filters. Args: session: Database session status: If not None, filter by particular status limit: how many results to return offset: the offset into the result set that should be applied owner: If not None, filter by requests that the owner can action requester: If not None, filter by requests that the requester made owners_by_arg_by_perm: List of groups that can grant a given permission, argument pair in the format of {perm_name: {argument: [group1, group2, ...], ...}, ...} This is for convenience/caching if the value has already been fetched. Returns: 2-tuple of (Requests, total) where total is total result size and Requests is the data transfer object with requests and associated comments/changes. """ # get all requests all_requests = session.query(PermissionRequest) if status: all_requests = all_requests.filter(PermissionRequest.status == status) if requester: all_requests = all_requests.filter( PermissionRequest.requester_id == requester.id) all_requests = all_requests.order_by( PermissionRequest.requested_at.desc()).all() if owners_by_arg_by_perm is None: owners_by_arg_by_perm = get_owners_by_grantable_permission(session) if owner: group_ids = {g.id for g, _ in get_groups_by_user(session, owner)} requests = [ request for request in all_requests if can_approve_request( session, request, owner, group_ids=group_ids, owners_by_arg_by_perm=owners_by_arg_by_perm, ) ] else: requests = all_requests total = len(requests) requests = requests[offset:limit] status_change_by_request_id: Dict[ int, List[PermissionRequestStatusChange]] = defaultdict(list) if not requests: comment_by_status_change_id: Dict[int, Comment] = {} else: status_changes = (session.query(PermissionRequestStatusChange).filter( PermissionRequestStatusChange.request_id.in_( [r.id for r in requests])).all()) for sc in status_changes: status_change_by_request_id[sc.request_id].append(sc) comments = (session.query(Comment).filter( Comment.obj_type == OBJ_TYPES_IDX.index( "PermissionRequestStatusChange"), Comment.obj_pk.in_([s.id for s in status_changes]), ).all()) comment_by_status_change_id = {c.obj_pk: c for c in comments} return (Requests(requests, status_change_by_request_id, comment_by_status_change_id), total)
def get_user_view_template_vars(session, actor, user, graph): # type: (Session, User, User, GroupGraph) -> Dict[str, Any] # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} # type: Dict[str, Any] if user.is_service_account: ret["can_control"] = can_manage_service_account( session, user.service_account, actor ) or user_is_user_admin(session, actor) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["can_enable_preserving_membership"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = user.name == actor.name or user_is_user_admin(session, actor) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable_preserving_membership"] = UserEnable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access_without_membership(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests( session, status="pending", limit=1, offset=0, owner=actor ) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = ( get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured" ) ret["shell"] = shell github_username = get_user_metadata_by_key(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY) ret["github_username"] = github_username.data_value if github_username else "(Unset)" ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [ {"name": g.name, "type": "Group", "role": ge._role} for g, ge in group_edge_list ] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp(permission["granted_on"]) return ret
def get_requests( session, status, limit, offset, owner=None, requester=None, owners_by_arg_by_perm=None ): """Load requests using the given filters. Args: session(sqlalchemy.orm.session.Session): database session status(models.base.constants.REQUEST_STATUS_CHOICES): if not None, filter by particular status limit(int): how many results to return offset(int): the offset into the result set that should be applied owner(models.User): if not None, filter by requests that the owner can action requester(models.User): if not None, filter by requests that the requester made owners_by_arg_by_perm(Dict): list of groups that can grant a given permission, argument pair in the format of {perm_name: {argument: [group1, group2, ...], ...}, ...} This is for convenience/caching if the value has already been fetched. Returns: 2-tuple of (Requests, total) where total is total result size and Requests is the namedtuple with requests and associated comments/changes. """ # get all requests all_requests = session.query(PermissionRequest) if status: all_requests = all_requests.filter(PermissionRequest.status == status) if requester: all_requests = all_requests.filter(PermissionRequest.requester_id == requester.id) all_requests = all_requests.order_by(PermissionRequest.requested_at.desc()).all() if owners_by_arg_by_perm is None: owners_by_arg_by_perm = get_owners_by_grantable_permission(session) if owner: group_ids = {g.id for g, _ in get_groups_by_user(session, owner)} requests = [ request for request in all_requests if can_approve_request( session, request, owner, group_ids=group_ids, owners_by_arg_by_perm=owners_by_arg_by_perm, ) ] else: requests = all_requests total = len(requests) requests = requests[offset:limit] status_change_by_request_id = defaultdict(list) if not requests: comment_by_status_change_id = {} else: status_changes = ( session.query(PermissionRequestStatusChange) .filter(PermissionRequestStatusChange.request_id.in_([r.id for r in requests])) .all() ) for sc in status_changes: status_change_by_request_id[sc.request_id].append(sc) comments = ( session.query(Comment) .filter( Comment.obj_type == OBJ_TYPES_IDX.index("PermissionRequestStatusChange"), Comment.obj_pk.in_([s.id for s in status_changes]), ) .all() ) comment_by_status_change_id = {c.obj_pk: c for c in comments} return (Requests(requests, status_change_by_request_id, comment_by_status_change_id), total)