Update admin theme/layout and refresh README details.

Align the project baseline with the latest admin interface styling and layout structure while documenting setup and usage updates in README.
This commit is contained in:
vlad
2026-07-14 17:12:28 +03:00
commit 86cc3fa541
278 changed files with 19416 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile
from app.core.dependencies import get_current_user
from app.core.media_signing import build_signed_media_url
from app.core.redis import check_rate_limit
from app.modules.media.service import AvatarValidationError
from app.modules.users.schemas import PasswordChangeIn, UserPatchIn
from app.modules.users.service import change_password, get_me, update_me, upload_avatar
router = APIRouter()
def _profile_response(data: dict) -> dict:
return {
"user": {
"id": data["user"].id,
"email": data["user"].email,
"role": data["user"].role,
"status": data["user"].status,
},
"profile": {
"display_name": data["profile"].display_name,
"avatar_url": build_signed_media_url(data["profile"].avatar_url),
},
}
@router.get("/me")
async def me_route(current_user=Depends(get_current_user)):
return _profile_response(get_me(current_user))
@router.patch("/me")
async def patch_me_route(payload: UserPatchIn, current_user=Depends(get_current_user)):
return _profile_response(update_me(current_user, payload.display_name))
@router.post("/me/password")
async def change_password_route(payload: PasswordChangeIn, current_user=Depends(get_current_user)):
try:
change_password(current_user, payload.current_password, payload.new_password)
except ValueError:
raise HTTPException(status_code=400, detail="INVALID_CURRENT_PASSWORD")
return {"message": "password_changed"}
@router.post("/me/avatar")
async def upload_avatar_route(
request: Request,
file: UploadFile = File(...),
current_user=Depends(get_current_user),
):
check_rate_limit(f"avatar:{current_user.id}", limit=10, window_seconds=3600)
content = await file.read()
try:
data = upload_avatar(current_user, content)
except AvatarValidationError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return _profile_response(data)