Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/sentry/apidocs/examples/replay_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,71 @@ class ReplayExamples:
)
]

GET_REPLAY_DELETION_JOBS = [
OpenApiExample(
"List replay deletion jobs",
value={
"data": [
{
"id": 1,
"dateCreated": "2024-01-01T00:00:00Z",
"dateUpdated": "2024-01-01T00:05:00Z",
"rangeStart": "2023-12-01T00:00:00Z",
"rangeEnd": "2024-01-01T00:00:00Z",
"environments": ["production"],
"status": "pending",
"query": "user.email:test@example.com",
"countDeleted": 0,
}
]
},
status_codes=["200"],
response_only=True,
)
]

CREATE_REPLAY_DELETION_JOB = [
OpenApiExample(
"Create a replay deletion job",
value={
"data": {
"id": 1,
"dateCreated": "2024-01-01T00:00:00Z",
"dateUpdated": "2024-01-01T00:05:00Z",
"rangeStart": "2023-12-01T00:00:00Z",
"rangeEnd": "2024-01-01T00:00:00Z",
"environments": ["production"],
"status": "pending",
"query": "user.email:test@example.com",
"countDeleted": 0,
}
},
status_codes=["201"],
response_only=True,
)
]

GET_REPLAY_DELETION_JOB = [
OpenApiExample(
"Get a replay deletion job",
value={
"data": {
"id": 1,
"dateCreated": "2024-01-01T00:00:00Z",
"dateUpdated": "2024-01-01T00:05:00Z",
"rangeStart": "2023-12-01T00:00:00Z",
"rangeEnd": "2024-01-01T00:00:00Z",
"environments": ["production"],
"status": "pending",
"query": "user.email:test@example.com",
"countDeleted": 0,
}
},
status_codes=["200"],
response_only=True,
)
]

GET_REPLAY_VIEWED_BY = [
OpenApiExample(
"Get list of users who have viewed a replay",
Expand Down
81 changes: 78 additions & 3 deletions src/sentry/replays/endpoints/project_replay_jobs_delete.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
from __future__ import annotations

from typing import TypedDict

from drf_spectacular.utils import extend_schema
from rest_framework import serializers
from rest_framework.request import Request
from rest_framework.response import Response
Expand All @@ -10,12 +15,36 @@
from sentry.api.exceptions import ResourceDoesNotExist
from sentry.api.paginator import OffsetPaginator
from sentry.api.serializers import Serializer, serialize
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST, RESPONSE_FORBIDDEN, RESPONSE_NOT_FOUND
from sentry.apidocs.examples.replay_examples import ReplayExamples
from sentry.apidocs.parameters import GlobalParams
from sentry.apidocs.utils import inline_sentry_response_serializer
from sentry.replays.endpoints.project_replay_endpoint import ProjectReplayEndpoint
from sentry.replays.models import ReplayDeletionJobModel
from sentry.replays.permissions import has_replay_permission
from sentry.replays.tasks import run_bulk_replay_delete_job


class ReplayDeletionJobResponseData(TypedDict):
id: int
dateCreated: str
dateUpdated: str
rangeStart: str
rangeEnd: str
environments: list[str]
status: str
query: str
countDeleted: int


class ReplayDeletionJobListResponse(TypedDict):
data: list[ReplayDeletionJobResponseData]


class ReplayDeletionJobDetailResponse(TypedDict):
data: ReplayDeletionJobResponseData


class ReplayDeletionJobPermission(ProjectPermission):
scope_map = {
"GET": ["project:write", "project:admin"],
Expand Down Expand Up @@ -57,14 +86,29 @@ class ReplayDeletionJobCreateSerializer(serializers.Serializer):


@cell_silo_endpoint
@extend_schema(tags=["Replays"])
class ProjectReplayDeletionJobsIndexEndpoint(ProjectEndpoint):
owner = ApiOwner.DATA_BROWSING
publish_status = {
"GET": ApiPublishStatus.PRIVATE,
"POST": ApiPublishStatus.PRIVATE,
"GET": ApiPublishStatus.PUBLIC,
"POST": ApiPublishStatus.PUBLIC,
}
permission_classes = (ReplayDeletionJobPermission,)

@extend_schema(
operation_id="List Replay Deletion Jobs",
parameters=[
GlobalParams.ORG_ID_OR_SLUG,
GlobalParams.PROJECT_ID_OR_SLUG,
],
responses={
200: inline_sentry_response_serializer(
"ListReplayDeletionJobs", ReplayDeletionJobListResponse
),
403: RESPONSE_FORBIDDEN,
},
examples=ReplayExamples.GET_REPLAY_DELETION_JOBS,
)
def get(self, request: Request, project) -> Response:
"""
Retrieve a collection of replay delete jobs.
Expand All @@ -86,6 +130,21 @@ def get(self, request: Request, project) -> Response:
paginator_cls=OffsetPaginator,
)

@extend_schema(
operation_id="Create a Replay Deletion Job",
parameters=[
GlobalParams.ORG_ID_OR_SLUG,
GlobalParams.PROJECT_ID_OR_SLUG,
],
responses={
201: inline_sentry_response_serializer(
"CreateReplayDeletionJob", ReplayDeletionJobDetailResponse
),
400: RESPONSE_BAD_REQUEST,
403: RESPONSE_FORBIDDEN,
},
examples=ReplayExamples.CREATE_REPLAY_DELETION_JOB,
)
def post(self, request: Request, project) -> Response:
"""
Create a new replay deletion job.
Expand Down Expand Up @@ -132,12 +191,28 @@ def post(self, request: Request, project) -> Response:


@cell_silo_endpoint
@extend_schema(tags=["Replays"])
class ProjectReplayDeletionJobDetailEndpoint(ProjectReplayEndpoint):
publish_status = {
"GET": ApiPublishStatus.PRIVATE,
"GET": ApiPublishStatus.PUBLIC,
}
permission_classes = (ReplayDeletionJobPermission,)

@extend_schema(
operation_id="Get a Replay Deletion Job",
parameters=[
GlobalParams.ORG_ID_OR_SLUG,
GlobalParams.PROJECT_ID_OR_SLUG,
],
responses={
200: inline_sentry_response_serializer(
"GetReplayDeletionJob", ReplayDeletionJobDetailResponse
),
403: RESPONSE_FORBIDDEN,
404: RESPONSE_NOT_FOUND,
},
examples=ReplayExamples.GET_REPLAY_DELETION_JOB,
)
def get(self, request: Request, project, job_id: int) -> Response:
"""
Fetch a replay delete job instance.
Expand Down
Loading