-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Fix (api): Removes duplicated entries from the patterns, and also fixes the schema url name to contain the namespace * Typing (users): Add Token reverse accessor for User model * Feat (users): Adds services to authenticate * Feat (api): Adds authentication classes and openapi extensions * Feat (api): Adds auth endpoints * Fix (conf): Updates the default CSRF_TRUSTED_ORIGINS to point to the new ngrok domain * Fix (conf): ngrok CSRF * Feat (api): Adds metadata class that takes value from the Schema class defined from the extend_schema decorator * Feat (app): Adds consts for HTTP statuses * Fix (api): Openapi enhancements and requires documented responses for errors defined on raises * Feat (dev): Add fixtures script and adds type checking code branches to coverage ignore * Feat (users): adds api for current user and authentication. Adds tests * Fix (dev): Updates launch configuration to overeride USE_DEBUG_TOOLBAR to false * Fix (notifications): Adds a method for defining/removing a notification/token. Adds tests for the api and some fixes with them * Fix (conf): Removes update last login from the drf-simple-jwt serializers, we take care of updating them
- Loading branch information
1 parent
c3bd926
commit 4018105
Showing
40 changed files
with
1,193 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import urls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from rest_framework import serializers | ||
|
||
from app.consts.i18n import Language, TimeZoneName | ||
from app.drf.fields import create_choice_human_field | ||
from users.models import User | ||
|
||
|
||
class AuthenticationInputSchema(serializers.Serializer): | ||
username = serializers.CharField() | ||
password = serializers.CharField() | ||
|
||
|
||
class StaticTokenSchema(serializers.Serializer): | ||
type = serializers.CharField(default="Token") | ||
access = serializers.CharField() | ||
refresh = serializers.CharField(default=None) | ||
|
||
|
||
class JwtTokenSchema(serializers.Serializer): | ||
type = serializers.CharField(default="Bearer") | ||
access = serializers.CharField() | ||
refresh = serializers.CharField() | ||
|
||
|
||
LanguageChoiceField = create_choice_human_field(Language) | ||
TimeZoneNameChoiceField = create_choice_human_field(TimeZoneName) | ||
|
||
|
||
class _AuthenticationOutputSchema(serializers.ModelSerializer): | ||
language_code = LanguageChoiceField() | ||
time_zone = TimeZoneNameChoiceField() | ||
token = serializers.CharField(default=None) | ||
|
||
class Meta: | ||
model = User | ||
fields = ( | ||
"id", | ||
"email", | ||
"full_name", | ||
"language_code", | ||
"time_zone", | ||
"token", | ||
) | ||
|
||
|
||
class TokenAuthenticationOutputSchema(_AuthenticationOutputSchema): | ||
token = StaticTokenSchema() | ||
|
||
|
||
class JwtTokenAuthenticationOutputSchema(_AuthenticationOutputSchema): | ||
token = JwtTokenSchema() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from rest_framework.routers import SimpleRouter | ||
|
||
from . import views | ||
|
||
router = SimpleRouter(trailing_slash=False) | ||
router.register("", views.AuthenticationViewSet, basename="auth") | ||
|
||
urlpatterns = router.urls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
from dataclasses import dataclass | ||
from typing import Literal | ||
|
||
from rest_framework.decorators import action | ||
from rest_framework.permissions import AllowAny | ||
from rest_framework.request import Request | ||
from rest_framework.response import Response | ||
from rest_framework_simplejwt import serializers as jwt_schemas | ||
|
||
from app.consts.http import HttpStatusCode | ||
from app.drf.openapi import openapi_schema | ||
from app.drf.viewsets import AppViewSet | ||
from users.services import auth | ||
|
||
from . import schemas | ||
|
||
|
||
@dataclass | ||
class TokenDTO: | ||
type: Literal["Token", "Bearer"] | ||
access: str | ||
refresh: str | None = None | ||
|
||
|
||
class AuthenticationViewSet(AppViewSet): | ||
permission_classes = [AllowAny] | ||
|
||
@openapi_schema( | ||
summary="Token authentication", | ||
description="Authenticates and returns a static Token that can be " | ||
"used to access protected endpoints", | ||
request=schemas.AuthenticationInputSchema, | ||
responses={HttpStatusCode.HTTP_200_OK: schemas.TokenAuthenticationOutputSchema}, | ||
tags=["auth"], | ||
operation_id="authentication:token", | ||
add_bad_request_response=True, | ||
add_unauthorized_response=True, | ||
raises=[auth.InactiveOrInexistentAccount, auth.InvalidCredentials], | ||
) | ||
@action(methods=["POST"], detail=False, url_path="token") | ||
def token(self, request: Request): | ||
data = self.get_valid_data(srlzr_class=schemas.AuthenticationInputSchema) | ||
user, token = auth.token_authenticate(**data) | ||
user.token = TokenDTO(type="Token", access=token.key, refresh=None) # type: ignore | ||
srlzr = schemas.TokenAuthenticationOutputSchema(instance=user) | ||
return Response(data=srlzr.data, status=200) | ||
|
||
@openapi_schema( | ||
summary="JWT authentication", | ||
description="Authenticates and returns a JWT Token that can be " | ||
"used to access protected endpoints", | ||
request=schemas.AuthenticationInputSchema, | ||
responses={HttpStatusCode.HTTP_200_OK: schemas.JwtTokenAuthenticationOutputSchema}, | ||
tags=["auth"], | ||
operation_id="authentication:jwt-token", | ||
add_bad_request_response=True, | ||
add_unauthorized_response=True, | ||
raises=[auth.InactiveOrInexistentAccount, auth.InvalidCredentials], | ||
) | ||
@action(methods=["POST"], detail=False, url_path="jwt") | ||
def jwt_token(self, request: Request): | ||
data = self.get_valid_data(srlzr_class=schemas.AuthenticationInputSchema) | ||
user = auth.authenticate(**data) | ||
|
||
refresh = jwt_schemas.TokenObtainPairSerializer().get_token(user) | ||
token = TokenDTO(type="Bearer", access=str(refresh.access_token), refresh=str(refresh)) | ||
user.token = token # type: ignore | ||
srlzr = schemas.JwtTokenAuthenticationOutputSchema(instance=user) | ||
return Response(data=srlzr.data, status=200) | ||
|
||
@openapi_schema( | ||
summary="JWT Refresh", | ||
description="Refreshes the given access token", | ||
request=jwt_schemas.TokenRefreshSerializer, | ||
responses={HttpStatusCode.HTTP_200_OK: jwt_schemas.TokenRefreshSerializer}, | ||
tags=["auth"], | ||
operation_id="authentication:jwt-refresh", | ||
add_bad_request_response=True, | ||
) | ||
@action(methods=["POST"], detail=False, url_path="jwt/refresh") | ||
def jwt_refresh(self, request: Request): | ||
return Response( | ||
data=self.get_valid_data(srlzr_class=jwt_schemas.TokenRefreshSerializer), | ||
status=200, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
from django.urls import include, path | ||
|
||
from . import push_notifications | ||
from . import auth, push_notifications, users | ||
|
||
urlpatterns = [ | ||
path("auth/", include((auth.urls, "auth"), namespace="auth")), | ||
path( | ||
"notifications/", | ||
include((push_notifications.urls, "push_notifications"), namespace="push_notifications"), | ||
), | ||
path("users/", include((users.urls, "users"), namespace="users")), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import urls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from rest_framework import serializers | ||
|
||
from api.v1.auth.schemas import LanguageChoiceField, TimeZoneNameChoiceField | ||
from users.models import User | ||
|
||
|
||
class CurrentUserOutputSchema(serializers.ModelSerializer): | ||
language_code = LanguageChoiceField() | ||
time_zone = TimeZoneNameChoiceField() | ||
|
||
class Meta: | ||
model = User | ||
fields = ( | ||
"id", | ||
"email", | ||
"full_name", | ||
"notification_token", | ||
"language_code", | ||
"time_zone", | ||
"date_joined", | ||
"is_staff", | ||
"is_superuser", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from rest_framework.routers import SimpleRouter | ||
|
||
from . import views | ||
|
||
router = SimpleRouter(trailing_slash=False) | ||
router.register("me", views.CurrentUserViewSet, basename="me") | ||
|
||
urlpatterns = router.urls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
from rest_framework.decorators import action | ||
from rest_framework.request import Request | ||
from rest_framework.response import Response | ||
|
||
from app.consts.http import HttpStatusCode | ||
from app.drf.openapi import openapi_schema | ||
from app.drf.viewsets import AppViewSet | ||
from users.services import account | ||
|
||
from . import schemas | ||
|
||
|
||
class CurrentUserViewSet(AppViewSet): | ||
@openapi_schema( | ||
summary="Current user", | ||
description="Returns details about the current user", | ||
request=None, | ||
responses={HttpStatusCode.HTTP_200_OK: schemas.CurrentUserOutputSchema}, | ||
tags=["users:me"], | ||
operation_id="users-me", | ||
add_unauthorized_response=True, | ||
) | ||
def list(self, request: Request) -> Response: | ||
srlzr = schemas.CurrentUserOutputSchema(instance=request.user) | ||
return Response(srlzr.data) | ||
|
||
@openapi_schema( | ||
summary="Delete account", | ||
description="Deletes the account for the current user", | ||
request=None, | ||
responses={HttpStatusCode.HTTP_204_NO_CONTENT: None}, | ||
tags=["users:me"], | ||
operation_id="users-me-delete-account", | ||
add_unauthorized_response=True, | ||
) | ||
@action(methods=["DELETE"], detail=False, url_name="delete-account", url_path="account") | ||
def delete_account(self, request: Request) -> Response: | ||
account.user_delete_account(user=request.user) | ||
return Response(status=204) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.