Skip to content

Commit 2d5d0e4

Browse files
committed
use user id for setting the allowlist instead of memberid
1 parent 3b98ee9 commit 2d5d0e4

File tree

4 files changed

+48
-44
lines changed

4 files changed

+48
-44
lines changed

src/sentry/api/serializers/models/organization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ def serialize( # type: ignore[override]
767767
context["replayAccessMembers"] = list(
768768
OrganizationMemberReplayAccess.objects.filter(
769769
organizationmember__organization=obj
770-
).values_list("organizationmember_id", flat=True)
770+
).values_list("organizationmember__user_id", flat=True)
771771
)
772772

773773
if has_custom_dynamic_sampling(obj, actor=user):

src/sentry/core/endpoints/organization_details.py

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ class OrganizationSerializer(BaseOrganizationSerializer):
377377
child=serializers.IntegerField(),
378378
required=False,
379379
allow_null=True,
380-
help_text="List of organization member IDs that have access to replay data. Only modifiable by owners and managers.",
380+
help_text="List of user IDs that have access to replay data. Only modifiable by owners and managers.",
381381
)
382382

383383
def _has_sso_enabled(self):
@@ -628,53 +628,57 @@ def save(self, **kwargs):
628628
changed_data["hasGranularReplayPermissions"] = f"to {new_value}"
629629

630630
if "replayAccessMembers" in data:
631-
member_ids = data["replayAccessMembers"]
632-
if member_ids is None:
633-
member_ids = []
634-
current_member_ids = set(
631+
user_ids = data["replayAccessMembers"]
632+
if user_ids is None:
633+
user_ids = []
634+
635+
current_user_ids = set(
635636
OrganizationMemberReplayAccess.objects.filter(
636637
organizationmember__organization=org
637-
).values_list("organizationmember_id", flat=True)
638+
).values_list("organizationmember__user_id", flat=True)
638639
)
639-
new_member_ids = set(member_ids)
640+
new_user_ids = set(user_ids)
641+
642+
to_add = new_user_ids - current_user_ids
643+
to_remove = current_user_ids - new_user_ids
640644

641-
to_add = new_member_ids - current_member_ids
642-
to_remove = current_member_ids - new_member_ids
643645
if to_add:
644-
valid_member_ids = set(
645-
OrganizationMember.objects.filter(organization=org, id__in=to_add).values_list(
646-
"id", flat=True
647-
)
646+
user_to_member = dict(
647+
OrganizationMember.objects.filter(
648+
organization=org, user_id__in=to_add
649+
).values_list("user_id", "id")
648650
)
649-
invalid_member_ids = to_add - valid_member_ids
650-
if invalid_member_ids:
651+
invalid_user_ids = to_add - set(user_to_member.keys())
652+
if invalid_user_ids:
651653
raise serializers.ValidationError(
652654
{
653-
"replayAccessMembers": f"Invalid organization member IDs: {sorted(invalid_member_ids)}"
655+
"replayAccessMembers": f"Invalid user IDs (not members of this organization): {sorted(invalid_user_ids)}"
654656
}
655657
)
656658

657659
OrganizationMemberReplayAccess.objects.bulk_create(
658660
[
659-
OrganizationMemberReplayAccess(organizationmember_id=member_id)
660-
for member_id in to_add
661+
OrganizationMemberReplayAccess(
662+
organizationmember_id=user_to_member[user_id]
663+
)
664+
for user_id in to_add
661665
],
662666
ignore_conflicts=True,
663667
)
664668

665669
if to_remove:
666670
OrganizationMemberReplayAccess.objects.filter(
667-
organizationmember__organization=org, organizationmember_id__in=to_remove
671+
organizationmember__organization=org, organizationmember__user_id__in=to_remove
668672
).delete()
669673

670674
if to_add or to_remove:
671675
changes = []
672676
if to_add:
673-
changes.append(f"added {len(to_add)} member(s)")
677+
changes.append(f"added {len(to_add)} user(s)")
674678
if to_remove:
675-
changes.append(f"removed {len(to_remove)} member(s)")
679+
changes.append(f"removed {len(to_remove)} user(s)")
676680
changed_data["replayAccessMembers"] = (
677-
f"{' and '.join(changes)} (total: {len(new_member_ids)} member(s) with access)"
681+
f"{' and '.join(changes)} (total: {len(new_user_ids)} user(s) with access)"
678682
)
679683

680684
if "openMembership" in data:
@@ -903,7 +907,7 @@ class OrganizationDetailsPutSerializer(serializers.Serializer):
903907
)
904908
replayAccessMembers = serializers.ListField(
905909
child=serializers.IntegerField(),
906-
help_text="A list of organization member IDs who have permission to access replay data. Requires the hasGranularReplayPermissions flag to be true to be enforced.",
910+
help_text="A list of user IDs who have permission to access replay data. Requires the hasGranularReplayPermissions flag to be true to be enforced.",
907911
required=False,
908912
allow_null=True,
909913
)

tests/sentry/api/serializers/test_organization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def test_replay_access_members_serialized(self) -> None:
212212
serializer = DetailedOrganizationSerializer()
213213
result = serialize(organization, user, serializer, access=acc)
214214

215-
assert set(result["replayAccessMembers"]) == {member1.id, member2.id}
215+
assert set(result["replayAccessMembers"]) == {member1.user_id, member2.user_id}
216216

217217
def test_replay_access_members_empty_when_none_set(self) -> None:
218218
user = self.create_user()

tests/sentry/core/endpoints/test_organization_details.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,7 +1542,7 @@ def test_replay_access_members_add(self) -> None:
15421542
with assume_test_silo_mode_of(AuditLogEntry):
15431543
AuditLogEntry.objects.filter(organization_id=self.organization.id).delete()
15441544

1545-
data = {"replayAccessMembers": [member1.id, member2.id]}
1545+
data = {"replayAccessMembers": [member1.user_id, member2.user_id]}
15461546
with outbox_runner():
15471547
self.get_success_response(self.organization.slug, **data)
15481548

@@ -1555,8 +1555,8 @@ def test_replay_access_members_add(self) -> None:
15551555

15561556
with assume_test_silo_mode_of(AuditLogEntry):
15571557
log = AuditLogEntry.objects.get(organization_id=self.organization.id)
1558-
assert "added 2 member(s)" in log.data["replayAccessMembers"]
1559-
assert "total: 2 member(s)" in log.data["replayAccessMembers"]
1558+
assert "added 2 user(s)" in log.data["replayAccessMembers"]
1559+
assert "total: 2 user(s)" in log.data["replayAccessMembers"]
15601560

15611561
@with_feature("organizations:granular-replay-permissions")
15621562
def test_replay_access_members_remove(self) -> None:
@@ -1571,7 +1571,7 @@ def test_replay_access_members_remove(self) -> None:
15711571
with assume_test_silo_mode_of(AuditLogEntry):
15721572
AuditLogEntry.objects.filter(organization_id=self.organization.id).delete()
15731573

1574-
data = {"replayAccessMembers": [member1.id]}
1574+
data = {"replayAccessMembers": [member1.user_id]}
15751575
with outbox_runner():
15761576
self.get_success_response(self.organization.slug, **data)
15771577

@@ -1584,8 +1584,8 @@ def test_replay_access_members_remove(self) -> None:
15841584

15851585
with assume_test_silo_mode_of(AuditLogEntry):
15861586
log = AuditLogEntry.objects.get(organization_id=self.organization.id)
1587-
assert "removed 1 member(s)" in log.data["replayAccessMembers"]
1588-
assert "total: 1 member(s)" in log.data["replayAccessMembers"]
1587+
assert "removed 1 user(s)" in log.data["replayAccessMembers"]
1588+
assert "total: 1 user(s)" in log.data["replayAccessMembers"]
15891589

15901590
@with_feature("organizations:granular-replay-permissions")
15911591
def test_replay_access_members_add_and_remove(self) -> None:
@@ -1602,7 +1602,7 @@ def test_replay_access_members_add_and_remove(self) -> None:
16021602
with assume_test_silo_mode_of(AuditLogEntry):
16031603
AuditLogEntry.objects.filter(organization_id=self.organization.id).delete()
16041604

1605-
data = {"replayAccessMembers": [member2.id, member3.id]}
1605+
data = {"replayAccessMembers": [member2.user_id, member3.user_id]}
16061606
with outbox_runner():
16071607
self.get_success_response(self.organization.slug, **data)
16081608

@@ -1615,9 +1615,9 @@ def test_replay_access_members_add_and_remove(self) -> None:
16151615

16161616
with assume_test_silo_mode_of(AuditLogEntry):
16171617
log = AuditLogEntry.objects.get(organization_id=self.organization.id)
1618-
assert "added 2 member(s)" in log.data["replayAccessMembers"]
1619-
assert "removed 1 member(s)" in log.data["replayAccessMembers"]
1620-
assert "total: 2 member(s)" in log.data["replayAccessMembers"]
1618+
assert "added 2 user(s)" in log.data["replayAccessMembers"]
1619+
assert "removed 1 user(s)" in log.data["replayAccessMembers"]
1620+
assert "total: 2 user(s)" in log.data["replayAccessMembers"]
16211621

16221622
@with_feature("organizations:granular-replay-permissions")
16231623
def test_replay_access_members_clear_all(self) -> None:
@@ -1639,14 +1639,14 @@ def test_replay_access_members_clear_all(self) -> None:
16391639

16401640
with assume_test_silo_mode_of(AuditLogEntry):
16411641
log = AuditLogEntry.objects.get(organization_id=self.organization.id)
1642-
assert "removed 1 member(s)" in log.data["replayAccessMembers"]
1643-
assert "total: 0 member(s)" in log.data["replayAccessMembers"]
1642+
assert "removed 1 user(s)" in log.data["replayAccessMembers"]
1643+
assert "total: 0 user(s)" in log.data["replayAccessMembers"]
16441644

16451645
def test_replay_access_members_requires_feature(self) -> None:
16461646
member1 = self.create_member(
16471647
organization=self.organization, user=self.create_user(), role="member"
16481648
)
1649-
data = {"replayAccessMembers": [member1.id]}
1649+
data = {"replayAccessMembers": [member1.user_id]}
16501650
self.get_error_response(self.organization.slug, **data, status_code=404)
16511651

16521652
@with_feature("organizations:granular-replay-permissions")
@@ -1660,11 +1660,11 @@ def test_replay_access_members_requires_admin_scope(self) -> None:
16601660
other_member = self.create_member(
16611661
organization=self.organization, user=self.create_user(), role="member"
16621662
)
1663-
data = {"replayAccessMembers": [other_member.id]}
1663+
data = {"replayAccessMembers": [other_member.user_id]}
16641664
self.get_error_response(self.organization.slug, **data, status_code=403)
16651665

16661666
@with_feature("organizations:granular-replay-permissions")
1667-
def test_replay_access_members_invalid_member_ids(self) -> None:
1667+
def test_replay_access_members_invalid_user_ids(self) -> None:
16681668
nonexistent_id = 999999999
16691669
data = {"replayAccessMembers": [nonexistent_id]}
16701670
response = self.get_error_response(self.organization.slug, **data, status_code=400)
@@ -1677,22 +1677,22 @@ def test_replay_access_members_from_other_organization(self) -> None:
16771677
other_org_member = self.create_member(
16781678
organization=other_org, user=self.create_user(), role="member"
16791679
)
1680-
data = {"replayAccessMembers": [other_org_member.id]}
1680+
data = {"replayAccessMembers": [other_org_member.user_id]}
16811681
response = self.get_error_response(self.organization.slug, **data, status_code=400)
16821682
assert "replayAccessMembers" in response.data
1683-
assert str(other_org_member.id) in response.data["replayAccessMembers"]
1683+
assert str(other_org_member.user_id) in response.data["replayAccessMembers"]
16841684

16851685
@with_feature("organizations:granular-replay-permissions")
16861686
def test_replay_access_members_mixed_valid_and_invalid(self) -> None:
16871687
valid_member = self.create_member(
16881688
organization=self.organization, user=self.create_user(), role="member"
16891689
)
16901690
nonexistent_id = 999999999
1691-
data = {"replayAccessMembers": [valid_member.id, nonexistent_id]}
1691+
data = {"replayAccessMembers": [valid_member.user_id, nonexistent_id]}
16921692
response = self.get_error_response(self.organization.slug, **data, status_code=400)
16931693
assert "replayAccessMembers" in response.data
16941694
assert str(nonexistent_id) in response.data["replayAccessMembers"]
1695-
assert str(valid_member.id) not in response.data["replayAccessMembers"]
1695+
assert str(valid_member.user_id) not in response.data["replayAccessMembers"]
16961696

16971697
access_count = OrganizationMemberReplayAccess.objects.filter(
16981698
organizationmember__organization=self.organization

0 commit comments

Comments
 (0)