Skip to content

Commit 666ebb9

Browse files
committed
squash!: Fix quality
1 parent f91dc12 commit 666ebb9

8 files changed

Lines changed: 61 additions & 38 deletions

File tree

openedx_authz/api/roles.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ def get_all_subject_role_assignments() -> list[RoleAssignmentData]:
294294
)
295295
return role_assignments
296296

297+
297298
def get_subject_role_assignments(subject: SubjectData) -> list[RoleAssignmentData]:
298299
"""Get all the roles for a subject across all scopes.
299300

openedx_authz/api/users.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def batch_unassign_role_from_users(users: list[str], role_external_key: str, sco
119119
ScopeData(external_key=scope_external_key),
120120
)
121121

122+
122123
def get_all_user_role_assignments() -> list[RoleAssignmentData]:
123124
"""Get all roles for all users across all scopes.
124125
@@ -127,6 +128,7 @@ def get_all_user_role_assignments() -> list[RoleAssignmentData]:
127128
"""
128129
return get_all_subject_role_assignments()
129130

131+
130132
def get_user_role_assignments(user_external_key: str) -> list[RoleAssignmentData]:
131133
"""Get all roles for a user across all scopes.
132134

openedx_authz/engine/matcher.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,24 @@
33
from django.contrib.auth import get_user_model
44
from edx_django_utils.cache import RequestCache
55

6-
from openedx_authz.api.data import ContentLibraryData, CourseOverviewData, ScopeData, UserData
7-
from openedx_authz.rest_api.utils import get_user_by_username_or_email
6+
from openedx_authz.api.data import (
7+
ContentLibraryData,
8+
CourseOverviewData,
9+
OrgContentLibraryGlobData,
10+
OrgCourseOverviewGlobData,
11+
ScopeData,
12+
UserData,
13+
)
14+
from openedx_authz.utils import get_user_by_username_or_email
815

916
User = get_user_model()
1017

1118

1219
SCOPES_WITH_ADMIN_OR_SUPERUSER_CHECK = {
1320
(ContentLibraryData.NAMESPACE, ContentLibraryData),
1421
(CourseOverviewData.NAMESPACE, CourseOverviewData),
22+
(OrgContentLibraryGlobData.NAMESPACE, OrgContentLibraryGlobData),
23+
(OrgCourseOverviewGlobData.NAMESPACE, OrgCourseOverviewGlobData),
1524
}
1625

1726

openedx_authz/rest_api/utils.py

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
"""Utility functions for the Open edX AuthZ REST API."""
22

3-
from dataclasses import dataclass
43
import logging
4+
from dataclasses import dataclass
55

66
from django.contrib.auth import get_user_model
7-
from django.db.models import Q
87

98
from openedx_authz.api.data import (
109
GLOBAL_SCOPE_WILDCARD,
@@ -66,26 +65,6 @@ def get_user_map(usernames: list[str]) -> dict[str, User]:
6665
return {user.username: user for user in users}
6766

6867

69-
def get_user_by_username_or_email(username_or_email: str) -> User:
70-
"""
71-
Retrieve a user by their username or email address.
72-
73-
Args:
74-
username_or_email (str): The username or email address to search for.
75-
76-
Returns:
77-
User: The User object if found and not retired.
78-
79-
Raises:
80-
User.DoesNotExist: If no user matches the provided username or email,
81-
or if the user has an associated retirement request.
82-
"""
83-
user = User.objects.get(Q(email=username_or_email) | Q(username=username_or_email))
84-
if hasattr(user, "userretirementrequest"):
85-
raise User.DoesNotExist
86-
return user
87-
88-
8968
def sort_users(
9069
users: list[dict],
9170
sort_by: SortField = SortField.USERNAME,
@@ -174,9 +153,7 @@ def get_user_assignment_map(role_assignments: list[RoleAssignmentData]) -> list[
174153
return users_with_assignments
175154

176155

177-
def filter_allowed_assignments(
178-
user: "User", assignments: list[RoleAssignmentData]
179-
) -> list[RoleAssignmentData]:
156+
def filter_allowed_assignments(user: "User", assignments: list[RoleAssignmentData]) -> list[RoleAssignmentData]:
180157
"""
181158
Filter the given role assignments to only include those that the user has permission to view.
182159
"""
@@ -193,7 +170,7 @@ def filter_allowed_assignments(
193170
if permission and is_user_allowed(
194171
user_external_key=user.username,
195172
action_external_key=permission,
196-
scope_external_key=assignment.scope.external_key
173+
scope_external_key=assignment.scope.external_key,
197174
):
198175
allowed_assignments.append(assignment)
199176

openedx_authz/rest_api/v1/fields.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ def to_internal_value(self, data):
1313
def to_representation(self, value):
1414
"""Convert list to string separated by commas"""
1515
return ",".join(value).lower()
16-
16+
17+
1718
class CaseSensitiveCommaSeparatedListField(serializers.CharField):
1819
"""Serializer for a comma-separated list of strings, case-sensitive."""
1920

openedx_authz/rest_api/v1/serializers.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
from openedx_authz import api
77
from openedx_authz.rest_api.data import SortField, SortOrder
88
from openedx_authz.rest_api.utils import UserAssignments, get_generic_scope
9-
from openedx_authz.rest_api.v1.fields import CaseSensitiveCommaSeparatedListField, CommaSeparatedListField, LowercaseCharField
9+
from openedx_authz.rest_api.v1.fields import (
10+
CaseSensitiveCommaSeparatedListField,
11+
CommaSeparatedListField,
12+
LowercaseCharField,
13+
)
1014

1115
User = get_user_model()
1216

@@ -204,6 +208,7 @@ def get_roles(self, obj: api.RoleAssignmentData) -> list[str]:
204208
"""Get the roles for the given role assignment."""
205209
return [role.external_key for role in obj.roles]
206210

211+
207212
class ListTeamMembersSerializer(serializers.Serializer): # pylint: disable=abstract-method
208213
"""Serializer for listing team members."""
209214

@@ -221,6 +226,7 @@ class ListTeamMembersSerializer(serializers.Serializer): # pylint: disable=abst
221226
)
222227
search = LowercaseCharField(required=False, default=None)
223228

229+
224230
class TeamMemberSerializer(serializers.Serializer): # pylint: disable=abstract-method
225231
"""Serializer for team members."""
226232

openedx_authz/rest_api/v1/views.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
filter_users,
2525
get_generic_scope,
2626
get_user_assignment_map,
27-
get_user_by_username_or_email,
2827
get_user_map,
2928
sort_users,
3029
)
@@ -42,6 +41,7 @@
4241
TeamMemberSerializer,
4342
UserRoleAssignmentSerializer,
4443
)
44+
from openedx_authz.utils import get_user_by_username_or_email
4545

4646
logger = logging.getLogger(__name__)
4747

@@ -463,7 +463,7 @@ class TeamMembersAPIView(APIView):
463463
"""
464464

465465
pagination_class = AuthZAPIViewPagination
466-
permission_classes = [DynamicScopePermission] # TODO check if this is needed/works
466+
permission_classes = [DynamicScopePermission] # TODO check if this is needed/works
467467

468468
@apidocs.schema(
469469
parameters=[
@@ -489,23 +489,24 @@ def get(self, request: HttpRequest) -> Response:
489489
query_params = serializer.validated_data
490490

491491
user_role_assignments = api.get_all_user_role_assignments()
492+
# Filter assignments based on the user's permissions
492493
user_role_assignments = filter_allowed_assignments(user=request.user, assignments=user_role_assignments)
493494
# Group assignments by user
494495
users_with_assignments = get_user_assignment_map(user_role_assignments)
495496

496-
scopes = query_params.get('scopes')
497-
orgs = query_params.get('orgs')
498-
search = query_params.get('search')
499-
order = query_params.get('order')
500-
sort_by = query_params.get('sort_by', SortField.USERNAME)
497+
scopes = query_params.get("scopes")
498+
orgs = query_params.get("orgs")
499+
search = query_params.get("search")
500+
order = query_params.get("order")
501+
sort_by = query_params.get("sort_by", SortField.USERNAME)
501502

502503
if scopes:
503504
# Filter by scopes
504505
filtered_users: list[UserAssignments] = []
505506
for uwa in users_with_assignments:
506507
if any(a.scope.external_key in scopes for a in uwa.assignments):
507508
# Also filter assignments to reflect the correct number of assignments
508-
filtered_assignments = [a for a in uwa.assignments if a.scope.external_key in scopes]
509+
filtered_assignments = [a for a in uwa.assignments if a.scope.external_key in scopes]
509510
filtered_users.append(UserAssignments(user=uwa.user, assignments=filtered_assignments))
510511
users_with_assignments = filtered_users
511512

openedx_authz/utils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""General utility functions for Open edX AuthZ."""
2+
3+
from django.contrib.auth import get_user_model
4+
from django.db.models import Q
5+
6+
User = get_user_model()
7+
8+
9+
def get_user_by_username_or_email(username_or_email: str) -> User:
10+
"""
11+
Retrieve a user by their username or email address.
12+
13+
Args:
14+
username_or_email (str): The username or email address to search for.
15+
16+
Returns:
17+
User: The User object if found and not retired.
18+
19+
Raises:
20+
User.DoesNotExist: If no user matches the provided username or email,
21+
or if the user has an associated retirement request.
22+
"""
23+
user = User.objects.get(Q(email=username_or_email) | Q(username=username_or_email))
24+
if hasattr(user, "userretirementrequest"):
25+
raise User.DoesNotExist
26+
return user

0 commit comments

Comments
 (0)