orama/pkg/gateway/handlers/serverless/secrets_handler.go
anonpenguin23 72fb5f1a5a feat: add secrets and triggers management to function commands
- Introduced `secrets` command for managing function secrets, including set, list, and delete operations.
- Added `triggers` command for managing PubSub triggers associated with functions, allowing addition, listing, and deletion of triggers.
- Implemented API handlers for secrets management, including setting, listing, and deleting secrets.
- Updated serverless handlers to support new secrets and triggers functionalities.
- Enhanced tests for the new features, ensuring proper functionality and error handling.
2026-02-23 19:18:39 +02:00

147 lines
3.8 KiB
Go

package serverless
import (
"context"
"encoding/json"
"errors"
"net/http"
"time"
"github.com/DeBrosOfficial/network/pkg/serverless"
"go.uber.org/zap"
)
// setSecretRequest is the request body for setting a secret.
type setSecretRequest struct {
Name string `json:"name"`
Value string `json:"value"`
}
// HandleSetSecret handles PUT /v1/functions/secrets
// Stores an encrypted secret scoped to the caller's namespace.
func (h *ServerlessHandlers) HandleSetSecret(w http.ResponseWriter, r *http.Request) {
if h.secretsManager == nil {
writeError(w, http.StatusNotImplemented, "Secrets management not available")
return
}
namespace := h.getNamespaceFromRequest(r)
if namespace == "" {
writeError(w, http.StatusBadRequest, "namespace required")
return
}
var req setSecretRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "Invalid JSON: "+err.Error())
return
}
if req.Name == "" {
writeError(w, http.StatusBadRequest, "secret name required")
return
}
if req.Value == "" {
writeError(w, http.StatusBadRequest, "secret value required")
return
}
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
if err := h.secretsManager.Set(ctx, namespace, req.Name, req.Value); err != nil {
h.logger.Error("Failed to set secret",
zap.String("namespace", namespace),
zap.String("name", req.Name),
zap.Error(err),
)
writeError(w, http.StatusInternalServerError, "Failed to set secret: "+err.Error())
return
}
h.logger.Info("Secret set via API",
zap.String("namespace", namespace),
zap.String("name", req.Name),
)
writeJSON(w, http.StatusOK, map[string]any{
"message": "Secret set",
"name": req.Name,
"namespace": namespace,
})
}
// HandleListSecrets handles GET /v1/functions/secrets
// Lists all secret names in the caller's namespace (values are never returned).
func (h *ServerlessHandlers) HandleListSecrets(w http.ResponseWriter, r *http.Request) {
if h.secretsManager == nil {
writeError(w, http.StatusNotImplemented, "Secrets management not available")
return
}
namespace := h.getNamespaceFromRequest(r)
if namespace == "" {
writeError(w, http.StatusBadRequest, "namespace required")
return
}
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
names, err := h.secretsManager.List(ctx, namespace)
if err != nil {
h.logger.Error("Failed to list secrets",
zap.String("namespace", namespace),
zap.Error(err),
)
writeError(w, http.StatusInternalServerError, "Failed to list secrets")
return
}
writeJSON(w, http.StatusOK, map[string]any{
"secrets": names,
"count": len(names),
})
}
// HandleDeleteSecret handles DELETE /v1/functions/secrets/{name}
// Deletes a secret from the caller's namespace.
func (h *ServerlessHandlers) HandleDeleteSecret(w http.ResponseWriter, r *http.Request, secretName string) {
if h.secretsManager == nil {
writeError(w, http.StatusNotImplemented, "Secrets management not available")
return
}
namespace := h.getNamespaceFromRequest(r)
if namespace == "" {
writeError(w, http.StatusBadRequest, "namespace required")
return
}
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
if err := h.secretsManager.Delete(ctx, namespace, secretName); err != nil {
if errors.Is(err, serverless.ErrSecretNotFound) {
writeError(w, http.StatusNotFound, "Secret not found")
return
}
h.logger.Error("Failed to delete secret",
zap.String("namespace", namespace),
zap.String("name", secretName),
zap.Error(err),
)
writeError(w, http.StatusInternalServerError, "Failed to delete secret: "+err.Error())
return
}
h.logger.Info("Secret deleted via API",
zap.String("namespace", namespace),
zap.String("name", secretName),
)
writeJSON(w, http.StatusOK, map[string]any{
"message": "Secret deleted",
})
}