feat: register done

This commit is contained in:
akhdanre 2025-03-19 22:35:02 +07:00
parent bc5094ed7d
commit c06b7ab899
21 changed files with 126 additions and 45 deletions

View File

@ -1,5 +1,6 @@
from .default import default_blueprint
from .auth import auth_blueprint
from .user import user_blueprint
# from .user import user_blueprint

View File

@ -1,4 +1,3 @@
import sys
from flask import Blueprint
from controllers import AuthController
from di_container import Container
@ -8,12 +7,6 @@ from dependency_injector.wiring import inject, Provide
auth_blueprint = Blueprint("auth", __name__)
@auth_blueprint.route("/register", methods=["POST"])
@inject
def register(auth_controller: AuthController = Provide[Container.auth_controller]):
return auth_controller.register()
@auth_blueprint.route("/login", methods=["POST"])
@inject
def login(auth_controller: AuthController = Provide[Container.auth_controller]):

View File

@ -1,12 +1,18 @@
from flask import Blueprint
from controllers import UserController
from di_container import container
from di_container import Container
from dependency_injector.wiring import inject, Provide
user_blueprint = Blueprint("user", __name__)
user_controller = UserController(container.user_service)
@user_blueprint.route("/users", methods=["GET"])
def get_users():
@inject
def get_users(user_controller: UserController = Provide[Container.user_controller]):
return user_controller.get_users()
@user_blueprint.route("/register", methods=["POST"])
@inject
def register(user_controller: UserController = Provide[Container.user_controller]):
return user_controller.register()

View File

@ -4,7 +4,7 @@ from schemas.basic_response_schema import ResponseSchema
from schemas.google_login_schema import GoogleLoginSchema
from schemas import LoginSchema
from services import UserService, AuthService
from core import AuthException
from exception import AuthException
class AuthController:
@ -17,10 +17,10 @@ class AuthController:
data = request.get_json()
dataSchema = LoginSchema(**data)
response = self.auth_service.login(dataSchema)
if response.success:
return jsonify({}), 200
return jsonify({}), 400
return (
jsonify(ResponseSchema(message="Register success", data=response)),
200,
)
except ValidationError as e:
current_app.logger.error(f"Validation error: {e}")
response = ResponseSchema(message="Invalid input", data=None, meta=None)
@ -79,11 +79,5 @@ class AuthController:
)
return jsonify(response.model_dump()), 500
def register(self):
return jsonify({"message": "register"}), 200
def logout(self):
return jsonify({"message": "logout"}), 200
def test(self):
return "test"

View File

@ -1,12 +1,41 @@
# /controllers/user_controller.py
from flask import jsonify
from flask import jsonify, request, current_app
from services import UserService
from schemas import RegisterSchema
from pydantic import ValidationError
from schemas import ResponseSchema
from exception import AlreadyExistException
class UserController:
def __init__(self, userService: UserService):
self.user_service = userService
def get_users(self):
users = self.user_service.get_all_users()
return jsonify(users)
def register(self):
try:
request_data = request.get_json()
register_data = RegisterSchema(**request_data)
self.user_service.register_user(register_data)
return jsonify(ResponseSchema(message="Register Success").model_dump()), 200
except ValidationError as e:
current_app.logger.error(f"Validation error: {e}")
response = ResponseSchema(message="Invalid input", data=None, meta=None)
return jsonify(response.model_dump()), 400
except AlreadyExistException as e:
return (
jsonify(
ResponseSchema(message=str(e), data=None, meta=None).model_dump()
),
409,
)
except Exception as e:
current_app.logger.error(
f"Error during Google login: {str(e)}", exc_info=True
)
response = ResponseSchema(
message="Internal server error", data=None, meta=None
)
return jsonify(response.model_dump()), 500

View File

@ -1 +0,0 @@
from .exception import AuthException

View File

@ -1 +0,0 @@
from .auth_exception import AuthException

View File

@ -1,9 +0,0 @@
class AuthException(Exception):
"""Custom exception for authentication-related errors"""
def __init__(self, message):
super().__init__(message)
self.message = message
def __str__(self):
return f"AuthException: {self.message}"

View File

@ -1,4 +1,5 @@
from dependency_injector import containers, providers
from controllers import UserController
from repositories.user_repository import UserRepository
from services import UserService, AuthService
from controllers import AuthController
@ -19,3 +20,4 @@ class Container(containers.DeclarativeContainer):
# controllers
auth_controller = providers.Factory(AuthController, user_service, auth_service)
user_controller = providers.Factory(UserController, user_service)

View File

@ -0,0 +1,2 @@
from .auth_exception import AuthException
from .already_exist_exception import AlreadyExistException

View File

@ -0,0 +1,6 @@
class AlreadyExistException(Exception):
def __init__(self, entity: str, message: str = None):
if message is None:
message = f"{entity} already exists"
self.message = message
super().__init__(self.message)

View File

@ -0,0 +1,8 @@
from .base_exception import BaseExceptionTemplate
class AuthException(BaseExceptionTemplate):
"""Exception for authentication-related errors"""
def __init__(self, message: str = "Authentication failed"):
super().__init__(message, status_code=401)

View File

@ -0,0 +1,10 @@
class BaseExceptionTemplate(Exception):
"""Base exception template for custom exceptions"""
def __init__(self, message: str, status_code: int = 400):
self.message = message
self.status_code = status_code
super().__init__(self.message)
def __str__(self):
return f"{self.__class__.__name__}: {self.message}"

View File

@ -2,7 +2,7 @@ from blueprints import default_blueprint
from di_container import Container
from configs import Config, LoggerConfig
from flask import Flask
from blueprints import auth_blueprint
from blueprints import auth_blueprint, user_blueprint
from database import init_db
@ -19,10 +19,12 @@ def createApp() -> Flask:
container.mongo.override(mongo)
container.wire(modules=["blueprints.auth"])
container.wire(modules=["blueprints.user"])
# Register Blueprints
app.register_blueprint(default_blueprint)
app.register_blueprint(auth_blueprint, url_prefix="/api")
app.register_blueprint(user_blueprint, url_prefix="/api")
# Initialize Logging
LoggerConfig.init_logger(app)

View File

@ -1,6 +1,7 @@
from datetime import datetime
from typing import Dict, Optional
from models import UserEntity
from schemas import RegisterSchema
class UserMapper:
@ -22,3 +23,19 @@ class UserMapper:
updated_at=datetime.now(),
verification_token=None,
)
@staticmethod
def from_register(data: RegisterSchema) -> UserEntity:
return UserEntity(
email=data.email,
password=data.password,
name=data.name,
birth_date=datetime.strptime(data.birth_date, "%d-%m-%Y").date(),
phone=data.phone,
role="user",
is_active=False,
address=None,
created_at=datetime.now(),
updated_at=datetime.now(),
verification_token=None,
)

View File

@ -1,6 +1,6 @@
from typing import Optional
from pydantic import BaseModel, EmailStr
from datetime import date, datetime
from datetime import datetime
from .base import PyObjectId
@ -10,7 +10,7 @@ class UserEntity(BaseModel):
email: EmailStr
password: Optional[str] = None
name: str
birth_date: Optional[date] = None
birth_date: Optional[datetime] = None
pic_url: Optional[str] = None
phone: Optional[str] = None
locale: str = "en-US"

View File

@ -1,2 +1,3 @@
from .login_schema import LoginSchema
from .basic_response_schema import ResponseSchema, MetaSchema
from .requests import RegisterSchema

View File

@ -0,0 +1 @@
from .register_schema import RegisterSchema

View File

@ -0,0 +1,10 @@
from pydantic import BaseModel
from typing import Optional
class RegisterSchema(BaseModel):
email: str
password: str
name: str
birth_date: str
phone: Optional[str] = None

View File

@ -4,7 +4,7 @@ from mapper import UserMapper
from google.oauth2 import id_token
from google.auth.transport import requests
from configs import Config
from core import AuthException
from exception import AuthException
from flask import current_app
@ -13,14 +13,12 @@ class AuthService:
self.user_repository = userRepository
def verify_google_id_token(self, id_token_str):
# Verifikasi token Google
payload = id_token.verify_oauth2_token(
id_token_str, requests.Request(), Config.GOOGLE_CLIENT_ID
)
if not payload:
return AuthException("Invalid Google ID Token")
raise AuthException("Invalid Google ID Token")
google_id = payload.get("sub")
email = payload.get("email")
@ -29,7 +27,7 @@ class AuthService:
if existing_user:
if existing_user.email == email:
return existing_user
return AuthException("Email not match")
raise AuthException("Email not match")
new_user = UserMapper.from_google_payload(google_id, email, payload)

View File

@ -1,4 +1,8 @@
from flask import current_app
from repositories import UserRepository
from schemas import RegisterSchema
from mapper import UserMapper
from exception import AlreadyExistException
class UserService:
@ -7,3 +11,11 @@ class UserService:
def get_all_users(self):
return self.user_repository.get_all_users()
def register_user(self, user_data: RegisterSchema):
existData = self.user_repository.get_user_by_email(user_data.email)
if existData:
raise AlreadyExistException(entity="Email")
data = UserMapper.from_register(user_data)
return self.user_repository.insert_user(data)