FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects
Commit f9d6e611 authored by E. Evstafiev's avatar E. Evstafiev :bulb:
Browse files

feat: add operation IDs to API endpoints for enhanced documentation clarity

parent c04003e0
No related branches found
No related tags found
1 merge request!52Resolve "Ensure OpenAPI specification is generated correctly"
Pipeline #650062 passed
......@@ -9,32 +9,49 @@ from rest_framework import generics
from api.v1alpha.serializers import AccountSerializer, MethodNotAllowedErrorSerializer
@extend_schema(
tags=["account management"],
summary="Manage Account Details",
description="Retrieves or updates the account details of the currently logged-in user.",
responses={
200: OpenApiResponse(
response=AccountSerializer,
description="Successful retrieval or update of account details.",
),
204: OpenApiResponse(
description="Successful update with no content to return when updating certain fields."
),
405: OpenApiResponse(
response=MethodNotAllowedErrorSerializer,
description=(
"Returned when attempting to perform an operation not allowed "
"by this endpoint, such as using an unsupported HTTP method "
"or modifying restricted fields."
),
),
},
methods=["GET", "PATCH"],
)
class AccountDetailsView(generics.RetrieveUpdateAPIView):
serializer_class = AccountSerializer
http_method_names = ["get", "patch", "options", "head"]
def get_object(self):
return self.request.user
@extend_schema(
tags=["account management"],
summary="Retrieve Account Details",
description="Retrieves the account details of the currently logged-in user.",
responses={
200: OpenApiResponse(
response=AccountSerializer,
description="Successful retrieval of account details.",
),
},
methods=["GET"],
operation_id="getAccountDetails",
)
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
@extend_schema(
tags=["account management"],
summary="Update Account Details",
description="Updates the account details of the currently logged-in user.",
responses={
200: OpenApiResponse(
response=AccountSerializer,
description="Successful update of account details.",
),
204: OpenApiResponse(
description="Successful update with no content to return "
"when updating certain fields."
),
405: OpenApiResponse(
response=MethodNotAllowedErrorSerializer,
description="Attempted to perform an unsupported operation.",
),
},
methods=["PATCH"],
operation_id="updateAccountDetails",
)
def patch(self, request, *args, **kwargs):
return super().patch(request, *args, **kwargs)
......@@ -22,25 +22,29 @@ def build_version_response_schema():
return {version_name: serializers.CharField() for version_name in AVAILABLE_VERSIONS}
@extend_schema(
summary="List API Versions",
description=(
"Lists the available versions of the API, responding with a dictionary of version "
"name to the url that version can be accessed at"
),
tags=["api versioning"],
responses={
200: OpenApiResponse(
response=inline_serializer(name="APIVersions", fields=build_version_response_schema()),
description="A dictionary of version name to the url that version can be accessed at",
),
},
)
class VersionsView(APIView):
# Disable versioning for this viewset as there will not be a 'version' param
# in the url.
versioning_class = None
@extend_schema(
summary="List API Versions",
description=(
"Lists the available versions of the API, responding with a dictionary of version "
"name to the url that version can be accessed at"
),
tags=["api versioning"],
responses={
200: OpenApiResponse(
response=inline_serializer(
name="APIVersions", fields=build_version_response_schema()
),
description="A dictionary of version name to the url "
"that version can be accessed at",
),
},
operation_id="getVersions",
)
def get(self, request):
return Response(
{
......
......@@ -12,22 +12,6 @@ from authentication.serializers import (
)
@extend_schema(
summary="Authenticate a User",
description="Authenticates a user and returns an access token.",
request=TokenRequestSerializer,
responses={
200: TokenResponseSerializer,
400: OpenApiResponse(
response=TokenErrorSerializer,
description=(
"Invalid request, such as both or none of crsid and last name are provided, "
"or no matching user."
),
),
},
tags=["authentication"],
)
class LoginView(KnoxLoginView):
throttle_classes = ()
permission_classes = ()
......@@ -44,6 +28,23 @@ class LoginView(KnoxLoginView):
kwargs["context"] = self.get_serializer_context()
return self.serializer_class(*args, **kwargs)
@extend_schema(
summary="Authenticate a User",
description="Authenticates a user and returns an access token.",
request=TokenRequestSerializer,
responses={
200: TokenResponseSerializer,
400: OpenApiResponse(
response=TokenErrorSerializer,
description=(
"Invalid request, such as both or none of crsid and last name are provided, "
"or no matching user."
),
),
},
tags=["authentication"],
operation_id="authenticateUser",
)
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
......@@ -92,21 +93,6 @@ class LoginView(KnoxLoginView):
return exception_handler
@extend_schema(
tags=["authentication"],
summary="Log out User",
description="Logs out the current logged-in user by revoking their authentication token.",
responses={
204: OpenApiResponse(
response=EmptySerializer, description="Successfully logged out, no content to return."
),
401: OpenApiResponse(
response=TokenErrorSerializer,
description="Unauthorized request, possibly due to an invalid token.",
),
},
methods=["POST"],
)
class LogoutView(views.APIView):
throttle_classes = ()
versioning_class = None
......@@ -116,28 +102,28 @@ class LogoutView(views.APIView):
def get_post_response(self, request):
return Response(None, status=status.HTTP_204_NO_CONTENT)
@extend_schema(
tags=["authentication"],
summary="Log out User",
description="Logs out the current logged-in user by revoking their authentication token.",
responses={
204: OpenApiResponse(
response=EmptySerializer,
description="Successfully logged out, no content to return.",
),
401: OpenApiResponse(
response=TokenErrorSerializer,
description="Unauthorized request, possibly due to an invalid token.",
),
},
methods=["POST"],
operation_id="logoutUser",
)
def post(self, request, format=None):
request._auth.delete()
return self.get_post_response(request)
@extend_schema(
tags=["authentication"],
summary="Log out from All Sessions",
description="Logs out the current logged-in user from all sessions by revoking all their "
"authentication tokens.",
responses={
204: OpenApiResponse(
response=EmptySerializer,
description="Successfully logged out from all sessions, no content to return.",
),
401: OpenApiResponse(
response=TokenErrorSerializer,
description="Unauthorized request, possibly due to an invalid token.",
),
},
methods=["POST"],
)
class LogoutAllView(views.APIView):
throttle_classes = ()
versioning_class = None
......@@ -147,6 +133,24 @@ class LogoutAllView(views.APIView):
def get_post_response(self, request):
return Response(None, status=status.HTTP_204_NO_CONTENT)
@extend_schema(
tags=["authentication"],
summary="Log out from All Sessions",
description="Logs out the current logged-in user from all sessions by revoking all their "
"authentication tokens.",
responses={
204: OpenApiResponse(
response=EmptySerializer,
description="Successfully logged out from all sessions, no content to return.",
),
401: OpenApiResponse(
response=TokenErrorSerializer,
description="Unauthorized request, possibly due to an invalid token.",
),
},
methods=["POST"],
operation_id="logoutFromAllSessions",
)
def post(self, request, format=None):
request.user.auth_token_set.all().delete()
return self.get_post_response(request)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment