73 lines
2.9 KiB
Python
73 lines
2.9 KiB
Python
"""登录 / 退出 / 当前用户 / 用户自己的设置(昵称、密码)。"""
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Request, Response
|
|
from sqlalchemy.orm import Session
|
|
|
|
from .. import config, security
|
|
from ..db import get_db
|
|
from ..models import User
|
|
from ..schemas import LoginIn, PasswordIn, ProfileIn
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/auth/login")
|
|
def login(body: LoginIn, response: Response, db: Session = Depends(get_db)):
|
|
user = db.query(User).filter(User.username == (body.username or "").strip()).one_or_none()
|
|
if user is None or not security.verify_password(body.password or "", user.password_hash, user.password_salt):
|
|
raise HTTPException(status_code=401, detail="用户名或密码不正确")
|
|
if not user.active:
|
|
raise HTTPException(status_code=403, detail="该账号已被停用,请联系管理员")
|
|
token = security.start_session(db, user)
|
|
response.set_cookie(
|
|
security.SESSION_COOKIE, token,
|
|
max_age=config.SESSION_DAYS * 86400,
|
|
httponly=True, samesite="lax", path="/",
|
|
)
|
|
return user.to_dict()
|
|
|
|
|
|
@router.post("/auth/logout")
|
|
def logout(request: Request, response: Response, db: Session = Depends(get_db)):
|
|
token = request.cookies.get(security.SESSION_COOKIE)
|
|
if token:
|
|
db.query(security.UserSession).filter(security.UserSession.token == token).delete()
|
|
db.commit()
|
|
response.delete_cookie(security.SESSION_COOKIE, path="/")
|
|
return {"ok": True}
|
|
|
|
|
|
@router.get("/auth/me")
|
|
def me(user: User = Depends(security.current_user)):
|
|
return user.to_dict()
|
|
|
|
|
|
@router.put("/auth/me")
|
|
def update_me(body: ProfileIn, user: User = Depends(security.current_user), db: Session = Depends(get_db)):
|
|
name = (body.name or "").strip()
|
|
if not name:
|
|
raise HTTPException(status_code=400, detail="昵称不能为空")
|
|
user.name = name[:64]
|
|
db.commit()
|
|
return user.to_dict()
|
|
|
|
|
|
@router.post("/auth/password")
|
|
def change_password(body: PasswordIn, request: Request, response: Response,
|
|
user: User = Depends(security.current_user), db: Session = Depends(get_db)):
|
|
if not security.verify_password(body.old_password or "", user.password_hash, user.password_salt):
|
|
raise HTTPException(status_code=400, detail="原密码不正确")
|
|
new = (body.new_password or "").strip()
|
|
if len(new) < 6:
|
|
raise HTTPException(status_code=400, detail="新密码至少 6 位")
|
|
user.password_hash, user.password_salt = security.hash_password(new)
|
|
# 改密后其余设备全部下线,只保留当前这次登录
|
|
keep = request.cookies.get(security.SESSION_COOKIE)
|
|
query = db.query(security.UserSession).filter(security.UserSession.user_id == user.id)
|
|
if keep:
|
|
query = query.filter(security.UserSession.token != keep)
|
|
query.delete(synchronize_session=False)
|
|
db.commit()
|
|
return {"ok": True}
|