[PROJECT] KUKKA CLONING #3

김기현·2022년 3월 12일
0

project_cakoo

목록 보기
3/7
post-thumbnail

거의 모든 사이트에는 회원가입과 로그인이 필요한데요...!

우아한 꾸까 커머스의 회원가입 페이지입니다.
이메일로 회원가입을 할 때 나타나는 화면은 다음과 같습니다~

westagram에서의 회원가입 미션처럼 차근히 진행합니다..!

회원가입

config/url

from django.urls import path, include

urlpatterns = [
    path("users", include('users.urls')),

]

users/urls

from django.urls import path
from users.views import SignUpView

urlpatterns = [
    path("/signup", SignUpView.as_view()),
] 

여기서 URI의 마지막 문자로 /를 사용하지 않아야 합니다. /는 자원의 계층관계를 나타낼 때 사용되는데, URI의 마지막 문자로 /를 사용하면 quyery 파라미터나 path 파라미터를 사용하는데 제한이 걸립니다.

validator

import re

def validate_email(email):
    email_regex = r'^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
    return re.match(email_regex, email)
             
def validate_password(password):
    password_regex = r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$'
    return re.match(password_regex, password)
 

정규식을 통해 email과 password가 validate한지 파악합니다.
^$로 각각 시작과 끝임을 지정하고 원하는 정규식을 입력합니다.
다음의 사이트를 참고하였습니다.

users/view

import json, bcrypt

from django.http  import JsonResponse
from django.views import View

from users.models     import User
from users.validators import validate_email, validate_password


class SignUpView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)

            name         = data["name"],
            email        = data['email']
            password     = data['password']
            phone_number = data['phone_number']
            birthdate    = data["birthdate"]

            hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

            if not validate_email(email):
                return JsonResponse({'message' : 'Invalid Email!'}, status = 400)
            
            if not validate_password(password):
                return JsonResponse({'message' : 'Invalid Password!'}, status = 400)
            
            if User.objects.filter(email = email).exists():
                return JsonResponse({'message' : 'Email Already Exists!'}, status = 400)

            User.objects.create(
                name         = name,
                email        = email,
                password     = hashed_password,
                phone_number = phone_number,
                birthdate    = birthdate
                
            )
            return JsonResponse({"message": "User Created!"}, status=201)

        except KeyError:
            return JsonResponse({"message": "KEY_ERROR"}, status=400)

bcrypt라는 라이브러리를 import하여 비밀번호를 encoding하고 랜덤의 값을 salting하여 유추하지 못하게 hashing합니다.

json을 response할 때 보통 Message보다는 message처럼 소문자 구성을 많이 사용함을 새로 알았습니다.

로그인

users/urls

from django.urls import path
from users.views import SignUpView, SignInView

urlpatterns = [
    path("/signup", SignUpView.as_view()),
    path("/signin", SignInView.as_view()),
] 

users/utils

import jwt

from django.http        import JsonResponse
from .models            import User
from config.settings    import SECRET_KEY, ALGORITHM

def login_decorator(func):
    def wrapper(self, request, *args, **kwargs):
        try:
            if 'Authorization' not in request.headers:
                return JsonResponse({"message" : "NO AUTHORIZATION IN HEADER"}, status = 401)
            
            access_token = request.headers.get('Authorization')           
            payload      = jwt.decode(access_token, SECRET_KEY, ALGORITHM)
            user_id      = payload['user_id']
         
            if not User.objects.filter(id = user_id).exists():
                return JsonResponse({"message" : "INVALID_UESR"}, status = 401)

            request.user = User.objects.get(id = user_id)

            return func(self, request, *args, **kwargs)
        
        except jwt.exceptions.DecodeError:
            return JsonResponse({"message" : "INVALID_TOKEN"}, status = 400)
        
        except KeyError:
            return JsonResponse({"message" : "KEY_ERROR"}, status = 400)

    return wrapper

users/view

class SignInView(View):
    def post(self, request):
        try:
            data            = json.loads(request.body)
            signin_email    = data['email']
            signin_password = data['password']

            if not User.objects.filter(email = signin_email).exists():
                return JsonResponse({"message" : "INVALID_UESR"}, status = 401)

            user         = User.objects.get(email = signin_email)
            access_token = jwt.encode({'user_id' : user.id}, SECRET_KEY, ALGORITHM)
            
            if not bcrypt.checkpw(signin_password.encode('utf-8'), user.password.encode('utf-8')):
                return JsonResponse({"message" : "INVALID_UESR"}, status = 401)

            return JsonResponse({"message" : "SUCCESS", "access_token" : access_token}, status = 200)
            
        except KeyError:
            return JsonResponse({"message" : "KEY_ERROR"}, status = 400)
profile
피자, 코드, 커피를 사랑하는 피코커

0개의 댓글