package handlers import ( "net/http" "github.com/breakpilot/ai-compliance-sdk/internal/rbac" "github.com/gin-gonic/gin" "github.com/google/uuid" ) // RBACHandlers handles RBAC-related API endpoints type RBACHandlers struct { store *rbac.Store service *rbac.Service policyEngine *rbac.PolicyEngine } // NewRBACHandlers creates new RBAC handlers func NewRBACHandlers(store *rbac.Store, service *rbac.Service, policyEngine *rbac.PolicyEngine) *RBACHandlers { return &RBACHandlers{ store: store, service: service, policyEngine: policyEngine, } } // ============================================================================ // Tenant Endpoints // ============================================================================ // ListTenants returns all tenants func (h *RBACHandlers) ListTenants(c *gin.Context) { tenants, err := h.store.ListTenants(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"tenants": tenants}) } // GetTenant returns a tenant by ID func (h *RBACHandlers) GetTenant(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid tenant ID"}) return } tenant, err := h.store.GetTenant(c.Request.Context(), id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "tenant not found"}) return } c.JSON(http.StatusOK, tenant) } // CreateTenant creates a new tenant func (h *RBACHandlers) CreateTenant(c *gin.Context) { var tenant rbac.Tenant if err := c.ShouldBindJSON(&tenant); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.store.CreateTenant(c.Request.Context(), &tenant); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, tenant) } // UpdateTenant updates a tenant func (h *RBACHandlers) UpdateTenant(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid tenant ID"}) return } var tenant rbac.Tenant if err := c.ShouldBindJSON(&tenant); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } tenant.ID = id if err := h.store.UpdateTenant(c.Request.Context(), &tenant); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, tenant) } // ============================================================================ // Namespace Endpoints // ============================================================================ // ListNamespaces returns namespaces for a tenant func (h *RBACHandlers) ListNamespaces(c *gin.Context) { tenantID, err := uuid.Parse(c.Param("id")) if err != nil { tenantID = rbac.GetTenantID(c) } if tenantID == uuid.Nil { c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"}) return } namespaces, err := h.store.ListNamespaces(c.Request.Context(), tenantID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"namespaces": namespaces}) } // GetNamespace returns a namespace by ID func (h *RBACHandlers) GetNamespace(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid namespace ID"}) return } namespace, err := h.store.GetNamespace(c.Request.Context(), id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "namespace not found"}) return } c.JSON(http.StatusOK, namespace) } // CreateNamespace creates a new namespace func (h *RBACHandlers) CreateNamespace(c *gin.Context) { tenantID, err := uuid.Parse(c.Param("id")) if err != nil { tenantID = rbac.GetTenantID(c) } if tenantID == uuid.Nil { c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"}) return } var namespace rbac.Namespace if err := c.ShouldBindJSON(&namespace); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } namespace.TenantID = tenantID if err := h.store.CreateNamespace(c.Request.Context(), &namespace); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, namespace) }