mirror of
https://github.com/luxfi/broker.git
synced 2026-09-24 00:25:18 +00:00
- Add RBAC guards to ALL read endpoints (pipelines, sessions, funds, esign, templates, dashboard, users, transactions, reports, settings, credentials, billing, envelope views) — previously 20+ GET routes had no permission checks - Wire Jube client into amlHandler via RouterOption pattern - Replace NewRouter variadic authStore param with proper RouterOption API - Delegate seed roles to rbac.DefaultRoles() — fixes drift where seed was missing aml and applications modules - Delegate modules list to rbac.ComplianceModules() — single source of truth - Delegate onboarding helpers (newApplicationSteps, isTerminalStatus, markStepCompleted, markStepFailed) to compliance library - SSN HMAC key: hard-fail in production if SSN_HMAC_KEY not set - Add audit logging when super_admin RBAC bypass is used - Credential management elevated to roles:admin (was unguarded)
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
package compliance
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/luxfi/compliance/pkg/rbac"
|
|
)
|
|
|
|
// rolesHandler holds RBAC HTTP handler state.
|
|
type rolesHandler struct {
|
|
store ComplianceStore
|
|
}
|
|
|
|
func (h *rolesHandler) handleListRoles(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusOK, h.store.ListRoles())
|
|
}
|
|
|
|
func (h *rolesHandler) handleCreateRole(w http.ResponseWriter, r *http.Request) {
|
|
var role Role
|
|
if err := json.NewDecoder(r.Body).Decode(&role); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid request body")
|
|
return
|
|
}
|
|
if role.Name == "" {
|
|
writeError(w, http.StatusBadRequest, "name is required")
|
|
return
|
|
}
|
|
if err := h.store.SaveRole(&role); err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusCreated, &role)
|
|
}
|
|
|
|
func (h *rolesHandler) handleGetRole(w http.ResponseWriter, r *http.Request) {
|
|
role, err := h.store.GetRole(chi.URLParam(r, "id"))
|
|
if err != nil {
|
|
writeError(w, http.StatusNotFound, err.Error())
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, role)
|
|
}
|
|
|
|
func (h *rolesHandler) handleUpdateRole(w http.ResponseWriter, r *http.Request) {
|
|
id := chi.URLParam(r, "id")
|
|
existing, err := h.store.GetRole(id)
|
|
if err != nil {
|
|
writeError(w, http.StatusNotFound, err.Error())
|
|
return
|
|
}
|
|
|
|
var patch struct {
|
|
Name *string `json:"name,omitempty"`
|
|
Description *string `json:"description,omitempty"`
|
|
Permissions []Permission `json:"permissions,omitempty"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&patch); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid request body")
|
|
return
|
|
}
|
|
if patch.Name != nil {
|
|
existing.Name = *patch.Name
|
|
}
|
|
if patch.Description != nil {
|
|
existing.Description = *patch.Description
|
|
}
|
|
if patch.Permissions != nil {
|
|
existing.Permissions = patch.Permissions
|
|
}
|
|
if err := h.store.SaveRole(existing); err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, existing)
|
|
}
|
|
|
|
func (h *rolesHandler) handleDeleteRole(w http.ResponseWriter, r *http.Request) {
|
|
if err := h.store.DeleteRole(chi.URLParam(r, "id")); err != nil {
|
|
writeError(w, http.StatusNotFound, err.Error())
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
|
}
|
|
|
|
// handleListModules returns the static list of compliance modules and their
|
|
// available actions, used to build a permission matrix UI.
|
|
// Uses the canonical definition from the compliance library to prevent drift.
|
|
func (h *rolesHandler) handleListModules(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusOK, rbac.ComplianceModules())
|
|
}
|