Skip to content

Commit

Permalink
fix: User LocalAuth 분리 및 api 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
200516bb committed Jul 24, 2023
1 parent 20e5347 commit 6ff7de5
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 37 deletions.
27 changes: 13 additions & 14 deletions app/api/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import requests

from app.models.user import SocialAuth, User
from app.models.user import LocalAuth, SocialAuth, User
from app.utils.user import UserDTO, UserService
from app.decorators.login_required import login_required
from app.utils.error_handler import InvalidTokenError
Expand Down Expand Up @@ -74,14 +74,12 @@ def post(self):
"""
content = request.json
user_dto = UserDTO(
uid=content['id'],
password=content['password'],
name=content['name'],
gender=content['gender'],
birth=content['birth'],
phone=content['phone']
)
UserService.create_user(user_dto)
UserService.create_local_user(user_dto, content['id'], content['password'])
return { 'message': '회원가입 되었습니다' }, 200


Expand All @@ -92,7 +90,7 @@ def get(self, id):
"""
IdDupCheck
"""
dupUserId = User.query.filter_by(uid=id).first()
dupUserId = LocalAuth.query.filter_by(id=id).first()
if dupUserId is None:
return { 'dup': False }, 200
return { 'dup' : True }, 200
Expand All @@ -109,24 +107,24 @@ def post(self):
"""
content = request.json

u = User.query.filter_by(uid=content['id']).first()
u = LocalAuth.query.filter_by(id=content['id']).first()
if u is None:
return { 'message' : '아이디가 존재하지 않습니다.' }, 400
if u.deleted_at is not None:
if u.user.deleted_at is not None:
return { 'message' : '탈퇴한 회원입니다.' }, 400
if bcrypt.checkpw(content['password'].encode('UTF-8'), u.password.encode('UTF-8')):
access_payload = {
'id': str(u.id),
'id': str(u.user_id),
'access_token_exp': (datetime.datetime.now() + datetime.timedelta(minutes=60*24)).isoformat()
}
access_token = jwt.encode(access_payload, os.getenv('SECRET_KEY'), algorithm="HS256")

refresh_payload = {
'id': str(u.id),
'id': str(u.user_id),
'refresh_token_exp': (datetime.datetime.now() + datetime.timedelta(minutes=60*24*60)).isoformat()
}
refresh_token = jwt.encode(refresh_payload, os.getenv('SECRET_KEY'), algorithm="HS256")
return { 'access_token': access_token, 'refresh_token': refresh_token, 'user_id': u.uid }, 200
return { 'access_token': access_token, 'refresh_token': refresh_token, 'user_id': u.id }, 200
else:
return { 'message' : '비밀번호를 잘못 입력하였습니다.' }, 400

Expand All @@ -145,7 +143,8 @@ def post(self):

if u is None:
return { 'message' : '유저가 존재하지 않습니다.' }, 400
return { 'message': u.uid }, 200
user = LocalAuth.query.filter_by(user_id=u.id).first()
return { 'message': user.id }, 200

@user.route('/find/password', methods=['PUT'])
class FindPassword(Resource):
Expand All @@ -161,7 +160,7 @@ def put(self):
if token is None:
return { 'message' : 'token을 입력해주세요.' }, 400

u = User.query.filter_by(reset_pw=token).first()
u = LocalAuth.query.join(User, User.id == LocalAuth.user_id).filter(User.reset_pw==token).first()
if u is None:
return { 'message' : '인증에 실패했습니다.' }, 400

Expand All @@ -180,7 +179,7 @@ def post(self):
CheckInform
"""
content = request.json
u = User.query.filter_by(uid=content['id'], phone=content['phone']).first()
u = User.query.join(LocalAuth, LocalAuth.user_id == User.id).filter(LocalAuth.id == content['id'], User.phone == content['phone']).first()

if u is None:
return { 'message' : False }, 200
Expand Down Expand Up @@ -230,7 +229,7 @@ def post(self):
CheckPassword
"""
content = request.json
user = g.user
user = g.local_auth
if bcrypt.checkpw(content['password'].encode('UTF-8'), user.password.encode('UTF-8')):
return { 'message' : True }, 200
else:
Expand Down
4 changes: 3 additions & 1 deletion app/decorators/login_required.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import jwt
import datetime
from flask import g, request
from app.models.user import User
from app.models.user import LocalAuth, User
from app.utils.error_handler import InvalidTokenError


Expand All @@ -21,9 +21,11 @@ def decorated_function(*args, **kwargs):
if datetime.datetime.fromisoformat(access_token_exp) < datetime.datetime.now():
raise InvalidTokenError("access token expired", 403, 403)
u = User.query.filter_by(id=user_id).first()
local_auth = LocalAuth.query.filter_by(user_id=user_id).first()
if u is not None and u.deleted_at is None:
g.user_id = user_id
g.user = u
g.local_auth = local_auth
else:
g.user = None
raise InvalidTokenError("user not found")
Expand Down
2 changes: 0 additions & 2 deletions app/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

class User(db.Model):
id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
uid = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
name = db.Column(db.String(150), nullable=False)
gender = db.Column(db.String(10), nullable=False)
birth = db.Column(db.DateTime(), nullable=False)
Expand Down
84 changes: 64 additions & 20 deletions app/utils/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,26 @@
from app.utils.error_handler import SignUpFail, UserFail
import datetime
from app.models import db
from app.models.user import SocialAuth, User, Notification, UserNotification
from app.models.user import LocalAuth, SocialAuth, User, Notification, UserNotification
import bcrypt
import re
from flask import g

@dataclass
class UserDTO:
id: Union[UUID, None]
uid: str
password: str
name: str
gender: str
birth: datetime
phone: str

def __init__(self, uid, password, name, gender, birth, phone, id=None):
self.uid = uid
self.password = password
def __init__(self, name, gender, birth, phone, id=None):
self.name = name
self.gender = gender
self.birth = birth
self.phone = phone
self.id = id

if not uid:
raise SignUpFail("아이디는 필수 입력 항목입니다.")
if not password:
raise SignUpFail("비밀번호는 필수 입력 항목입니다.")
if not name:
raise SignUpFail("이름은 필수 입력 항목입니다.")
if not gender:
Expand All @@ -44,8 +36,6 @@ def __init__(self, uid, password, name, gender, birth, phone, id=None):
def to_model(self) -> User:
return User(
id=self.id,
uid=self.uid,
password=self.password,
name=self.name,
gender=self.gender,
birth=self.birth,
Expand Down Expand Up @@ -102,7 +92,7 @@ def find_password(user, password):


def update_password(password):
user = User.query.filter_by(id=g.user_id).first()
user = LocalAuth.query.filter_by(user_id=g.user_id).first()
if user is None:
raise UserFail("존재하지 않는 유저입니다.")

Expand All @@ -120,11 +110,59 @@ def create_user(user) -> 'UserDTO':
"""
새로운 유저를 생성합니다.
"""
# uid_pattern = r'^[a-z0-9]{6,15}$'
# pw_pattern = r'^[a-zA-Z0-9!@#$%^&*()_+{}|:"<>?~\[\]\\;\',./]{8,16}$'
phone_pattern = r'^01([0|1|6|7|8|9])?([0-9]{3,4})?([0-9]{4})$'
# uid_reg = bool(re.match(uid_pattern, user.uid))
# pw_reg = bool(re.match(pw_pattern, user.password))
phone_reg = bool(re.match(phone_pattern, user.phone))
# if not uid_reg:
# raise SignUpFail("아이디 형식이 잘못되었습니다. (6~15 영문소, 숫)")
# if not pw_reg:
# raise SignUpFail("비밀번호 형식이 잘못되었습니다. (8~16 영문대소, 숫, 특수)")
if not phone_reg:
raise SignUpFail("전화번호 형식이 잘못되었습니다. (01012345678 형식))")

# dup_user_id = User.query.filter_by(uid=user.uid).first()
dup_phone = User.query.filter_by(phone=user.phone).first()

# if dup_user_id is not None:
# raise SignUpFail("중복된 아이디가 존재합니다.")
if dup_phone is not None:
raise SignUpFail("중복된 전화번호가 존재합니다.")

# new_password = bcrypt.hashpw(user.password.encode('UTF-8'), bcrypt.gensalt())

user_dto = UserDTO(
id=None,
name=user.name,
gender=user.gender,
birth=user.birth,
phone=user.phone
)
user_dto.save()

notifications = Notification.query.all()
for notification in notifications:
user_notification = UserNotification(
user_id=user_dto.id,
notification_id=notification.id,
is_enabled=True
)
db.session.add(user_notification)
db.session.commit()
return user_dto


def create_local_user(user, id, password) -> 'UserDTO':
"""
새로운 로컬 유저를 생성합니다.
"""
uid_pattern = r'^[a-z0-9]{6,15}$'
pw_pattern = r'^[a-zA-Z0-9!@#$%^&*()_+{}|:"<>?~\[\]\\;\',./]{8,16}$'
phone_pattern = r'^01([0|1|6|7|8|9])?([0-9]{3,4})?([0-9]{4})$'
uid_reg = bool(re.match(uid_pattern, user.uid))
pw_reg = bool(re.match(pw_pattern, user.password))
uid_reg = bool(re.match(uid_pattern, id))
pw_reg = bool(re.match(pw_pattern, password))
phone_reg = bool(re.match(phone_pattern, user.phone))
if not uid_reg:
raise SignUpFail("아이디 형식이 잘못되었습니다. (6~15 영문소, 숫)")
Expand All @@ -133,27 +171,33 @@ def create_user(user) -> 'UserDTO':
if not phone_reg:
raise SignUpFail("전화번호 형식이 잘못되었습니다. (01012345678 형식))")

dup_user_id = User.query.filter_by(uid=user.uid).first()
dup_user_id = LocalAuth.query.filter_by(id=id).first()
dup_phone = User.query.filter_by(phone=user.phone).first()

if dup_user_id is not None:
raise SignUpFail("중복된 아이디가 존재합니다.")
if dup_phone is not None:
raise SignUpFail("중복된 전화번호가 존재합니다.")

new_password = bcrypt.hashpw(user.password.encode('UTF-8'), bcrypt.gensalt())
new_password = bcrypt.hashpw(password.encode('UTF-8'), bcrypt.gensalt())

user_dto = UserDTO(
id=None,
uid=user.uid,
password=new_password.decode('UTF-8'),
name=user.name,
gender=user.gender,
birth=user.birth,
phone=user.phone
)
user_dto.save()

local_user = LocalAuth(
id=id,
user_id=user_dto.id,
password=new_password.decode('UTF-8'),
)
db.session.add(local_user)
db.session.commit()

notifications = Notification.query.all()
for notification in notifications:
user_notification = UserNotification(
Expand All @@ -165,7 +209,7 @@ def create_user(user) -> 'UserDTO':
db.session.commit()
return user_dto


def create_social_auth(user_dto, content):
social_user = SocialAuth(
id=content['id'],
Expand Down

0 comments on commit 6ff7de5

Please sign in to comment.