Skip to content

Commit d41bc9d

Browse files
committed
use user id for setting the allowlist instead of memberid
1 parent 1751ff4 commit d41bc9d

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
@@ -743,7 +743,7 @@ def serialize( # type: ignore[override]
743743
context["replayAccessMembers"] = list(
744744
OrganizationMemberReplayAccess.objects.filter(
745745
organizationmember__organization=obj
746-
).values_list("organizationmember_id", flat=True)
746+
).values_list("organizationmember__user_id", flat=True)
747747
)
748748

749749
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
@@ -346,7 +346,7 @@ class OrganizationSerializer(BaseOrganizationSerializer):
346346
child=serializers.IntegerField(),
347347
required=False,
348348
allow_null=True,
349-
help_text="List of organization member IDs that have access to replay data. Only modifiable by owners and managers.",
349+
help_text="List of user IDs that have access to replay data. Only modifiable by owners and managers.",
350350
)
351351

352352
def _has_sso_enabled(self):
@@ -597,53 +597,57 @@ def save(self, **kwargs):
597597
changed_data["hasGranularReplayPermissions"] = f"to {new_value}"
598598

599599
if "replayAccessMembers" in data:
600-
member_ids = data["replayAccessMembers"]
601-
if member_ids is None:
602-
member_ids = []
603-
current_member_ids = set(
600+
user_ids = data["replayAccessMembers"]
601+
if user_ids is None:
602+
user_ids = []
603+
604+
current_user_ids = set(
604605
OrganizationMemberReplayAccess.objects.filter(
605606
organizationmember__organization=org
606-
).values_list("organizationmember_id", flat=True)
607+
).values_list("organizationmember__user_id", flat=True)
607608
)
608-
new_member_ids = set(member_ids)
609+
new_user_ids = set(user_ids)
610+
611+
to_add = new_user_ids - current_user_ids
612+
to_remove = current_user_ids - new_user_ids
609613

610-
to_add = new_member_ids - current_member_ids
611-
to_remove = current_member_ids - new_member_ids
612614
if to_add:
613-
valid_member_ids = set(
614-
OrganizationMember.objects.filter(organization=org, id__in=to_add).values_list(
615-
"id", flat=True
616-
)
615+
user_to_member = dict(
616+
OrganizationMember.objects.filter(
617+
organization=org, user_id__in=to_add
618+
).values_list("user_id", "id")
617619
)
618-
invalid_member_ids = to_add - valid_member_ids
619-
if invalid_member_ids:
620+
invalid_user_ids = to_add - set(user_to_member.keys())
621+
if invalid_user_ids:
620622
raise serializers.ValidationError(
621623
{
622-
"replayAccessMembers": f"Invalid organization member IDs: {sorted(invalid_member_ids)}"
624+
"replayAccessMembers": f"Invalid user IDs (not members of this organization): {sorted(invalid_user_ids)}"
623625
}
624626
)
625627

626628
OrganizationMemberReplayAccess.objects.bulk_create(
627629
[
628-
OrganizationMemberReplayAccess(organizationmember_id=member_id)
629-
for member_id in to_add
630+
OrganizationMemberReplayAccess(
631+
organizationmember_id=user_to_member[user_id]
632+
)
633+
for user_id in to_add
630634
],
631635
ignore_conflicts=True,
632636
)
633637

634638
if to_remove:
635639
OrganizationMemberReplayAccess.objects.filter(
636-
organizationmember__organization=org, organizationmember_id__in=to_remove
640+
organizationmember__organization=org, organizationmember__user_id__in=to_remove
637641
).delete()
638642

639643
if to_add or to_remove:
640644
changes = []
641645
if to_add:
642-
changes.append(f"added {len(to_add)} member(s)")
646+
changes.append(f"added {len(to_add)} user(s)")
643647
if to_remove:
644-
changes.append(f"removed {len(to_remove)} member(s)")
648+
changes.append(f"removed {len(to_remove)} user(s)")
645649
changed_data["replayAccessMembers"] = (
646-
f"{' and '.join(changes)} (total: {len(new_member_ids)} member(s) with access)"
650+
f"{' and '.join(changes)} (total: {len(new_user_ids)} user(s) with access)"
647651
)
648652

649653
if "openMembership" in data:
@@ -869,7 +873,7 @@ class OrganizationDetailsPutSerializer(serializers.Serializer):
869873
)
870874
replayAccessMembers = serializers.ListField(
871875
child=serializers.IntegerField(),
872-
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.",
876+
help_text="A list of user IDs who have permission to access replay data. Requires the hasGranularReplayPermissions flag to be true to be enforced.",
873877
required=False,
874878
allow_null=True,
875879
)

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)