|
3 | 3 | import functools
|
4 | 4 | import inspect
|
5 | 5 | import re
|
6 |
| -import sys |
7 | 6 | from contextlib import contextmanager
|
8 | 7 | from typing import Any, Callable, Dict, Iterable, List, MutableMapping, MutableSet, Set, Tuple, Type
|
9 | 8 | from unittest import TestCase
|
10 | 9 |
|
11 | 10 | import pytest
|
12 | 11 | from django.apps import apps
|
13 | 12 | from django.conf import settings
|
14 |
| -from django.db import connections, router |
15 | 13 | from django.db.models import Model
|
16 | 14 | from django.db.models.fields.related import RelatedField
|
17 |
| -from django.db.models.signals import post_migrate |
18 |
| -from django.db.transaction import get_connection |
19 | 15 | from django.test import override_settings
|
20 | 16 |
|
21 | 17 | from sentry import deletions
|
@@ -195,116 +191,6 @@ def assume_test_silo_mode(desired_silo: SiloMode) -> Any:
|
195 | 191 | yield
|
196 | 192 |
|
197 | 193 |
|
198 |
| -def reset_test_role(role: str, using: str, create_role: bool) -> None: |
199 |
| - # Deprecated, will remove once getsentry is updated. |
200 |
| - connection_names = [conn.alias for conn in connections.all()] |
201 |
| - |
202 |
| - if create_role: |
203 |
| - role_exists = False |
204 |
| - with get_connection(using).cursor() as connection: |
205 |
| - connection.execute("SELECT 1 FROM pg_roles WHERE rolname = %s", [role]) |
206 |
| - role_exists = connection.fetchone() |
207 |
| - |
208 |
| - if role_exists: |
209 |
| - # Drop role permissions on each connection, or we can't drop the role. |
210 |
| - for alias in connection_names: |
211 |
| - with get_connection(alias).cursor() as conn: |
212 |
| - conn.execute(f"REASSIGN OWNED BY {role} TO postgres") |
213 |
| - conn.execute(f"DROP OWNED BY {role} CASCADE") |
214 |
| - |
215 |
| - # Drop and re-create the role as required. |
216 |
| - with get_connection(using).cursor() as conn: |
217 |
| - conn.execute(f"DROP ROLE {role}") |
218 |
| - |
219 |
| - with get_connection(using).cursor() as conn: |
220 |
| - conn.execute(f"CREATE ROLE {role}") |
221 |
| - |
222 |
| - # Create permissions on the current connection as we'll build up permissions incrementally. |
223 |
| - with get_connection(using).cursor() as conn: |
224 |
| - conn.execute(f"GRANT USAGE ON SCHEMA public TO {role};") |
225 |
| - conn.execute(f"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO {role};") |
226 |
| - conn.execute(f"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO {role};") |
227 |
| - |
228 |
| - |
229 |
| -_role_created: bool = False |
230 |
| -_role_privileges_created: MutableMapping[str, bool] = {} |
231 |
| - |
232 |
| - |
233 |
| -def create_model_role_guards(app_config: Any, using: str, **kwargs: Any): |
234 |
| - # Deprecated, will remove once getsentry is updated. |
235 |
| - global _role_created |
236 |
| - if "pytest" not in sys.argv[0] or not settings.USE_ROLE_SWAPPING_IN_TESTS: |
237 |
| - return |
238 |
| - |
239 |
| - from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey |
240 |
| - from sentry.models import ( |
241 |
| - Organization, |
242 |
| - OrganizationMapping, |
243 |
| - OrganizationMember, |
244 |
| - OrganizationMemberMapping, |
245 |
| - ) |
246 |
| - from sentry.testutils.silo import iter_models, reset_test_role, restrict_role |
247 |
| - |
248 |
| - if not app_config or app_config.name != "sentry": |
249 |
| - return |
250 |
| - |
251 |
| - with get_connection(using).cursor() as conn: |
252 |
| - conn.execute("SET ROLE 'postgres'") |
253 |
| - |
254 |
| - if not _role_privileges_created.get(using, False): |
255 |
| - reset_test_role(role="postgres_unprivileged", using=using, create_role=not _role_created) |
256 |
| - _role_created = True |
257 |
| - _role_privileges_created[using] = True |
258 |
| - |
259 |
| - # Protect Foreign Keys using hybrid cloud models from being deleted without using the privileged user. |
260 |
| - # Deletion should only occur when the developer is actively aware of the need to generate outboxes. |
261 |
| - seen_models: MutableSet[type] = set() |
262 |
| - for model in iter_models(app_config.name): |
263 |
| - for field in model._meta.fields: |
264 |
| - if not isinstance(field, HybridCloudForeignKey): |
265 |
| - continue |
266 |
| - fk_model = field.foreign_model |
267 |
| - if fk_model is None or fk_model in seen_models: |
268 |
| - continue |
269 |
| - seen_models.add(fk_model) |
270 |
| - |
271 |
| - restrict_role( |
272 |
| - role="postgres_unprivileged", model=fk_model, revocation_type="DELETE", using=using |
273 |
| - ) |
274 |
| - |
275 |
| - # Protect organization members from being updated without also invoking the correct outbox logic. |
276 |
| - # If you hit test failures as a result of lacking these privileges, first ensure that you create the correct |
277 |
| - # outboxes in a transaction, and cover that transaction with `in_test_psql_role_override` |
278 |
| - restrict_role(role="postgres_unprivileged", model=OrganizationMember, revocation_type="INSERT") |
279 |
| - restrict_role(role="postgres_unprivileged", model=OrganizationMember, revocation_type="UPDATE") |
280 |
| - restrict_role(role="postgres_unprivileged", model=Organization, revocation_type="INSERT") |
281 |
| - restrict_role(role="postgres_unprivileged", model=Organization, revocation_type="UPDATE") |
282 |
| - restrict_role(role="postgres_unprivileged", model=OrganizationMapping, revocation_type="INSERT") |
283 |
| - restrict_role(role="postgres_unprivileged", model=OrganizationMapping, revocation_type="UPDATE") |
284 |
| - # OrganizationMember objects need to cascade, but they can't use the standard hybrid cloud foreign key because the |
285 |
| - # identifiers are not snowflake ids. |
286 |
| - restrict_role(role="postgres_unprivileged", model=OrganizationMember, revocation_type="DELETE") |
287 |
| - |
288 |
| - restrict_role( |
289 |
| - role="postgres_unprivileged", model=OrganizationMemberMapping, revocation_type="INSERT" |
290 |
| - ) |
291 |
| - |
292 |
| - |
293 |
| -# Listen to django's migration signal so that we're not trapped inside |
294 |
| -# test method transactions. |
295 |
| -post_migrate.connect(create_model_role_guards, dispatch_uid="create_model_role_guards", weak=False) |
296 |
| - |
297 |
| - |
298 |
| -def restrict_role(role: str, model: Any, revocation_type: str, using: str = "default") -> None: |
299 |
| - # Deprecated, will remove once getsentry is updated. |
300 |
| - if router.db_for_write(model) != using: |
301 |
| - return |
302 |
| - |
303 |
| - using = router.db_for_write(model) |
304 |
| - with get_connection(using).cursor() as connection: |
305 |
| - connection.execute(f"REVOKE {revocation_type} ON public.{model._meta.db_table} FROM {role}") |
306 |
| - |
307 |
| - |
308 | 194 | def protected_table(table: str, operation: str) -> re.Pattern:
|
309 | 195 | return re.compile(f'{operation}[^"]+"{table}"', re.IGNORECASE)
|
310 | 196 |
|
|
0 commit comments