mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-06-04 11:25:52 +08:00

* chore: update auth * chore: password changes * chore: make changes in oss code * chore: login * chore: get to a running state * fix: migration inital commit * fix: signoz cloud intgtn tests * fix: minor fixes * chore: sso code fixed with org domain * fix: tests * fix: ee auth api's * fix: changes in name * fix: return user in login api * fix: address comments * fix: validate password * fix: handle get domain by email properly * fix: move authomain to usermodule * fix: use displayname instead of hname * fix: rename back endpoints * fix: update telemetry * fix: correct errors * fix: test and fix the invite endpoints * fix: delete all things related to user in store * fix: address issues * fix: ee delete invite * fix: rename func * fix: update user and update role * fix: update role * fix: login and invite changes * fix: return org name in users response * fix: update user role * fix: nil check * fix: getinvite and update role * fix: sso * fix: getinvite use sso ctx * fix: use correct sourceurl * fix: getsourceurl from req payload * fix: update created_at * fix: fix reset password * fix: sso signup and token password change * fix: don't delete last admin * fix: reset password and migration * fix: migration * fix: reset password for sso users * fix: clean up invite * fix: migration * fix: update claims and store code * fix: use correct error * fix: proper nil checks * fix: make migration multitenant * fix: address comments * fix: minor fixes * fix: test * fix: rename reset password --------- Co-authored-by: Vikrant Gupta <vikrant@signoz.io>
246 lines
8.9 KiB
Go
246 lines
8.9 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"time"
|
|
|
|
"github.com/SigNoz/signoz/ee/query-service/dao"
|
|
"github.com/SigNoz/signoz/ee/query-service/integrations/gateway"
|
|
"github.com/SigNoz/signoz/ee/query-service/interfaces"
|
|
"github.com/SigNoz/signoz/ee/query-service/license"
|
|
"github.com/SigNoz/signoz/ee/query-service/model"
|
|
"github.com/SigNoz/signoz/ee/query-service/usage"
|
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
|
"github.com/SigNoz/signoz/pkg/apis/fields"
|
|
"github.com/SigNoz/signoz/pkg/errors"
|
|
"github.com/SigNoz/signoz/pkg/http/middleware"
|
|
"github.com/SigNoz/signoz/pkg/http/render"
|
|
"github.com/SigNoz/signoz/pkg/modules/quickfilter"
|
|
quickfilterscore "github.com/SigNoz/signoz/pkg/modules/quickfilter/core"
|
|
baseapp "github.com/SigNoz/signoz/pkg/query-service/app"
|
|
"github.com/SigNoz/signoz/pkg/query-service/app/cloudintegrations"
|
|
"github.com/SigNoz/signoz/pkg/query-service/app/integrations"
|
|
"github.com/SigNoz/signoz/pkg/query-service/app/logparsingpipeline"
|
|
baseint "github.com/SigNoz/signoz/pkg/query-service/interfaces"
|
|
basemodel "github.com/SigNoz/signoz/pkg/query-service/model"
|
|
rules "github.com/SigNoz/signoz/pkg/query-service/rules"
|
|
"github.com/SigNoz/signoz/pkg/signoz"
|
|
"github.com/SigNoz/signoz/pkg/types"
|
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
|
"github.com/SigNoz/signoz/pkg/version"
|
|
"github.com/gorilla/mux"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type APIHandlerOptions struct {
|
|
DataConnector interfaces.DataConnector
|
|
PreferSpanMetrics bool
|
|
AppDao dao.ModelDao
|
|
RulesManager *rules.Manager
|
|
UsageManager *usage.Manager
|
|
FeatureFlags baseint.FeatureLookup
|
|
LicenseManager *license.Manager
|
|
IntegrationsController *integrations.Controller
|
|
CloudIntegrationsController *cloudintegrations.Controller
|
|
LogsParsingPipelineController *logparsingpipeline.LogParsingPipelineController
|
|
Gateway *httputil.ReverseProxy
|
|
GatewayUrl string
|
|
// Querier Influx Interval
|
|
FluxInterval time.Duration
|
|
UseLogsNewSchema bool
|
|
UseTraceNewSchema bool
|
|
JWT *authtypes.JWT
|
|
}
|
|
|
|
type APIHandler struct {
|
|
opts APIHandlerOptions
|
|
baseapp.APIHandler
|
|
}
|
|
|
|
// NewAPIHandler returns an APIHandler
|
|
func NewAPIHandler(opts APIHandlerOptions, signoz *signoz.SigNoz) (*APIHandler, error) {
|
|
quickfiltermodule := quickfilterscore.NewQuickFilters(quickfilterscore.NewStore(signoz.SQLStore))
|
|
quickFilter := quickfilter.NewAPI(quickfiltermodule)
|
|
baseHandler, err := baseapp.NewAPIHandler(baseapp.APIHandlerOpts{
|
|
Reader: opts.DataConnector,
|
|
PreferSpanMetrics: opts.PreferSpanMetrics,
|
|
AppDao: opts.AppDao,
|
|
RuleManager: opts.RulesManager,
|
|
FeatureFlags: opts.FeatureFlags,
|
|
IntegrationsController: opts.IntegrationsController,
|
|
CloudIntegrationsController: opts.CloudIntegrationsController,
|
|
LogsParsingPipelineController: opts.LogsParsingPipelineController,
|
|
FluxInterval: opts.FluxInterval,
|
|
AlertmanagerAPI: alertmanager.NewAPI(signoz.Alertmanager),
|
|
FieldsAPI: fields.NewAPI(signoz.TelemetryStore),
|
|
Signoz: signoz,
|
|
QuickFilters: quickFilter,
|
|
QuickFilterModule: quickfiltermodule,
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ah := &APIHandler{
|
|
opts: opts,
|
|
APIHandler: *baseHandler,
|
|
}
|
|
return ah, nil
|
|
}
|
|
|
|
func (ah *APIHandler) FF() baseint.FeatureLookup {
|
|
return ah.opts.FeatureFlags
|
|
}
|
|
|
|
func (ah *APIHandler) RM() *rules.Manager {
|
|
return ah.opts.RulesManager
|
|
}
|
|
|
|
func (ah *APIHandler) LM() *license.Manager {
|
|
return ah.opts.LicenseManager
|
|
}
|
|
|
|
func (ah *APIHandler) UM() *usage.Manager {
|
|
return ah.opts.UsageManager
|
|
}
|
|
|
|
func (ah *APIHandler) AppDao() dao.ModelDao {
|
|
return ah.opts.AppDao
|
|
}
|
|
|
|
func (ah *APIHandler) Gateway() *httputil.ReverseProxy {
|
|
return ah.opts.Gateway
|
|
}
|
|
|
|
func (ah *APIHandler) CheckFeature(f string) bool {
|
|
err := ah.FF().CheckFeature(f)
|
|
return err == nil
|
|
}
|
|
|
|
// RegisterRoutes registers routes for this handler on the given router
|
|
func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
|
// note: add ee override methods first
|
|
|
|
// routes available only in ee version
|
|
|
|
router.HandleFunc("/api/v1/featureFlags", am.OpenAccess(ah.getFeatureFlags)).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/v1/loginPrecheck", am.OpenAccess(ah.loginPrecheck)).Methods(http.MethodGet)
|
|
|
|
// invite
|
|
router.HandleFunc("/api/v1/invite/{token}", am.OpenAccess(ah.getInvite)).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/v1/invite/accept", am.OpenAccess(ah.acceptInvite)).Methods(http.MethodPost)
|
|
|
|
// paid plans specific routes
|
|
router.HandleFunc("/api/v1/complete/saml", am.OpenAccess(ah.receiveSAML)).Methods(http.MethodPost)
|
|
router.HandleFunc("/api/v1/complete/google", am.OpenAccess(ah.receiveGoogleAuth)).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/v1/orgs/{orgId}/domains", am.AdminAccess(ah.listDomainsByOrg)).Methods(http.MethodGet)
|
|
|
|
router.HandleFunc("/api/v1/domains", am.AdminAccess(ah.postDomain)).Methods(http.MethodPost)
|
|
router.HandleFunc("/api/v1/domains/{id}", am.AdminAccess(ah.putDomain)).Methods(http.MethodPut)
|
|
router.HandleFunc("/api/v1/domains/{id}", am.AdminAccess(ah.deleteDomain)).Methods(http.MethodDelete)
|
|
|
|
// base overrides
|
|
router.HandleFunc("/api/v1/version", am.OpenAccess(ah.getVersion)).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/v1/login", am.OpenAccess(ah.loginUser)).Methods(http.MethodPost)
|
|
|
|
// PAT APIs
|
|
router.HandleFunc("/api/v1/pats", am.AdminAccess(ah.createPAT)).Methods(http.MethodPost)
|
|
router.HandleFunc("/api/v1/pats", am.AdminAccess(ah.getPATs)).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/v1/pats/{id}", am.AdminAccess(ah.updatePAT)).Methods(http.MethodPut)
|
|
router.HandleFunc("/api/v1/pats/{id}", am.AdminAccess(ah.revokePAT)).Methods(http.MethodDelete)
|
|
|
|
router.HandleFunc("/api/v1/checkout", am.AdminAccess(ah.checkout)).Methods(http.MethodPost)
|
|
router.HandleFunc("/api/v1/billing", am.AdminAccess(ah.getBilling)).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/v1/portal", am.AdminAccess(ah.portalSession)).Methods(http.MethodPost)
|
|
|
|
router.HandleFunc("/api/v1/dashboards/{uuid}/lock", am.EditAccess(ah.lockDashboard)).Methods(http.MethodPut)
|
|
router.HandleFunc("/api/v1/dashboards/{uuid}/unlock", am.EditAccess(ah.unlockDashboard)).Methods(http.MethodPut)
|
|
|
|
// v3
|
|
router.HandleFunc("/api/v3/licenses", am.ViewAccess(ah.listLicensesV3)).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/v3/licenses", am.AdminAccess(ah.applyLicenseV3)).Methods(http.MethodPost)
|
|
router.HandleFunc("/api/v3/licenses", am.AdminAccess(ah.refreshLicensesV3)).Methods(http.MethodPut)
|
|
router.HandleFunc("/api/v3/licenses/active", am.ViewAccess(ah.getActiveLicenseV3)).Methods(http.MethodGet)
|
|
|
|
// v4
|
|
router.HandleFunc("/api/v4/query_range", am.ViewAccess(ah.queryRangeV4)).Methods(http.MethodPost)
|
|
|
|
// Gateway
|
|
router.PathPrefix(gateway.RoutePrefix).HandlerFunc(am.EditAccess(ah.ServeGatewayHTTP))
|
|
|
|
ah.APIHandler.RegisterRoutes(router, am)
|
|
|
|
}
|
|
|
|
// TODO(nitya): remove this once we know how to get the FF's
|
|
func (ah *APIHandler) updateRequestContext(w http.ResponseWriter, r *http.Request) (*http.Request, error) {
|
|
ssoAvailable := true
|
|
err := ah.FF().CheckFeature(model.SSO)
|
|
if err != nil {
|
|
switch err.(type) {
|
|
case basemodel.ErrFeatureUnavailable:
|
|
// do nothing, just skip sso
|
|
ssoAvailable = false
|
|
default:
|
|
zap.L().Error("feature check failed", zap.String("featureKey", model.SSO), zap.Error(err))
|
|
return r, errors.New(errors.TypeInternal, errors.CodeInternal, "error checking SSO feature")
|
|
}
|
|
}
|
|
ctx := context.WithValue(r.Context(), types.SSOAvailable, ssoAvailable)
|
|
return r.WithContext(ctx), nil
|
|
}
|
|
|
|
func (ah *APIHandler) loginPrecheck(w http.ResponseWriter, r *http.Request) {
|
|
r, err := ah.updateRequestContext(w, r)
|
|
if err != nil {
|
|
render.Error(w, err)
|
|
return
|
|
}
|
|
ah.Signoz.Handlers.User.LoginPrecheck(w, r)
|
|
return
|
|
}
|
|
|
|
func (ah *APIHandler) acceptInvite(w http.ResponseWriter, r *http.Request) {
|
|
r, err := ah.updateRequestContext(w, r)
|
|
if err != nil {
|
|
render.Error(w, err)
|
|
return
|
|
}
|
|
ah.Signoz.Handlers.User.AcceptInvite(w, r)
|
|
return
|
|
}
|
|
|
|
func (ah *APIHandler) getInvite(w http.ResponseWriter, r *http.Request) {
|
|
r, err := ah.updateRequestContext(w, r)
|
|
if err != nil {
|
|
render.Error(w, err)
|
|
return
|
|
}
|
|
ah.Signoz.Handlers.User.GetInvite(w, r)
|
|
return
|
|
}
|
|
|
|
func (ah *APIHandler) RegisterCloudIntegrationsRoutes(router *mux.Router, am *middleware.AuthZ) {
|
|
|
|
ah.APIHandler.RegisterCloudIntegrationsRoutes(router, am)
|
|
|
|
router.HandleFunc(
|
|
"/api/v1/cloud-integrations/{cloudProvider}/accounts/generate-connection-params",
|
|
am.EditAccess(ah.CloudIntegrationsGenerateConnectionParams),
|
|
).Methods(http.MethodGet)
|
|
|
|
}
|
|
|
|
func (ah *APIHandler) getVersion(w http.ResponseWriter, r *http.Request) {
|
|
versionResponse := basemodel.GetVersionResponse{
|
|
Version: version.Info.Version(),
|
|
EE: "Y",
|
|
SetupCompleted: ah.SetupCompleted,
|
|
}
|
|
|
|
ah.WriteJSON(w, r, versionResponse)
|
|
}
|