influxdb/secret/http_server.go

153 lines
3.6 KiB
Go
Raw Normal View History

package secret
import (
"fmt"
"net/http"
"github.com/go-chi/chi"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/platform/errors"
kithttp "github.com/influxdata/influxdb/v2/kit/transport/http"
"go.uber.org/zap"
)
type handler struct {
log *zap.Logger
svc influxdb.SecretService
api *kithttp.API
idLookupKey string
}
// NewHandler creates a new handler for the secret service
func NewHandler(log *zap.Logger, idLookupKey string, svc influxdb.SecretService) http.Handler {
h := &handler{
log: log,
svc: svc,
api: kithttp.NewAPI(kithttp.WithLog(log)),
idLookupKey: idLookupKey,
}
r := chi.NewRouter()
r.Get("/", h.handleGetSecrets)
r.Patch("/", h.handlePatchSecrets)
r.Delete("/{secretID}", h.handleDeleteSecret)
r.Post("/delete", h.handleDeleteSecrets) // deprecated
return r
}
// handleGetSecrets is the HTTP handler for the GET /api/v2/orgs/:id/secrets route.
func (h *handler) handleGetSecrets(w http.ResponseWriter, r *http.Request) {
orgID, err := h.decodeOrgID(r)
if err != nil {
h.api.Err(w, r, err)
}
ks, err := h.svc.GetSecretKeys(r.Context(), orgID)
if err != nil && errors.ErrorCode(err) != errors.ENotFound {
h.api.Err(w, r, err)
return
}
h.api.Respond(w, r, http.StatusOK, newSecretsResponse(orgID, ks))
}
type secretsResponse struct {
Links map[string]string `json:"links"`
Secrets []string `json:"secrets"`
}
func newSecretsResponse(orgID platform.ID, ks []string) *secretsResponse {
if ks == nil {
ks = []string{}
}
return &secretsResponse{
Links: map[string]string{
"org": fmt.Sprintf("/api/v2/orgs/%s", orgID),
"self": fmt.Sprintf("/api/v2/orgs/%s/secrets", orgID),
},
Secrets: ks,
}
}
// handleGetPatchSecrets is the HTTP handler for the PATCH /api/v2/orgs/:id/secrets route.
func (h *handler) handlePatchSecrets(w http.ResponseWriter, r *http.Request) {
orgID, err := h.decodeOrgID(r)
if err != nil {
h.api.Err(w, r, err)
}
var secrets map[string]string
if err := h.api.DecodeJSON(r.Body, &secrets); err != nil {
h.api.Err(w, r, err)
return
}
if err := h.svc.PatchSecrets(r.Context(), orgID, secrets); err != nil {
h.api.Err(w, r, err)
return
}
h.api.Respond(w, r, http.StatusNoContent, nil)
}
type secretsDeleteBody struct {
Secrets []string `json:"secrets"`
}
// handleDeleteSecrets is the HTTP handler for the POST /api/v2/orgs/:id/secrets/delete route.
// deprecated.
func (h *handler) handleDeleteSecrets(w http.ResponseWriter, r *http.Request) {
orgID, err := h.decodeOrgID(r)
if err != nil {
h.api.Err(w, r, err)
}
var reqBody secretsDeleteBody
if err := h.api.DecodeJSON(r.Body, &reqBody); err != nil {
h.api.Err(w, r, err)
return
}
if err := h.svc.DeleteSecret(r.Context(), orgID, reqBody.Secrets...); err != nil {
h.api.Err(w, r, err)
return
}
h.api.Respond(w, r, http.StatusNoContent, nil)
}
// handleDeleteSecret is the HTTP handler for the DELETE /api/v2/orgs/:id/secrets/:id route.
func (h *handler) handleDeleteSecret(w http.ResponseWriter, r *http.Request) {
orgID, err := h.decodeOrgID(r)
if err != nil {
h.api.Err(w, r, err)
}
if err := h.svc.DeleteSecret(r.Context(), orgID, chi.URLParam(r, "secretID")); err != nil {
h.api.Err(w, r, err)
return
}
h.api.Respond(w, r, http.StatusNoContent, nil)
}
func (h *handler) decodeOrgID(r *http.Request) (platform.ID, error) {
org := chi.URLParam(r, h.idLookupKey)
if org == "" {
return platform.InvalidID(), &errors.Error{
Code: errors.EInvalid,
Msg: "url missing id",
}
}
id, err := platform.IDFromString(org)
if err != nil {
return platform.InvalidID(), err
}
return *id, nil
}