agnes-the-ai-analyst/app/api/users.py
ZdenekSrotyr a3918d3833 feat: add FastAPI server with auth, RBAC, and all API endpoints
- JWT auth with role-based access control (viewer/analyst/admin/km_admin)
- Endpoints: health, sync manifest, data download, query, users CRUD,
  corporate memory, session/artifact upload
- 18 API tests covering auth, RBAC, all endpoints
2026-03-27 15:19:18 +01:00

74 lines
2.1 KiB
Python

"""User management endpoints."""
import uuid
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from typing import Optional, List
import duckdb
from app.auth.dependencies import require_role, Role, _get_db
from src.repositories.users import UserRepository
router = APIRouter(prefix="/api/users", tags=["users"])
class CreateUserRequest(BaseModel):
email: str
name: str
role: str = "analyst"
class UpdateUserRequest(BaseModel):
name: Optional[str] = None
role: Optional[str] = None
class UserResponse(BaseModel):
id: str
email: str
name: Optional[str]
role: str
created_at: Optional[str]
@router.get("", response_model=List[UserResponse])
async def list_users(
user: dict = Depends(require_role(Role.ADMIN)),
conn: duckdb.DuckDBPyConnection = Depends(_get_db),
):
repo = UserRepository(conn)
users = repo.list_all()
return [
UserResponse(
id=u["id"], email=u["email"], name=u.get("name"),
role=u["role"], created_at=str(u.get("created_at", "")),
) for u in users
]
@router.post("", response_model=UserResponse, status_code=201)
async def create_user(
request: CreateUserRequest,
user: dict = Depends(require_role(Role.ADMIN)),
conn: duckdb.DuckDBPyConnection = Depends(_get_db),
):
repo = UserRepository(conn)
if repo.get_by_email(request.email):
raise HTTPException(status_code=409, detail="User with this email already exists")
user_id = str(uuid.uuid4())
repo.create(id=user_id, email=request.email, name=request.name, role=request.role)
return UserResponse(id=user_id, email=request.email, name=request.name, role=request.role, created_at=None)
@router.delete("/{user_id}", status_code=204)
async def delete_user(
user_id: str,
user: dict = Depends(require_role(Role.ADMIN)),
conn: duckdb.DuckDBPyConnection = Depends(_get_db),
):
repo = UserRepository(conn)
if not repo.get_by_id(user_id):
raise HTTPException(status_code=404, detail="User not found")
repo.delete(user_id)