feat(auth): support change password

This commit is contained in:
MingxuanGame
2025-10-07 13:07:14 +00:00
parent 95f7c010af
commit 60049a777f
3 changed files with 68 additions and 14 deletions

View File

@@ -60,6 +60,20 @@ def validate_username(username: str) -> list[str]:
return errors
def validate_password(password: str) -> list[str]:
"""验证密码"""
errors = []
if not password:
errors.append("Password is required")
return errors
if len(password) < 8:
errors.append("Password must be at least 8 characters long")
return errors
def verify_password_legacy(plain_password: str, bcrypt_hash: str) -> bool:
"""
验证密码 - 使用 osu! 的验证方式

View File

@@ -10,6 +10,7 @@ from app.auth import (
get_token_by_refresh_token,
get_user_by_authorization_code,
store_token,
validate_password,
validate_username,
)
from app.config import settings
@@ -68,20 +69,6 @@ def validate_email(email: str) -> list[str]:
return errors
def validate_password(password: str) -> list[str]:
"""验证密码"""
errors = []
if not password:
errors.append("Password is required")
return errors
if len(password) < 8:
errors.append("Password must be at least 8 characters long")
return errors
router = APIRouter(tags=["osu! OAuth 认证"])

View File

@@ -0,0 +1,53 @@
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")