From 62d4c37c1db6f0adef96bba66559072caac85e3a Mon Sep 17 00:00:00 2001 From: Claude AI Date: Thu, 29 Jan 2026 11:13:26 +0000 Subject: [PATCH] feat(fase4): add GlobalVariable API routes Add schemas and router for global variables with CRUD operations and admin-only access controls for create/update/delete. Co-Authored-By: Claude Opus 4.5 --- services/api-gateway/app/main.py | 3 +- .../app/routers/global_variables.py | 95 +++++++++++++++++++ .../app/schemas/global_variable.py | 33 +++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 services/api-gateway/app/routers/global_variables.py create mode 100644 services/api-gateway/app/schemas/global_variable.py diff --git a/services/api-gateway/app/main.py b/services/api-gateway/app/main.py index 3820844..fd96cf0 100644 --- a/services/api-gateway/app/main.py +++ b/services/api-gateway/app/main.py @@ -2,7 +2,7 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.core.config import get_settings from app.core.database import engine, Base -from app.routers import auth, whatsapp, flows, queues, supervisor, flow_templates +from app.routers import auth, whatsapp, flows, queues, supervisor, flow_templates, global_variables settings = get_settings() @@ -32,6 +32,7 @@ app.include_router(flows.router) app.include_router(queues.router) app.include_router(supervisor.router) app.include_router(flow_templates.router) +app.include_router(global_variables.router) @app.get("/health") diff --git a/services/api-gateway/app/routers/global_variables.py b/services/api-gateway/app/routers/global_variables.py new file mode 100644 index 0000000..6c9e1ae --- /dev/null +++ b/services/api-gateway/app/routers/global_variables.py @@ -0,0 +1,95 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from typing import List +from uuid import UUID +from app.core.database import get_db +from app.core.security import get_current_user +from app.models.user import User, UserRole +from app.models.global_variable import GlobalVariable +from app.schemas.global_variable import ( + GlobalVariableCreate, GlobalVariableUpdate, GlobalVariableResponse +) + +router = APIRouter(prefix="/api/global-variables", tags=["global-variables"]) + + +def require_admin(current_user: User = Depends(get_current_user)): + if current_user.role != UserRole.ADMIN: + raise HTTPException(status_code=403, detail="Admin required") + return current_user + + +@router.get("", response_model=List[GlobalVariableResponse]) +def list_global_variables( + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), +): + variables = db.query(GlobalVariable).all() + for var in variables: + if var.is_secret: + var.value = "********" + return variables + + +@router.post("", response_model=GlobalVariableResponse) +def create_global_variable( + request: GlobalVariableCreate, + db: Session = Depends(get_db), + current_user: User = Depends(require_admin), +): + existing = db.query(GlobalVariable).filter(GlobalVariable.key == request.key).first() + if existing: + raise HTTPException(status_code=400, detail="Variable key already exists") + + variable = GlobalVariable(**request.model_dump()) + db.add(variable) + db.commit() + db.refresh(variable) + return variable + + +@router.put("/{variable_id}", response_model=GlobalVariableResponse) +def update_global_variable( + variable_id: UUID, + request: GlobalVariableUpdate, + db: Session = Depends(get_db), + current_user: User = Depends(require_admin), +): + variable = db.query(GlobalVariable).filter(GlobalVariable.id == variable_id).first() + if not variable: + raise HTTPException(status_code=404, detail="Variable not found") + + for key, value in request.model_dump(exclude_unset=True).items(): + setattr(variable, key, value) + + db.commit() + db.refresh(variable) + return variable + + +@router.delete("/{variable_id}") +def delete_global_variable( + variable_id: UUID, + db: Session = Depends(get_db), + current_user: User = Depends(require_admin), +): + variable = db.query(GlobalVariable).filter(GlobalVariable.id == variable_id).first() + if not variable: + raise HTTPException(status_code=404, detail="Variable not found") + + db.delete(variable) + db.commit() + return {"success": True} + + +@router.get("/by-key/{key}") +def get_variable_by_key( + key: str, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), +): + variable = db.query(GlobalVariable).filter(GlobalVariable.key == key).first() + if not variable: + raise HTTPException(status_code=404, detail="Variable not found") + + return {"key": variable.key, "value": variable.value if not variable.is_secret else None} diff --git a/services/api-gateway/app/schemas/global_variable.py b/services/api-gateway/app/schemas/global_variable.py new file mode 100644 index 0000000..6e18967 --- /dev/null +++ b/services/api-gateway/app/schemas/global_variable.py @@ -0,0 +1,33 @@ +from pydantic import BaseModel +from typing import Optional +from uuid import UUID +from datetime import datetime + + +class GlobalVariableCreate(BaseModel): + key: str + value: Optional[str] = None + value_type: str = "string" + description: Optional[str] = None + is_secret: bool = False + + +class GlobalVariableUpdate(BaseModel): + value: Optional[str] = None + value_type: Optional[str] = None + description: Optional[str] = None + is_secret: Optional[bool] = None + + +class GlobalVariableResponse(BaseModel): + id: UUID + key: str + value: Optional[str] + value_type: str + description: Optional[str] + is_secret: bool + created_at: datetime + updated_at: datetime + + class Config: + from_attributes = True