Files
amb_rag/backend/app/services/auth_service.py
T
2026-09-01 13:00:36 +08:00

86 lines
3.1 KiB
Python

"""认证服务:注册、登录、登出、Session 校验。"""
from app.core.errors import (
AuthRequiredError,
ConflictError,
InvalidCredentialsError,
)
from app.core.security import hash_password, verify_password
from app.core.session import create_session, delete_session, get_session_user
from app.models.user import User
from app.repositories.plan_repo import PlanRepository
from app.repositories.user_repo import UserRepository
from sqlalchemy.orm import Session
class AuthService:
def __init__(self, session: Session) -> None:
self._session = session
self._user_repo = UserRepository(session)
self._plan_repo = PlanRepository(session)
def register(self, username: str, email: str, password: str) -> tuple[User, str]:
"""注册新用户。返回 (user, session_token)。
Raises:
ConflictError: 用户名或邮箱已存在
"""
username_taken, email_taken = self._user_repo.exists_username_or_email(username, email)
if username_taken:
raise ConflictError("用户名已被占用。", code="USERNAME_TAKEN")
if email_taken:
raise ConflictError("邮箱已被注册。", code="EMAIL_TAKEN")
plan = self._plan_repo.get_or_create_free()
user = self._user_repo.create(
username=username,
email=email,
password_hash=hash_password(password),
plan_id=plan.id,
)
self._session.commit()
token = create_session(user.id)
return user, token
def login(self, username_or_email: str, password: str) -> tuple[User, str]:
"""登录。返回 (user, session_token)。
Raises:
InvalidCredentialsError: 用户名/邮箱或密码错误
"""
user = self._user_repo.get_by_username_or_email(username_or_email)
if user is None:
raise InvalidCredentialsError()
if not verify_password(password, user.password_hash):
raise InvalidCredentialsError()
if user.status != "active":
raise InvalidCredentialsError("账户已被禁用。")
token = create_session(user.id)
return user, token
def logout(self, session_token: str) -> None:
"""登出:删除 session。"""
delete_session(session_token)
def get_current_user(self, session_token: str | None) -> User:
"""根据 session token 获取当前用户。
Raises:
AuthRequiredError: 未登录或 session 已过期
"""
if not session_token:
raise AuthRequiredError()
user_id = get_session_user(session_token)
if user_id is None:
raise AuthRequiredError("登录已过期,请重新登录。")
user = self._user_repo.get_by_id(user_id)
if user is None or user.status != "active":
raise AuthRequiredError()
return user
def change_password(self, user: User, new_password: str) -> None:
"""修改密码。"""
self._user_repo.update_password(user, hash_password(new_password))
self._session.commit()