baseline: Clover 独立仓库首次基线提交

将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。
当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包),
M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
yangqianqian
2026-06-16 11:30:22 +08:00
commit 6a2632da70
253 changed files with 27467 additions and 0 deletions

View 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,
}