feat(backend): add FastAPI backend — procurement, inventory domain, Casdoor auth, PM arrival endpoints
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
"""Users — profile + role assignment (v2.6, Casdoor-backed).
|
||||
|
||||
GET /users/me — the caller's profile: role, PM's project, display name.
|
||||
PATCH /users/{id} — assign role (admin only).
|
||||
"""
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.auth import UserContext, get_current_user, require_role
|
||||
from app.db.engine import get_db
|
||||
from app.models.procurement import Project, User
|
||||
from app.schemas.procurement import UserRoleUpdate
|
||||
from app.utils.errors import NotFoundError
|
||||
from app.utils.serialization import to_iso
|
||||
|
||||
router = APIRouter(prefix="/users", tags=["users"])
|
||||
|
||||
USER_ROLE_LABELS = {
|
||||
"pm": "مدیر پروژه",
|
||||
"procurement_manager": "مدیر تدارکات",
|
||||
"admin": "ادمین",
|
||||
}
|
||||
|
||||
|
||||
def user_to_dict(user: User, project: Project | None = None) -> dict:
|
||||
return {
|
||||
"id": str(user.id),
|
||||
"casdoor_id": user.casdoor_id,
|
||||
"first_name": user.first_name,
|
||||
"last_name": user.last_name,
|
||||
"phone": user.phone,
|
||||
"role": user.role,
|
||||
"role_label": USER_ROLE_LABELS.get(user.role) if user.role else None,
|
||||
"project_id": str(project.id) if project else None,
|
||||
"project_name": project.name if project else None,
|
||||
"created_at": to_iso(user.created_at),
|
||||
}
|
||||
|
||||
|
||||
@router.get("/me")
|
||||
async def me(ctx: UserContext = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
|
||||
project = await db.scalar(select(Project).where(Project.pm_user_id == ctx.user.id)) if ctx.role == "pm" else None
|
||||
return {"data": user_to_dict(ctx.user, project)}
|
||||
|
||||
|
||||
@router.patch("/{user_id}")
|
||||
async def update_user_role(
|
||||
user_id,
|
||||
payload: UserRoleUpdate,
|
||||
_: UserContext = Depends(require_role("admin")),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
user = await db.get(User, user_id)
|
||||
if user is None:
|
||||
raise NotFoundError("کاربر یافت نشد")
|
||||
user.role = payload.role
|
||||
await db.flush()
|
||||
project = await db.scalar(select(Project).where(Project.pm_user_id == user.id)) if user.role == "pm" else None
|
||||
return {"data": user_to_dict(user, project)}
|
||||
Reference in New Issue
Block a user