baseline: Clover 独立仓库首次基线提交
将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。 当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包), M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
71
backend/app/services/auth_service.py
Normal file
71
backend/app/services/auth_service.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
app/services/auth_service.py — 认证 service
|
||||
密码哈希校验、用户查找、响应格式化。
|
||||
路由层不含业务逻辑,全在此。
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from passlib.context import CryptContext
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.response import raise_unauthorized
|
||||
from app.middleware.workspace_guard import CurrentUser
|
||||
from app.models.user import User
|
||||
from app.models.workspace import WorkspaceMember
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
|
||||
def hash_password(plain: str) -> str:
|
||||
return pwd_context.hash(plain)
|
||||
|
||||
|
||||
def verify_password(plain: str, hashed: str) -> bool:
|
||||
return pwd_context.verify(plain, hashed)
|
||||
|
||||
|
||||
def authenticate_user(
|
||||
db: Session, username: str, password: str
|
||||
) -> tuple[User, int, str]:
|
||||
"""
|
||||
验证用户名+密码,返回 (user, workspace_id, role)。
|
||||
失败抛 CloverHTTPException 40101。
|
||||
"""
|
||||
user = db.query(User).filter(
|
||||
User.username == username, User.is_active == True
|
||||
).first()
|
||||
if not user or not verify_password(password, user.hashed_password):
|
||||
raise_unauthorized("用户名或密码错误")
|
||||
|
||||
# 取用户所在的第一个 workspace(手动建账号场景只有一个)
|
||||
member = (
|
||||
db.query(WorkspaceMember)
|
||||
.filter(WorkspaceMember.user_id == user.id)
|
||||
.first()
|
||||
)
|
||||
if not member:
|
||||
raise_unauthorized("用户未加入任何 workspace,请联系管理员")
|
||||
|
||||
# 记录登录
|
||||
try:
|
||||
from app.models.user import LoginRecord
|
||||
db.add(LoginRecord(user_id=user.id))
|
||||
db.commit()
|
||||
except Exception:
|
||||
logger.warning("Failed to write login_record for user=%s", user.id)
|
||||
db.rollback()
|
||||
|
||||
return user, member.workspace_id, member.role
|
||||
|
||||
|
||||
def build_user_response(user: User, workspace_id: int, role: str) -> dict:
|
||||
"""格式化用户响应体(契约§4 DTO)。"""
|
||||
return {
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"email": user.email,
|
||||
"current_workspace_id": workspace_id,
|
||||
"role": role,
|
||||
}
|
||||
Reference in New Issue
Block a user