123 lines
4.4 KiB
Python
123 lines
4.4 KiB
Python
"""마스터 조직 관리, 활동 기록 및 시스템 관리자 API."""
|
|
|
|
import json
|
|
|
|
import psutil
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
|
|
from common_util.common_util_auth import require_master, require_system_admin, verify_session
|
|
from common_util.common_util_auth_repository import (
|
|
admin_dashboard,
|
|
admin_list,
|
|
admin_update_status,
|
|
decide_join_request,
|
|
list_company_members,
|
|
list_join_requests,
|
|
master_dashboard,
|
|
remove_member,
|
|
)
|
|
from common_util.common_util_email import send_email_background
|
|
from common_util.common_util_email_templates import join_result_email
|
|
from config.config_db import get_db_pool
|
|
|
|
from .A09_Security_Schema import ActivityLogRequest, AdminStatusRequest, JoinDecisionRequest
|
|
|
|
router = APIRouter(prefix="/api/security", tags=["Security"])
|
|
|
|
|
|
@router.get("/master/dashboard")
|
|
async def get_master_dashboard(session: dict = Depends(require_master)):
|
|
return {"status": "success", "dashboard": await master_dashboard(session["company_id"])}
|
|
|
|
|
|
@router.get("/master/members")
|
|
async def get_members(session: dict = Depends(require_master)):
|
|
return {"status": "success", "members": await list_company_members(session["company_id"])}
|
|
|
|
|
|
@router.get("/master/join-requests")
|
|
async def get_join_requests(session: dict = Depends(require_master)):
|
|
return {"status": "success", "requests": await list_join_requests(session["company_id"])}
|
|
|
|
|
|
@router.post("/master/join-requests/{request_id}/decision")
|
|
async def review_join_request(
|
|
request_id: int,
|
|
payload: JoinDecisionRequest,
|
|
session: dict = Depends(require_master),
|
|
):
|
|
user = await decide_join_request(
|
|
request_id, session["company_id"], session["user_id"], payload.approved, payload.comment
|
|
)
|
|
if not user:
|
|
raise HTTPException(status_code=404, detail="처리할 가입 요청이 없습니다.")
|
|
subject, html = join_result_email(payload.approved)
|
|
send_email_background(user["email"], subject, html)
|
|
return {"status": "success"}
|
|
|
|
|
|
@router.post("/master/members/{user_id}/remove")
|
|
async def deactivate_member(user_id: int, session: dict = Depends(require_master)):
|
|
if not await remove_member(user_id, session["company_id"]):
|
|
raise HTTPException(status_code=404, detail="내보낼 팀원을 찾을 수 없습니다.")
|
|
return {"status": "success"}
|
|
|
|
|
|
@router.post("/activity", status_code=202)
|
|
async def write_activity(payload: ActivityLogRequest, session: dict = Depends(verify_session)):
|
|
pool = get_db_pool()
|
|
async with pool.acquire() as connection, connection.cursor() as cursor:
|
|
await cursor.execute(
|
|
"""INSERT INTO activity_logs
|
|
(user_id, action_type, resource_id, status, details)
|
|
VALUES (%s, %s, %s, %s, %s)""",
|
|
(
|
|
session["user_id"],
|
|
payload.action_type,
|
|
payload.resource_id,
|
|
payload.status,
|
|
json.dumps(payload.details),
|
|
),
|
|
)
|
|
await connection.commit()
|
|
return {"status": "success"}
|
|
|
|
|
|
@router.get("/admin/dashboard")
|
|
async def get_admin_dashboard(session: dict = Depends(require_system_admin)):
|
|
disk = psutil.disk_usage("/")
|
|
process = psutil.Process()
|
|
resources = {
|
|
"cpu_percent": psutil.cpu_percent(interval=None),
|
|
"memory_percent": psutil.virtual_memory().percent,
|
|
"disk_total_gb": round(disk.total / 1024**3, 2),
|
|
"disk_used_gb": round(disk.used / 1024**3, 2),
|
|
"process_count": len(psutil.pids()),
|
|
"app_memory_mb": round(process.memory_info().rss / 1024**2, 2),
|
|
}
|
|
return {"status": "success", "dashboard": await admin_dashboard(), "resources": resources}
|
|
|
|
|
|
@router.get("/admin/{collection}")
|
|
async def get_admin_collection(collection: str, session: dict = Depends(require_system_admin)):
|
|
try:
|
|
rows = await admin_list(collection)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
return {"status": "success", "items": rows}
|
|
|
|
|
|
@router.patch("/admin/{entity}/{target_id}/status")
|
|
async def set_admin_status(
|
|
entity: str,
|
|
target_id: int,
|
|
payload: AdminStatusRequest,
|
|
session: dict = Depends(require_system_admin),
|
|
):
|
|
changed = await admin_update_status(
|
|
session["user_id"], entity, target_id, payload.status, {"reason": payload.reason}
|
|
)
|
|
if not changed:
|
|
raise HTTPException(status_code=400, detail="대상 또는 상태값이 올바르지 않습니다.")
|
|
return {"status": "success"}
|