Skip to content

Commit 33c073c

Browse files
Revert "feat(flags): Store options changes in the audit log (#78622)"
This reverts commit 5f5d2ed. Co-authored-by: cmanallen <[email protected]>
1 parent da58a20 commit 33c073c

File tree

7 files changed

+205
-214
lines changed

7 files changed

+205
-214
lines changed

src/sentry/flags/endpoints/hooks.py

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import datetime
2+
from typing import Any, TypedDict
3+
4+
from rest_framework import serializers
15
from rest_framework.request import Request
26
from rest_framework.response import Response
37

@@ -7,12 +11,7 @@
711
from sentry.api.base import Endpoint, region_silo_endpoint
812
from sentry.api.bases.organization import OrganizationPermission
913
from sentry.api.exceptions import ResourceDoesNotExist
10-
from sentry.flags.providers import (
11-
DeserializationError,
12-
InvalidProvider,
13-
handle_provider_event,
14-
write,
15-
)
14+
from sentry.flags.models import ACTION_MAP, CREATED_BY_TYPE_MAP, FlagAuditLogModel
1615
from sentry.models.organization import Organization
1716
from sentry.utils.sdk import bind_organization_context
1817

@@ -66,9 +65,97 @@ def convert_args(
6665

6766
def post(self, request: Request, organization: Organization, provider: str) -> Response:
6867
try:
69-
write(handle_provider_event(provider, request.data, organization.id))
68+
rows_data = handle_provider_event(provider, request.data, organization.id)
69+
FlagAuditLogModel.objects.bulk_create(FlagAuditLogModel(**row) for row in rows_data)
7070
return Response(status=200)
7171
except InvalidProvider:
7272
raise ResourceDoesNotExist
7373
except DeserializationError as exc:
7474
return Response(exc.errors, status=400)
75+
76+
77+
"""Provider definitions.
78+
79+
Provider definitions are pure functions. They accept data and return data. Providers do not
80+
initiate any IO operations. Instead they return commands in the form of the return type or
81+
an exception. These commands inform the caller (the endpoint defintion) what IO must be
82+
emitted to satisfy the request. This is done primarily to improve testability and test
83+
performance but secondarily to allow easy extension of the endpoint without knowledge of
84+
the underlying systems.
85+
"""
86+
87+
88+
class FlagAuditLogRow(TypedDict):
89+
"""A complete flag audit log row instance."""
90+
91+
action: int
92+
created_at: datetime.datetime
93+
created_by: str
94+
created_by_type: int
95+
flag: str
96+
organization_id: int
97+
tags: dict[str, Any]
98+
99+
100+
class DeserializationError(Exception):
101+
"""The request body could not be deserialized."""
102+
103+
def __init__(self, errors):
104+
self.errors = errors
105+
106+
107+
class InvalidProvider(Exception):
108+
"""An unsupported provider type was specified."""
109+
110+
...
111+
112+
113+
def handle_provider_event(
114+
provider: str,
115+
request_data: dict[str, Any],
116+
organization_id: int,
117+
) -> list[FlagAuditLogRow]:
118+
if provider == "flag-pole":
119+
return handle_flag_pole_event(request_data, organization_id)
120+
else:
121+
raise InvalidProvider(provider)
122+
123+
124+
"""Flag pole provider definition.
125+
126+
If you are not Sentry you will not ever use this driver. Metadata provider by flag pole is
127+
limited to what we can extract from the git repository on merge.
128+
"""
129+
130+
131+
class FlagPoleItemSerializer(serializers.Serializer):
132+
action = serializers.ChoiceField(choices=("created", "updated"), required=True)
133+
created_at = serializers.DateTimeField(required=True)
134+
created_by = serializers.CharField(required=True)
135+
flag = serializers.CharField(max_length=100, required=True)
136+
tags = serializers.DictField(required=True)
137+
138+
139+
class FlagPoleSerializer(serializers.Serializer):
140+
data = FlagPoleItemSerializer(many=True, required=True) # type: ignore[assignment]
141+
142+
143+
def handle_flag_pole_event(
144+
request_data: dict[str, Any], organization_id: int
145+
) -> list[FlagAuditLogRow]:
146+
serializer = FlagPoleSerializer(data=request_data)
147+
if not serializer.is_valid():
148+
raise DeserializationError(serializer.errors)
149+
150+
return [
151+
dict(
152+
action=ACTION_MAP[validated_item["action"]],
153+
created_at=validated_item["created_at"],
154+
created_by=validated_item["created_by"],
155+
created_by_type=CREATED_BY_TYPE_MAP["email"],
156+
flag=validated_item["flag"],
157+
organization_id=organization_id,
158+
tags=validated_item["tags"],
159+
)
160+
for validated_item in serializer.validated_data["data"]
161+
]

src/sentry/flags/providers.py

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

src/sentry/options/defaults.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -424,20 +424,6 @@
424424
flags=FLAG_ALLOW_EMPTY | FLAG_PRIORITIZE_DISK | FLAG_AUTOMATOR_MODIFIABLE,
425425
)
426426

427-
# Flag Options
428-
register(
429-
"flags:options-audit-log-is-enabled",
430-
default=True,
431-
flags=FLAG_ALLOW_EMPTY | FLAG_PRIORITIZE_DISK | FLAG_AUTOMATOR_MODIFIABLE,
432-
type=Bool,
433-
)
434-
register(
435-
"flags:options-audit-log-organization-id",
436-
default=None,
437-
flags=FLAG_ALLOW_EMPTY | FLAG_PRIORITIZE_DISK | FLAG_AUTOMATOR_MODIFIABLE,
438-
type=Int,
439-
)
440-
441427
# Replay Options
442428
#
443429
# Replay storage backend configuration (only applicable if the direct-storage driver is used)

src/sentry/runner/commands/presenters/audit_log_presenter.py

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

src/sentry/runner/commands/presenters/presenterdelegator.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,16 @@
66

77
class PresenterDelegator:
88
def __init__(self, source: str) -> None:
9-
from sentry.runner.commands.presenters.audit_log_presenter import AuditLogPresenter
10-
119
self._consolepresenter = ConsolePresenter()
1210

1311
self._slackpresenter = None
1412
if WebhookPresenter.is_webhook_enabled():
1513
self._slackpresenter = WebhookPresenter(source)
16-
if AuditLogPresenter.is_webhook_enabled():
17-
self._auditlogpresenter = AuditLogPresenter(source)
1814

1915
def __getattr__(self, attr: str) -> Any:
2016
def wrapper(*args: Any, **kwargs: Any) -> None:
2117
getattr(self._consolepresenter, attr)(*args, **kwargs)
2218
if self._slackpresenter:
2319
getattr(self._slackpresenter, attr)(*args, **kwargs)
24-
if self._auditlogpresenter:
25-
getattr(self._auditlogpresenter, attr)(*args, **kwargs)
2620

2721
return wrapper

0 commit comments

Comments
 (0)