package gateway import ( "encoding/json" "net/http" "strconv" "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/http/render" "github.com/SigNoz/signoz/pkg/types/authtypes" "github.com/SigNoz/signoz/pkg/types/gatewaytypes" "github.com/SigNoz/signoz/pkg/valuer" "github.com/gorilla/mux" ) const ( DefaultPage = 1 DefaultPageSize = 10 ) type handler struct { gateway Gateway } func NewHandler(gateway Gateway) Handler { return &handler{ gateway: gateway, } } func (handler *handler) GetIngestionKeys(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) pageString := r.URL.Query().Get("page") perPageString := r.URL.Query().Get("per_page") page, err := parseIntWithDefaultValue(pageString, DefaultPage) if err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "page must be a valid integer")) return } perPage, err := parseIntWithDefaultValue(perPageString, DefaultPageSize) if err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "per_page must be a valid integer")) return } response, err := handler.gateway.GetIngestionKeys(ctx, orgID, page, perPage) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusOK, response) } func (handler *handler) SearchIngestionKeys(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) pageString := r.URL.Query().Get("page") perPageString := r.URL.Query().Get("per_page") name := r.URL.Query().Get("name") page, err := parseIntWithDefaultValue(pageString, DefaultPage) if err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "page must be a valid integer")) return } perPage, err := parseIntWithDefaultValue(perPageString, DefaultPageSize) if err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "per_page must be a valid integer")) return } response, err := handler.gateway.SearchIngestionKeysByName(ctx, orgID, name, page, perPage) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusOK, response) } func (handler *handler) CreateIngestionKey(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) var req gatewaytypes.PostableIngestionKey if err := json.NewDecoder(r.Body).Decode(&req); err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid request body")) return } response, err := handler.gateway.CreateIngestionKey(ctx, orgID, req.Name, req.Tags, req.ExpiresAt) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusCreated, response) } func (handler *handler) UpdateIngestionKey(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) keyID := mux.Vars(r)["keyId"] if keyID == "" { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "keyId is required")) return } var req gatewaytypes.PostableIngestionKey if err := json.NewDecoder(r.Body).Decode(&req); err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid request body")) return } err = handler.gateway.UpdateIngestionKey(ctx, orgID, keyID, req.Name, req.Tags, req.ExpiresAt) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusNoContent, nil) } func (handler *handler) DeleteIngestionKey(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) keyID := mux.Vars(r)["keyId"] if keyID == "" { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "keyId is required")) return } err = handler.gateway.DeleteIngestionKey(ctx, orgID, keyID) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusNoContent, nil) } func (handler *handler) CreateIngestionKeyLimit(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) keyID := mux.Vars(r)["keyId"] if keyID == "" { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "keyId is required")) return } var req gatewaytypes.PostableIngestionKeyLimit if err := json.NewDecoder(r.Body).Decode(&req); err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid request body")) return } response, err := handler.gateway.CreateIngestionKeyLimit(ctx, orgID, keyID, req.Signal, req.Config, req.Tags) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusCreated, response) } func (handler *handler) UpdateIngestionKeyLimit(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) limitID := mux.Vars(r)["limitId"] if limitID == "" { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "limitId is required")) return } var req gatewaytypes.UpdatableIngestionKeyLimit if err := json.NewDecoder(r.Body).Decode(&req); err != nil { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid request body")) return } err = handler.gateway.UpdateIngestionKeyLimit(ctx, orgID, limitID, req.Config, req.Tags) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusNoContent, nil) } func (handler *handler) DeleteIngestionKeyLimit(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return } orgID := valuer.MustNewUUID(claims.OrgID) limitID := mux.Vars(r)["limitId"] if limitID == "" { render.Error(rw, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "limitId is required")) return } err = handler.gateway.DeleteIngestionKeyLimit(ctx, orgID, limitID) if err != nil { render.Error(rw, err) return } render.Success(rw, http.StatusNoContent, nil) } func parseIntWithDefaultValue(value string, defaultValue int) (int, error) { if value == "" { return defaultValue, nil } result, err := strconv.Atoi(value) if err != nil { return 0, err } return result, nil }