Skip to content

Commit 89d4135

Browse files
fix(auth): Adding scoping_organization_id to replica (#81213)
Adding scoping_organization_id to both ApiTokenReplica and SystemToken. The reason is that we want to limit auth tokens that are scoped to a specific organizations to any other organization. Context on why we need this is here: #81193
1 parent 2e3a412 commit 89d4135

File tree

9 files changed

+51
-2
lines changed

9 files changed

+51
-2
lines changed

fixtures/backup/model_dependencies/detailed.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@
119119
"model": "sentry.organization",
120120
"nullable": true
121121
},
122+
"scoping_organization_id": {
123+
"kind": "HybridCloudForeignKey",
124+
"model": "sentry.organization",
125+
"nullable": true
126+
},
122127
"user_id": {
123128
"kind": "HybridCloudForeignKey",
124129
"model": "sentry.user",

migrations_lockfile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ will then be regenerated, and you should be able to merge without conflicts.
77

88
feedback: 0004_index_together
99

10-
hybridcloud: 0016_add_control_cacheversion
10+
hybridcloud: 0017_add_scoping_organization_apitokenreplica
1111

1212
nodestore: 0002_nodestore_no_dictfield
1313

src/sentry/auth/services/auth/model.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class RpcApiToken(RpcModel):
4040
expires_at: datetime.datetime | None = None
4141
allowed_origins: list[str] = Field(default_factory=list)
4242
scope_list: list[str] = Field(default_factory=list)
43+
scoping_organization_id: int | None = None
4344

4445

4546
class RpcMemberSsoState(RpcModel):

src/sentry/auth/services/auth/serial.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def serialize_api_token(at: ApiToken) -> RpcApiToken:
8585
user_id=at.user_id,
8686
application_id=at.application_id,
8787
organization_id=at.organization_id,
88+
scoping_organization_id=at.scoping_organization_id,
8889
application_is_active=at.application is None or at.application.is_active,
8990
token=at.token,
9091
hashed_token=at.hashed_token,

src/sentry/auth/system.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class SystemToken:
4646
token = "<system.secret-key>"
4747
application = None
4848
organization_id = None
49+
scoping_organization_id = None
4950

5051
@classmethod
5152
def from_request(cls, request: HttpRequest, token: str) -> SystemToken | None:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Generated by Django 5.1.1 on 2024-11-22 22:03
2+
3+
from django.db import migrations
4+
5+
import sentry.db.models.fields.hybrid_cloud_foreign_key
6+
from sentry.new_migrations.migrations import CheckedMigration
7+
8+
9+
class Migration(CheckedMigration):
10+
# This flag is used to mark that a migration shouldn't be automatically run in production.
11+
# This should only be used for operations where it's safe to run the migration after your
12+
# code has deployed. So this should not be used for most operations that alter the schema
13+
# of a table.
14+
# Here are some things that make sense to mark as post deployment:
15+
# - Large data migrations. Typically we want these to be run manually so that they can be
16+
# monitored and not block the deploy for a long period of time while they run.
17+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
18+
# run this outside deployments so that we don't block them. Note that while adding an index
19+
# is a schema change, it's completely safe to run the operation after the code has deployed.
20+
# Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment
21+
22+
is_post_deployment = False
23+
24+
dependencies = [
25+
("hybridcloud", "0016_add_control_cacheversion"),
26+
]
27+
28+
operations = [
29+
migrations.AddField(
30+
model_name="apitokenreplica",
31+
name="scoping_organization_id",
32+
field=sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey(
33+
"sentry.Organization", db_index=True, null=True, on_delete="CASCADE"
34+
),
35+
),
36+
]

src/sentry/hybridcloud/models/apitokenreplica.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class ApiTokenReplica(Model, HasApiScopes):
2424
expires_at = models.DateTimeField(null=True)
2525
allowed_origins = models.TextField(blank=True, null=True)
2626
date_added = models.DateTimeField(default=timezone.now)
27+
scoping_organization_id = HybridCloudForeignKey(
28+
"sentry.Organization", null=True, on_delete="CASCADE"
29+
)
2730

2831
class Meta:
2932
app_label = "hybridcloud"

src/sentry/hybridcloud/services/replica/impl.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ def upsert_replicated_api_token(self, *, api_token: RpcApiToken, region_name: st
163163
"\n".join(api_token.allowed_origins) if api_token.allowed_origins else None
164164
),
165165
user_id=api_token.user_id,
166+
scoping_organization_id=api_token.scoping_organization_id,
166167
)
167168
handle_replication(ApiToken, destination)
168169

tests/sentry/backup/snapshots/test_comparators/test_default_comparators.pysnap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
created: '2024-11-21T21:10:04.656611+00:00'
2+
created: '2024-11-25T20:44:29.207064+00:00'
33
creator: sentry
44
source: tests/sentry/backup/test_comparators.py
55
---
@@ -33,6 +33,7 @@ source: tests/sentry/backup/test_comparators.py
3333
- apitoken_id
3434
- application_id
3535
- organization
36+
- scoping_organization_id
3637
- user_id
3738
model_name: hybridcloud.apitokenreplica
3839
- comparators:

0 commit comments

Comments
 (0)