diff --git a/ee/query-service/app/api/api.go b/ee/query-service/app/api/api.go index fa9f9ac797..04ca9daccc 100644 --- a/ee/query-service/app/api/api.go +++ b/ee/query-service/app/api/api.go @@ -13,9 +13,6 @@ import ( "github.com/SigNoz/signoz/pkg/alertmanager" "github.com/SigNoz/signoz/pkg/apis/fields" "github.com/SigNoz/signoz/pkg/http/middleware" - "github.com/SigNoz/signoz/pkg/modules/organization/implorganization" - "github.com/SigNoz/signoz/pkg/modules/preference" - preferencecore "github.com/SigNoz/signoz/pkg/modules/preference/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" @@ -26,7 +23,6 @@ import ( rules "github.com/SigNoz/signoz/pkg/query-service/rules" "github.com/SigNoz/signoz/pkg/signoz" "github.com/SigNoz/signoz/pkg/types/authtypes" - "github.com/SigNoz/signoz/pkg/types/preferencetypes" "github.com/SigNoz/signoz/pkg/version" "github.com/gorilla/mux" ) @@ -60,10 +56,6 @@ type APIHandler struct { // NewAPIHandler returns an APIHandler func NewAPIHandler(opts APIHandlerOptions, signoz *signoz.SigNoz) (*APIHandler, error) { - preference := preference.NewAPI(preferencecore.NewPreference(preferencecore.NewStore(signoz.SQLStore), preferencetypes.NewDefaultPreferenceMap())) - organizationAPI := implorganization.NewAPI(implorganization.NewModule(implorganization.NewStore(signoz.SQLStore))) - organizationModule := implorganization.NewModule(implorganization.NewStore(signoz.SQLStore)) - baseHandler, err := baseapp.NewAPIHandler(baseapp.APIHandlerOpts{ Reader: opts.DataConnector, SkipConfig: opts.SkipConfig, @@ -81,9 +73,6 @@ func NewAPIHandler(opts APIHandlerOptions, signoz *signoz.SigNoz) (*APIHandler, AlertmanagerAPI: alertmanager.NewAPI(signoz.Alertmanager), FieldsAPI: fields.NewAPI(signoz.TelemetryStore), Signoz: signoz, - Preference: preference, - OrganizationAPI: organizationAPI, - OrganizationModule: organizationModule, }) if err != nil { diff --git a/ee/query-service/app/api/auth.go b/ee/query-service/app/api/auth.go index 469d39f85b..8e4c0fc069 100644 --- a/ee/query-service/app/api/auth.go +++ b/ee/query-service/app/api/auth.go @@ -134,7 +134,7 @@ func (ah *APIHandler) registerUser(w http.ResponseWriter, r *http.Request) { return } - _, registerError := baseauth.Register(ctx, req, ah.Signoz.Alertmanager, ah.OrganizationModule) + _, registerError := baseauth.Register(ctx, req, ah.Signoz.Alertmanager, ah.Signoz.Modules.Organization) if !registerError.IsNil() { RespondError(w, apierr, nil) return @@ -152,7 +152,7 @@ func (ah *APIHandler) getInvite(w http.ResponseWriter, r *http.Request) { token := mux.Vars(r)["token"] sourceUrl := r.URL.Query().Get("ref") - inviteObject, err := baseauth.GetInvite(r.Context(), token, ah.OrganizationModule) + inviteObject, err := baseauth.GetInvite(r.Context(), token, ah.Signoz.Modules.Organization) if err != nil { RespondError(w, model.BadRequest(err), nil) return diff --git a/ee/sqlstore/postgressqlstore/dialect.go b/ee/sqlstore/postgressqlstore/dialect.go index 2fa2c0084e..f7b44cf687 100644 --- a/ee/sqlstore/postgressqlstore/dialect.go +++ b/ee/sqlstore/postgressqlstore/dialect.go @@ -194,7 +194,7 @@ func (dialect *dialect) RenameColumn(ctx context.Context, bun bun.IDB, table str } if !oldColumnExists { - return false, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("old column: %s doesn't exist", oldColumnName)) + return false, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "old column: %s doesn't exist", oldColumnName) } _, err = bun. diff --git a/ee/sqlstore/postgressqlstore/provider.go b/ee/sqlstore/postgressqlstore/provider.go index 550e40c1e7..6c098b448f 100644 --- a/ee/sqlstore/postgressqlstore/provider.go +++ b/ee/sqlstore/postgressqlstore/provider.go @@ -4,8 +4,10 @@ import ( "context" "database/sql" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/factory" "github.com/SigNoz/signoz/pkg/sqlstore" + "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/stdlib" "github.com/jmoiron/sqlx" @@ -87,3 +89,20 @@ func (provider *provider) BunDBCtx(ctx context.Context) bun.IDB { func (provider *provider) RunInTxCtx(ctx context.Context, opts *sql.TxOptions, cb func(ctx context.Context) error) error { return provider.bundb.RunInTxCtx(ctx, opts, cb) } + +func (provider *provider) WrapNotFoundErrf(err error, code errors.Code, format string, args ...any) error { + if err == sql.ErrNoRows { + return errors.Wrapf(err, errors.TypeNotFound, code, format, args...) + } + + return err +} + +func (provider *provider) WrapAlreadyExistsErrf(err error, code errors.Code, format string, args ...any) error { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) && pgErr.Code == "23505" { + return errors.Wrapf(err, errors.TypeAlreadyExists, code, format, args...) + } + + return err +} diff --git a/pkg/errors/code.go b/pkg/errors/code.go index 3da31f37e2..8457aa5575 100644 --- a/pkg/errors/code.go +++ b/pkg/errors/code.go @@ -6,31 +6,31 @@ import ( ) var ( - CodeInvalidInput code = code{"invalid_input"} - CodeInternal = code{"internal"} - CodeUnsupported = code{"unsupported"} - CodeNotFound = code{"not_found"} - CodeMethodNotAllowed = code{"method_not_allowed"} - CodeAlreadyExists = code{"already_exists"} - CodeUnauthenticated = code{"unauthenticated"} - CodeForbidden = code{"forbidden"} + CodeInvalidInput Code = Code{"invalid_input"} + CodeInternal = Code{"internal"} + CodeUnsupported = Code{"unsupported"} + CodeNotFound = Code{"not_found"} + CodeMethodNotAllowed = Code{"method_not_allowed"} + CodeAlreadyExists = Code{"already_exists"} + CodeUnauthenticated = Code{"unauthenticated"} + CodeForbidden = Code{"forbidden"} ) var ( codeRegex = regexp.MustCompile(`^[a-z_]+$`) ) -type code struct{ s string } +type Code struct{ s string } -func NewCode(s string) (code, error) { +func NewCode(s string) (Code, error) { if !codeRegex.MatchString(s) { - return code{}, fmt.Errorf("invalid code: %v", s) + return Code{}, fmt.Errorf("invalid code: %v", s) } - return code{s: s}, nil + return Code{s: s}, nil } -func MustNewCode(s string) code { +func MustNewCode(s string) Code { code, err := NewCode(s) if err != nil { panic(err) @@ -39,6 +39,6 @@ func MustNewCode(s string) code { return code } -func (c code) String() string { +func (c Code) String() string { return c.s } diff --git a/pkg/errors/errors.go b/pkg/errors/errors.go index 779cd62f4d..f4ded01185 100644 --- a/pkg/errors/errors.go +++ b/pkg/errors/errors.go @@ -7,7 +7,7 @@ import ( ) var ( - codeUnknown code = MustNewCode("unknown") + codeUnknown Code = MustNewCode("unknown") ) // base is the fundamental struct that implements the error interface. @@ -16,7 +16,7 @@ type base struct { // t denotes the custom type of the error. t typ // c denotes the short code for the error message. - c code + c Code // m contains error message passed through errors.New. m string // e is the actual error being wrapped. @@ -47,7 +47,7 @@ func (b *base) Error() string { } // New returns a base error. It requires type, code and message as input. -func New(t typ, code code, message string) *base { +func New(t typ, code Code, message string) *base { return &base{ t: t, c: code, @@ -59,7 +59,7 @@ func New(t typ, code code, message string) *base { } // Newf returns a new base by formatting the error message with the supplied format specifier. -func Newf(t typ, code code, format string, args ...interface{}) *base { +func Newf(t typ, code Code, format string, args ...interface{}) *base { return &base{ t: t, c: code, @@ -70,7 +70,7 @@ func Newf(t typ, code code, format string, args ...interface{}) *base { // Wrapf returns a new error by formatting the error message with the supplied format specifier // and wrapping another error with base. -func Wrapf(cause error, t typ, code code, format string, args ...interface{}) *base { +func Wrapf(cause error, t typ, code Code, format string, args ...interface{}) *base { return &base{ t: t, c: code, @@ -110,7 +110,7 @@ func (b *base) WithAdditional(a ...string) *base { // and the error itself. // //lint:ignore ST1008 we want to return arguments in the 'TCMEUA' order of the struct -func Unwrapb(cause error) (typ, code, string, error, string, []string) { +func Unwrapb(cause error) (typ, Code, string, error, string, []string) { base, ok := cause.(*base) if ok { return base.t, base.c, base.m, base.e, base.u, base.a @@ -127,7 +127,7 @@ func Ast(cause error, typ typ) bool { } // Ast checks if the provided error matches the specified custom error code. -func Asc(cause error, code code) bool { +func Asc(cause error, code Code) bool { _, c, _, _, _, _ := Unwrapb(cause) return c.s == code.s @@ -137,3 +137,7 @@ func Asc(cause error, code code) bool { func Join(errs ...error) error { return errors.Join(errs...) } + +func As(err error, target any) bool { + return errors.As(err, target) +} diff --git a/pkg/modules/organization/implorganization/api.go b/pkg/modules/organization/implorganization/handler.go similarity index 59% rename from pkg/modules/organization/implorganization/api.go rename to pkg/modules/organization/implorganization/handler.go index fdbacb3127..9c5ca484ed 100644 --- a/pkg/modules/organization/implorganization/api.go +++ b/pkg/modules/organization/implorganization/handler.go @@ -1,8 +1,10 @@ package implorganization import ( + "context" "encoding/json" "net/http" + "time" "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/http/render" @@ -12,16 +14,19 @@ import ( "github.com/SigNoz/signoz/pkg/valuer" ) -type organizationAPI struct { +type handler struct { module organization.Module } -func NewAPI(module organization.Module) organization.API { - return &organizationAPI{module: module} +func NewHandler(module organization.Module) organization.Handler { + return &handler{module: module} } -func (api *organizationAPI) Get(rw http.ResponseWriter, r *http.Request) { - claims, err := authtypes.ClaimsFromContext(r.Context()) +func (handler *handler) Get(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return @@ -29,11 +34,11 @@ func (api *organizationAPI) Get(rw http.ResponseWriter, r *http.Request) { orgID, err := valuer.NewUUID(claims.OrgID) if err != nil { - render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid org id")) + render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "orgId is invalid")) return } - organization, err := api.module.Get(r.Context(), orgID) + organization, err := handler.module.Get(ctx, orgID) if err != nil { render.Error(rw, err) return @@ -42,18 +47,11 @@ func (api *organizationAPI) Get(rw http.ResponseWriter, r *http.Request) { render.Success(rw, http.StatusOK, organization) } -func (api *organizationAPI) GetAll(rw http.ResponseWriter, r *http.Request) { - organizations, err := api.module.GetAll(r.Context()) - if err != nil { - render.Error(rw, err) - return - } +func (handler *handler) Update(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() - render.Success(rw, http.StatusOK, organizations) -} - -func (api *organizationAPI) Update(rw http.ResponseWriter, r *http.Request) { - claims, err := authtypes.ClaimsFromContext(r.Context()) + claims, err := authtypes.ClaimsFromContext(ctx) if err != nil { render.Error(rw, err) return @@ -72,7 +70,7 @@ func (api *organizationAPI) Update(rw http.ResponseWriter, r *http.Request) { } req.ID = orgID - err = api.module.Update(r.Context(), req) + err = handler.module.Update(ctx, req) if err != nil { render.Error(rw, err) return diff --git a/pkg/modules/organization/implorganization/module.go b/pkg/modules/organization/implorganization/module.go index 7162e2e6a1..27fe2f1e6f 100644 --- a/pkg/modules/organization/implorganization/module.go +++ b/pkg/modules/organization/implorganization/module.go @@ -8,26 +8,26 @@ import ( "github.com/SigNoz/signoz/pkg/valuer" ) -type organizationModule struct { +type module struct { store types.OrganizationStore } func NewModule(organizationStore types.OrganizationStore) organization.Module { - return &organizationModule{store: organizationStore} + return &module{store: organizationStore} } -func (o *organizationModule) Create(ctx context.Context, organization *types.Organization) error { - return o.store.Create(ctx, organization) +func (module *module) Create(ctx context.Context, organization *types.Organization) error { + return module.store.Create(ctx, organization) } -func (o *organizationModule) Get(ctx context.Context, id valuer.UUID) (*types.Organization, error) { - return o.store.Get(ctx, id) +func (module *module) Get(ctx context.Context, id valuer.UUID) (*types.Organization, error) { + return module.store.Get(ctx, id) } -func (o *organizationModule) GetAll(ctx context.Context) ([]*types.Organization, error) { - return o.store.GetAll(ctx) +func (module *module) GetAll(ctx context.Context) ([]*types.Organization, error) { + return module.store.GetAll(ctx) } -func (o *organizationModule) Update(ctx context.Context, updatedOrganization *types.Organization) error { - return o.store.Update(ctx, updatedOrganization) +func (module *module) Update(ctx context.Context, updatedOrganization *types.Organization) error { + return module.store.Update(ctx, updatedOrganization) } diff --git a/pkg/modules/organization/implorganization/store.go b/pkg/modules/organization/implorganization/store.go index 0c043adfca..ec33cd04bd 100644 --- a/pkg/modules/organization/implorganization/store.go +++ b/pkg/modules/organization/implorganization/store.go @@ -2,77 +2,69 @@ package implorganization import ( "context" - "database/sql" "time" - "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/sqlstore" "github.com/SigNoz/signoz/pkg/types" "github.com/SigNoz/signoz/pkg/valuer" ) type store struct { - store sqlstore.SQLStore + sqlstore sqlstore.SQLStore } -func NewStore(db sqlstore.SQLStore) types.OrganizationStore { - return &store{store: db} +func NewStore(sqlstore sqlstore.SQLStore) types.OrganizationStore { + return &store{sqlstore: sqlstore} } -func (s *store) Create(ctx context.Context, organization *types.Organization) error { - _, err := s. - store. +func (store *store) Create(ctx context.Context, organization *types.Organization) error { + _, err := store. + sqlstore. BunDB(). NewInsert(). Model(organization). Exec(ctx) if err != nil { - return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to create organization") + return store.sqlstore.WrapAlreadyExistsErrf(err, types.ErrOrganizationAlreadyExists, "organization with name: %s already exists", organization.Name) } return nil } -func (s *store) Get(ctx context.Context, id valuer.UUID) (*types.Organization, error) { +func (store *store) Get(ctx context.Context, id valuer.UUID) (*types.Organization, error) { organization := new(types.Organization) - err := s. - store. + err := store. + sqlstore. BunDB(). NewSelect(). Model(organization). Where("id = ?", id.StringValue()). Scan(ctx) if err != nil { - if err == sql.ErrNoRows { - return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "no organization found with id: %s", id.StringValue()) - } - return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to get organization with id: %s", id.StringValue()) + return nil, store.sqlstore.WrapNotFoundErrf(err, types.ErrOrganizationNotFound, "organization with id: %s does not exist", id.StringValue()) } return organization, nil } -func (s *store) GetAll(ctx context.Context) ([]*types.Organization, error) { +func (store *store) GetAll(ctx context.Context) ([]*types.Organization, error) { organizations := make([]*types.Organization, 0) - err := s. - store. + err := store. + sqlstore. BunDB(). NewSelect(). Model(&organizations). Scan(ctx) if err != nil { - if err == sql.ErrNoRows { - return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "no organizations found") - } - return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to get all organizations") + return nil, err } return organizations, nil } -func (s *store) Update(ctx context.Context, organization *types.Organization) error { - _, err := s. - store. +func (store *store) Update(ctx context.Context, organization *types.Organization) error { + _, err := store. + sqlstore. BunDB(). NewUpdate(). Model(organization). @@ -81,21 +73,21 @@ func (s *store) Update(ctx context.Context, organization *types.Organization) er Where("id = ?", organization.ID.StringValue()). Exec(ctx) if err != nil { - return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to update organization with id: %s", organization.ID.StringValue()) + return store.sqlstore.WrapAlreadyExistsErrf(err, types.ErrOrganizationAlreadyExists, "organization already exists") } return nil } -func (s *store) Delete(ctx context.Context, id valuer.UUID) error { - _, err := s. - store. +func (store *store) Delete(ctx context.Context, id valuer.UUID) error { + _, err := store. + sqlstore. BunDB(). NewDelete(). Model(new(types.Organization)). Where("id = ?", id.StringValue()). Exec(ctx) if err != nil { - return errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to delete organization with id: %s", id.StringValue()) + return err } return nil diff --git a/pkg/modules/organization/organization.go b/pkg/modules/organization/organization.go index fc2a445969..00ba48f95d 100644 --- a/pkg/modules/organization/organization.go +++ b/pkg/modules/organization/organization.go @@ -22,13 +22,10 @@ type Module interface { Update(context.Context, *types.Organization) error } -type API interface { +type Handler interface { // Get gets the organization based on the id in claims Get(http.ResponseWriter, *http.Request) - // GetAll gets all the organizations - GetAll(http.ResponseWriter, *http.Request) - // Update updates the organization based on the id in claims Update(http.ResponseWriter, *http.Request) } diff --git a/pkg/modules/preference/api.go b/pkg/modules/preference/api.go deleted file mode 100644 index d02b682038..0000000000 --- a/pkg/modules/preference/api.go +++ /dev/null @@ -1,147 +0,0 @@ -package preference - -import ( - "encoding/json" - "net/http" - - "github.com/SigNoz/signoz/pkg/http/render" - "github.com/SigNoz/signoz/pkg/types/authtypes" - "github.com/SigNoz/signoz/pkg/types/preferencetypes" - "github.com/gorilla/mux" -) - -type API interface { - GetOrgPreference(http.ResponseWriter, *http.Request) - UpdateOrgPreference(http.ResponseWriter, *http.Request) - GetAllOrgPreferences(http.ResponseWriter, *http.Request) - GetUserPreference(http.ResponseWriter, *http.Request) - UpdateUserPreference(http.ResponseWriter, *http.Request) - GetAllUserPreferences(http.ResponseWriter, *http.Request) -} - -type preferenceAPI struct { - usecase Usecase -} - -func NewAPI(usecase Usecase) API { - return &preferenceAPI{usecase: usecase} -} - -func (p *preferenceAPI) GetOrgPreference(rw http.ResponseWriter, r *http.Request) { - preferenceId := mux.Vars(r)["preferenceId"] - claims, err := authtypes.ClaimsFromContext(r.Context()) - if err != nil { - render.Error(rw, err) - return - } - preference, err := p.usecase.GetOrgPreference( - r.Context(), preferenceId, claims.OrgID, - ) - if err != nil { - render.Error(rw, err) - return - } - - render.Success(rw, http.StatusOK, preference) -} - -func (p *preferenceAPI) UpdateOrgPreference(rw http.ResponseWriter, r *http.Request) { - preferenceId := mux.Vars(r)["preferenceId"] - req := preferencetypes.UpdatablePreference{} - claims, err := authtypes.ClaimsFromContext(r.Context()) - if err != nil { - render.Error(rw, err) - return - } - - err = json.NewDecoder(r.Body).Decode(&req) - if err != nil { - render.Error(rw, err) - return - } - - err = p.usecase.UpdateOrgPreference(r.Context(), preferenceId, req.PreferenceValue, claims.OrgID) - if err != nil { - render.Error(rw, err) - return - } - - render.Success(rw, http.StatusNoContent, nil) -} - -func (p *preferenceAPI) GetAllOrgPreferences(rw http.ResponseWriter, r *http.Request) { - claims, err := authtypes.ClaimsFromContext(r.Context()) - if err != nil { - render.Error(rw, err) - return - } - preferences, err := p.usecase.GetAllOrgPreferences( - r.Context(), claims.OrgID, - ) - if err != nil { - render.Error(rw, err) - return - } - - render.Success(rw, http.StatusOK, preferences) -} - -func (p *preferenceAPI) GetUserPreference(rw http.ResponseWriter, r *http.Request) { - preferenceId := mux.Vars(r)["preferenceId"] - claims, err := authtypes.ClaimsFromContext(r.Context()) - if err != nil { - render.Error(rw, err) - return - } - - preference, err := p.usecase.GetUserPreference( - r.Context(), preferenceId, claims.OrgID, claims.UserID, - ) - if err != nil { - render.Error(rw, err) - return - } - - render.Success(rw, http.StatusOK, preference) -} - -func (p *preferenceAPI) UpdateUserPreference(rw http.ResponseWriter, r *http.Request) { - preferenceId := mux.Vars(r)["preferenceId"] - claims, err := authtypes.ClaimsFromContext(r.Context()) - if err != nil { - render.Error(rw, err) - return - } - req := preferencetypes.UpdatablePreference{} - - err = json.NewDecoder(r.Body).Decode(&req) - - if err != nil { - render.Error(rw, err) - return - } - err = p.usecase.UpdateUserPreference(r.Context(), preferenceId, req.PreferenceValue, claims.UserID) - if err != nil { - render.Error(rw, err) - return - } - - render.Success(rw, http.StatusNoContent, nil) -} - -func (p *preferenceAPI) GetAllUserPreferences(rw http.ResponseWriter, r *http.Request) { - claims, err := authtypes.ClaimsFromContext(r.Context()) - if err != nil { - render.Error(rw, err) - return - } - preferences, err := p.usecase.GetAllUserPreferences( - r.Context(), claims.OrgID, claims.UserID, - ) - if err != nil { - render.Error(rw, err) - return - } - - render.Success(rw, http.StatusOK, preferences) -} diff --git a/pkg/modules/preference/implpreference/handler.go b/pkg/modules/preference/implpreference/handler.go new file mode 100644 index 0000000000..9d96219f42 --- /dev/null +++ b/pkg/modules/preference/implpreference/handler.go @@ -0,0 +1,176 @@ +package implpreference + +import ( + "context" + "encoding/json" + "net/http" + "time" + + "github.com/SigNoz/signoz/pkg/errors" + "github.com/SigNoz/signoz/pkg/http/render" + "github.com/SigNoz/signoz/pkg/modules/preference" + "github.com/SigNoz/signoz/pkg/types/authtypes" + "github.com/SigNoz/signoz/pkg/types/preferencetypes" + "github.com/gorilla/mux" +) + +type handler struct { + module preference.Module +} + +func NewHandler(module preference.Module) preference.Handler { + return &handler{module: module} +} + +func (handler *handler) GetOrg(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + claims, err := authtypes.ClaimsFromContext(ctx) + if err != nil { + render.Error(rw, err) + return + } + + id, ok := mux.Vars(r)["preferenceId"] + if !ok { + render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is required")) + return + } + + preference, err := handler.module.GetOrg(ctx, id, claims.OrgID) + if err != nil { + render.Error(rw, err) + return + } + + render.Success(rw, http.StatusOK, preference) +} + +func (handler *handler) UpdateOrg(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + claims, err := authtypes.ClaimsFromContext(ctx) + if err != nil { + render.Error(rw, err) + return + } + + id, ok := mux.Vars(r)["preferenceId"] + if !ok { + render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is required")) + return + } + + req := new(preferencetypes.UpdatablePreference) + + err = json.NewDecoder(r.Body).Decode(req) + if err != nil { + render.Error(rw, err) + return + } + + err = handler.module.UpdateOrg(ctx, id, req.PreferenceValue, claims.OrgID) + if err != nil { + render.Error(rw, err) + return + } + + render.Success(rw, http.StatusNoContent, nil) +} + +func (handler *handler) GetAllOrg(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + claims, err := authtypes.ClaimsFromContext(ctx) + if err != nil { + render.Error(rw, err) + return + } + + preferences, err := handler.module.GetAllOrg(ctx, claims.OrgID) + if err != nil { + render.Error(rw, err) + return + } + + render.Success(rw, http.StatusOK, preferences) +} + +func (handler *handler) GetUser(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + claims, err := authtypes.ClaimsFromContext(ctx) + if err != nil { + render.Error(rw, err) + return + } + + id, ok := mux.Vars(r)["preferenceId"] + if !ok { + render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is required")) + return + } + + preference, err := handler.module.GetUser(ctx, id, claims.OrgID, claims.UserID) + if err != nil { + render.Error(rw, err) + return + } + + render.Success(rw, http.StatusOK, preference) +} + +func (handler *handler) UpdateUser(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + claims, err := authtypes.ClaimsFromContext(ctx) + if err != nil { + render.Error(rw, err) + return + } + + id, ok := mux.Vars(r)["preferenceId"] + if !ok { + render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is required")) + return + } + + req := new(preferencetypes.UpdatablePreference) + err = json.NewDecoder(r.Body).Decode(req) + if err != nil { + render.Error(rw, err) + return + } + + err = handler.module.UpdateUser(ctx, id, req.PreferenceValue, claims.UserID) + if err != nil { + render.Error(rw, err) + return + } + + render.Success(rw, http.StatusNoContent, nil) +} + +func (handler *handler) GetAllUser(rw http.ResponseWriter, r *http.Request) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + claims, err := authtypes.ClaimsFromContext(ctx) + if err != nil { + render.Error(rw, err) + return + } + + preferences, err := handler.module.GetAllUser(ctx, claims.OrgID, claims.UserID) + if err != nil { + render.Error(rw, err) + return + } + + render.Success(rw, http.StatusOK, preferences) +} diff --git a/pkg/modules/preference/core/preference.go b/pkg/modules/preference/implpreference/module.go similarity index 54% rename from pkg/modules/preference/core/preference.go rename to pkg/modules/preference/implpreference/module.go index 3a447e0a1d..b00261e706 100644 --- a/pkg/modules/preference/core/preference.go +++ b/pkg/modules/preference/implpreference/module.go @@ -1,10 +1,9 @@ -package core +package implpreference import ( "context" "database/sql" "encoding/json" - "fmt" "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/modules/preference" @@ -12,27 +11,28 @@ import ( "github.com/SigNoz/signoz/pkg/valuer" ) -type usecase struct { - store preferencetypes.PreferenceStore +// Do not take inspiration from this code, it is a work in progress. See Organization module for a better implementation. +type module struct { + store preferencetypes.Store defaultMap map[string]preferencetypes.Preference } -func NewPreference(store preferencetypes.PreferenceStore, defaultMap map[string]preferencetypes.Preference) preference.Usecase { - return &usecase{store: store, defaultMap: defaultMap} +func NewModule(store preferencetypes.Store, defaultMap map[string]preferencetypes.Preference) preference.Module { + return &module{store: store, defaultMap: defaultMap} } -func (usecase *usecase) GetOrgPreference(ctx context.Context, preferenceID string, orgID string) (*preferencetypes.GettablePreference, error) { - preference, seen := usecase.defaultMap[preferenceID] +func (module *module) GetOrg(ctx context.Context, preferenceID string, orgID string) (*preferencetypes.GettablePreference, error) { + preference, seen := module.defaultMap[preferenceID] if !seen { - return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("no such preferenceID exists: %s", preferenceID)) + return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot find preference with id: %s", preferenceID) } - isPreferenceEnabled := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope) - if !isPreferenceEnabled { - return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("preference is not enabled at org scope: %s", preferenceID)) + isEnabled := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope) + if !isEnabled { + return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "preference is not enabled at org scope: %s", preferenceID) } - orgPreference, err := usecase.store.GetOrgPreference(ctx, orgID, preferenceID) + org, err := module.store.GetOrg(ctx, orgID, preferenceID) if err != nil { if err == sql.ErrNoRows { return &preferencetypes.GettablePreference{ @@ -40,24 +40,24 @@ func (usecase *usecase) GetOrgPreference(ctx context.Context, preferenceID strin PreferenceValue: preference.DefaultValue, }, nil } - return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, fmt.Sprintf("error in fetching the org preference: %s", preferenceID)) + return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in fetching the org preference: %s", preferenceID) } return &preferencetypes.GettablePreference{ PreferenceID: preferenceID, - PreferenceValue: preference.SanitizeValue(orgPreference.PreferenceValue), + PreferenceValue: preference.SanitizeValue(org.PreferenceValue), }, nil } -func (usecase *usecase) UpdateOrgPreference(ctx context.Context, preferenceID string, preferenceValue interface{}, orgID string) error { - preference, seen := usecase.defaultMap[preferenceID] +func (module *module) UpdateOrg(ctx context.Context, preferenceID string, preferenceValue interface{}, orgID string) error { + preference, seen := module.defaultMap[preferenceID] if !seen { - return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("no such preferenceID exists: %s", preferenceID)) + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot find preference with id: %s", preferenceID) } - isPreferenceEnabled := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope) - if !isPreferenceEnabled { - return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("preference is not enabled at org scope: %s", preferenceID)) + isEnabled := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope) + if !isEnabled { + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "preference is not enabled at org scope: %s", preferenceID) } err := preference.IsValidValue(preferenceValue) @@ -65,26 +65,26 @@ func (usecase *usecase) UpdateOrgPreference(ctx context.Context, preferenceID st return err } - storablePreferenceValue, encodeErr := json.Marshal(preferenceValue) + storableValue, encodeErr := json.Marshal(preferenceValue) if encodeErr != nil { return errors.Wrapf(encodeErr, errors.TypeInvalidInput, errors.CodeInvalidInput, "error in encoding the preference value") } - orgPreference, dberr := usecase.store.GetOrgPreference(ctx, orgID, preferenceID) + org, dberr := module.store.GetOrg(ctx, orgID, preferenceID) if dberr != nil && dberr != sql.ErrNoRows { return errors.Wrapf(dberr, errors.TypeInternal, errors.CodeInternal, "error in getting the preference value") } if dberr != nil { - orgPreference.ID = valuer.GenerateUUID() - orgPreference.PreferenceID = preferenceID - orgPreference.PreferenceValue = string(storablePreferenceValue) - orgPreference.OrgID = orgID + org.ID = valuer.GenerateUUID() + org.PreferenceID = preferenceID + org.PreferenceValue = string(storableValue) + org.OrgID = orgID } else { - orgPreference.PreferenceValue = string(storablePreferenceValue) + org.PreferenceValue = string(storableValue) } - dberr = usecase.store.UpsertOrgPreference(ctx, orgPreference) + dberr = module.store.UpsertOrg(ctx, org) if dberr != nil { return errors.Wrapf(dberr, errors.TypeInternal, errors.CodeInternal, "error in setting the preference value") } @@ -92,19 +92,19 @@ func (usecase *usecase) UpdateOrgPreference(ctx context.Context, preferenceID st return nil } -func (usecase *usecase) GetAllOrgPreferences(ctx context.Context, orgID string) ([]*preferencetypes.PreferenceWithValue, error) { - allOrgPreferences := []*preferencetypes.PreferenceWithValue{} - orgPreferences, err := usecase.store.GetAllOrgPreferences(ctx, orgID) +func (module *module) GetAllOrg(ctx context.Context, orgID string) ([]*preferencetypes.PreferenceWithValue, error) { + allOrgs := []*preferencetypes.PreferenceWithValue{} + orgs, err := module.store.GetAllOrg(ctx, orgID) if err != nil { return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in setting all org preference values") } preferenceValueMap := map[string]interface{}{} - for _, preferenceValue := range orgPreferences { + for _, preferenceValue := range orgs { preferenceValueMap[preferenceValue.PreferenceID] = preferenceValue.PreferenceValue } - for _, preference := range usecase.defaultMap { + for _, preference := range module.defaultMap { isEnabledForOrgScope := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope) if isEnabledForOrgScope { preferenceWithValue := &preferencetypes.PreferenceWithValue{} @@ -126,16 +126,16 @@ func (usecase *usecase) GetAllOrgPreferences(ctx context.Context, orgID string) } preferenceWithValue.Value = preference.SanitizeValue(preferenceWithValue.Value) - allOrgPreferences = append(allOrgPreferences, preferenceWithValue) + allOrgs = append(allOrgs, preferenceWithValue) } } - return allOrgPreferences, nil + return allOrgs, nil } -func (usecase *usecase) GetUserPreference(ctx context.Context, preferenceID string, orgID string, userID string) (*preferencetypes.GettablePreference, error) { - preference, seen := usecase.defaultMap[preferenceID] +func (module *module) GetUser(ctx context.Context, preferenceID string, orgID string, userID string) (*preferencetypes.GettablePreference, error) { + preference, seen := module.defaultMap[preferenceID] if !seen { - return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("no such preferenceID exists: %s", preferenceID)) + return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot find preference with id: %s", preferenceID) } preferenceValue := preferencetypes.GettablePreference{ @@ -143,29 +143,29 @@ func (usecase *usecase) GetUserPreference(ctx context.Context, preferenceID stri PreferenceValue: preference.DefaultValue, } - isPreferenceEnabledAtUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope) - if !isPreferenceEnabledAtUserScope { - return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("preference is not enabled at user scope: %s", preferenceID)) + isEnabledAtUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope) + if !isEnabledAtUserScope { + return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "preference is not enabled at user scope: %s", preferenceID) } - isPreferenceEnabledAtOrgScope := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope) - if isPreferenceEnabledAtOrgScope { - orgPreference, err := usecase.store.GetOrgPreference(ctx, orgID, preferenceID) + isEnabledAtOrgScope := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope) + if isEnabledAtOrgScope { + org, err := module.store.GetOrg(ctx, orgID, preferenceID) if err != nil && err != sql.ErrNoRows { - return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, fmt.Sprintf("error in fetching the org preference: %s", preferenceID)) + return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in fetching the org preference: %s", preferenceID) } if err == nil { - preferenceValue.PreferenceValue = orgPreference.PreferenceValue + preferenceValue.PreferenceValue = org.PreferenceValue } } - userPreference, err := usecase.store.GetUserPreference(ctx, userID, preferenceID) + user, err := module.store.GetUser(ctx, userID, preferenceID) if err != nil && err != sql.ErrNoRows { - return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, fmt.Sprintf("error in fetching the user preference: %s", preferenceID)) + return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in fetching the user preference: %s", preferenceID) } if err == nil { - preferenceValue.PreferenceValue = userPreference.PreferenceValue + preferenceValue.PreferenceValue = user.PreferenceValue } return &preferencetypes.GettablePreference{ @@ -174,15 +174,15 @@ func (usecase *usecase) GetUserPreference(ctx context.Context, preferenceID stri }, nil } -func (usecase *usecase) UpdateUserPreference(ctx context.Context, preferenceID string, preferenceValue interface{}, userID string) error { - preference, seen := usecase.defaultMap[preferenceID] +func (module *module) UpdateUser(ctx context.Context, preferenceID string, preferenceValue interface{}, userID string) error { + preference, seen := module.defaultMap[preferenceID] if !seen { - return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("no such preferenceID exists: %s", preferenceID)) + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot find preference with id: %s", preferenceID) } - isPreferenceEnabledAtUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope) - if !isPreferenceEnabledAtUserScope { - return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("preference is not enabled at user scope: %s", preferenceID)) + isEnabledAtUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope) + if !isEnabledAtUserScope { + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "preference is not enabled at user scope: %s", preferenceID) } err := preference.IsValidValue(preferenceValue) @@ -190,26 +190,26 @@ func (usecase *usecase) UpdateUserPreference(ctx context.Context, preferenceID s return err } - storablePreferenceValue, encodeErr := json.Marshal(preferenceValue) + storableValue, encodeErr := json.Marshal(preferenceValue) if encodeErr != nil { return errors.Wrapf(encodeErr, errors.TypeInvalidInput, errors.CodeInvalidInput, "error in encoding the preference value") } - userPreference, dberr := usecase.store.GetUserPreference(ctx, userID, preferenceID) + user, dberr := module.store.GetUser(ctx, userID, preferenceID) if dberr != nil && dberr != sql.ErrNoRows { return errors.Wrapf(dberr, errors.TypeInternal, errors.CodeInternal, "error in getting the preference value") } if dberr != nil { - userPreference.ID = valuer.GenerateUUID() - userPreference.PreferenceID = preferenceID - userPreference.PreferenceValue = string(storablePreferenceValue) - userPreference.UserID = userID + user.ID = valuer.GenerateUUID() + user.PreferenceID = preferenceID + user.PreferenceValue = string(storableValue) + user.UserID = userID } else { - userPreference.PreferenceValue = string(storablePreferenceValue) + user.PreferenceValue = string(storableValue) } - dberr = usecase.store.UpsertUserPreference(ctx, userPreference) + dberr = module.store.UpsertUser(ctx, user) if dberr != nil { return errors.Wrapf(dberr, errors.TypeInternal, errors.CodeInternal, "error in setting the preference value") } @@ -217,30 +217,30 @@ func (usecase *usecase) UpdateUserPreference(ctx context.Context, preferenceID s return nil } -func (usecase *usecase) GetAllUserPreferences(ctx context.Context, orgID string, userID string) ([]*preferencetypes.PreferenceWithValue, error) { - allUserPreferences := []*preferencetypes.PreferenceWithValue{} +func (module *module) GetAllUser(ctx context.Context, orgID string, userID string) ([]*preferencetypes.PreferenceWithValue, error) { + allUsers := []*preferencetypes.PreferenceWithValue{} - orgPreferences, err := usecase.store.GetAllOrgPreferences(ctx, orgID) + orgs, err := module.store.GetAllOrg(ctx, orgID) if err != nil { return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in setting all org preference values") } preferenceOrgValueMap := map[string]interface{}{} - for _, preferenceValue := range orgPreferences { + for _, preferenceValue := range orgs { preferenceOrgValueMap[preferenceValue.PreferenceID] = preferenceValue.PreferenceValue } - userPreferences, err := usecase.store.GetAllUserPreferences(ctx, userID) + users, err := module.store.GetAllUser(ctx, userID) if err != nil { return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in setting all user preference values") } preferenceUserValueMap := map[string]interface{}{} - for _, preferenceValue := range userPreferences { + for _, preferenceValue := range users { preferenceUserValueMap[preferenceValue.PreferenceID] = preferenceValue.PreferenceValue } - for _, preference := range usecase.defaultMap { + for _, preference := range module.defaultMap { isEnabledForUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope) if isEnabledForUserScope { @@ -271,8 +271,8 @@ func (usecase *usecase) GetAllUserPreferences(ctx context.Context, orgID string, } preferenceWithValue.Value = preference.SanitizeValue(preferenceWithValue.Value) - allUserPreferences = append(allUserPreferences, preferenceWithValue) + allUsers = append(allUsers, preferenceWithValue) } } - return allUserPreferences, nil + return allUsers, nil } diff --git a/pkg/modules/preference/core/store.go b/pkg/modules/preference/implpreference/store.go similarity index 65% rename from pkg/modules/preference/core/store.go rename to pkg/modules/preference/implpreference/store.go index 329a308c4b..9ac8734a22 100644 --- a/pkg/modules/preference/core/store.go +++ b/pkg/modules/preference/implpreference/store.go @@ -1,4 +1,4 @@ -package core +package implpreference import ( "context" @@ -11,11 +11,11 @@ type store struct { store sqlstore.SQLStore } -func NewStore(db sqlstore.SQLStore) preferencetypes.PreferenceStore { +func NewStore(db sqlstore.SQLStore) preferencetypes.Store { return &store{store: db} } -func (store *store) GetOrgPreference(ctx context.Context, orgID string, preferenceID string) (*preferencetypes.StorableOrgPreference, error) { +func (store *store) GetOrg(ctx context.Context, orgID string, preferenceID string) (*preferencetypes.StorableOrgPreference, error) { orgPreference := new(preferencetypes.StorableOrgPreference) err := store. store. @@ -33,7 +33,7 @@ func (store *store) GetOrgPreference(ctx context.Context, orgID string, preferen return orgPreference, nil } -func (store *store) GetAllOrgPreferences(ctx context.Context, orgID string) ([]*preferencetypes.StorableOrgPreference, error) { +func (store *store) GetAllOrg(ctx context.Context, orgID string) ([]*preferencetypes.StorableOrgPreference, error) { orgPreferences := make([]*preferencetypes.StorableOrgPreference, 0) err := store. store. @@ -50,7 +50,7 @@ func (store *store) GetAllOrgPreferences(ctx context.Context, orgID string) ([]* return orgPreferences, nil } -func (store *store) UpsertOrgPreference(ctx context.Context, orgPreference *preferencetypes.StorableOrgPreference) error { +func (store *store) UpsertOrg(ctx context.Context, orgPreference *preferencetypes.StorableOrgPreference) error { _, err := store. store. BunDB(). @@ -65,7 +65,7 @@ func (store *store) UpsertOrgPreference(ctx context.Context, orgPreference *pref return nil } -func (store *store) GetUserPreference(ctx context.Context, userID string, preferenceID string) (*preferencetypes.StorableUserPreference, error) { +func (store *store) GetUser(ctx context.Context, userID string, preferenceID string) (*preferencetypes.StorableUserPreference, error) { userPreference := new(preferencetypes.StorableUserPreference) err := store. store. @@ -83,7 +83,7 @@ func (store *store) GetUserPreference(ctx context.Context, userID string, prefer return userPreference, nil } -func (store *store) GetAllUserPreferences(ctx context.Context, userID string) ([]*preferencetypes.StorableUserPreference, error) { +func (store *store) GetAllUser(ctx context.Context, userID string) ([]*preferencetypes.StorableUserPreference, error) { userPreferences := make([]*preferencetypes.StorableUserPreference, 0) err := store. store. @@ -100,7 +100,7 @@ func (store *store) GetAllUserPreferences(ctx context.Context, userID string) ([ return userPreferences, nil } -func (store *store) UpsertUserPreference(ctx context.Context, userPreference *preferencetypes.StorableUserPreference) error { +func (store *store) UpsertUser(ctx context.Context, userPreference *preferencetypes.StorableUserPreference) error { _, err := store. store. BunDB(). diff --git a/pkg/modules/preference/preference.go b/pkg/modules/preference/preference.go new file mode 100644 index 0000000000..e740634466 --- /dev/null +++ b/pkg/modules/preference/preference.go @@ -0,0 +1,48 @@ +package preference + +import ( + "context" + "net/http" + + "github.com/SigNoz/signoz/pkg/types/preferencetypes" +) + +type Module interface { + // Returns the preference for the given organization + GetOrg(ctx context.Context, preferenceId string, orgId string) (*preferencetypes.GettablePreference, error) + + // Returns the preference for the given user + GetUser(ctx context.Context, preferenceId string, orgId string, userId string) (*preferencetypes.GettablePreference, error) + + // Returns all preferences for the given organization + GetAllOrg(ctx context.Context, orgId string) ([]*preferencetypes.PreferenceWithValue, error) + + // Returns all preferences for the given user + GetAllUser(ctx context.Context, orgId string, userId string) ([]*preferencetypes.PreferenceWithValue, error) + + // Updates the preference for the given organization + UpdateOrg(ctx context.Context, preferenceId string, preferenceValue interface{}, orgId string) error + + // Updates the preference for the given user + UpdateUser(ctx context.Context, preferenceId string, preferenceValue interface{}, userId string) error +} + +type Handler interface { + // Returns the preference for the given organization + GetOrg(http.ResponseWriter, *http.Request) + + // Updates the preference for the given organization + UpdateOrg(http.ResponseWriter, *http.Request) + + // Returns all preferences for the given organization + GetAllOrg(http.ResponseWriter, *http.Request) + + // Returns the preference for the given user + GetUser(http.ResponseWriter, *http.Request) + + // Updates the preference for the given user + UpdateUser(http.ResponseWriter, *http.Request) + + // Returns all preferences for the given user + GetAllUser(http.ResponseWriter, *http.Request) +} diff --git a/pkg/modules/preference/usecase.go b/pkg/modules/preference/usecase.go deleted file mode 100644 index 1d1e2a223d..0000000000 --- a/pkg/modules/preference/usecase.go +++ /dev/null @@ -1,16 +0,0 @@ -package preference - -import ( - "context" - - "github.com/SigNoz/signoz/pkg/types/preferencetypes" -) - -type Usecase interface { - GetOrgPreference(ctx context.Context, preferenceId string, orgId string) (*preferencetypes.GettablePreference, error) - UpdateOrgPreference(ctx context.Context, preferenceId string, preferenceValue interface{}, orgId string) error - GetAllOrgPreferences(ctx context.Context, orgId string) ([]*preferencetypes.PreferenceWithValue, error) - GetUserPreference(ctx context.Context, preferenceId string, orgId string, userId string) (*preferencetypes.GettablePreference, error) - UpdateUserPreference(ctx context.Context, preferenceId string, preferenceValue interface{}, userId string) error - GetAllUserPreferences(ctx context.Context, orgId string, userId string) ([]*preferencetypes.PreferenceWithValue, error) -} diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go index 52d7ff0d87..4e23910b3b 100644 --- a/pkg/query-service/app/http_handler.go +++ b/pkg/query-service/app/http_handler.go @@ -23,8 +23,6 @@ import ( errorsV2 "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/organization" - "github.com/SigNoz/signoz/pkg/modules/preference" "github.com/SigNoz/signoz/pkg/query-service/app/integrations" "github.com/SigNoz/signoz/pkg/query-service/app/metricsexplorer" "github.com/SigNoz/signoz/pkg/signoz" @@ -147,11 +145,6 @@ type APIHandler struct { FieldsAPI *fields.API Signoz *signoz.SigNoz - - Preference preference.API - - OrganizationAPI organization.API - OrganizationModule organization.Module } type APIHandlerOpts struct { @@ -199,10 +192,6 @@ type APIHandlerOpts struct { FieldsAPI *fields.API Signoz *signoz.SigNoz - - Preference preference.API - OrganizationAPI organization.API - OrganizationModule organization.Module } // NewAPIHandler returns an APIHandler @@ -271,10 +260,7 @@ func NewAPIHandler(opts APIHandlerOpts) (*APIHandler, error) { SummaryService: summaryService, AlertmanagerAPI: opts.AlertmanagerAPI, Signoz: opts.Signoz, - Preference: opts.Preference, FieldsAPI: opts.FieldsAPI, - OrganizationAPI: opts.OrganizationAPI, - OrganizationModule: opts.OrganizationModule, } logsQueryBuilder := logsv3.PrepareLogsQuery @@ -596,23 +582,13 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) { router.HandleFunc("/api/v1/disks", am.ViewAccess(aH.getDisks)).Methods(http.MethodGet) - // === Preference APIs === + router.HandleFunc("/api/v1/user/preferences", am.ViewAccess(aH.Signoz.Handlers.Preference.GetAllUser)).Methods(http.MethodGet) + router.HandleFunc("/api/v1/user/preferences/{preferenceId}", am.ViewAccess(aH.Signoz.Handlers.Preference.GetUser)).Methods(http.MethodGet) + router.HandleFunc("/api/v1/user/preferences/{preferenceId}", am.ViewAccess(aH.Signoz.Handlers.Preference.UpdateUser)).Methods(http.MethodPut) + router.HandleFunc("/api/v1/org/preferences", am.AdminAccess(aH.Signoz.Handlers.Preference.GetAllOrg)).Methods(http.MethodGet) + router.HandleFunc("/api/v1/org/preferences/{preferenceId}", am.AdminAccess(aH.Signoz.Handlers.Preference.GetOrg)).Methods(http.MethodGet) + router.HandleFunc("/api/v1/org/preferences/{preferenceId}", am.AdminAccess(aH.Signoz.Handlers.Preference.UpdateOrg)).Methods(http.MethodPut) - // user actions - router.HandleFunc("/api/v1/user/preferences", am.ViewAccess(aH.getAllUserPreferences)).Methods(http.MethodGet) - - router.HandleFunc("/api/v1/user/preferences/{preferenceId}", am.ViewAccess(aH.getUserPreference)).Methods(http.MethodGet) - - router.HandleFunc("/api/v1/user/preferences/{preferenceId}", am.ViewAccess(aH.updateUserPreference)).Methods(http.MethodPut) - - // org actions - router.HandleFunc("/api/v1/org/preferences", am.AdminAccess(aH.getAllOrgPreferences)).Methods(http.MethodGet) - - router.HandleFunc("/api/v1/org/preferences/{preferenceId}", am.AdminAccess(aH.getOrgPreference)).Methods(http.MethodGet) - - router.HandleFunc("/api/v1/org/preferences/{preferenceId}", am.AdminAccess(aH.updateOrgPreference)).Methods(http.MethodPut) - - // === Authentication APIs === router.HandleFunc("/api/v1/invite", am.AdminAccess(aH.inviteUser)).Methods(http.MethodPost) router.HandleFunc("/api/v1/invite/bulk", am.AdminAccess(aH.inviteUsers)).Methods(http.MethodPost) router.HandleFunc("/api/v1/invite/{token}", am.OpenAccess(aH.getInvite)).Methods(http.MethodGet) @@ -633,9 +609,8 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) { router.HandleFunc("/api/v1/orgUsers/{id}", am.AdminAccess(aH.getOrgUsers)).Methods(http.MethodGet) - router.HandleFunc("/api/v2/orgs", am.AdminAccess(aH.getOrgs)).Methods(http.MethodGet) - router.HandleFunc("/api/v2/orgs/me", am.AdminAccess(aH.getOrg)).Methods(http.MethodGet) - router.HandleFunc("/api/v2/orgs/me", am.AdminAccess(aH.updateOrg)).Methods(http.MethodPut) + router.HandleFunc("/api/v2/orgs/me", am.AdminAccess(aH.Signoz.Handlers.Organization.Get)).Methods(http.MethodGet) + router.HandleFunc("/api/v2/orgs/me", am.AdminAccess(aH.Signoz.Handlers.Organization.Update)).Methods(http.MethodPut) router.HandleFunc("/api/v1/getResetPasswordToken/{id}", am.AdminAccess(aH.getResetPasswordToken)).Methods(http.MethodGet) router.HandleFunc("/api/v1/resetPassword", am.OpenAccess(aH.resetPassword)).Methods(http.MethodPost) @@ -2064,7 +2039,7 @@ func (aH *APIHandler) inviteUsers(w http.ResponseWriter, r *http.Request) { func (aH *APIHandler) getInvite(w http.ResponseWriter, r *http.Request) { token := mux.Vars(r)["token"] - resp, err := auth.GetInvite(context.Background(), token, aH.OrganizationModule) + resp, err := auth.GetInvite(context.Background(), token, aH.Signoz.Modules.Organization) if err != nil { RespondError(w, &model.ApiError{Err: err, Typ: model.ErrorNotFound}, nil) return @@ -2105,7 +2080,7 @@ func (aH *APIHandler) listPendingInvites(w http.ResponseWriter, r *http.Request) if err != nil { render.Error(w, errorsV2.Newf(errorsV2.TypeInvalidInput, errorsV2.CodeInvalidInput, "invalid org_id in the invite")) } - org, err := aH.OrganizationModule.Get(ctx, orgID) + org, err := aH.Signoz.Modules.Organization.Get(ctx, orgID) if err != nil { render.Error(w, errorsV2.Newf(errorsV2.TypeInternal, errorsV2.CodeInternal, err.Error())) } @@ -2132,7 +2107,7 @@ func (aH *APIHandler) registerUser(w http.ResponseWriter, r *http.Request) { return } - _, apiErr := auth.Register(context.Background(), req, aH.Signoz.Alertmanager, aH.OrganizationModule) + _, apiErr := auth.Register(context.Background(), req, aH.Signoz.Alertmanager, aH.Signoz.Modules.Organization) if apiErr != nil { RespondError(w, apiErr, nil) return @@ -2391,18 +2366,6 @@ func (aH *APIHandler) editRole(w http.ResponseWriter, r *http.Request) { aH.WriteJSON(w, r, map[string]string{"data": "user group updated successfully"}) } -func (aH *APIHandler) getOrgs(w http.ResponseWriter, r *http.Request) { - aH.OrganizationAPI.GetAll(w, r) -} - -func (aH *APIHandler) getOrg(w http.ResponseWriter, r *http.Request) { - aH.OrganizationAPI.Get(w, r) -} - -func (aH *APIHandler) updateOrg(w http.ResponseWriter, r *http.Request) { - aH.OrganizationAPI.Update(w, r) -} - func (aH *APIHandler) getOrgUsers(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] users, apiErr := dao.DB().GetUsersByOrg(context.Background(), id) @@ -3437,44 +3400,6 @@ func (aH *APIHandler) getProducerConsumerEval( aH.Respond(w, resp) } -// Preferences - -func (aH *APIHandler) getUserPreference( - w http.ResponseWriter, r *http.Request, -) { - aH.Preference.GetUserPreference(w, r) -} - -func (aH *APIHandler) updateUserPreference( - w http.ResponseWriter, r *http.Request, -) { - aH.Preference.UpdateUserPreference(w, r) -} - -func (aH *APIHandler) getAllUserPreferences( - w http.ResponseWriter, r *http.Request, -) { - aH.Preference.GetAllUserPreferences(w, r) -} - -func (aH *APIHandler) getOrgPreference( - w http.ResponseWriter, r *http.Request, -) { - aH.Preference.GetOrgPreference(w, r) -} - -func (aH *APIHandler) updateOrgPreference( - w http.ResponseWriter, r *http.Request, -) { - aH.Preference.UpdateOrgPreference(w, r) -} - -func (aH *APIHandler) getAllOrgPreferences( - w http.ResponseWriter, r *http.Request, -) { - aH.Preference.GetAllOrgPreferences(w, r) -} - // RegisterIntegrationRoutes Registers all Integrations func (aH *APIHandler) RegisterIntegrationRoutes(router *mux.Router, am *middleware.AuthZ) { subRouter := router.PathPrefix("/api/v1/integrations").Subrouter() @@ -4700,7 +4625,6 @@ func (aH *APIHandler) updateSavedView(w http.ResponseWriter, r *http.Request) { } func (aH *APIHandler) deleteSavedView(w http.ResponseWriter, r *http.Request) { - viewID := mux.Vars(r)["viewId"] viewUUID, err := valuer.NewUUID(viewID) if err != nil { diff --git a/pkg/query-service/app/server.go b/pkg/query-service/app/server.go index 2d0034f29e..ecff9d19a9 100644 --- a/pkg/query-service/app/server.go +++ b/pkg/query-service/app/server.go @@ -14,9 +14,6 @@ import ( "github.com/SigNoz/signoz/pkg/alertmanager" "github.com/SigNoz/signoz/pkg/apis/fields" "github.com/SigNoz/signoz/pkg/http/middleware" - "github.com/SigNoz/signoz/pkg/modules/organization/implorganization" - "github.com/SigNoz/signoz/pkg/modules/preference" - preferencecore "github.com/SigNoz/signoz/pkg/modules/preference/core" "github.com/SigNoz/signoz/pkg/prometheus" "github.com/SigNoz/signoz/pkg/query-service/agentConf" "github.com/SigNoz/signoz/pkg/query-service/app/clickhouseReader" @@ -30,7 +27,6 @@ import ( "github.com/SigNoz/signoz/pkg/sqlstore" "github.com/SigNoz/signoz/pkg/telemetrystore" "github.com/SigNoz/signoz/pkg/types/authtypes" - "github.com/SigNoz/signoz/pkg/types/preferencetypes" "github.com/SigNoz/signoz/pkg/web" "github.com/rs/cors" "github.com/soheilhy/cmux" @@ -183,9 +179,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) { } telemetry.GetInstance().SetReader(reader) - preferenceAPI := preference.NewAPI(preferencecore.NewPreference(preferencecore.NewStore(serverOptions.SigNoz.SQLStore), preferencetypes.NewDefaultPreferenceMap())) - organizationAPI := implorganization.NewAPI(implorganization.NewModule(implorganization.NewStore(serverOptions.SigNoz.SQLStore))) - organizationModule := implorganization.NewModule(implorganization.NewStore(serverOptions.SigNoz.SQLStore)) apiHandler, err := NewAPIHandler(APIHandlerOpts{ Reader: reader, SkipConfig: skipConfig, @@ -204,9 +197,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) { AlertmanagerAPI: alertmanager.NewAPI(serverOptions.SigNoz.Alertmanager), FieldsAPI: fields.NewAPI(serverOptions.SigNoz.TelemetryStore), Signoz: serverOptions.SigNoz, - Preference: preferenceAPI, - OrganizationAPI: organizationAPI, - OrganizationModule: organizationModule, }) if err != nil { return nil, err diff --git a/pkg/query-service/tests/integration/filter_suggestions_test.go b/pkg/query-service/tests/integration/filter_suggestions_test.go index afb2eb80e8..2f0b22db14 100644 --- a/pkg/query-service/tests/integration/filter_suggestions_test.go +++ b/pkg/query-service/tests/integration/filter_suggestions_test.go @@ -18,6 +18,7 @@ import ( "github.com/SigNoz/signoz/pkg/query-service/featureManager" v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3" "github.com/SigNoz/signoz/pkg/query-service/utils" + "github.com/SigNoz/signoz/pkg/signoz" "github.com/SigNoz/signoz/pkg/types" mockhouse "github.com/srikanthccv/ClickHouse-go-mock" "github.com/stretchr/testify/require" @@ -297,11 +298,17 @@ func NewFilterSuggestionsTestBed(t *testing.T) *FilterSuggestionsTestBed { reader, mockClickhouse := NewMockClickhouseReader(t, testDB) mockClickhouse.MatchExpectationsInOrder(false) + modules := signoz.NewModules(testDB) + apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{ Reader: reader, AppDao: dao.DB(), FeatureFlags: fm, JWT: jwt, + Signoz: &signoz.SigNoz{ + Modules: modules, + Handlers: signoz.NewHandlers(modules), + }, }) if err != nil { t.Fatalf("could not create a new ApiHandler: %v", err) diff --git a/pkg/query-service/tests/integration/signoz_cloud_integrations_test.go b/pkg/query-service/tests/integration/signoz_cloud_integrations_test.go index f8b4a4d4a5..a15c860e0d 100644 --- a/pkg/query-service/tests/integration/signoz_cloud_integrations_test.go +++ b/pkg/query-service/tests/integration/signoz_cloud_integrations_test.go @@ -10,6 +10,7 @@ import ( "github.com/SigNoz/signoz/pkg/http/middleware" "github.com/SigNoz/signoz/pkg/modules/organization/implorganization" + "github.com/SigNoz/signoz/pkg/signoz" "github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest" "github.com/SigNoz/signoz/pkg/query-service/app" @@ -360,12 +361,19 @@ func NewCloudIntegrationsTestBed(t *testing.T, testDB sqlstore.SQLStore) *CloudI reader, mockClickhouse := NewMockClickhouseReader(t, testDB) mockClickhouse.MatchExpectationsInOrder(false) + modules := signoz.NewModules(testDB) + handlers := signoz.NewHandlers(modules) + apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{ Reader: reader, AppDao: dao.DB(), CloudIntegrationsController: controller, FeatureFlags: fm, JWT: jwt, + Signoz: &signoz.SigNoz{ + Modules: modules, + Handlers: handlers, + }, }) if err != nil { t.Fatalf("could not create a new ApiHandler: %v", err) diff --git a/pkg/query-service/tests/integration/signoz_integrations_test.go b/pkg/query-service/tests/integration/signoz_integrations_test.go index f20764d28d..06e3184833 100644 --- a/pkg/query-service/tests/integration/signoz_integrations_test.go +++ b/pkg/query-service/tests/integration/signoz_integrations_test.go @@ -19,6 +19,7 @@ import ( "github.com/SigNoz/signoz/pkg/query-service/model" v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3" "github.com/SigNoz/signoz/pkg/query-service/utils" + "github.com/SigNoz/signoz/pkg/signoz" "github.com/SigNoz/signoz/pkg/sqlstore" "github.com/SigNoz/signoz/pkg/types" "github.com/SigNoz/signoz/pkg/types/pipelinetypes" @@ -566,6 +567,9 @@ func NewIntegrationsTestBed(t *testing.T, testDB sqlstore.SQLStore) *Integration t.Fatalf("could not create cloud integrations controller: %v", err) } + modules := signoz.NewModules(testDB) + handlers := signoz.NewHandlers(modules) + apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{ Reader: reader, AppDao: dao.DB(), @@ -573,6 +577,10 @@ func NewIntegrationsTestBed(t *testing.T, testDB sqlstore.SQLStore) *Integration FeatureFlags: fm, JWT: jwt, CloudIntegrationsController: cloudIntegrationsController, + Signoz: &signoz.SigNoz{ + Modules: modules, + Handlers: handlers, + }, }) if err != nil { t.Fatalf("could not create a new ApiHandler: %v", err) diff --git a/pkg/signoz/handler.go b/pkg/signoz/handler.go new file mode 100644 index 0000000000..84cf783980 --- /dev/null +++ b/pkg/signoz/handler.go @@ -0,0 +1,20 @@ +package signoz + +import ( + "github.com/SigNoz/signoz/pkg/modules/organization" + "github.com/SigNoz/signoz/pkg/modules/organization/implorganization" + "github.com/SigNoz/signoz/pkg/modules/preference" + "github.com/SigNoz/signoz/pkg/modules/preference/implpreference" +) + +type Handlers struct { + Organization organization.Handler + Preference preference.Handler +} + +func NewHandlers(modules Modules) Handlers { + return Handlers{ + Organization: implorganization.NewHandler(modules.Organization), + Preference: implpreference.NewHandler(modules.Preference), + } +} diff --git a/pkg/signoz/module.go b/pkg/signoz/module.go new file mode 100644 index 0000000000..68a3c96c01 --- /dev/null +++ b/pkg/signoz/module.go @@ -0,0 +1,22 @@ +package signoz + +import ( + "github.com/SigNoz/signoz/pkg/modules/organization" + "github.com/SigNoz/signoz/pkg/modules/organization/implorganization" + "github.com/SigNoz/signoz/pkg/modules/preference" + "github.com/SigNoz/signoz/pkg/modules/preference/implpreference" + "github.com/SigNoz/signoz/pkg/sqlstore" + "github.com/SigNoz/signoz/pkg/types/preferencetypes" +) + +type Modules struct { + Organization organization.Module + Preference preference.Module +} + +func NewModules(sqlstore sqlstore.SQLStore) Modules { + return Modules{ + Organization: implorganization.NewModule(implorganization.NewStore(sqlstore)), + Preference: implpreference.NewModule(implpreference.NewStore(sqlstore), preferencetypes.NewDefaultPreferenceMap()), + } +} diff --git a/pkg/signoz/signoz.go b/pkg/signoz/signoz.go index 0a1ab8b757..1bfb2640d0 100644 --- a/pkg/signoz/signoz.go +++ b/pkg/signoz/signoz.go @@ -26,6 +26,8 @@ type SigNoz struct { TelemetryStore telemetrystore.TelemetryStore Prometheus prometheus.Prometheus Alertmanager alertmanager.Alertmanager + Modules Modules + Handlers Handlers } func New( @@ -124,6 +126,7 @@ func New( return nil, err } + // Initialize alertmanager from the available alertmanager provider factories alertmanager, err := factory.NewProviderFromNamedMap( ctx, providerSettings, @@ -135,6 +138,12 @@ func New( return nil, err } + // Initialize all modules + modules := NewModules(sqlstore) + + // Initialize all handlers for the modules + handlers := NewHandlers(modules) + registry, err := factory.NewRegistry( instrumentation.Logger(), factory.NewNamedService(factory.MustNewName("instrumentation"), instrumentation), @@ -153,5 +162,7 @@ func New( TelemetryStore: telemetrystore, Prometheus: prometheus, Alertmanager: alertmanager, + Modules: modules, + Handlers: handlers, }, nil } diff --git a/pkg/sqlmigration/018_drop_licenses_sites.go b/pkg/sqlmigration/018_drop_licenses_sites.go index 9ff7225d14..bcc85364c9 100644 --- a/pkg/sqlmigration/018_drop_licenses_sites.go +++ b/pkg/sqlmigration/018_drop_licenses_sites.go @@ -38,14 +38,26 @@ func (migration *dropLicensesSites) Up(ctx context.Context, db *bun.DB) error { } defer tx.Rollback() - if _, err := tx.NewDropTable().IfExists().Table("sites").Exec(ctx); err != nil { - return err - } - if _, err := tx.NewDropTable().IfExists().Table("licenses").Exec(ctx); err != nil { + if _, err := tx. + NewDropTable(). + IfExists(). + Table("sites"). + Exec(ctx); err != nil { return err } - _, err = migration.store.Dialect().RenameColumn(ctx, tx, "saved_views", "uuid", "id") + if _, err := tx. + NewDropTable(). + IfExists(). + Table("licenses"). + Exec(ctx); err != nil { + return err + } + + _, err = migration. + store. + Dialect(). + RenameColumn(ctx, tx, "saved_views", "uuid", "id") if err != nil { return err } diff --git a/pkg/sqlmigration/019_update_invites.go b/pkg/sqlmigration/019_update_invites.go index cb7a78ddbc..6c6f1271ab 100644 --- a/pkg/sqlmigration/019_update_invites.go +++ b/pkg/sqlmigration/019_update_invites.go @@ -42,12 +42,9 @@ type newInvite struct { } func NewUpdateInvitesFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] { - return factory. - NewProviderFactory( - factory.MustNewName("update_invites"), - func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { - return newUpdateInvites(ctx, ps, c, sqlstore) - }) + return factory.NewProviderFactory(factory.MustNewName("update_invites"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { + return newUpdateInvites(ctx, ps, c, sqlstore) + }) } func newUpdateInvites(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { @@ -55,8 +52,7 @@ func newUpdateInvites(_ context.Context, _ factory.ProviderSettings, _ Config, s } func (migration *updateInvites) Register(migrations *migrate.Migrations) error { - if err := migrations. - Register(migration.Up, migration.Down); err != nil { + if err := migrations.Register(migration.Up, migration.Down); err != nil { return err } @@ -64,8 +60,7 @@ func (migration *updateInvites) Register(migrations *migrate.Migrations) error { } func (migration *updateInvites) Up(ctx context.Context, db *bun.DB) error { - tx, err := db. - BeginTx(ctx, nil) + tx, err := db.BeginTx(ctx, nil) if err != nil { return err } @@ -88,8 +83,7 @@ func (migration *updateInvites) Up(ctx context.Context, db *bun.DB) error { } if err == nil && len(existingInvites) > 0 { - newInvites := migration. - CopyOldInvitesToNewInvites(existingInvites) + newInvites := migration.CopyOldInvitesToNewInvites(existingInvites) _, err = tx. NewInsert(). Model(&newInvites). diff --git a/pkg/sqlmigration/020_pat_update.go b/pkg/sqlmigration/020_pat_update.go index b4aeca243e..935cb1b2f1 100644 --- a/pkg/sqlmigration/020_pat_update.go +++ b/pkg/sqlmigration/020_pat_update.go @@ -20,9 +20,7 @@ func NewUpdatePatFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQL } func newUpdatePat(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { - return &updatePat{ - store: store, - }, nil + return &updatePat{store: store}, nil } func (migration *updatePat) Register(migrations *migrate.Migrations) error { @@ -34,25 +32,33 @@ func (migration *updatePat) Register(migrations *migrate.Migrations) error { } func (migration *updatePat) Up(ctx context.Context, db *bun.DB) error { - - // begin transaction tx, err := db.BeginTx(ctx, nil) if err != nil { return err } + defer tx.Rollback() for _, column := range []string{"last_used", "expires_at"} { - if err := migration.store.Dialect().AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", column, "INTEGER", "0"); err != nil { + if err := migration. + store. + Dialect(). + AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", column, "INTEGER", "0"); err != nil { return err } } - if err := migration.store.Dialect().AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", "revoked", "BOOLEAN", "false"); err != nil { + if err := migration. + store. + Dialect(). + AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", "revoked", "BOOLEAN", "false"); err != nil { return err } - if err := migration.store.Dialect().AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", "updated_by_user_id", "TEXT", "''"); err != nil { + if err := migration. + store. + Dialect(). + AddNotNullDefaultToColumn(ctx, tx, "personal_access_tokens", "updated_by_user_id", "TEXT", "''"); err != nil { return err } diff --git a/pkg/sqlmigration/021_update_alertmanager.go b/pkg/sqlmigration/021_update_alertmanager.go index 49ce90ce0c..c1d04594a6 100644 --- a/pkg/sqlmigration/021_update_alertmanager.go +++ b/pkg/sqlmigration/021_update_alertmanager.go @@ -77,12 +77,9 @@ type newAlertmanagerState struct { } func NewUpdateAlertmanagerFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] { - return factory. - NewProviderFactory( - factory.MustNewName("update_alertmanager"), - func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { - return newUpdateAlertmanager(ctx, ps, c, sqlstore) - }) + return factory.NewProviderFactory(factory.MustNewName("update_alertmanager"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { + return newUpdateAlertmanager(ctx, ps, c, sqlstore) + }) } func newUpdateAlertmanager(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { @@ -90,8 +87,7 @@ func newUpdateAlertmanager(_ context.Context, _ factory.ProviderSettings, _ Conf } func (migration *updateAlertmanager) Register(migrations *migrate.Migrations) error { - if err := migrations. - Register(migration.Up, migration.Down); err != nil { + if err := migrations.Register(migration.Up, migration.Down); err != nil { return err } @@ -99,8 +95,7 @@ func (migration *updateAlertmanager) Register(migrations *migrate.Migrations) er } func (migration *updateAlertmanager) Up(ctx context.Context, db *bun.DB) error { - tx, err := db. - BeginTx(ctx, nil) + tx, err := db.BeginTx(ctx, nil) if err != nil { return err } diff --git a/pkg/sqlmigration/022_update_preferences.go b/pkg/sqlmigration/022_update_preferences.go index 93ead90744..ad3a8a0c31 100644 --- a/pkg/sqlmigration/022_update_preferences.go +++ b/pkg/sqlmigration/022_update_preferences.go @@ -49,12 +49,9 @@ type newUserPreference struct { } func NewUpdatePreferencesFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] { - return factory. - NewProviderFactory( - factory.MustNewName("update_preferences"), - func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { - return newUpdatePreferences(ctx, ps, c, sqlstore) - }) + return factory.NewProviderFactory(factory.MustNewName("update_preferences"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { + return newUpdatePreferences(ctx, ps, c, sqlstore) + }) } func newUpdatePreferences(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { @@ -62,8 +59,7 @@ func newUpdatePreferences(_ context.Context, _ factory.ProviderSettings, _ Confi } func (migration *updatePreferences) Register(migrations *migrate.Migrations) error { - if err := migrations. - Register(migration.Up, migration.Down); err != nil { + if err := migrations.Register(migration.Up, migration.Down); err != nil { return err } @@ -71,8 +67,7 @@ func (migration *updatePreferences) Register(migrations *migrate.Migrations) err } func (migration *updatePreferences) Up(ctx context.Context, db *bun.DB) error { - tx, err := db. - BeginTx(ctx, nil) + tx, err := db.BeginTx(ctx, nil) if err != nil { return err } @@ -135,8 +130,7 @@ func (migration *updatePreferences) Up(ctx context.Context, db *bun.DB) error { } if err == nil && len(existingUserPreferences) > 0 { - newUserPreferences := migration. - CopyOldUserPreferencesToNewUserPreferences(existingUserPreferences) + newUserPreferences := migration.CopyOldUserPreferencesToNewUserPreferences(existingUserPreferences) _, err = tx. NewInsert(). Model(&newUserPreferences). diff --git a/pkg/sqlmigration/023_update_apdex_ttl.go b/pkg/sqlmigration/023_update_apdex_ttl.go index 7f78e4d569..7164842ceb 100644 --- a/pkg/sqlmigration/023_update_apdex_ttl.go +++ b/pkg/sqlmigration/023_update_apdex_ttl.go @@ -61,12 +61,9 @@ type newTTLStatus struct { } func NewUpdateApdexTtlFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] { - return factory. - NewProviderFactory( - factory.MustNewName("update_apdex_ttl"), - func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { - return newUpdateApdexTtl(ctx, ps, c, sqlstore) - }) + return factory.NewProviderFactory(factory.MustNewName("update_apdex_ttl"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { + return newUpdateApdexTtl(ctx, ps, c, sqlstore) + }) } func newUpdateApdexTtl(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { @@ -74,8 +71,7 @@ func newUpdateApdexTtl(_ context.Context, _ factory.ProviderSettings, _ Config, } func (migration *updateApdexTtl) Register(migrations *migrate.Migrations) error { - if err := migrations. - Register(migration.Up, migration.Down); err != nil { + if err := migrations.Register(migration.Up, migration.Down); err != nil { return err } @@ -83,8 +79,7 @@ func (migration *updateApdexTtl) Register(migrations *migrate.Migrations) error } func (migration *updateApdexTtl) Up(ctx context.Context, db *bun.DB) error { - tx, err := db. - BeginTx(ctx, nil) + tx, err := db.BeginTx(ctx, nil) if err != nil { return err } @@ -161,8 +156,7 @@ func (migration *updateApdexTtl) Up(ctx context.Context, db *bun.DB) error { } if err == nil { - newTTLStatus := migration. - CopyExistingTTLStatusToNewTTLStatus(existingTTLStatus, orgID) + newTTLStatus := migration.CopyExistingTTLStatusToNewTTLStatus(existingTTLStatus, orgID) _, err = tx. NewInsert(). Model(&newTTLStatus). diff --git a/pkg/sqlmigration/024_update_reset_password.go b/pkg/sqlmigration/024_update_reset_password.go index 613c787986..c2c0e7ca04 100644 --- a/pkg/sqlmigration/024_update_reset_password.go +++ b/pkg/sqlmigration/024_update_reset_password.go @@ -61,12 +61,9 @@ type newPersonalAccessToken struct { } func NewUpdateResetPasswordFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] { - return factory. - NewProviderFactory( - factory.MustNewName("update_reset_password"), - func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { - return newUpdateResetPassword(ctx, ps, c, sqlstore) - }) + return factory.NewProviderFactory(factory.MustNewName("update_reset_password"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { + return newUpdateResetPassword(ctx, ps, c, sqlstore) + }) } func newUpdateResetPassword(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { @@ -74,8 +71,7 @@ func newUpdateResetPassword(_ context.Context, _ factory.ProviderSettings, _ Con } func (migration *updateResetPassword) Register(migrations *migrate.Migrations) error { - if err := migrations. - Register(migration.Up, migration.Down); err != nil { + if err := migrations.Register(migration.Up, migration.Down); err != nil { return err } @@ -83,8 +79,7 @@ func (migration *updateResetPassword) Register(migrations *migrate.Migrations) e } func (migration *updateResetPassword) Up(ctx context.Context, db *bun.DB) error { - tx, err := db. - BeginTx(ctx, nil) + tx, err := db.BeginTx(ctx, nil) if err != nil { return err } @@ -104,8 +99,7 @@ func (migration *updateResetPassword) Up(ctx context.Context, db *bun.DB) error } if err == nil && len(existingResetPasswordRequests) > 0 { - newResetPasswordRequests := migration. - CopyExistingResetPasswordRequestsToNewResetPasswordRequests(existingResetPasswordRequests) + newResetPasswordRequests := migration.CopyExistingResetPasswordRequestsToNewResetPasswordRequests(existingResetPasswordRequests) _, err = tx. NewInsert(). Model(&newResetPasswordRequests). @@ -134,8 +128,7 @@ func (migration *updateResetPassword) Up(ctx context.Context, db *bun.DB) error } if err == nil && len(existingPersonalAccessTokens) > 0 { - newPersonalAccessTokens := migration. - CopyExistingPATsToNewPATs(existingPersonalAccessTokens) + newPersonalAccessTokens := migration.CopyExistingPATsToNewPATs(existingPersonalAccessTokens) _, err = tx.NewInsert().Model(&newPersonalAccessTokens).Exec(ctx) if err != nil { return err diff --git a/pkg/sqlmigration/026_update_integrations.go b/pkg/sqlmigration/026_update_integrations.go index ceb7be5ede..05772dafad 100644 --- a/pkg/sqlmigration/026_update_integrations.go +++ b/pkg/sqlmigration/026_update_integrations.go @@ -26,9 +26,7 @@ func NewUpdateIntegrationsFactory(sqlstore sqlstore.SQLStore) factory.ProviderFa } func newUpdateIntegrations(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { - return &updateIntegrations{ - store: store, - }, nil + return &updateIntegrations{store: store}, nil } func (migration *updateIntegrations) Register(migrations *migrate.Migrations) error { @@ -136,9 +134,7 @@ func (migration *updateIntegrations) Up(ctx context.Context, db *bun.DB) error { return nil } - // --- // installed integrations - // --- err = migration. store. Dialect(). @@ -171,9 +167,7 @@ func (migration *updateIntegrations) Up(ctx context.Context, db *bun.DB) error { return err } - // --- // cloud integrations - // --- err = migration. store. Dialect(). @@ -213,9 +207,7 @@ func (migration *updateIntegrations) Up(ctx context.Context, db *bun.DB) error { return err } - // --- // cloud integration service - // --- err = migration. store. Dialect(). diff --git a/pkg/sqlmigration/027_update_rules.go b/pkg/sqlmigration/027_update_rules.go index eb4bc15a37..0d1e962dd3 100644 --- a/pkg/sqlmigration/027_update_rules.go +++ b/pkg/sqlmigration/027_update_rules.go @@ -93,12 +93,9 @@ type ruleHistory struct { } func NewUpdateRulesFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] { - return factory. - NewProviderFactory( - factory.MustNewName("update_rules"), - func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { - return newUpdateRules(ctx, ps, c, sqlstore) - }) + return factory.NewProviderFactory(factory.MustNewName("update_rules"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { + return newUpdateRules(ctx, ps, c, sqlstore) + }) } func newUpdateRules(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { @@ -106,8 +103,7 @@ func newUpdateRules(_ context.Context, _ factory.ProviderSettings, _ Config, sto } func (migration *updateRules) Register(migrations *migrate.Migrations) error { - if err := migrations. - Register(migration.Up, migration.Down); err != nil { + if err := migrations.Register(migration.Up, migration.Down); err != nil { return err } @@ -115,8 +111,7 @@ func (migration *updateRules) Register(migrations *migrate.Migrations) error { } func (migration *updateRules) Up(ctx context.Context, db *bun.DB) error { - tx, err := db. - BeginTx(ctx, nil) + tx, err := db.BeginTx(ctx, nil) if err != nil { return err } diff --git a/pkg/sqlmigration/028_update_organizations.go b/pkg/sqlmigration/028_update_organizations.go index ef67ccc8e4..cf7ca6a5e2 100644 --- a/pkg/sqlmigration/028_update_organizations.go +++ b/pkg/sqlmigration/028_update_organizations.go @@ -14,11 +14,9 @@ type updateOrganizations struct { } func NewUpdateOrganizationsFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] { - return factory.NewProviderFactory( - factory.MustNewName("update_organizations"), - func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { - return newUpdateOrganizations(ctx, ps, c, sqlstore) - }) + return factory.NewProviderFactory(factory.MustNewName("update_organizations"), func(ctx context.Context, ps factory.ProviderSettings, c Config) (SQLMigration, error) { + return newUpdateOrganizations(ctx, ps, c, sqlstore) + }) } func newUpdateOrganizations(_ context.Context, _ factory.ProviderSettings, _ Config, store sqlstore.SQLStore) (SQLMigration, error) { @@ -26,8 +24,7 @@ func newUpdateOrganizations(_ context.Context, _ factory.ProviderSettings, _ Con } func (migration *updateOrganizations) Register(migrations *migrate.Migrations) error { - if err := migrations. - Register(migration.Up, migration.Down); err != nil { + if err := migrations.Register(migration.Up, migration.Down); err != nil { return err } @@ -35,8 +32,7 @@ func (migration *updateOrganizations) Register(migrations *migrate.Migrations) e } func (migration *updateOrganizations) Up(ctx context.Context, db *bun.DB) error { - tx, err := db. - BeginTx(ctx, nil) + tx, err := db.BeginTx(ctx, nil) if err != nil { return err } diff --git a/pkg/sqlstore/sqlitesqlstore/provider.go b/pkg/sqlstore/sqlitesqlstore/provider.go index 53cdd33fce..f393df221d 100644 --- a/pkg/sqlstore/sqlitesqlstore/provider.go +++ b/pkg/sqlstore/sqlitesqlstore/provider.go @@ -4,10 +4,11 @@ import ( "context" "database/sql" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/factory" "github.com/SigNoz/signoz/pkg/sqlstore" "github.com/jmoiron/sqlx" - _ "github.com/mattn/go-sqlite3" + sqlite3 "github.com/mattn/go-sqlite3" "github.com/uptrace/bun" "github.com/uptrace/bun/dialect/sqlitedialect" ) @@ -77,3 +78,21 @@ func (provider *provider) BunDBCtx(ctx context.Context) bun.IDB { func (provider *provider) RunInTxCtx(ctx context.Context, opts *sql.TxOptions, cb func(ctx context.Context) error) error { return provider.bundb.RunInTxCtx(ctx, opts, cb) } + +func (provider *provider) WrapNotFoundErrf(err error, code errors.Code, format string, args ...any) error { + if err == sql.ErrNoRows { + return errors.Wrapf(err, errors.TypeNotFound, code, format, args...) + } + + return err +} + +func (provider *provider) WrapAlreadyExistsErrf(err error, code errors.Code, format string, args ...any) error { + if sqlite3Err, ok := err.(sqlite3.Error); ok { + if sqlite3Err.ExtendedCode == sqlite3.ErrConstraintUnique { + return errors.Wrapf(err, errors.TypeAlreadyExists, code, format, args...) + } + } + + return err +} diff --git a/pkg/sqlstore/sqlstore.go b/pkg/sqlstore/sqlstore.go index d3b6cb3b30..072a06c3f4 100644 --- a/pkg/sqlstore/sqlstore.go +++ b/pkg/sqlstore/sqlstore.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" + "github.com/SigNoz/signoz/pkg/errors" "github.com/jmoiron/sqlx" "github.com/uptrace/bun" ) @@ -30,6 +31,12 @@ type SQLStore interface { // BunDBCtx returns an instance of bun.IDB for the given context. // If a transaction is present in the context, it will be used. Otherwise, the default will be used. BunDBCtx(ctx context.Context) bun.IDB + + // WrapNotFoundErrf wraps the given error with the given message and returns it. + WrapNotFoundErrf(err error, code errors.Code, format string, args ...any) error + + // WrapAlreadyExistsErrf wraps the given error with the given message and returns it. + WrapAlreadyExistsErrf(err error, code errors.Code, format string, args ...any) error } type SQLStoreHook interface { diff --git a/pkg/sqlstore/sqlstoretest/provider.go b/pkg/sqlstore/sqlstoretest/provider.go index 55567b4df6..837d0a92c3 100644 --- a/pkg/sqlstore/sqlstoretest/provider.go +++ b/pkg/sqlstore/sqlstoretest/provider.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/DATA-DOG/go-sqlmock" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/sqlstore" "github.com/jmoiron/sqlx" "github.com/uptrace/bun" @@ -74,3 +75,11 @@ func (provider *Provider) BunDBCtx(ctx context.Context) bun.IDB { func (provider *Provider) RunInTxCtx(ctx context.Context, opts *sql.TxOptions, cb func(ctx context.Context) error) error { return cb(ctx) } + +func (provider *Provider) WrapNotFoundErrf(err error, code errors.Code, format string, args ...any) error { + return fmt.Errorf(format, args...) +} + +func (provider *Provider) WrapAlreadyExistsErrf(err error, code errors.Code, format string, args ...any) error { + return fmt.Errorf(format, args...) +} diff --git a/pkg/types/organization.go b/pkg/types/organization.go index c403c161cc..d18e149890 100644 --- a/pkg/types/organization.go +++ b/pkg/types/organization.go @@ -4,10 +4,16 @@ import ( "context" "time" + "github.com/SigNoz/signoz/pkg/errors" "github.com/SigNoz/signoz/pkg/valuer" "github.com/uptrace/bun" ) +var ( + ErrOrganizationAlreadyExists = errors.MustNewCode("organization_already_exists") + ErrOrganizationNotFound = errors.MustNewCode("organization_not_found") +) + type Organization struct { bun.BaseModel `bun:"table:organizations"` TimeAuditable diff --git a/pkg/types/preferencetypes/preference.go b/pkg/types/preferencetypes/preference.go index 1ce7410d5d..9e38064a6d 100644 --- a/pkg/types/preferencetypes/preference.go +++ b/pkg/types/preferencetypes/preference.go @@ -2,7 +2,6 @@ package preferencetypes import ( "context" - "fmt" "strings" "github.com/SigNoz/signoz/pkg/errors" @@ -133,7 +132,7 @@ func NewDefaultPreferenceMap() map[string]Preference { } func (p *Preference) ErrorValueTypeMismatch() error { - return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("the preference value is not of expected type: %s", p.ValueType)) + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "the preference value is not of expected type: %s", p.ValueType) } func (p *Preference) checkIfInAllowedValues(preferenceValue interface{}) (bool, error) { @@ -219,7 +218,7 @@ func (p *Preference) IsValidValue(preferenceValue interface{}) error { } if !p.IsDiscreteValues { if val < p.Range.Min || val > p.Range.Max { - return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("the preference value is not in the range specified, min: %v , max:%v", p.Range.Min, p.Range.Max)) + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "the preference value is not in the range specified, min: %v , max: %v", p.Range.Min, p.Range.Max) } } case PreferenceValueTypeString: @@ -248,7 +247,7 @@ func (p *Preference) IsValidValue(preferenceValue interface{}) error { return valueMisMatchErr } if !isInAllowedValues { - return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, fmt.Sprintf("the preference value is not in the list of allowedValues: %v", p.AllowedValues)) + return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "the preference value is not in the list of allowedValues: %v", p.AllowedValues) } } } @@ -280,11 +279,11 @@ func (p *Preference) SanitizeValue(preferenceValue interface{}) interface{} { } } -type PreferenceStore interface { - GetOrgPreference(context.Context, string, string) (*StorableOrgPreference, error) - GetAllOrgPreferences(context.Context, string) ([]*StorableOrgPreference, error) - UpsertOrgPreference(context.Context, *StorableOrgPreference) error - GetUserPreference(context.Context, string, string) (*StorableUserPreference, error) - GetAllUserPreferences(context.Context, string) ([]*StorableUserPreference, error) - UpsertUserPreference(context.Context, *StorableUserPreference) error +type Store interface { + GetOrg(context.Context, string, string) (*StorableOrgPreference, error) + GetAllOrg(context.Context, string) ([]*StorableOrgPreference, error) + UpsertOrg(context.Context, *StorableOrgPreference) error + GetUser(context.Context, string, string) (*StorableUserPreference, error) + GetAllUser(context.Context, string) ([]*StorableUserPreference, error) + UpsertUser(context.Context, *StorableUserPreference) error }