Skip to content

Commit e11c855

Browse files
committed
Deduplicate some code
1 parent f3ffd0a commit e11c855

File tree

3 files changed

+64
-27
lines changed

3 files changed

+64
-27
lines changed

Diff for: h/security/identity.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from dataclasses import dataclass, field
44
from typing import List, Optional, Self
55

6-
from h.models import AuthClient, Group, User
6+
from h.models import AuthClient, Group, GroupMembershipRoles, User
77

88

99
@dataclass
@@ -126,3 +126,14 @@ def authenticated_userid(identity: Self | None) -> str | None:
126126
return identity.user.userid
127127

128128
return None
129+
130+
def get_roles(self, group) -> list[GroupMembershipRoles]:
131+
"""Return this identity's roles in `group`."""
132+
if self.user is None:
133+
return []
134+
135+
for membership in self.user.memberships:
136+
if membership.group.id == group.id:
137+
return membership.roles
138+
139+
return []

Diff for: h/security/predicates.py

+9-26
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,9 @@ def group_matches_authenticated_client_authority(identity, context):
180180

181181
@requires(authenticated_user, group_found)
182182
def group_member_remove(identity, context: GroupMembershipContext):
183-
def get_authenticated_users_membership():
184-
"""Return the authenticated user's membership of the target group."""
185-
for membership in identity.user.memberships:
186-
if membership.group.id == context.group.id:
187-
return membership
183+
authenticated_users_roles = identity.get_roles(context.group)
188184

189-
return None
190-
191-
authenticated_users_membership = get_authenticated_users_membership()
192-
193-
if not authenticated_users_membership:
185+
if not authenticated_users_roles:
194186
# You can't remove anyone from a group you're not a member of.
195187
return False
196188

@@ -200,43 +192,34 @@ def get_authenticated_users_membership():
200192

201193
if "owner" in context.membership.roles or "admin" in context.membership.roles:
202194
# Only owners can remove admins or other owners.
203-
return "owner" in authenticated_users_membership.roles
195+
return "owner" in authenticated_users_roles
204196

205197
if "moderator" in context.membership.roles:
206198
# Owners and admins can remove moderators.
207199
return (
208-
"owner" in authenticated_users_membership.roles
209-
or "admin" in authenticated_users_membership.roles
200+
"owner" in authenticated_users_roles or "admin" in authenticated_users_roles
210201
)
211202

212203
# Owners, admins and moderators can remove plain members.
213204
return (
214-
"owner" in authenticated_users_membership.roles
215-
or "admin" in authenticated_users_membership.roles
216-
or "moderator" in authenticated_users_membership.roles
205+
"owner" in authenticated_users_roles
206+
or "admin" in authenticated_users_roles
207+
or "moderator" in authenticated_users_roles
217208
)
218209

219210

220211
@requires(authenticated_user, group_found)
221212
def group_member_edit(
222213
identity, context: EditGroupMembershipContext
223-
): # pylint:disable=too-many-return-statements,too-complex
214+
): # pylint:disable=too-many-return-statements
224215
assert (
225216
context.new_roles is not None
226217
), "new_roles must be set before checking permissions"
227218

228219
old_roles = context.membership.roles
229220
new_roles = context.new_roles
230221

231-
def get_authenticated_users_roles():
232-
"""Return the authenticated users roles in the target group."""
233-
for membership in identity.user.memberships:
234-
if membership.group.id == context.group.id:
235-
return membership.roles
236-
237-
return None
238-
239-
authenticated_users_roles = get_authenticated_users_roles()
222+
authenticated_users_roles = identity.get_roles(context.group)
240223

241224
if not authenticated_users_roles:
242225
return False

Diff for: tests/unit/h/security/identity_test.py

+43
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,46 @@ def LongLivedUser(self, patch):
136136
@pytest.fixture(autouse=True)
137137
def LongLivedAuthClient(self, patch):
138138
return patch("h.security.identity.LongLivedAuthClient")
139+
140+
141+
class TestGetRoles:
142+
def test_it(self, identity, group):
143+
identity.user.memberships.append(
144+
LongLivedMembership(
145+
user=identity.user, group=group, roles=[GroupMembershipRoles.MODERATOR]
146+
),
147+
)
148+
149+
assert identity.get_roles(group) == [GroupMembershipRoles.MODERATOR]
150+
151+
def test_when_no_membership(self, identity, group):
152+
assert identity.get_roles(group) == []
153+
154+
def test_when_no_user(self, identity, group):
155+
identity.user = None
156+
157+
assert identity.get_roles(group) == []
158+
159+
@pytest.fixture
160+
def identity(self):
161+
identity = Identity(
162+
user=LongLivedUser(
163+
id=sentinel.id,
164+
userid=sentinel.userid,
165+
authority=sentinel.authority,
166+
staff=sentinel.staff,
167+
admin=sentinel.admin,
168+
)
169+
)
170+
identity.user.memberships = [
171+
LongLivedMembership(
172+
user=identity.user,
173+
group=LongLivedGroup(id=24, pubid="other"),
174+
roles=[GroupMembershipRoles.MEMBER],
175+
)
176+
]
177+
return identity
178+
179+
@pytest.fixture
180+
def group(self):
181+
return LongLivedGroup(id=42, pubid="pubid")

0 commit comments

Comments
 (0)