from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.schemas.user import TokenResponse, WecomLoginRequest, CasdoorLoginRequest, WecomBindRequest from app.services.auth import ( exchange_casdoor_code, get_or_create_user_from_casdoor, get_user_by_wecom_id, bind_wecom_user, build_token_for_user, ) from app.services.wecom import wecom_client from app.config import settings router = APIRouter(prefix="/auth", tags=["Authentication"]) @router.post("/casdoor-login", response_model=TokenResponse) async def casdoor_login(req: CasdoorLoginRequest, db: AsyncSession = Depends(get_db)): """Standard Casdoor OIDC login — exchange code for userinfo, get or create user, return JWT.""" userinfo = await exchange_casdoor_code(req.code) if not userinfo: raise HTTPException(status_code=400, detail="Failed to exchange code with Casdoor") casdoor_id = userinfo.get("sub") or userinfo.get("id") if not casdoor_id: raise HTTPException(status_code=400, detail="Invalid userinfo from Casdoor") name = userinfo.get("name") or userinfo.get("preferred_username") or casdoor_id role = userinfo.get("role", "manager") user = await get_or_create_user_from_casdoor(db, casdoor_id, name, role) token = build_token_for_user(user) return TokenResponse( access_token=token, user_id=str(user.id), name=user.name, role=user.role, theme=user.theme or "editorial", ) @router.post("/wecom-login") async def wecom_login(req: WecomLoginRequest, db: AsyncSession = Depends(get_db)): """WeChat Work silent login — exchange wecom code for userid, find bound user, return JWT.""" userinfo = await wecom_client.get_userinfo_by_code(req.code) if not userinfo: raise HTTPException(status_code=400, detail="Failed to exchange wecom code") wecom_userid = userinfo.get("UserId") or userinfo.get("userid") if not wecom_userid: raise HTTPException(status_code=400, detail="Could not get userid from wecom") user = await get_user_by_wecom_id(db, wecom_userid) if user: token = build_token_for_user(user) return TokenResponse( access_token=token, user_id=str(user.id), name=user.name, role=user.role, theme=user.theme or "editorial", ) raise HTTPException( status_code=403, detail="企业微信账号尚未绑定。请在企业微信内使用一次性绑定链接完成绑定。", ) @router.post("/bind-wecom") async def bind_wecom(req: WecomBindRequest, db: AsyncSession = Depends(get_db)): """Deprecated unsafe binding flow. Use /wecom/bind-confirm with a one-time token.""" raise HTTPException( status_code=410, detail="该绑定接口已停用,请使用企业微信一次性绑定链接。", )