Skip to content

Commit 6938277

Browse files
committed
remove organization, move model to replays
1 parent 9456d84 commit 6938277

File tree

9 files changed

+55
-86
lines changed

9 files changed

+55
-86
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@
7373
from sentry.models.options.project_option import ProjectOption
7474
from sentry.models.organization import Organization, OrganizationStatus
7575
from sentry.models.organizationaccessrequest import OrganizationAccessRequest
76-
from sentry.models.organizationmemberreplayaccess import OrganizationMemberReplayAccess
7776
from sentry.models.organizationonboardingtask import OrganizationOnboardingTask
7877
from sentry.models.project import Project
7978
from sentry.models.team import Team, TeamStatus
8079
from sentry.organizations.absolute_url import generate_organization_url
8180
from sentry.organizations.services.organization import RpcOrganizationSummary
81+
from sentry.replays.models import OrganizationMemberReplayAccess
8282
from sentry.users.models.user import User
8383
from sentry.users.services.user.model import RpcUser
8484
from sentry.users.services.user.service import user_service
@@ -741,9 +741,9 @@ def serialize( # type: ignore[override]
741741
)
742742
context["hasGranularReplayPermissions"] = bool(permissions_enabled)
743743
context["replayAccessMembers"] = list(
744-
OrganizationMemberReplayAccess.objects.filter(organization=obj).values_list(
745-
"organizationmember_id", flat=True
746-
)
744+
OrganizationMemberReplayAccess.objects.filter(
745+
organizationmember__organization=obj
746+
).values_list("organizationmember_id", flat=True)
747747
)
748748

749749
if has_custom_dynamic_sampling(obj, actor=user):

src/sentry/core/endpoints/organization_details.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@
9494
from sentry.models.options.project_option import ProjectOption
9595
from sentry.models.organization import Organization, OrganizationStatus
9696
from sentry.models.organizationmember import OrganizationMember
97-
from sentry.models.organizationmemberreplayaccess import OrganizationMemberReplayAccess
9897
from sentry.models.project import Project
9998
from sentry.organizations.services.organization import organization_service
10099
from sentry.organizations.services.organization.model import (
@@ -103,6 +102,7 @@
103102
RpcOrganizationDeleteState,
104103
)
105104
from sentry.relay.datascrubbing import validate_pii_config_update, validate_pii_selectors
105+
from sentry.replays.models import OrganizationMemberReplayAccess
106106
from sentry.seer.autofix.constants import AutofixAutomationTuningSettings
107107
from sentry.services.organization.provisioning import (
108108
OrganizationSlugCollisionException,
@@ -602,9 +602,9 @@ def save(self, **kwargs):
602602
if member_ids is None:
603603
member_ids = []
604604
current_member_ids = set(
605-
OrganizationMemberReplayAccess.objects.filter(organization=org).values_list(
606-
"organizationmember_id", flat=True
607-
)
605+
OrganizationMemberReplayAccess.objects.filter(
606+
organizationmember__organization=org
607+
).values_list("organizationmember_id", flat=True)
608608
)
609609
new_member_ids = set(member_ids)
610610

@@ -626,17 +626,15 @@ def save(self, **kwargs):
626626

627627
OrganizationMemberReplayAccess.objects.bulk_create(
628628
[
629-
OrganizationMemberReplayAccess(
630-
organization=org, organizationmember_id=member_id
631-
)
629+
OrganizationMemberReplayAccess(organizationmember_id=member_id)
632630
for member_id in to_add
633631
],
634632
ignore_conflicts=True,
635633
)
636634

637635
if to_remove:
638636
OrganizationMemberReplayAccess.objects.filter(
639-
organization=org, organizationmember_id__in=to_remove
637+
organizationmember__organization=org, organizationmember_id__in=to_remove
640638
).delete()
641639

642640
if to_add or to_remove:

src/sentry/models/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
from .organizationmember import * # NOQA
7575
from .organizationmemberinvite import * # NOQA
7676
from .organizationmembermapping import * # NOQA
77-
from .organizationmemberreplayaccess import * # NOQA
7877
from .organizationmemberteam import * # NOQA
7978
from .organizationmemberteamreplica import * # NOQA
8079
from .organizationonboardingtask import * # NOQA

src/sentry/models/organizationmemberreplayaccess.py

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/sentry/migrations/1012_organizationmember_replay_access.py renamed to src/sentry/replays/migrations/0007_organizationmember_replay_access.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Generated by Django 5.2.8 on 2025-12-02 12:31
22

33
import django.db.models.deletion
4-
import django.utils.timezone
54
from django.db import migrations, models
65

76
import sentry.db.models.fields.bounded
@@ -25,7 +24,7 @@ class Migration(CheckedMigration):
2524
is_post_deployment = False
2625

2726
dependencies = [
28-
("sentry", "1011_update_oc_integration_cascade_to_null"),
27+
("replays", "0006_add_bulk_delete_job"),
2928
]
3029

3130
operations = [
@@ -38,27 +37,20 @@ class Migration(CheckedMigration):
3837
primary_key=True, serialize=False
3938
),
4039
),
41-
("date_added", models.DateTimeField(default=django.utils.timezone.now)),
42-
(
43-
"organization",
44-
sentry.db.models.fields.foreignkey.FlexibleForeignKey(
45-
on_delete=django.db.models.deletion.CASCADE,
46-
related_name="replay_access_set",
47-
to="sentry.organization",
48-
),
49-
),
40+
("date_updated", models.DateTimeField(auto_now=True)),
41+
("date_added", models.DateTimeField(auto_now_add=True)),
5042
(
5143
"organizationmember",
5244
sentry.db.models.fields.foreignkey.FlexibleForeignKey(
5345
on_delete=django.db.models.deletion.CASCADE,
5446
related_name="replay_access",
5547
to="sentry.organizationmember",
48+
unique=True,
5649
),
5750
),
5851
],
5952
options={
6053
"db_table": "sentry_organizationmemberreplayaccess",
61-
"unique_together": {("organization", "organizationmember")},
6254
},
6355
),
6456
]

src/sentry/replays/models.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from sentry.db.models import (
99
BoundedBigIntegerField,
1010
DefaultFieldsModel,
11+
FlexibleForeignKey,
1112
Model,
1213
region_silo_model,
1314
sane_repr,
@@ -78,3 +79,28 @@ def delete(self, *args, **kwargs):
7879

7980
rv = super().delete(*args, **kwargs)
8081
return rv
82+
83+
84+
@region_silo_model
85+
class OrganizationMemberReplayAccess(DefaultFieldsModel):
86+
"""
87+
Tracks which organization members have permission to access replay data.
88+
89+
When no records exist for an organization, all members have access (default).
90+
When records exist, only members with a record can access replays.
91+
"""
92+
93+
__relocation_scope__ = RelocationScope.Organization
94+
95+
organizationmember = FlexibleForeignKey(
96+
"sentry.OrganizationMember",
97+
on_delete=models.CASCADE,
98+
related_name="replay_access",
99+
unique=True,
100+
)
101+
102+
class Meta:
103+
app_label = "replays"
104+
db_table = "sentry_organizationmemberreplayaccess"
105+
106+
__repr__ = sane_repr("organizationmember_id")

src/sentry/testutils/helpers/backups.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,12 +473,10 @@ def create_exhaustive_organization(
473473
)
474474

475475
# OrganizationMemberReplayAccess - add for the owner member
476-
from sentry.models.organizationmemberreplayaccess import OrganizationMemberReplayAccess
476+
from sentry.replays.models import OrganizationMemberReplayAccess
477477

478478
owner_member = OrganizationMember.objects.get(organization=org, user_id=owner_id)
479-
OrganizationMemberReplayAccess.objects.create(
480-
organization=org, organizationmember=owner_member
481-
)
479+
OrganizationMemberReplayAccess.objects.create(organizationmember=owner_member)
482480

483481
# Team
484482
team = self.create_team(name=f"test_team_in_{slug}", organization=org)

tests/sentry/api/serializers/test_organization.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
from sentry.models.deploy import Deploy
1818
from sentry.models.environment import Environment
1919
from sentry.models.options.organization_option import OrganizationOption
20-
from sentry.models.organizationmemberreplayaccess import OrganizationMemberReplayAccess
2120
from sentry.models.organizationonboardingtask import (
2221
OnboardingTask,
2322
OnboardingTaskStatus,
2423
OrganizationOnboardingTask,
2524
)
2625
from sentry.models.releaseprojectenvironment import ReleaseProjectEnvironment
26+
from sentry.replays.models import OrganizationMemberReplayAccess
2727
from sentry.testutils.cases import TestCase
2828
from sentry.testutils.skips import requires_snuba
2929

@@ -204,12 +204,8 @@ def test_replay_access_members_serialized(self) -> None:
204204
member2 = self.create_member(
205205
organization=organization, user=self.create_user(), role="member"
206206
)
207-
OrganizationMemberReplayAccess.objects.create(
208-
organization=organization, organizationmember=member1
209-
)
210-
OrganizationMemberReplayAccess.objects.create(
211-
organization=organization, organizationmember=member2
212-
)
207+
OrganizationMemberReplayAccess.objects.create(organizationmember=member1)
208+
OrganizationMemberReplayAccess.objects.create(organizationmember=member2)
213209
acc = access.from_user(user, organization)
214210

215211
with self.feature("organizations:granular-replay-permissions"):

tests/sentry/core/endpoints/test_organization_details.py

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
from sentry.models.options.project_option import ProjectOption
3232
from sentry.models.organization import Organization, OrganizationStatus
3333
from sentry.models.organizationmapping import OrganizationMapping
34-
from sentry.models.organizationmemberreplayaccess import OrganizationMemberReplayAccess
3534
from sentry.models.organizationslugreservation import OrganizationSlugReservation
35+
from sentry.replays.models import OrganizationMemberReplayAccess
3636
from sentry.signals import project_created
3737
from sentry.silo.safety import unguarded_write
3838
from sentry.snuba.metrics import TransactionMRI
@@ -1548,7 +1548,7 @@ def test_replay_access_members_add(self) -> None:
15481548

15491549
access_members = list(
15501550
OrganizationMemberReplayAccess.objects.filter(
1551-
organization=self.organization
1551+
organizationmember__organization=self.organization
15521552
).values_list("organizationmember_id", flat=True)
15531553
)
15541554
assert set(access_members) == {member1.id, member2.id}
@@ -1566,12 +1566,8 @@ def test_replay_access_members_remove(self) -> None:
15661566
member2 = self.create_member(
15671567
organization=self.organization, user=self.create_user(), role="member"
15681568
)
1569-
OrganizationMemberReplayAccess.objects.create(
1570-
organization=self.organization, organizationmember=member1
1571-
)
1572-
OrganizationMemberReplayAccess.objects.create(
1573-
organization=self.organization, organizationmember=member2
1574-
)
1569+
OrganizationMemberReplayAccess.objects.create(organizationmember=member1)
1570+
OrganizationMemberReplayAccess.objects.create(organizationmember=member2)
15751571
with assume_test_silo_mode_of(AuditLogEntry):
15761572
AuditLogEntry.objects.filter(organization_id=self.organization.id).delete()
15771573

@@ -1581,7 +1577,7 @@ def test_replay_access_members_remove(self) -> None:
15811577

15821578
access_members = list(
15831579
OrganizationMemberReplayAccess.objects.filter(
1584-
organization=self.organization
1580+
organizationmember__organization=self.organization
15851581
).values_list("organizationmember_id", flat=True)
15861582
)
15871583
assert access_members == [member1.id]
@@ -1602,9 +1598,7 @@ def test_replay_access_members_add_and_remove(self) -> None:
16021598
member3 = self.create_member(
16031599
organization=self.organization, user=self.create_user(), role="member"
16041600
)
1605-
OrganizationMemberReplayAccess.objects.create(
1606-
organization=self.organization, organizationmember=member1
1607-
)
1601+
OrganizationMemberReplayAccess.objects.create(organizationmember=member1)
16081602
with assume_test_silo_mode_of(AuditLogEntry):
16091603
AuditLogEntry.objects.filter(organization_id=self.organization.id).delete()
16101604

@@ -1614,7 +1608,7 @@ def test_replay_access_members_add_and_remove(self) -> None:
16141608

16151609
access_members = set(
16161610
OrganizationMemberReplayAccess.objects.filter(
1617-
organization=self.organization
1611+
organizationmember__organization=self.organization
16181612
).values_list("organizationmember_id", flat=True)
16191613
)
16201614
assert access_members == {member2.id, member3.id}
@@ -1630,9 +1624,7 @@ def test_replay_access_members_clear_all(self) -> None:
16301624
member1 = self.create_member(
16311625
organization=self.organization, user=self.create_user(), role="member"
16321626
)
1633-
OrganizationMemberReplayAccess.objects.create(
1634-
organization=self.organization, organizationmember=member1
1635-
)
1627+
OrganizationMemberReplayAccess.objects.create(organizationmember=member1)
16361628
with assume_test_silo_mode_of(AuditLogEntry):
16371629
AuditLogEntry.objects.filter(organization_id=self.organization.id).delete()
16381630

@@ -1641,7 +1633,7 @@ def test_replay_access_members_clear_all(self) -> None:
16411633
self.get_success_response(self.organization.slug, **data)
16421634

16431635
access_count = OrganizationMemberReplayAccess.objects.filter(
1644-
organization=self.organization
1636+
organizationmember__organization=self.organization
16451637
).count()
16461638
assert access_count == 0
16471639

@@ -1703,7 +1695,7 @@ def test_replay_access_members_mixed_valid_and_invalid(self) -> None:
17031695
assert str(valid_member.id) not in response.data["replayAccessMembers"]
17041696

17051697
access_count = OrganizationMemberReplayAccess.objects.filter(
1706-
organization=self.organization
1698+
organizationmember__organization=self.organization
17071699
).count()
17081700
assert access_count == 0
17091701

0 commit comments

Comments
 (0)