-
Notifications
You must be signed in to change notification settings - Fork 4
로그인 & 회원가입
hyukjunkim1116 edited this page Jul 6, 2023
·
3 revisions
✔️ 로그인
- 로그인 시 fetch를 사용하여 DB에 있는 이메일과 PW를 가져와 사용자가 입력한 값과 비교해서 값이 일치할 때 로그인 허용
- 로그인 시 2시간 동안 jwt 토큰을 로컬스토리지에 저장
- 소셜 로그인시 이메일이 기존에 있는지 파악후 중복되면 로그인 제한
💻 code
users/serializers.py
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token["id"] = user.id
token["email"] = user.email
token["username"] = user.username
token["login_type"] = user.login_type
token["avatar"] = user.avatar
return token
users/views.py
def social_login_validate(**kwargs):
data = {k: v for k, v in kwargs.items()}
email = data.get("email")
login_type = data.get("login_type")
if not email:
return Response(
{"error": "해당 계정에 email정보가 없습니다."}, status=status.HTTP_400_BAD_REQUEST
)
try:
user = User.objects.get(email=email)
if login_type == user.login_type:
refresh = RefreshToken.for_user(user)
access_token = serializers.CustomTokenObtainPairSerializer.get_token(user)
return Response(
{"refresh": str(refresh), "access": str(access_token.access_token)},
status=status.HTTP_200_OK,
)
else:
return Response(
{"error": f"{user.login_type}으로 이미 가입된 계정이 있습니다!"},
status=status.HTTP_400_BAD_REQUEST,
)
except User.DoesNotExist:
# with transaction.atomic():
new_user = User.objects.create(**data)
new_user.set_unusable_password()
new_user.save()
refresh = RefreshToken.for_user(new_user)
access_token = serializers.CustomTokenObtainPairSerializer.get_token(new_user)
html = render_to_string(
"users/email_welcome.html",
{
"front_base_url": settings.FRONT_BASE_URL,
"user": new_user,
},
)
to_email = new_user.email
send_mail(
"안녕하세요 Cookai입니다. 회원가입을 축하드립니다!",
"_",
settings.DEFAULT_FROM_MAIL,
[to_email],
html_message=html,
)
return Response(
{"refresh": str(refresh), "access": str(access_token.access_token)},
status=status.HTTP_200_OK,
)
📷 View
Image
✔️ 회원가입
- 회원가입 시 이메일 인증을 통해 유효한 이메일인지 확인한다.
- 비밀번호 전용 validator를 생성하여 모델에 적용.
- 이메일 유무, 유저 존재 유무 비밀번호와 확인 비밀번호가 일치하는지 판단 후 유저 생성
- 이메일 인증이 완료되면 유저의 is_active=True로 변경.
💻 code
users/views.py
class UserView(APIView):
def post(self, request):
email = request.data.get("email")
password = request.data.get("password")
password2 = request.data.get("second_password")
username = request.data.get("username")
if not password or not password2:
return Response(
{"error": "비밀번호 입력은 필수입니다!"}, status=status.HTTP_400_BAD_REQUEST
)
if not email:
return Response(
{"error": "이메일 입력은 필수입니다!"}, status=status.HTTP_400_BAD_REQUEST
)
if password != password2:
return Response(
{"error": "비밀번호가 일치하지 않습니다!"}, status=status.HTTP_400_BAD_REQUEST
)
if User.objects.filter(email=email).exists():
return Response(
{"error": "해당 이메일을 가진 유저가 이미 있습니다!"}, status=status.HTTP_400_BAD_REQUEST
)
if User.objects.filter(username=username).exists():
return Response(
{"error": "해당 닉네임을 가진 유저가 이미 있습니다!"}, status=status.HTTP_400_BAD_REQUEST
)
serializer = UserSerializer(
data=request.data,
context={"request": request},
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(
serializer.errors,
status=status.HTTP_400_BAD_REQUEST,
)
users/validators.py
def validate_password(password):
if len(password) < 8:
raise ValidationError({"password": "비밀번호는 8자리 이상이어야 합니다."})
if not re.search(r"[a-zA-Z]", password):
raise ValidationError({"password": "비밀번호는 하나 이상의 영문이 포함되어야 합니다."})
if not re.search(r"\d", password):
raise ValidationError({"password": "비밀번호는 하나 이상의 숫자가 포함되어야 합니다."})
if not re.search(r"[!@#$%^&*()]", password):
raise ValidationError(
{"password": "비밀번호는 적어도 하나 이상의 특수문자(!@#$%^&*())가 포함되어야 합니다."}
)
return password
users/validators.py
class UserSignUpPermitView(APIView):
def get(self, request, uidb64, token):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
if account_activation_token.check_token(user, token):
User.objects.filter(pk=uid).update(is_active=True)
html = render_to_string(
"users/email_welcome.html",
{
"front_base_url": settings.FRONT_BASE_URL,
"user": user,
},
)
to_email = user.email
send_mail(
"안녕하세요 Cookai입니다. 회원가입을 축하드립니다!",
"_",
settings.DEFAULT_FROM_MAIL,
[to_email],
html_message=html,
)
return redirect(f"{settings.FRONT_BASE_URL}/login.html")
return Response({"error": "AUTH_FAIL"}, status=status.HTTP_400_BAD_REQUEST)
except:
return Response({"error": "KEY_ERROR"}, status=status.HTTP_400_BAD_REQUEST)
📷 View