Files
Pulse-API/solution/pulse/api/users/views.py
T

178 lines
5.4 KiB
Python

from datetime import timedelta
import bcrypt
import jwt
from django.conf import settings
from django.utils import timezone
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from api.users.models import Profile
from api.users.permissions import CanAccessProfile
from api.users.serializers import (
ProfileSerializer,
PublicProfileSerializer,
UpdateProfileSerializer,
)
class RegisterUserApiView(APIView):
def post(self, request):
serializer = ProfileSerializer(data=request.data)
if serializer.is_valid():
errors = Profile.check_unique(None, serializer.validated_data)
if errors:
return Response(errors, status=status.HTTP_409_CONFLICT)
password = serializer.validated_data["password"]
password_hash = bcrypt.hashpw(
password.encode("utf-8"), bcrypt.gensalt()
).decode("utf-8")
serializer.validated_data["password"] = password_hash
user = serializer.save()
profile = {
"profile": {
"login": user.login,
"email": user.email,
"countryCode": user.countryCode,
"isPublic": user.isPublic,
}
}
if user.phone is not None:
profile["profile"]["phone"] = user.phone
if user.image is not None:
profile["profile"]["image"] = user.image
return Response(profile, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class SigninUserApiView(APIView):
def post(self, request):
login = request.data.get("login")
password = request.data.get("password")
user = Profile.objects.filter(login=login).first()
if user is not None:
if not bcrypt.checkpw(
password.encode("utf-8"), user.password.encode("utf-8")
):
return Response(
{"error": "Invalid credentials"},
status=status.HTTP_401_UNAUTHORIZED,
)
else:
return Response(
{"error": "Invalid credentials"},
status=status.HTTP_401_UNAUTHORIZED,
)
token = jwt.encode(
{
"id": user.id,
"password": password,
"exp": timezone.now() + timedelta(hours=24),
},
settings.SECRET_KEY,
algorithm="HS256",
)
return Response({"token": token})
class ProfileMeApiView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
profile_data = self._get_profile_data(user)
return Response(profile_data)
def patch(self, request):
user = request.user
serializer = UpdateProfileSerializer(
user, data=request.data, partial=True
)
if serializer.is_valid():
errors = Profile.check_unique(user.id, serializer.validated_data)
if errors:
return Response(errors, status=status.HTTP_409_CONFLICT)
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def _get_profile_data(self, user):
profile = {
"login": user.login,
"email": user.email,
"countryCode": user.countryCode,
"isPublic": user.isPublic,
}
if user.phone is not None:
profile["phone"] = user.phone
if user.image is not None:
profile["image"] = user.image
return profile
class ProfileAPIView(APIView):
permission_classes = [IsAuthenticated, CanAccessProfile]
def get(self, request, login):
try:
profile = Profile.objects.get(login=login)
self.check_object_permissions(request, profile)
serializer = PublicProfileSerializer(profile)
return Response(serializer.data)
except Profile.DoesNotExist:
return Response(
{"detail": "Profile not found."},
status=status.HTTP_403_FORBIDDEN,
)
class AddFriendAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
login = request.data.get("login")
profile = Profile.objects.get(login=login)
request.user.add_friend(profile)
return Response(
{"status": "ok"},
status=status.HTTP_200_OK,
)
except Profile.DoesNotExist:
return Response(
{"detail": "Profile not found."},
status=status.HTTP_404_NOT_FOUND,
)
class RemoveFriendAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
login = request.data.get("login")
profile = Profile.objects.get(login=login)
request.user.remove_friend(profile)
return Response(
{"status": "ok"},
status=status.HTTP_200_OK,
)
except Profile.DoesNotExist:
return Response(
{"detail": "Profile not found."},
status=status.HTTP_404_NOT_FOUND,
)