54 lines
1.8 KiB
Python
54 lines
1.8 KiB
Python
from typing import Annotated
|
|
|
|
from app.auth import (
|
|
authenticate_user,
|
|
get_password_hash,
|
|
validate_password,
|
|
)
|
|
from app.database.auth import OAuthToken
|
|
from app.database.verification import LoginSession, TrustedDevice
|
|
from app.dependencies.database import Database
|
|
from app.dependencies.user import ClientUser
|
|
from app.log import log
|
|
|
|
from .router import router
|
|
|
|
from fastapi import Depends, Form, HTTPException
|
|
from fastapi_limiter.depends import RateLimiter
|
|
from sqlmodel import col, delete
|
|
|
|
logger = log("Auth")
|
|
|
|
|
|
@router.post(
|
|
"/password/change",
|
|
name="更改密码",
|
|
tags=["验证", "g0v0 API"],
|
|
status_code=204,
|
|
dependencies=[Depends(RateLimiter(times=3, minutes=5))],
|
|
)
|
|
async def change_password(
|
|
current_user: ClientUser,
|
|
session: Database,
|
|
current_password: Annotated[str, Form(..., description="当前密码")],
|
|
new_password: Annotated[str, Form(..., description="新密码")],
|
|
):
|
|
"""更改用户密码
|
|
|
|
同时删除所有的已登录会话和信任设备
|
|
|
|
速率限制: 5 分钟内最多 3 次
|
|
"""
|
|
if not await authenticate_user(session, current_user.username, current_password):
|
|
raise HTTPException(status_code=403, detail="Password incorrect")
|
|
if errors := validate_password(new_password):
|
|
raise HTTPException(status_code=400, detail="; ".join(errors))
|
|
|
|
async with session.begin():
|
|
current_user.pw_bcrypt = get_password_hash(new_password)
|
|
|
|
await session.execute(delete(TrustedDevice).where(col(TrustedDevice.user_id) == current_user.id))
|
|
await session.execute(delete(LoginSession).where(col(LoginSession.user_id) == current_user.id))
|
|
await session.execute(delete(OAuthToken).where(col(OAuthToken.user_id) == current_user.id))
|
|
logger.info(f"User {current_user.id} changed password and sessions revoked")
|