Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ per-file-ignores =
src/sentry/testutils/helpers/options.py, tests/sentry/options/test_manager.py, tests/sentry/options/test_update_channels.py, tests/sentry/runner/commands/test_configoptions.py: S011
# session setup, a fake settings object, and a script run in a subprocess
src/sentry/testutils/pytest/sentry.py, tests/sentry/runner/test_initializer.py, tests/sentry/test_devimports.py: S031
# S021-S028 lint the shipped API surface and its lint infrastructure; test
# S021-S028 and S034 lint the shipped API surface and its lint infrastructure; test
# modules deliberately contain the shapes they exercise
tests/*: S021, S022, S023, S024, S025, S026, S027, S028
tests/*: S021, S022, S023, S024, S025, S026, S027, S028, S034

[flake8:local-plugins]
paths = .
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from sentry.api.bases.organization import ControlSiloOrganizationEndpoint, OrganizationPermission
from sentry.api.permissions import DisallowImpersonatedTokenCreation, SentryIsAuthenticated
from sentry.api.serializers.rest_framework import CamelSnakeSerializer
from sentry.apidocs.constants import RESPONSE_FORBIDDEN
from sentry.apidocs.utils import inline_sentry_response_serializer
from sentry.auth.principal import require_user
from sentry.organizations.services.organization.model import (
Expand Down Expand Up @@ -126,7 +127,10 @@ class OrganizationAgentHandoffEndpoint(ControlSiloOrganizationEndpoint):
@extend_schema(
operation_id="Create a private agent onboarding prompt",
request=AgentHandoffRequestSerializer,
responses={201: inline_sentry_response_serializer("AgentHandoff", AgentHandoffResponse)},
responses={
201: inline_sentry_response_serializer("AgentHandoff", AgentHandoffResponse),
403: RESPONSE_FORBIDDEN,
},
)
def post(
self,
Expand Down
23 changes: 20 additions & 3 deletions src/sentry/api/endpoints/auth_2fa.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
serialize_auth_mfa_required,
)
from sentry.api.serializers.rest_framework import CamelSnakeSerializer
from sentry.apidocs.constants import (
RESPONSE_BAD_REQUEST,
RESPONSE_NOT_FOUND,
RESPONSE_TOO_MANY_REQUESTS,
RESPONSE_UNAUTHORIZED,
)
from sentry.auth.authenticators.base import (
ActivationChallengeResult,
ActivationMessageResult,
Expand Down Expand Up @@ -100,7 +106,7 @@ class AuthTwoFactorEndpoint(Endpoint):

@extend_schema(
operation_id="Get available methods for a pending two-factor authentication login",
responses={200: AuthMfaRequiredSerializer},
responses={200: AuthMfaRequiredSerializer, 404: RESPONSE_NOT_FOUND},
)
def get(self, request: Request) -> Response:
user = auth.get_pending_2fa_user(request)
Expand All @@ -117,7 +123,13 @@ def get(self, request: Request) -> Response:
@extend_schema(
operation_id="Complete a pending two-factor authentication login",
request=AuthTwoFactorRequestSerializer,
responses={200: AuthSuccessSerializer, 403: AuthDetailSerializer},
responses={
200: AuthSuccessSerializer,
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: AuthDetailSerializer,
429: RESPONSE_TOO_MANY_REQUESTS,
},
)
def post(self, request: Request) -> Response:
serializer = AuthTwoFactorRequestSerializer(data=request.data)
Expand Down Expand Up @@ -208,7 +220,12 @@ class AuthTwoFactorChallengeEndpoint(Endpoint):
@extend_schema(
operation_id="Activate a two-factor authentication challenge",
request=AuthTwoFactorChallengeRequestSerializer,
responses={200: AuthMfaChallengeSerializer},
responses={
200: AuthMfaChallengeSerializer,
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
429: RESPONSE_TOO_MANY_REQUESTS,
},
)
def post(self, request: Request) -> Response:
serializer = AuthTwoFactorChallengeRequestSerializer(data=request.data)
Expand Down
7 changes: 4 additions & 3 deletions src/sentry/api/endpoints/auth_recovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
AuthRecoveryAcceptedSerializer,
)
from sentry.api.serializers.rest_framework.base import CamelSnakeSerializer
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST, RESPONSE_TOO_MANY_REQUESTS
from sentry.auth import password_validation
from sentry.auth.twofactor import reset_2fa_rate_limits
from sentry.security.utils import capture_security_activity
Expand Down Expand Up @@ -81,7 +82,7 @@ class AuthRecoveryEndpoint(Endpoint):
@extend_schema(
operation_id="Request account password recovery",
request=AuthRecoveryRequestSerializer,
responses={202: AuthRecoveryAcceptedSerializer},
responses={202: AuthRecoveryAcceptedSerializer, 429: RESPONSE_TOO_MANY_REQUESTS},
)
def post(self, request: Request) -> Response:
if is_rate_limited(request, "request"):
Expand Down Expand Up @@ -120,7 +121,7 @@ class AuthRecoveryConfirmEndpoint(Endpoint):
@extend_schema(
operation_id="Validate account password recovery token",
parameters=[AuthRecoveryTokenRequestSerializer],
responses={200: AuthRecoveryTokenResponseSerializer},
responses={200: AuthRecoveryTokenResponseSerializer, 429: RESPONSE_TOO_MANY_REQUESTS},
)
def get(self, request: Request) -> Response:
if is_rate_limited(request, "validate"):
Expand Down Expand Up @@ -148,7 +149,7 @@ def get(self, request: Request) -> Response:
@extend_schema(
operation_id="Complete account password recovery",
request=AuthRecoveryConfirmRequestSerializer,
responses={204: None},
responses={204: None, 400: RESPONSE_BAD_REQUEST, 429: RESPONSE_TOO_MANY_REQUESTS},
)
def post(self, request: Request) -> Response:
if is_rate_limited(request, "confirm"):
Expand Down
3 changes: 2 additions & 1 deletion src/sentry/api/endpoints/auth_register.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
RegistrationRequest,
RegistrationValidator,
)
from sentry.apidocs.constants import RESPONSE_CONFLICT, RESPONSE_FORBIDDEN
from sentry.organizations.services.organization import RpcOrganization, organization_service
from sentry.ratelimits.config import RateLimitConfig
from sentry.signals import user_signup
Expand Down Expand Up @@ -141,7 +142,7 @@ class AuthRegisterEndpoint(Endpoint):
@extend_schema(
operation_id="Register a user account",
request=RegistrationValidator,
responses={200: AuthSuccessSerializer},
responses={200: AuthSuccessSerializer, 403: RESPONSE_FORBIDDEN, 409: RESPONSE_CONFLICT},
)
def post(self, request: Request) -> Response:
if request.user.is_authenticated:
Expand Down
20 changes: 18 additions & 2 deletions src/sentry/api/endpoints/organization_agentic_onboarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
AgenticOnboardingRunSerializer,
)
from sentry.api.serializers.rest_framework import CamelSnakeSerializer
from sentry.apidocs.constants import (
RESPONSE_BAD_REQUEST,
RESPONSE_CONFLICT,
RESPONSE_GONE,
RESPONSE_NOT_FOUND,
)
from sentry.auth.principal import require_user
from sentry.models.organization import Organization
from sentry.onboarding.agentic_progress.model import (
Expand Down Expand Up @@ -240,7 +246,11 @@ class OrganizationAgenticOnboardingRunIndexEndpoint(OrganizationEndpoint):

@extend_schema(
request=AgenticOnboardingRunRequestSerializer,
responses={201: AgenticOnboardingRunSerializer},
responses={
201: AgenticOnboardingRunSerializer,
404: RESPONSE_NOT_FOUND,
409: RESPONSE_CONFLICT,
},
)
def post(self, request: Request, organization: Organization) -> Response:
serializer = AgenticOnboardingRunRequestSerializer(data=request.data)
Expand Down Expand Up @@ -280,7 +290,13 @@ class OrganizationAgenticOnboardingStatusEndpoint(OrganizationEndpoint):

@extend_schema(
request=AgenticOnboardingStatusRequestSerializer,
responses={200: AgenticOnboardingRunSerializer},
responses={
200: AgenticOnboardingRunSerializer,
400: RESPONSE_BAD_REQUEST,
404: RESPONSE_NOT_FOUND,
409: RESPONSE_CONFLICT,
410: RESPONSE_GONE,
},
)
def post(self, request: Request, organization: Organization) -> Response:
serializer = AgenticOnboardingStatusRequestSerializer(data=request.data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from sentry.api.serializers.models.agentic_onboarding import (
AgenticOnboardingRunSerializer,
)
from sentry.apidocs.constants import RESPONSE_CONFLICT, RESPONSE_NOT_FOUND
from sentry.auth.principal import require_user
from sentry.models.organization import Organization
from sentry.onboarding.agentic_progress.model import OnboardingRunTerminal
Expand All @@ -26,7 +27,7 @@ class OrganizationAgenticOnboardingRunDetailsEndpoint(OrganizationEndpoint):
publish_status = {"GET": ApiPublishStatus.PRIVATE, "DELETE": ApiPublishStatus.PRIVATE}
owner = ApiOwner.VALUE_DISCOVERY

@extend_schema(responses={200: AgenticOnboardingRunSerializer})
@extend_schema(responses={200: AgenticOnboardingRunSerializer, 404: RESPONSE_NOT_FOUND})
def get(self, request: Request, organization: Organization, run_id: str) -> Response:
user_id = require_user(request).id
run = get_onboarding_progress_service().get(
Expand All @@ -37,7 +38,13 @@ def get(self, request: Request, organization: Organization, run_id: str) -> Resp

return Response(serialize(run, request.user, AgenticOnboardingRunSerializer()))

@extend_schema(responses={200: AgenticOnboardingRunSerializer})
@extend_schema(
responses={
200: AgenticOnboardingRunSerializer,
404: RESPONSE_NOT_FOUND,
409: RESPONSE_CONFLICT,
}
)
def delete(self, request: Request, organization: Organization, run_id: str) -> Response:
user_id = require_user(request).id
try:
Expand Down
4 changes: 3 additions & 1 deletion src/sentry/api/endpoints/organization_events_facets.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from sentry.api.bases import NoProjects, OrganizationEventsEndpointBase
from sentry.api.paginator import GenericOffsetPaginator
from sentry.api.utils import handle_query_errors, update_snuba_params_with_timestamp
from sentry.apidocs.constants import RESPONSE_NOT_FOUND
from sentry.apidocs.utils import inline_sentry_response_serializer
from sentry.models.organization import Organization
from sentry.search.utils import DEVICE_CLASS
Expand All @@ -38,7 +39,8 @@ class OrganizationEventsFacetsEndpoint(OrganizationEventsEndpointBase):
responses={
200: inline_sentry_response_serializer(
"OrganizationEventsFacetsResponse", list[_KeyTopValues]
)
),
404: RESPONSE_NOT_FOUND,
},
)
def get(self, request: Request, organization: Organization) -> Response:
Expand Down
4 changes: 3 additions & 1 deletion src/sentry/api/endpoints/organization_events_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
transform_query_columns_for_error_upsampling,
)
from sentry.api.serializers.snuba import StatsTimeSeriesResult
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST
from sentry.apidocs.utils import inline_sentry_response_serializer
from sentry.auth.principal import acting_user
from sentry.constants import MAX_TOP_EVENTS
Expand Down Expand Up @@ -123,7 +124,8 @@ def check_if_results_have_data(self, results: SnubaTSResult | dict[str, SnubaTSR
200: inline_sentry_response_serializer(
"OrganizationEventsStatsResponse",
StatsTimeSeriesResult | dict[str, StatsTimeSeriesResult],
)
),
400: RESPONSE_BAD_REQUEST,
},
)
def get(self, request: Request, organization: Organization) -> Response:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class OrganizationProfilingFlamegraphEndpoint(OrganizationProfilingBaseEndpoint)
200: inline_sentry_response_serializer(
"OrganizationProfilingFlamegraphResponse", dict[str, Any]
),
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: RESPONSE_FORBIDDEN,
404: RESPONSE_NOT_FOUND,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ class OrganizationTraceItemAttributesEndpoint(OrganizationTraceItemAttributesEnd
200: inline_sentry_response_serializer(
"ListTraceItemAttributesResponse", list[TraceItemAttributeKey]
),
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: RESPONSE_FORBIDDEN,
404: RESPONSE_NOT_FOUND,
Expand Down
8 changes: 7 additions & 1 deletion src/sentry/api/endpoints/organization_trace_item_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@
)
from sentry.api.serializers.base import serialize
from sentry.api.utils import handle_query_errors
from sentry.apidocs.constants import RESPONSE_FORBIDDEN, RESPONSE_NOT_FOUND, RESPONSE_UNAUTHORIZED
from sentry.apidocs.constants import (
RESPONSE_BAD_REQUEST,
RESPONSE_FORBIDDEN,
RESPONSE_NOT_FOUND,
RESPONSE_UNAUTHORIZED,
)
from sentry.apidocs.examples.trace_item_stats_examples import TraceItemStatsExamples
from sentry.apidocs.omissions import sentry_schema_serializer
from sentry.apidocs.parameters import CursorQueryParam, GlobalParams, OrganizationParams
Expand Down Expand Up @@ -206,6 +211,7 @@ class OrganizationTraceItemStatsEndpoint(OrganizationEventsEndpointBase):
200: inline_sentry_response_serializer(
"TraceItemStatsResponse", TraceItemStatsResponse
),
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: RESPONSE_FORBIDDEN,
404: RESPONSE_NOT_FOUND,
Expand Down
3 changes: 3 additions & 0 deletions src/sentry/apidocs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@
# 409
RESPONSE_CONFLICT = OpenApiResponse(description="Conflict")

# 410
RESPONSE_GONE = OpenApiResponse(description="Gone")

# 429
RESPONSE_TOO_MANY_REQUESTS = OpenApiResponse(description="Too Many Requests")
3 changes: 3 additions & 0 deletions src/sentry/core/endpoints/organization_member_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
RESPONSE_FORBIDDEN,
RESPONSE_NO_CONTENT,
RESPONSE_NOT_FOUND,
RESPONSE_TOO_MANY_REQUESTS,
RESPONSE_UNAUTHORIZED,
)
from sentry.apidocs.examples.organization_examples import OrganizationExamples
Expand Down Expand Up @@ -199,6 +200,7 @@ def get(
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: RESPONSE_FORBIDDEN,
429: RESPONSE_TOO_MANY_REQUESTS,
},
examples=OrganizationExamples.UPDATE_ORG_MEMBER,
)
Expand Down Expand Up @@ -494,6 +496,7 @@ def _handle_deletion_by_member(
],
responses={
204: RESPONSE_NO_CONTENT,
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: RESPONSE_FORBIDDEN,
404: RESPONSE_NOT_FOUND,
Expand Down
10 changes: 9 additions & 1 deletion src/sentry/core/endpoints/organization_member_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
from sentry.api.serializers import serialize
from sentry.api.serializers.models.organization_member import OrganizationMemberSerializer
from sentry.api.serializers.models.organization_member.response import OrganizationMemberResponse
from sentry.apidocs.constants import RESPONSE_FORBIDDEN, RESPONSE_NOT_FOUND, RESPONSE_UNAUTHORIZED
from sentry.apidocs.constants import (
RESPONSE_BAD_REQUEST,
RESPONSE_FORBIDDEN,
RESPONSE_NOT_FOUND,
RESPONSE_TOO_MANY_REQUESTS,
RESPONSE_UNAUTHORIZED,
)
from sentry.apidocs.examples.organization_member_examples import OrganizationMemberExamples
from sentry.apidocs.parameters import CursorQueryParam, GlobalParams, OrganizationParams
from sentry.apidocs.response_types import (
Expand Down Expand Up @@ -346,9 +352,11 @@ def get(
request=OrganizationMemberRequestSerializer,
responses={
201: OrganizationMemberSerializer,
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: RESPONSE_FORBIDDEN,
404: RESPONSE_NOT_FOUND,
429: RESPONSE_TOO_MANY_REQUESTS,
},
examples=OrganizationMemberExamples.CREATE_ORG_MEMBER,
)
Expand Down
1 change: 1 addition & 0 deletions src/sentry/core/endpoints/organization_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class OrganizationProjectsEndpoint(OrganizationEndpoint):
200: inline_sentry_response_serializer(
"OrganizationProjectResponseDict", list[OrganizationProjectResponse]
),
400: RESPONSE_BAD_REQUEST,
401: RESPONSE_UNAUTHORIZED,
403: RESPONSE_FORBIDDEN,
404: RESPONSE_NOT_FOUND,
Expand Down
8 changes: 7 additions & 1 deletion src/sentry/core/endpoints/organization_teams.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
from sentry.api.paginator import OffsetPaginator
from sentry.api.serializers import serialize
from sentry.api.serializers.models.team import TeamSerializer, TeamSerializerResponse
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST, RESPONSE_FORBIDDEN, RESPONSE_NOT_FOUND
from sentry.apidocs.constants import (
RESPONSE_BAD_REQUEST,
RESPONSE_CONFLICT,
RESPONSE_FORBIDDEN,
RESPONSE_NOT_FOUND,
)
from sentry.apidocs.examples.team_examples import TeamExamples
from sentry.apidocs.omissions import sentry_schema_serializer
from sentry.apidocs.parameters import (
Expand Down Expand Up @@ -200,6 +205,7 @@ def should_add_creator_to_team(self, request: Request) -> bool:
400: RESPONSE_BAD_REQUEST,
403: RESPONSE_FORBIDDEN,
404: OpenApiResponse(description="A team with this slug already exists."),
409: RESPONSE_CONFLICT,
},
examples=TeamExamples.CREATE_TEAM,
)
Expand Down
Loading
Loading