Files
colio/users/views.py

260 lines
12 KiB
Python

from django.conf import settings
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.viewsets import ReadOnlyModelViewSet
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenRefreshSerializer, TokenObtainSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.exceptions import TokenError, InvalidToken
from rest_framework import status
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from django.contrib.auth import authenticate
from django.db.models import Case, When, Value, IntegerField, Q
from .models import *
from .serializers import *
from .services import *
from projects.serializers import *
from portfolios.serializers import *
from django.db import transaction
class RefreshAPIView(APIView):
permission_classes = [AllowAny]
# access token 재발급
@transaction.atomic
def post(self, request):
refresh = request.COOKIES.get("refresh")
if not refresh:
return Response({"message": "No refresh token"}, status=status.HTTP_400_BAD_REQUEST)
if request.data.get("user_id", None) != RefreshToken(refresh).payload.get("user_id", None):
return Response({"message": "Wrong userid"}, status=status.HTTP_400_BAD_REQUEST)
try:
serializer = TokenRefreshSerializer(data={'refresh': refresh})
if serializer.is_valid():
res = Response({"access": serializer.validated_data['access']}, status=status.HTTP_200_OK)
res.set_cookie("refresh", serializer.validated_data['refresh'], httponly=True, samesite=None, secure=not settings.DEBUG)
return res
except TokenError as e:
return Response({"message": f"Invalid token: {e}"}, status=status.HTTP_401_UNAUTHORIZED)
class JoinAPIView(APIView):
permission_classes = [AllowAny]
# 회원가입
@transaction.atomic
def post(self, request):
serializer = JoinSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
access = str(RefreshToken.for_user(user).access_token)
res = Response({
"message": "회원가입이 완료되었습니다.",
"access": access
}, status=status.HTTP_200_OK)
return res
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class LoginAPIView(APIView):
permission_classes = [AllowAny]
# 로그인
@transaction.atomic
def post(self, request):
email=request.data.get("email", None)
password=request.data.get("password", None)
# 로그인 전 쿠키에 있는 리프레시 토큰 무효화
try:
refresh = request.COOKIES.get('refresh')
if refresh:
refresh_token = RefreshToken(refresh)
refresh_token.blacklist()
except TokenError as e:
pass
if user := authenticate(email=email, password=password):
serializer = TokenObtainPairSerializer(data={'email': email, 'password': password})
# id, 비번 맞나 틀리나 검사
if serializer.is_valid():
res = Response(
{
"message": "login success",
"user_id": user.id,
"nickname": user.nickname,
"access": serializer.validated_data['access'],
"is_custom_url": user.is_custom_url
},
status=status.HTTP_200_OK,
)
res.set_cookie("refresh", serializer.validated_data['refresh'], httponly=True, samesite=None, secure=not settings.DEBUG)
return res
else:
return Response(serializer.errors)
else: # id, 비번 둘 중 하나가 틀렸을 때
return Response({"message": "아이디 혹은 비밀번호가 맞지 않습니다."}, status=status.HTTP_400_BAD_REQUEST)
class CheckUserFieldDuplicateAPIView(APIView):
permission_classes = [AllowAny]
# 유저 필드 중복 확인
def get(self, request):
field = request.query_params.get('field')
value = request.query_params.get('value')
if not field or not value:
return Response({"message": "올바르지 않은 요청입니다."}, status=status.HTTP_400_BAD_REQUEST)
try:
if CheckUserFieldDuplicateService.check_duplicate(field, value):
return Response({"message": f"존재하는 {field} 입니다."}, status=status.HTTP_400_BAD_REQUEST)
else:
return Response({"message": f"사용해도 되는 {field} 입니다."}, status=status.HTTP_200_OK)
except ValueError as e:
return Response({"message": str(e)}, status=status.HTTP_400_BAD_REQUEST)
class TagUserAPIView(APIView):
def get(self, request):
nickname = request.query_params.get('nickname')
users = User.objects.filter(nickname__icontains=nickname).annotate(
priority=Case(
When(nickname__iexact=nickname, then=Value(0)),
default=Value(1),
output_field=IntegerField()
)
).order_by('priority').values('profile_image', 'nickname')[:5]
serializer = TagUserSerializer(users, many=True)
return Response({'users': serializer.data})
class SetPortofolioRequiredInfoAPIView(APIView):
def get(self, request):
custom_url = request.GET.get('custom_url', None)
if not custom_url:
return Response({"message": "no url"}, status=status.HTTP_400_BAD_REQUEST)
if User.objects.filter(custom_url=custom_url).exists():
return Response({"message": "already used url"}, status=status.HTTP_400_BAD_REQUEST)
else:
return Response({"message": "can use this url"}, status=status.HTTP_200_OK)
@transaction.atomic
def patch(self, request):
user = request.user
serializer = SetPortofolioRequiredInfoSerializer(user, data=request.data)
if serializer.is_valid():
serializer.save()
user.is_custom_url = True
user.save()
return Response({"message": "updated successfully"}, status=status.HTTP_202_ACCEPTED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# 마이페이지 관련
class MyPageProfileAPIView(APIView):
# 프로필 조회(안 읽은 알림 수)
def get(self, request, nickname):
target_user = get_object_or_404(User, nickname=nickname)
user = request.user
serializer = UserProfileSerializer(target_user)
data = serializer.data
data['represent_portfolio_id'] = UserToPortfolioService.get_represent_portfolio(target_user)
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK)
# 프로필 수정
@transaction.atomic
def patch(self, request, nickname):
target_user = get_object_or_404(User, nickname=nickname)
user = request.user
if user == target_user:
serializer = UserProfileSerializer(user, request.data, partial=True)
if serializer.is_valid():
serializer.save()
data = serializer.data
data['represent_portfolio_id'] = UserToPortfolioService.get_represent_portfolio(target_user)
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response({"message": "Not account owner"}, status=status.HTTP_400_BAD_REQUEST)
class MyPageWorkListAPIView(APIView):
# 포폴, 플젝, 작업중, 스크랩 조회(안 읽은 알림 수)
def get(self, request, nickname):
target_user = get_object_or_404(User, nickname=nickname)
user = request.user
retreive_type = request.query_params.get('type')
data = {}
if retreive_type == 'portfolio':
portfolios = UserToPortfolioService.get_published_portfolio(target_user)
serializer = PortfolioListViewSerializer(portfolios, many=True)
data = {
"portfolios": serializer.data
}
elif retreive_type == 'project':
solo_projects = UserToProjectService.get_published_solo_project(target_user)
team_projects = UserToProjectService.get_published_team_project(target_user)
sp_serializer = ProjectListViewSerializer(solo_projects, many=True)
tp_serializer = ProjectListViewSerializer(team_projects, many=True)
data = {
"solo_projects": sp_serializer.data,
"team_projects": tp_serializer.data,
}
elif retreive_type == 'working':
if user != target_user:
return Response({"message": "Not account owner"}, status=status.HTTP_400_BAD_REQUEST)
portfolios = UserToPortfolioService.get_unpublished_portfolio(target_user)
solo_projects = UserToProjectService.get_unpublished_solo_project(target_user)
team_projects = UserToProjectService.get_unpublished_team_project(target_user)
po_serializer = PortfolioListViewSerializer(portfolios, many=True)
sp_serializer = ProjectListViewSerializer(solo_projects, many=True)
tp_serializer = ProjectListViewSerializer(team_projects, many=True)
data = {
"portfolios": po_serializer.data,
"solo_projects": sp_serializer.data,
"team_projects": tp_serializer.data,
}
elif retreive_type == 'scrap':
if user != target_user:
return Response({"message": "Not account owner"}, status=status.HTTP_400_BAD_REQUEST)
portfolios = UserToPortfolioService.get_scrap_portfolio(target_user)
po_serializer = PortfolioListViewSerializer(portfolios, many=True)
projects = UserToProjectService.get_scrap_project(target_user)
pr_serializer = ProjectListViewSerializer(projects, many=True)
data = {
"portfolios": po_serializer.data,
"projects": pr_serializer.data,
}
else:
return Response({"message": "not allowed retreive_type"}, status=status.HTTP_400_BAD_REQUEST)
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK)
class MyPageMemberInfoAPIView(APIView):
# 내 정보 조회(안 읽은 알림 수)
def get(self, request):
user = request.user
serializer = UserMemberInfoSerializer(user)
data = serializer.data
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK)
# 내 정보 수정
@transaction.atomic
def patch(self, request):
user = request.user
serializer = UserMemberInfoSerializer(user, request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)