2025-02-14 16:31:12 +07:00

127 lines
4.0 KiB
Python

"""all user api views"""
from common.serializers import ErrorResponseSerializer
from common.views import ApiBaseView
from django.contrib.auth import authenticate, login, logout
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from user.models import Account
from user.serializers import (
AccountSerializer,
LoginSerializer,
UserMeConfigSerializer,
)
from user.src.user_config import UserConfig
class UserAccountView(ApiBaseView):
"""resolves to /api/user/account/
GET: return current user account
"""
@extend_schema(
responses=AccountSerializer(),
)
def get(self, request):
"""get user account"""
user_id = request.user.id
account = Account.objects.get(id=user_id)
account_serializer = AccountSerializer(account)
return Response(account_serializer.data)
class UserConfigView(ApiBaseView):
"""resolves to /api/user/me/
GET: return current user config
POST: update user config
"""
@extend_schema(responses=UserMeConfigSerializer())
def get(self, request):
"""get user config"""
config = UserConfig(request.user.id).get_config()
serializer = UserMeConfigSerializer(config)
return Response(serializer.data)
@extend_schema(
request=UserMeConfigSerializer(required=False),
responses={
200: UserMeConfigSerializer(),
400: OpenApiResponse(
ErrorResponseSerializer(), description="Bad request"
),
},
)
def post(self, request):
"""update config, allows partial update"""
data_serializer = UserMeConfigSerializer(
data=request.data, partial=True
)
data_serializer.is_valid(raise_exception=True)
validated_data = data_serializer.validated_data
UserConfig(request.user.id).update_config(to_update=validated_data)
config = UserConfig(request.user.id).get_config()
serializer = UserMeConfigSerializer(config)
return Response(serializer.data)
@method_decorator(csrf_exempt, name="dispatch")
class LoginApiView(APIView):
"""resolves to /api/user/login/
POST: return token and username after successful login
"""
permission_classes = [AllowAny]
SEC_IN_DAY = 60 * 60 * 24
@extend_schema(
request=LoginSerializer(),
responses={204: OpenApiResponse(description="login successful")},
)
def post(self, request, *args, **kwargs):
"""login with username and password"""
# pylint: disable=no-member
data_serializer = LoginSerializer(data=request.data)
data_serializer.is_valid(raise_exception=True)
validated_data = data_serializer.validated_data
username = validated_data["username"]
password = validated_data["password"]
remember_me = validated_data.get("remember_me")
user = authenticate(request, username=username, password=password)
if user is None:
error = ErrorResponseSerializer({"error": "Invalid credentials"})
return Response(error.data, status=400)
if remember_me == "on":
request.session.set_expiry(self.SEC_IN_DAY * 365)
else:
request.session.set_expiry(self.SEC_IN_DAY * 2)
print(f"expire session in {request.session.get_expiry_age()} secs")
login(request, user) # Creates a session for the user
return Response(status=204)
class LogoutApiView(ApiBaseView):
"""resolves to /api/user/logout/
POST: handle logout
"""
@extend_schema(
responses={204: OpenApiResponse(description="logout successful")}
)
def post(self, request, *args, **kwargs):
"""logout user from session"""
logout(request)
return Response(status=204)