"""B01_Dashboard 역할별 대시보드 API.""" from typing import Any from fastapi import APIRouter, Depends, HTTPException, Query from common_util.common_util_auth import require_system_admin, verify_session from .B01_Dashboard_Repository import ( add_company_member, assign_user_company, change_user_role, create_company, get_dashboard_me, get_system_resources, get_user_company, join_company, list_all_companies, list_all_projects, list_all_users, list_audit_logs, list_company_members, list_company_projects, list_join_requests, list_user_projects, process_join_request, remove_company_member, search_companies, update_user_profile, ) from .B01_Dashboard_Schema import ( AddMemberRequest, AssignCompanyRequest, ChangeUserRoleRequest, CreateCompanyRequest, JoinCompanyRequest, ProcessJoinRequest, UpdateUserRequest, ) router = APIRouter(prefix="/api/dashboard", tags=["B01_Dashboard"]) async def require_company_admin( session: dict[str, Any] = Depends(verify_session), ) -> dict[str, Any]: if session["role"] not in ("ADMIN", "SYSTEM_ADMIN") and not session["is_master"]: raise HTTPException(status_code=403, detail="회사 관리자 권한이 필요합니다.") return session def _require_company_id(session: dict[str, Any]) -> int: company_id = session.get("company_id") if company_id is None: raise HTTPException(status_code=403, detail="회사 연결이 필요합니다.") return int(company_id) @router.get("/me") async def dashboard_me(session: dict[str, Any] = Depends(verify_session)): user = await get_dashboard_me(int(session["user_id"])) if not user: raise HTTPException(status_code=404, detail="사용자 정보를 찾을 수 없습니다.") return {"status": "success", "user": user} @router.patch("/me") async def patch_dashboard_me( payload: UpdateUserRequest, session: dict[str, Any] = Depends(verify_session), ): user = await update_user_profile(int(session["user_id"]), payload.model_dump()) return {"status": "success", "user": user} @router.get("/user/projects") async def user_projects(session: dict[str, Any] = Depends(verify_session)): return {"status": "success", "projects": await list_user_projects(int(session["user_id"]))} @router.get("/user/company") async def user_company(session: dict[str, Any] = Depends(verify_session)): return {"status": "success", "company": await get_user_company(session.get("company_id"))} @router.get("/user/companies") async def user_company_search( q: str = Query(min_length=1, max_length=100), session: dict[str, Any] = Depends(verify_session), ): _ = session return {"status": "success", "companies": await search_companies(q.strip())} @router.post("/user/company/create") async def user_company_create( payload: CreateCompanyRequest, session: dict[str, Any] = Depends(verify_session), ): result = await create_company(int(session["user_id"]), payload.model_dump()) return {"status": "success", **result} @router.post("/user/company/join") async def user_company_join( payload: JoinCompanyRequest, session: dict[str, Any] = Depends(verify_session), ): result = await join_company(int(session["user_id"]), payload.company_id) return {"status": "success", **result} @router.get("/admin/members") async def admin_members(session: dict[str, Any] = Depends(require_company_admin)): return { "status": "success", "members": await list_company_members(_require_company_id(session)), } @router.post("/admin/members") async def admin_add_member( payload: AddMemberRequest, session: dict[str, Any] = Depends(require_company_admin), ): member = await add_company_member(_require_company_id(session), payload.email) if not member: raise HTTPException(status_code=409, detail="사용자를 찾을 수 없거나 이미 팀원입니다.") return {"status": "success", "member": member} @router.delete("/admin/members/{user_id}") async def admin_remove_member( user_id: int, session: dict[str, Any] = Depends(require_company_admin) ): if not await remove_company_member(_require_company_id(session), user_id): raise HTTPException(status_code=404, detail="제거할 팀원을 찾을 수 없습니다.") return {"status": "success"} @router.get("/admin/join-requests") async def admin_join_requests(session: dict[str, Any] = Depends(require_company_admin)): return {"status": "success", "requests": await list_join_requests(_require_company_id(session))} @router.patch("/admin/join-requests/{request_id}") async def admin_process_join_request( request_id: int, payload: ProcessJoinRequest, session: dict[str, Any] = Depends(require_company_admin), ): changed = await process_join_request( request_id, int(session["user_id"]), payload.action == "APPROVE", _require_company_id(session), ) if not changed: raise HTTPException(status_code=404, detail="처리할 가입 신청을 찾을 수 없습니다.") return {"status": "success"} @router.get("/admin/projects") async def admin_projects(session: dict[str, Any] = Depends(require_company_admin)): return { "status": "success", "projects": await list_company_projects(_require_company_id(session)), } @router.get("/admin/companies") async def system_companies(session: dict[str, Any] = Depends(require_system_admin)): _ = session return {"status": "success", "companies": await list_all_companies()} @router.get("/admin/users") async def system_users(session: dict[str, Any] = Depends(require_system_admin)): _ = session return {"status": "success", "users": await list_all_users()} @router.patch("/admin/users/{user_id}/role") async def system_change_role( user_id: int, payload: ChangeUserRoleRequest, session: dict[str, Any] = Depends(require_system_admin), ): _ = session if not await change_user_role(user_id, payload.role): raise HTTPException(status_code=404, detail="사용자를 찾을 수 없습니다.") return {"status": "success"} @router.patch("/admin/users/{user_id}/company") async def system_assign_company( user_id: int, payload: AssignCompanyRequest, session: dict[str, Any] = Depends(require_system_admin), ): _ = session if not await assign_user_company(user_id, payload.company_id): raise HTTPException(status_code=404, detail="사용자를 찾을 수 없습니다.") return {"status": "success"} @router.get("/admin/join-requests-all") async def system_join_requests(session: dict[str, Any] = Depends(require_system_admin)): _ = session return {"status": "success", "requests": await list_join_requests()} @router.patch("/admin/join-requests/{request_id}/approve") async def system_approve_join_request( request_id: int, session: dict[str, Any] = Depends(require_system_admin), ): if not await process_join_request(request_id, int(session["user_id"]), True): raise HTTPException(status_code=404, detail="처리할 가입 신청을 찾을 수 없습니다.") return {"status": "success"} @router.get("/admin/audit-logs") async def system_audit_logs( page: int = Query(1, ge=1), limit: int = Query(50, ge=1, le=100), session: dict[str, Any] = Depends(require_system_admin), ): _ = session return {"status": "success", **await list_audit_logs(limit, (page - 1) * limit)} @router.get("/admin/resources") async def system_resources( days: int = Query(30, ge=1, le=90), session: dict[str, Any] = Depends(require_system_admin), ): _ = session return {"status": "success", **await get_system_resources(days)} @router.get("/admin/projects-all") async def system_projects(session: dict[str, Any] = Depends(require_system_admin)): _ = session return {"status": "success", "projects": await list_all_projects()}