feat: initialize aivideo project
This commit is contained in:
123
backend/app/modules/auth/service.py
Normal file
123
backend/app/modules/auth/service.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import Request, Response
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.common.errors.app_error import AuthenticationError, ConflictAppError
|
||||
from app.common.security.jwt import (
|
||||
clear_auth_cookies,
|
||||
create_access_token,
|
||||
create_refresh_token,
|
||||
decode_refresh_token,
|
||||
set_auth_cookies,
|
||||
)
|
||||
from app.common.security.password import hash_password, verify_password
|
||||
from app.common.utils.id_gen import new_public_id
|
||||
from app.models.entities import InviteCode, InviteRelation, User, Wallet
|
||||
from app.modules.auth.repository import AuthRepository
|
||||
from app.modules.wallets.service import WalletService
|
||||
|
||||
|
||||
class AuthService:
|
||||
def __init__(self, db: Session) -> None:
|
||||
self.db = db
|
||||
self.repository = AuthRepository(db)
|
||||
self.wallet_service = WalletService(db)
|
||||
|
||||
def register(self, payload, request: Request, response: Response) -> dict:
|
||||
if self.repository.get_user_by_account(payload.account):
|
||||
raise ConflictAppError("account already exists", code=10010)
|
||||
|
||||
user = User(
|
||||
public_id=new_public_id("usr"),
|
||||
email=payload.account,
|
||||
password_hash=hash_password(payload.password),
|
||||
nickname=payload.account.split("@")[0],
|
||||
status=1,
|
||||
register_ip=request.client.host if request.client else "",
|
||||
last_login_ip=request.client.host if request.client else "",
|
||||
last_login_at=datetime.utcnow(),
|
||||
)
|
||||
self.db.add(user)
|
||||
self.db.flush()
|
||||
self.db.add(Wallet(user_id=user.id))
|
||||
self.db.flush()
|
||||
self._bind_invite_relation(user.id, payload.invite_code, request)
|
||||
self.wallet_service.try_issue_signup_reward(user.id)
|
||||
self.db.commit()
|
||||
self.db.refresh(user)
|
||||
self._issue_tokens(user.public_id, response)
|
||||
return self.serialize_user(user)
|
||||
|
||||
def login(self, payload, request: Request, response: Response) -> dict:
|
||||
user = self.repository.get_user_by_account(payload.account)
|
||||
if not user or not verify_password(payload.password, user.password_hash):
|
||||
raise AuthenticationError("invalid credentials")
|
||||
user.last_login_at = datetime.utcnow()
|
||||
user.last_login_ip = request.client.host if request.client else ""
|
||||
self.db.commit()
|
||||
self._issue_tokens(user.public_id, response)
|
||||
return self.serialize_user(user)
|
||||
|
||||
def refresh(self, refresh_token: str | None, response: Response) -> dict:
|
||||
if not refresh_token:
|
||||
raise AuthenticationError()
|
||||
try:
|
||||
payload = decode_refresh_token(refresh_token)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise AuthenticationError() from exc
|
||||
if payload.get("scope") != "user":
|
||||
raise AuthenticationError()
|
||||
user = self.repository.get_user_by_public_id(payload["sub"])
|
||||
if not user:
|
||||
raise AuthenticationError()
|
||||
self._issue_tokens(user.public_id, response)
|
||||
return self.serialize_user(user)
|
||||
|
||||
def logout(self, response: Response) -> None:
|
||||
clear_auth_cookies(response, prefix="user")
|
||||
|
||||
@staticmethod
|
||||
def serialize_user(user: User) -> dict:
|
||||
return {
|
||||
"publicId": user.public_id,
|
||||
"username": user.username or "",
|
||||
"nickname": user.nickname,
|
||||
"avatarUrl": user.avatar_url,
|
||||
"email": user.email or "",
|
||||
"mobile": user.mobile or "",
|
||||
"status": user.status,
|
||||
}
|
||||
|
||||
def _issue_tokens(self, public_id: str, response: Response) -> None:
|
||||
access_token = create_access_token(public_id, scope="user")
|
||||
refresh_token = create_refresh_token(public_id, scope="user")
|
||||
set_auth_cookies(response, access_token, refresh_token, prefix="user")
|
||||
|
||||
def _bind_invite_relation(
|
||||
self,
|
||||
invitee_user_id: int,
|
||||
invite_code_value: str | None,
|
||||
request: Request,
|
||||
) -> None:
|
||||
if not invite_code_value:
|
||||
return
|
||||
invite_code = self.db.query(InviteCode).filter(
|
||||
InviteCode.invite_code == invite_code_value,
|
||||
InviteCode.status == 1,
|
||||
).first()
|
||||
if not invite_code:
|
||||
return
|
||||
self.db.add(
|
||||
InviteRelation(
|
||||
inviter_user_id=invite_code.user_id,
|
||||
invitee_user_id=invitee_user_id,
|
||||
invite_code_id=invite_code.id,
|
||||
reward_status="pending",
|
||||
reward_points=0,
|
||||
register_ip=request.client.host if request.client else "",
|
||||
)
|
||||
)
|
||||
invite_code.used_count += 1
|
||||
Reference in New Issue
Block a user