forked from openedx/openedx-authz
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
129 lines (100 loc) · 4.17 KB
/
utils.py
File metadata and controls
129 lines (100 loc) · 4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""Utility functions for the Open edX AuthZ REST API."""
from openedx_authz.api.data import (
GLOBAL_SCOPE_WILDCARD,
ScopeData,
)
from openedx_authz.rest_api.data import AssignmentSortField, SearchField, SortField, SortOrder
def get_generic_scope(scope: ScopeData) -> ScopeData:
"""
Create a generic scope from a given scope by replacing its key with a wildcard.
This function preserves the namespace of the original scope but replaces the specific
key with a wildcard, allowing for broader permission checks across all scopes within
the same namespace.
Args:
scope (ScopeData): The specific scope to generalize.
Returns:
ScopeData: A new scope with the same namespace but a wildcard key.
Examples:
>>> scope = ScopeData(namespaced_key="lib^lib:DemoX:CSPROB")
>>> get_generic_scope(scope)
ScopeData(namespaced_key="lib^*")
"""
return ScopeData(namespaced_key=f"{scope.NAMESPACE}{ScopeData.SEPARATOR}{GLOBAL_SCOPE_WILDCARD}")
def sort_users(
users: list[dict],
sort_by: SortField = SortField.USERNAME,
order: SortOrder = SortOrder.ASC,
) -> list[dict]:
"""
Sort users by a given field and order.
Args:
users (list[dict]): The users to sort.
sort_by (SortField, optional): The field to sort by. Defaults to SortField.USERNAME.
order (SortOrder, optional): The order to sort by. Defaults to SortOrder.ASC.
Raises:
ValueError: If the sort field is invalid.
ValueError: If the sort order is invalid.
Returns:
list[dict]: The sorted users.
"""
if sort_by not in SortField.values():
raise ValueError(f"Invalid field: '{sort_by}'. Must be one of {SortField.values()}")
if order not in SortOrder.values():
raise ValueError(f"Invalid order: '{order}'. Must be one of {SortOrder.values()}")
sorted_users = sorted(
users,
key=lambda user: (user.get(sort_by) or "").lower(),
reverse=order == SortOrder.DESC,
)
return sorted_users
def filter_users(users: list[dict], search: str | None, roles: list[str] | None) -> list[dict]:
"""
Filter users by a case-insensitive search string and/or by roles.
Args:
users (list[dict]): The users to filter.
search (str | None): Optional search term matched against fields in ``SearchField``.
roles (list[str] | None): Optional list of roles; include users that have any of these roles.
Returns:
list[dict]: The filtered users, preserving the original order.
"""
if not search and not roles:
return users
filtered_users = []
for user in users:
if search:
matches_search = any(search in (user.get(field) or "").lower() for field in SearchField.values())
if not matches_search:
continue
if roles:
matches_role = any(role in user.get("roles", []) for role in roles)
if not matches_role:
continue
filtered_users.append(user)
return filtered_users
def sort_assignments(
assignments: list[dict],
sort_by: AssignmentSortField = AssignmentSortField.ROLE,
order: SortOrder = SortOrder.ASC,
) -> list[dict]:
"""
Sort role assignments by a given field and order.
Args:
assignments (list[dict]): The assignments to sort.
sort_by (AssignmentSortField, optional): The field to sort by. Defaults to AssignmentSortField.ROLE.
order (SortOrder, optional): The order to sort by. Defaults to SortOrder.ASC.
Raises:
ValueError: If the sort field is invalid.
ValueError: If the sort order is invalid.
Returns:
list[dict]: The sorted assignments.
"""
if sort_by not in AssignmentSortField.values():
raise ValueError(f"Invalid field: '{sort_by}'. Must be one of {AssignmentSortField.values()}")
if order not in SortOrder.values():
raise ValueError(f"Invalid order: '{order}'. Must be one of {SortOrder.values()}")
sorted_assignments = sorted(
assignments,
key=lambda assignment: (assignment.get(sort_by) or "").lower(),
reverse=order == SortOrder.DESC,
)
return sorted_assignments