mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-15 17:55:56 +08:00
refactor(preference): better readability
This commit is contained in:
parent
6ed30318bd
commit
a7d0ae21ac
@ -11,6 +11,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/preference"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/preferencetypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
@ -22,7 +23,7 @@ func NewHandler(module preference.Module) preference.Handler {
|
||||
return &handler{module: module}
|
||||
}
|
||||
|
||||
func (handler *handler) GetOrg(rw http.ResponseWriter, r *http.Request) {
|
||||
func (handler *handler) ListByOrg(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -32,65 +33,7 @@ func (handler *handler) GetOrg(rw http.ResponseWriter, r *http.Request) {
|
||||
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)
|
||||
preferences, err := handler.module.ListByOrg(ctx, valuer.MustNewUUID(claims.OrgID))
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -99,7 +42,7 @@ func (handler *handler) GetAllOrg(rw http.ResponseWriter, r *http.Request) {
|
||||
render.Success(rw, http.StatusOK, preferences)
|
||||
}
|
||||
|
||||
func (handler *handler) GetUser(rw http.ResponseWriter, r *http.Request) {
|
||||
func (handler *handler) GetByOrg(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -109,13 +52,19 @@ func (handler *handler) GetUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
id, ok := mux.Vars(r)["preferenceId"]
|
||||
nameString, 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)
|
||||
name, err := preferencetypes.NewName(nameString)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
preference, err := handler.module.GetByOrg(ctx, valuer.MustNewUUID(claims.OrgID), name)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -124,7 +73,7 @@ func (handler *handler) GetUser(rw http.ResponseWriter, r *http.Request) {
|
||||
render.Success(rw, http.StatusOK, preference)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateUser(rw http.ResponseWriter, r *http.Request) {
|
||||
func (handler *handler) UpdateByOrg(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -134,12 +83,18 @@ func (handler *handler) UpdateUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
id, ok := mux.Vars(r)["preferenceId"]
|
||||
nameString, ok := mux.Vars(r)["preferenceId"]
|
||||
if !ok {
|
||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is required"))
|
||||
return
|
||||
}
|
||||
|
||||
name, err := preferencetypes.NewName(nameString)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(preferencetypes.UpdatablePreference)
|
||||
err = json.NewDecoder(r.Body).Decode(req)
|
||||
if err != nil {
|
||||
@ -147,7 +102,7 @@ func (handler *handler) UpdateUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.module.UpdateUser(ctx, id, req.PreferenceValue, claims.UserID)
|
||||
err = handler.module.UpdateByOrg(ctx, valuer.MustNewUUID(claims.OrgID), name, req.Value)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -156,7 +111,7 @@ func (handler *handler) UpdateUser(rw http.ResponseWriter, r *http.Request) {
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (handler *handler) GetAllUser(rw http.ResponseWriter, r *http.Request) {
|
||||
func (handler *handler) ListByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@ -166,7 +121,7 @@ func (handler *handler) GetAllUser(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
preferences, err := handler.module.GetAllUser(ctx, claims.OrgID, claims.UserID)
|
||||
preferences, err := handler.module.ListByUser(ctx, valuer.MustNewUUID(claims.UserID))
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -174,3 +129,72 @@ func (handler *handler) GetAllUser(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
render.Success(rw, http.StatusOK, preferences)
|
||||
}
|
||||
|
||||
func (handler *handler) GetByUser(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
|
||||
}
|
||||
|
||||
nameString, ok := mux.Vars(r)["preferenceId"]
|
||||
if !ok {
|
||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is required"))
|
||||
return
|
||||
}
|
||||
|
||||
name, err := preferencetypes.NewName(nameString)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
preference, err := handler.module.GetByUser(ctx, valuer.MustNewUUID(claims.UserID), name)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, preference)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateByUser(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
|
||||
}
|
||||
|
||||
nameString, ok := mux.Vars(r)["preferenceId"]
|
||||
if !ok {
|
||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "id is required"))
|
||||
return
|
||||
}
|
||||
|
||||
name, err := preferencetypes.NewName(nameString)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := new(preferencetypes.UpdatablePreference)
|
||||
err = json.NewDecoder(r.Body).Decode(req)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = handler.module.UpdateByUser(ctx, valuer.MustNewUUID(claims.UserID), name, req.Value)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusNoContent, nil)
|
||||
}
|
||||
|
@ -2,8 +2,6 @@ package implpreference
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/modules/preference"
|
||||
@ -14,265 +12,155 @@ import (
|
||||
// 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
|
||||
available map[preferencetypes.Name]preferencetypes.Preference
|
||||
}
|
||||
|
||||
func NewModule(store preferencetypes.Store, defaultMap map[string]preferencetypes.Preference) preference.Module {
|
||||
return &module{store: store, defaultMap: defaultMap}
|
||||
func NewModule(store preferencetypes.Store, available map[preferencetypes.Name]preferencetypes.Preference) preference.Module {
|
||||
return &module{store: store, available: available}
|
||||
}
|
||||
|
||||
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, "cannot find preference with id: %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)
|
||||
}
|
||||
|
||||
org, err := module.store.GetOrg(ctx, orgID, preferenceID)
|
||||
func (module *module) ListByOrg(ctx context.Context, orgID valuer.UUID) ([]*preferencetypes.GettablePreference, error) {
|
||||
storableOrgPreferences, err := module.store.ListByOrg(ctx, orgID)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return &preferencetypes.GettablePreference{
|
||||
PreferenceID: preferenceID,
|
||||
PreferenceValue: preference.DefaultValue,
|
||||
}, nil
|
||||
}
|
||||
return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in fetching the org preference: %s", preferenceID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &preferencetypes.GettablePreference{
|
||||
PreferenceID: preferenceID,
|
||||
PreferenceValue: preference.SanitizeValue(org.PreferenceValue),
|
||||
}, nil
|
||||
var gettablePreferences []*preferencetypes.GettablePreference
|
||||
for _, preference := range module.available {
|
||||
copyOfPreference, err := preferencetypes.NewPreferenceFromAvailable(preference.Name, module.available)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, storableOrgPreference := range storableOrgPreferences {
|
||||
if storableOrgPreference.Name == preference.Name {
|
||||
gettablePreferences = append(gettablePreferences, preferencetypes.NewGettablePreference(copyOfPreference, storableOrgPreference.Value))
|
||||
continue
|
||||
}
|
||||
|
||||
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, "cannot find preference with id: %s", preferenceID)
|
||||
gettablePreferences = append(gettablePreferences, preferencetypes.NewGettablePreference(copyOfPreference, preference.DefaultValue))
|
||||
}
|
||||
}
|
||||
|
||||
isEnabled := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope)
|
||||
if !isEnabled {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "preference is not enabled at org scope: %s", preferenceID)
|
||||
return gettablePreferences, nil
|
||||
}
|
||||
|
||||
err := preference.IsValidValue(preferenceValue)
|
||||
func (module *module) GetByOrg(ctx context.Context, orgID valuer.UUID, name preferencetypes.Name) (*preferencetypes.GettablePreference, error) {
|
||||
preference, err := preferencetypes.NewPreference(name, preferencetypes.ScopeOrg, module.available)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
org, err := module.store.GetByOrg(ctx, orgID, name)
|
||||
if err != nil {
|
||||
if errors.As(err, errors.TypeNotFound) {
|
||||
return preferencetypes.NewGettablePreference(preference, preference.DefaultValue), nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return preferencetypes.NewGettablePreference(preference, org.Value), nil
|
||||
}
|
||||
|
||||
func (module *module) UpdateByOrg(ctx context.Context, orgID valuer.UUID, name preferencetypes.Name, preferenceValue string) error {
|
||||
preference, err := preferencetypes.NewPreference(name, preferencetypes.ScopeOrg, module.available)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storableValue, encodeErr := json.Marshal(preferenceValue)
|
||||
if encodeErr != nil {
|
||||
return errors.Wrapf(encodeErr, errors.TypeInvalidInput, errors.CodeInvalidInput, "error in encoding the preference value")
|
||||
_, err = preferencetypes.NewPreferenceValueFromString(preference, preferenceValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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")
|
||||
storableOrgPreference, err := module.store.GetByOrg(ctx, orgID, name)
|
||||
if err != nil {
|
||||
if !errors.As(err, errors.TypeNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if dberr != nil {
|
||||
org.ID = valuer.GenerateUUID()
|
||||
org.PreferenceID = preferenceID
|
||||
org.PreferenceValue = string(storableValue)
|
||||
org.OrgID = orgID
|
||||
} else {
|
||||
org.PreferenceValue = string(storableValue)
|
||||
if storableOrgPreference == nil {
|
||||
storableOrgPreference = preferencetypes.NewStorableOrgPreference(preference, preferenceValue, orgID)
|
||||
}
|
||||
|
||||
dberr = module.store.UpsertOrg(ctx, org)
|
||||
if dberr != nil {
|
||||
return errors.Wrapf(dberr, errors.TypeInternal, errors.CodeInternal, "error in setting the preference value")
|
||||
err = module.store.UpsertByOrg(ctx, storableOrgPreference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) GetAllOrg(ctx context.Context, orgID string) ([]*preferencetypes.PreferenceWithValue, error) {
|
||||
allOrgs := []*preferencetypes.PreferenceWithValue{}
|
||||
orgs, err := module.store.GetAllOrg(ctx, orgID)
|
||||
func (module *module) ListByUser(ctx context.Context, userID valuer.UUID) ([]*preferencetypes.GettablePreference, error) {
|
||||
storableUserPreferences, err := module.store.ListByUser(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in setting all org preference values")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
preferenceValueMap := map[string]interface{}{}
|
||||
for _, preferenceValue := range orgs {
|
||||
preferenceValueMap[preferenceValue.PreferenceID] = preferenceValue.PreferenceValue
|
||||
var gettablePreferences []*preferencetypes.GettablePreference
|
||||
for _, preference := range module.available {
|
||||
copyOfPreference, err := preferencetypes.NewPreferenceFromAvailable(preference.Name, module.available)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, storableUserPreference := range storableUserPreferences {
|
||||
if storableUserPreference.Name == preference.Name {
|
||||
gettablePreferences = append(gettablePreferences, preferencetypes.NewGettablePreference(copyOfPreference, storableUserPreference.Value))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, preference := range module.defaultMap {
|
||||
isEnabledForOrgScope := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope)
|
||||
if isEnabledForOrgScope {
|
||||
preferenceWithValue := &preferencetypes.PreferenceWithValue{}
|
||||
preferenceWithValue.Key = preference.Key
|
||||
preferenceWithValue.Name = preference.Name
|
||||
preferenceWithValue.Description = preference.Description
|
||||
preferenceWithValue.AllowedScopes = preference.AllowedScopes
|
||||
preferenceWithValue.AllowedValues = preference.AllowedValues
|
||||
preferenceWithValue.DefaultValue = preference.DefaultValue
|
||||
preferenceWithValue.Range = preference.Range
|
||||
preferenceWithValue.ValueType = preference.ValueType
|
||||
preferenceWithValue.IsDiscreteValues = preference.IsDiscreteValues
|
||||
value, seen := preferenceValueMap[preference.Key]
|
||||
|
||||
if seen {
|
||||
preferenceWithValue.Value = value
|
||||
} else {
|
||||
preferenceWithValue.Value = preference.DefaultValue
|
||||
}
|
||||
|
||||
preferenceWithValue.Value = preference.SanitizeValue(preferenceWithValue.Value)
|
||||
allOrgs = append(allOrgs, preferenceWithValue)
|
||||
}
|
||||
}
|
||||
return allOrgs, nil
|
||||
}
|
||||
|
||||
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, "cannot find preference with id: %s", preferenceID)
|
||||
}
|
||||
|
||||
preferenceValue := preferencetypes.GettablePreference{
|
||||
PreferenceID: preferenceID,
|
||||
PreferenceValue: preference.DefaultValue,
|
||||
}
|
||||
|
||||
isEnabledAtUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope)
|
||||
if !isEnabledAtUserScope {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "preference is not enabled at user scope: %s", 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, "error in fetching the org preference: %s", preferenceID)
|
||||
}
|
||||
if err == nil {
|
||||
preferenceValue.PreferenceValue = org.PreferenceValue
|
||||
gettablePreferences = append(gettablePreferences, preferencetypes.NewGettablePreference(copyOfPreference, preference.DefaultValue))
|
||||
}
|
||||
}
|
||||
|
||||
user, err := module.store.GetUser(ctx, userID, preferenceID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error in fetching the user preference: %s", preferenceID)
|
||||
return gettablePreferences, nil
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
preferenceValue.PreferenceValue = user.PreferenceValue
|
||||
func (module *module) GetByUser(ctx context.Context, userID valuer.UUID, name preferencetypes.Name) (*preferencetypes.GettablePreference, error) {
|
||||
preference, err := preferencetypes.NewPreference(name, preferencetypes.ScopeUser, module.available)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &preferencetypes.GettablePreference{
|
||||
PreferenceID: preferenceValue.PreferenceID,
|
||||
PreferenceValue: preference.SanitizeValue(preferenceValue.PreferenceValue),
|
||||
}, nil
|
||||
storableUserPreference, err := module.store.GetByUser(ctx, userID, name)
|
||||
if err != nil {
|
||||
if errors.As(err, errors.TypeNotFound) {
|
||||
return preferencetypes.NewGettablePreference(preference, preference.DefaultValue), nil
|
||||
}
|
||||
|
||||
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, "cannot find preference with id: %s", preferenceID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isEnabledAtUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope)
|
||||
if !isEnabledAtUserScope {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "preference is not enabled at user scope: %s", preferenceID)
|
||||
return preferencetypes.NewGettablePreference(preference, storableUserPreference.Value), nil
|
||||
}
|
||||
|
||||
err := preference.IsValidValue(preferenceValue)
|
||||
func (module *module) UpdateByUser(ctx context.Context, userID valuer.UUID, name preferencetypes.Name, preferenceValue string) error {
|
||||
preference, err := preferencetypes.NewPreference(name, preferencetypes.ScopeUser, module.available)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storableValue, encodeErr := json.Marshal(preferenceValue)
|
||||
if encodeErr != nil {
|
||||
return errors.Wrapf(encodeErr, errors.TypeInvalidInput, errors.CodeInvalidInput, "error in encoding the preference value")
|
||||
_, err = preferencetypes.NewPreferenceValueFromString(preference, preferenceValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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")
|
||||
storableUserPreference, err := module.store.GetByUser(ctx, userID, name)
|
||||
if err != nil {
|
||||
if !errors.As(err, errors.TypeNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if dberr != nil {
|
||||
user.ID = valuer.GenerateUUID()
|
||||
user.PreferenceID = preferenceID
|
||||
user.PreferenceValue = string(storableValue)
|
||||
user.UserID = userID
|
||||
} else {
|
||||
user.PreferenceValue = string(storableValue)
|
||||
if storableUserPreference == nil {
|
||||
storableUserPreference = preferencetypes.NewStorableUserPreference(preference, preferenceValue, userID)
|
||||
}
|
||||
|
||||
dberr = module.store.UpsertUser(ctx, user)
|
||||
if dberr != nil {
|
||||
return errors.Wrapf(dberr, errors.TypeInternal, errors.CodeInternal, "error in setting the preference value")
|
||||
err = module.store.UpsertByUser(ctx, storableUserPreference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (module *module) GetAllUser(ctx context.Context, orgID string, userID string) ([]*preferencetypes.PreferenceWithValue, error) {
|
||||
allUsers := []*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")
|
||||
}
|
||||
|
||||
preferenceOrgValueMap := map[string]interface{}{}
|
||||
for _, preferenceValue := range orgs {
|
||||
preferenceOrgValueMap[preferenceValue.PreferenceID] = preferenceValue.PreferenceValue
|
||||
}
|
||||
|
||||
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 users {
|
||||
preferenceUserValueMap[preferenceValue.PreferenceID] = preferenceValue.PreferenceValue
|
||||
}
|
||||
|
||||
for _, preference := range module.defaultMap {
|
||||
isEnabledForUserScope := preference.IsEnabledForScope(preferencetypes.UserAllowedScope)
|
||||
|
||||
if isEnabledForUserScope {
|
||||
preferenceWithValue := &preferencetypes.PreferenceWithValue{}
|
||||
preferenceWithValue.Key = preference.Key
|
||||
preferenceWithValue.Name = preference.Name
|
||||
preferenceWithValue.Description = preference.Description
|
||||
preferenceWithValue.AllowedScopes = preference.AllowedScopes
|
||||
preferenceWithValue.AllowedValues = preference.AllowedValues
|
||||
preferenceWithValue.DefaultValue = preference.DefaultValue
|
||||
preferenceWithValue.Range = preference.Range
|
||||
preferenceWithValue.ValueType = preference.ValueType
|
||||
preferenceWithValue.IsDiscreteValues = preference.IsDiscreteValues
|
||||
preferenceWithValue.Value = preference.DefaultValue
|
||||
|
||||
isEnabledForOrgScope := preference.IsEnabledForScope(preferencetypes.OrgAllowedScope)
|
||||
if isEnabledForOrgScope {
|
||||
value, seen := preferenceOrgValueMap[preference.Key]
|
||||
if seen {
|
||||
preferenceWithValue.Value = value
|
||||
}
|
||||
}
|
||||
|
||||
value, seen := preferenceUserValueMap[preference.Key]
|
||||
|
||||
if seen {
|
||||
preferenceWithValue.Value = value
|
||||
}
|
||||
|
||||
preferenceWithValue.Value = preference.SanitizeValue(preferenceWithValue.Value)
|
||||
allUsers = append(allUsers, preferenceWithValue)
|
||||
}
|
||||
}
|
||||
return allUsers, nil
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/preferencetypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
@ -15,14 +16,14 @@ func NewStore(db sqlstore.SQLStore) preferencetypes.Store {
|
||||
return &store{store: db}
|
||||
}
|
||||
|
||||
func (store *store) GetOrg(ctx context.Context, orgID string, preferenceID string) (*preferencetypes.StorableOrgPreference, error) {
|
||||
func (store *store) GetByOrg(ctx context.Context, orgID valuer.UUID, name preferencetypes.Name) (*preferencetypes.StorableOrgPreference, error) {
|
||||
orgPreference := new(preferencetypes.StorableOrgPreference)
|
||||
err := store.
|
||||
store.
|
||||
BunDB().
|
||||
NewSelect().
|
||||
Model(orgPreference).
|
||||
Where("preference_id = ?", preferenceID).
|
||||
Where("preference_id = ?", name).
|
||||
Where("org_id = ?", orgID).
|
||||
Scan(ctx)
|
||||
|
||||
@ -33,7 +34,7 @@ func (store *store) GetOrg(ctx context.Context, orgID string, preferenceID strin
|
||||
return orgPreference, nil
|
||||
}
|
||||
|
||||
func (store *store) GetAllOrg(ctx context.Context, orgID string) ([]*preferencetypes.StorableOrgPreference, error) {
|
||||
func (store *store) ListByOrg(ctx context.Context, orgID valuer.UUID) ([]*preferencetypes.StorableOrgPreference, error) {
|
||||
orgPreferences := make([]*preferencetypes.StorableOrgPreference, 0)
|
||||
err := store.
|
||||
store.
|
||||
@ -50,7 +51,7 @@ func (store *store) GetAllOrg(ctx context.Context, orgID string) ([]*preferencet
|
||||
return orgPreferences, nil
|
||||
}
|
||||
|
||||
func (store *store) UpsertOrg(ctx context.Context, orgPreference *preferencetypes.StorableOrgPreference) error {
|
||||
func (store *store) UpsertByOrg(ctx context.Context, orgPreference *preferencetypes.StorableOrgPreference) error {
|
||||
_, err := store.
|
||||
store.
|
||||
BunDB().
|
||||
@ -65,17 +66,16 @@ func (store *store) UpsertOrg(ctx context.Context, orgPreference *preferencetype
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *store) GetUser(ctx context.Context, userID string, preferenceID string) (*preferencetypes.StorableUserPreference, error) {
|
||||
func (store *store) GetByUser(ctx context.Context, userID valuer.UUID, name preferencetypes.Name) (*preferencetypes.StorableUserPreference, error) {
|
||||
userPreference := new(preferencetypes.StorableUserPreference)
|
||||
|
||||
err := store.
|
||||
store.
|
||||
BunDB().
|
||||
NewSelect().
|
||||
Model(userPreference).
|
||||
Where("preference_id = ?", preferenceID).
|
||||
Where("user_id = ?", userID).
|
||||
Scan(ctx)
|
||||
|
||||
if err != nil {
|
||||
return userPreference, err
|
||||
}
|
||||
@ -83,7 +83,7 @@ func (store *store) GetUser(ctx context.Context, userID string, preferenceID str
|
||||
return userPreference, nil
|
||||
}
|
||||
|
||||
func (store *store) GetAllUser(ctx context.Context, userID string) ([]*preferencetypes.StorableUserPreference, error) {
|
||||
func (store *store) ListByUser(ctx context.Context, userID valuer.UUID) ([]*preferencetypes.StorableUserPreference, error) {
|
||||
userPreferences := make([]*preferencetypes.StorableUserPreference, 0)
|
||||
err := store.
|
||||
store.
|
||||
@ -100,7 +100,7 @@ func (store *store) GetAllUser(ctx context.Context, userID string) ([]*preferenc
|
||||
return userPreferences, nil
|
||||
}
|
||||
|
||||
func (store *store) UpsertUser(ctx context.Context, userPreference *preferencetypes.StorableUserPreference) error {
|
||||
func (store *store) UpsertByUser(ctx context.Context, userPreference *preferencetypes.StorableUserPreference) error {
|
||||
_, err := store.
|
||||
store.
|
||||
BunDB().
|
||||
|
@ -5,44 +5,45 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types/preferencetypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
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)
|
||||
ListByOrg(context.Context, valuer.UUID) ([]*preferencetypes.GettablePreference, error)
|
||||
|
||||
// Returns all preferences for the given user
|
||||
GetAllUser(ctx context.Context, orgId string, userId string) ([]*preferencetypes.PreferenceWithValue, error)
|
||||
// Returns the preference for the given organization by name.
|
||||
GetByOrg(context.Context, valuer.UUID, preferencetypes.Name) (*preferencetypes.GettablePreference, error)
|
||||
|
||||
// Updates the preference for the given organization
|
||||
UpdateOrg(ctx context.Context, preferenceId string, preferenceValue interface{}, orgId string) error
|
||||
UpdateByOrg(context.Context, valuer.UUID, preferencetypes.Name, string) error
|
||||
|
||||
// Returns all preferences for the given user
|
||||
ListByUser(context.Context, valuer.UUID) ([]*preferencetypes.GettablePreference, error)
|
||||
|
||||
// Returns the preference for the given user by name.
|
||||
GetByUser(context.Context, valuer.UUID, preferencetypes.Name) (*preferencetypes.GettablePreference, error)
|
||||
|
||||
// Updates the preference for the given user
|
||||
UpdateUser(ctx context.Context, preferenceId string, preferenceValue interface{}, userId string) error
|
||||
UpdateByUser(context.Context, valuer.UUID, preferencetypes.Name, string) error
|
||||
}
|
||||
|
||||
type Handler interface {
|
||||
// Returns the preference for the given organization
|
||||
GetOrg(http.ResponseWriter, *http.Request)
|
||||
GetByOrg(http.ResponseWriter, *http.Request)
|
||||
|
||||
// Updates the preference for the given organization
|
||||
UpdateOrg(http.ResponseWriter, *http.Request)
|
||||
UpdateByOrg(http.ResponseWriter, *http.Request)
|
||||
|
||||
// Returns all preferences for the given organization
|
||||
GetAllOrg(http.ResponseWriter, *http.Request)
|
||||
ListByOrg(http.ResponseWriter, *http.Request)
|
||||
|
||||
// Returns the preference for the given user
|
||||
GetUser(http.ResponseWriter, *http.Request)
|
||||
GetByUser(http.ResponseWriter, *http.Request)
|
||||
|
||||
// Updates the preference for the given user
|
||||
UpdateUser(http.ResponseWriter, *http.Request)
|
||||
UpdateByUser(http.ResponseWriter, *http.Request)
|
||||
|
||||
// Returns all preferences for the given user
|
||||
GetAllUser(http.ResponseWriter, *http.Request)
|
||||
ListByUser(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
@ -561,12 +561,12 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
||||
|
||||
router.HandleFunc("/api/v1/disks", am.ViewAccess(aH.getDisks)).Methods(http.MethodGet)
|
||||
|
||||
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)
|
||||
router.HandleFunc("/api/v1/user/preferences", am.ViewAccess(aH.Signoz.Handlers.Preference.ListByUser)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/user/preferences/{preferenceId}", am.ViewAccess(aH.Signoz.Handlers.Preference.GetByUser)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/user/preferences/{preferenceId}", am.ViewAccess(aH.Signoz.Handlers.Preference.UpdateByUser)).Methods(http.MethodPut)
|
||||
router.HandleFunc("/api/v1/org/preferences", am.AdminAccess(aH.Signoz.Handlers.Preference.ListByOrg)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/org/preferences/{preferenceId}", am.AdminAccess(aH.Signoz.Handlers.Preference.GetByOrg)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/org/preferences/{preferenceId}", am.AdminAccess(aH.Signoz.Handlers.Preference.UpdateByOrg)).Methods(http.MethodPut)
|
||||
|
||||
// Quick Filters
|
||||
router.HandleFunc("/api/v1/orgs/me/filters", am.ViewAccess(aH.Signoz.Handlers.QuickFilter.GetQuickFilters)).Methods(http.MethodGet)
|
||||
|
@ -51,7 +51,7 @@ func NewModules(
|
||||
return Modules{
|
||||
OrgGetter: orgGetter,
|
||||
OrgSetter: orgSetter,
|
||||
Preference: implpreference.NewModule(implpreference.NewStore(sqlstore), preferencetypes.NewDefaultPreferenceMap()),
|
||||
Preference: implpreference.NewModule(implpreference.NewStore(sqlstore), preferencetypes.NewAvailablePreference()),
|
||||
SavedView: implsavedview.NewModule(sqlstore),
|
||||
Apdex: implapdex.NewModule(sqlstore),
|
||||
Dashboard: impldashboard.NewModule(sqlstore, providerSettings),
|
||||
|
44
pkg/types/preferencetypes/name.go
Normal file
44
pkg/types/preferencetypes/name.go
Normal file
@ -0,0 +1,44 @@
|
||||
package preferencetypes
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
var (
|
||||
NameOrgOnboarding = Name{valuer.NewString("org_onboarding")}
|
||||
NameWelcomeChecklistDoLater = Name{valuer.NewString("welcome_checklist_do_later")}
|
||||
NameWelcomeChecklistSendLogsSkipped = Name{valuer.NewString("welcome_checklist_send_logs_skipped")}
|
||||
NameWelcomeChecklistSendTracesSkipped = Name{valuer.NewString("welcome_checklist_send_traces_skipped")}
|
||||
NameWelcomeChecklistSendInfraMetricsSkipped = Name{valuer.NewString("welcome_checklist_send_infra_metrics_skipped")}
|
||||
NameWelcomeChecklistSetupDashboardsSkipped = Name{valuer.NewString("welcome_checklist_setup_dashboards_skipped")}
|
||||
NameWelcomeChecklistSetupAlertsSkipped = Name{valuer.NewString("welcome_checklist_setup_alerts_skipped")}
|
||||
NameWelcomeChecklistSetupSavedViewSkipped = Name{valuer.NewString("welcome_checklist_setup_saved_view_skipped")}
|
||||
NameSidenavPinned = Name{valuer.NewString("sidenav_pinned")}
|
||||
)
|
||||
|
||||
type Name struct{ valuer.String }
|
||||
|
||||
func NewName(name string) (Name, error) {
|
||||
ok := slices.Contains(
|
||||
[]string{
|
||||
NameOrgOnboarding.StringValue(),
|
||||
NameWelcomeChecklistDoLater.StringValue(),
|
||||
NameWelcomeChecklistSendLogsSkipped.StringValue(),
|
||||
NameWelcomeChecklistSendTracesSkipped.StringValue(),
|
||||
NameWelcomeChecklistSendInfraMetricsSkipped.StringValue(),
|
||||
NameWelcomeChecklistSetupDashboardsSkipped.StringValue(),
|
||||
NameWelcomeChecklistSetupAlertsSkipped.StringValue(),
|
||||
NameWelcomeChecklistSetupSavedViewSkipped.StringValue(),
|
||||
NameSidenavPinned.StringValue(),
|
||||
},
|
||||
name,
|
||||
)
|
||||
if !ok {
|
||||
return Name{}, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "invalid name: %s", name)
|
||||
}
|
||||
|
||||
return Name{valuer.NewString(name)}, nil
|
||||
}
|
@ -2,298 +2,204 @@ package preferencetypes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"slices"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type GettablePreference struct {
|
||||
PreferenceID string `json:"preference_id" db:"preference_id"`
|
||||
PreferenceValue interface{} `json:"preference_value" db:"preference_value"`
|
||||
}
|
||||
|
||||
type UpdatablePreference struct {
|
||||
PreferenceValue interface{} `json:"preference_value" db:"preference_value"`
|
||||
type Preference struct {
|
||||
Name Name `json:"name"`
|
||||
Description string `json:"description"`
|
||||
ValueType ValueType `json:"valueType"`
|
||||
DefaultValue any `json:"defaultValue"`
|
||||
AllowedValues []any `json:"allowedValues"`
|
||||
IsDiscreteValues bool `json:"isDiscreteValues"`
|
||||
Range Range `json:"range"`
|
||||
AllowedScopes []Scope `json:"allowedScopes"`
|
||||
}
|
||||
|
||||
type StorableOrgPreference struct {
|
||||
bun.BaseModel `bun:"table:org_preference"`
|
||||
types.Identifiable
|
||||
PreferenceID string `bun:"preference_id,type:text,notnull"`
|
||||
PreferenceValue string `bun:"preference_value,type:text,notnull"`
|
||||
OrgID string `bun:"org_id,type:text,notnull"`
|
||||
Name Name `bun:"preference_id,type:text,notnull"`
|
||||
Value string `bun:"preference_value,type:text,notnull"`
|
||||
OrgID valuer.UUID `bun:"org_id,type:text,notnull"`
|
||||
}
|
||||
|
||||
type StorableUserPreference struct {
|
||||
bun.BaseModel `bun:"table:user_preference"`
|
||||
types.Identifiable
|
||||
PreferenceID string `bun:"preference_id,type:text,notnull"`
|
||||
PreferenceValue string `bun:"preference_value,type:text,notnull"`
|
||||
UserID string `bun:"user_id,type:text,notnull"`
|
||||
Name Name `bun:"preference_id,type:text,notnull"`
|
||||
Value string `bun:"preference_value,type:text,notnull"`
|
||||
UserID valuer.UUID `bun:"user_id,type:text,notnull"`
|
||||
}
|
||||
|
||||
type Preference struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
ValueType string `json:"valueType"`
|
||||
DefaultValue interface{} `json:"defaultValue"`
|
||||
AllowedValues []interface{} `json:"allowedValues"`
|
||||
IsDiscreteValues bool `json:"isDiscreteValues"`
|
||||
Range Range `json:"range"`
|
||||
AllowedScopes []string `json:"allowedScopes"`
|
||||
type GettablePreference struct {
|
||||
*Preference
|
||||
Value any `json:"preference_value"`
|
||||
}
|
||||
|
||||
func NewDefaultPreferenceMap() map[string]Preference {
|
||||
return map[string]Preference{
|
||||
"ORG_ONBOARDING": {
|
||||
Key: "ORG_ONBOARDING",
|
||||
Name: "Organisation Onboarding",
|
||||
type UpdatablePreference struct {
|
||||
Value string `json:"preference_value"`
|
||||
}
|
||||
|
||||
func NewAvailablePreference() map[Name]Preference {
|
||||
return map[Name]Preference{
|
||||
NameOrgOnboarding: {
|
||||
Name: NameOrgOnboarding,
|
||||
Description: "Organisation Onboarding",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"org"},
|
||||
AllowedScopes: []Scope{ScopeOrg},
|
||||
},
|
||||
"WELCOME_CHECKLIST_DO_LATER": {
|
||||
Key: "WELCOME_CHECKLIST_DO_LATER",
|
||||
Name: "Welcome Checklist Do Later",
|
||||
NameWelcomeChecklistDoLater: {
|
||||
Name: NameWelcomeChecklistDoLater,
|
||||
Description: "Welcome Checklist Do Later",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
"WELCOME_CHECKLIST_SEND_LOGS_SKIPPED": {
|
||||
Key: "WELCOME_CHECKLIST_SEND_LOGS_SKIPPED",
|
||||
Name: "Welcome Checklist Send Logs Skipped",
|
||||
NameWelcomeChecklistSendLogsSkipped: {
|
||||
Name: NameWelcomeChecklistSendLogsSkipped,
|
||||
Description: "Welcome Checklist Send Logs Skipped",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
"WELCOME_CHECKLIST_SEND_TRACES_SKIPPED": {
|
||||
Key: "WELCOME_CHECKLIST_SEND_TRACES_SKIPPED",
|
||||
Name: "Welcome Checklist Send Traces Skipped",
|
||||
NameWelcomeChecklistSendTracesSkipped: {
|
||||
Name: NameWelcomeChecklistSendTracesSkipped,
|
||||
Description: "Welcome Checklist Send Traces Skipped",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
"WELCOME_CHECKLIST_SEND_INFRA_METRICS_SKIPPED": {
|
||||
Key: "WELCOME_CHECKLIST_SEND_INFRA_METRICS_SKIPPED",
|
||||
Name: "Welcome Checklist Send Infra Metrics Skipped",
|
||||
NameWelcomeChecklistSendInfraMetricsSkipped: {
|
||||
Name: NameWelcomeChecklistSendInfraMetricsSkipped,
|
||||
Description: "Welcome Checklist Send Infra Metrics Skipped",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
"WELCOME_CHECKLIST_SETUP_DASHBOARDS_SKIPPED": {
|
||||
Key: "WELCOME_CHECKLIST_SETUP_DASHBOARDS_SKIPPED",
|
||||
Name: "Welcome Checklist Setup Dashboards Skipped",
|
||||
NameWelcomeChecklistSetupDashboardsSkipped: {
|
||||
Name: NameWelcomeChecklistSetupDashboardsSkipped,
|
||||
Description: "Welcome Checklist Setup Dashboards Skipped",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
"WELCOME_CHECKLIST_SETUP_ALERTS_SKIPPED": {
|
||||
Key: "WELCOME_CHECKLIST_SETUP_ALERTS_SKIPPED",
|
||||
Name: "Welcome Checklist Setup Alerts Skipped",
|
||||
NameWelcomeChecklistSetupAlertsSkipped: {
|
||||
Name: NameWelcomeChecklistSetupAlertsSkipped,
|
||||
Description: "Welcome Checklist Setup Alerts Skipped",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
"WELCOME_CHECKLIST_SETUP_SAVED_VIEW_SKIPPED": {
|
||||
Key: "WELCOME_CHECKLIST_SETUP_SAVED_VIEW_SKIPPED",
|
||||
Name: "Welcome Checklist Setup Saved View Skipped",
|
||||
NameWelcomeChecklistSetupSavedViewSkipped: {
|
||||
Name: NameWelcomeChecklistSetupSavedViewSkipped,
|
||||
Description: "Welcome Checklist Setup Saved View Skipped",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
"SIDENAV_PINNED": {
|
||||
Key: "SIDENAV_PINNED",
|
||||
Name: "Keep the primary sidenav always open",
|
||||
NameSidenavPinned: {
|
||||
Name: NameSidenavPinned,
|
||||
Description: "Controls whether the primary sidenav remains expanded or can be collapsed. When enabled, the sidenav will stay open and pinned to provide constant visibility of navigation options.",
|
||||
ValueType: "boolean",
|
||||
ValueType: ValueTypeBoolean,
|
||||
DefaultValue: false,
|
||||
AllowedValues: []interface{}{true, false},
|
||||
AllowedValues: []any{true, false},
|
||||
IsDiscreteValues: true,
|
||||
AllowedScopes: []string{"user"},
|
||||
AllowedScopes: []Scope{ScopeUser},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Preference) ErrorValueTypeMismatch() error {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "the preference value is not of expected type: %s", p.ValueType)
|
||||
func NewPreference(name Name, scope Scope, available map[Name]Preference) (*Preference, error) {
|
||||
preference, ok := available[name]
|
||||
if !ok {
|
||||
return nil, errors.Newf(errors.TypeNotFound, errors.CodeNotFound, "the preference does not exist: %s", name)
|
||||
}
|
||||
|
||||
func (p *Preference) checkIfInAllowedValues(preferenceValue interface{}) (bool, error) {
|
||||
|
||||
switch p.ValueType {
|
||||
case PreferenceValueTypeInteger:
|
||||
_, ok := preferenceValue.(int64)
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
}
|
||||
case PreferenceValueTypeFloat:
|
||||
_, ok := preferenceValue.(float64)
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
}
|
||||
case PreferenceValueTypeString:
|
||||
_, ok := preferenceValue.(string)
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
}
|
||||
case PreferenceValueTypeBoolean:
|
||||
_, ok := preferenceValue.(bool)
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
}
|
||||
}
|
||||
isInAllowedValues := false
|
||||
for _, value := range p.AllowedValues {
|
||||
switch p.ValueType {
|
||||
case PreferenceValueTypeInteger:
|
||||
allowedValue, ok := value.(int64)
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
if !slices.Contains(preference.AllowedScopes, scope) {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "the preference is not allowed for the given scope: %s", scope)
|
||||
}
|
||||
|
||||
if allowedValue == preferenceValue {
|
||||
isInAllowedValues = true
|
||||
}
|
||||
case PreferenceValueTypeFloat:
|
||||
allowedValue, ok := value.(float64)
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
return &Preference{
|
||||
Name: name,
|
||||
Description: preference.Description,
|
||||
ValueType: preference.ValueType,
|
||||
DefaultValue: preference.DefaultValue,
|
||||
AllowedValues: preference.AllowedValues,
|
||||
IsDiscreteValues: preference.IsDiscreteValues,
|
||||
Range: preference.Range,
|
||||
AllowedScopes: preference.AllowedScopes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if allowedValue == preferenceValue {
|
||||
isInAllowedValues = true
|
||||
}
|
||||
case PreferenceValueTypeString:
|
||||
allowedValue, ok := value.(string)
|
||||
func NewPreferenceFromAvailable(name Name, available map[Name]Preference) (*Preference, error) {
|
||||
preference, ok := available[name]
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
return nil, errors.Newf(errors.TypeNotFound, errors.CodeNotFound, "the preference does not exist: %s", name)
|
||||
}
|
||||
|
||||
if allowedValue == preferenceValue {
|
||||
isInAllowedValues = true
|
||||
}
|
||||
case PreferenceValueTypeBoolean:
|
||||
allowedValue, ok := value.(bool)
|
||||
if !ok {
|
||||
return false, p.ErrorValueTypeMismatch()
|
||||
return &Preference{
|
||||
Name: name,
|
||||
Description: preference.Description,
|
||||
ValueType: preference.ValueType,
|
||||
DefaultValue: preference.DefaultValue,
|
||||
AllowedValues: preference.AllowedValues,
|
||||
IsDiscreteValues: preference.IsDiscreteValues,
|
||||
Range: preference.Range,
|
||||
AllowedScopes: preference.AllowedScopes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if allowedValue == preferenceValue {
|
||||
isInAllowedValues = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return isInAllowedValues, nil
|
||||
}
|
||||
|
||||
func (p *Preference) IsValidValue(preferenceValue interface{}) error {
|
||||
typeSafeValue := preferenceValue
|
||||
switch p.ValueType {
|
||||
case PreferenceValueTypeInteger:
|
||||
val, ok := preferenceValue.(int64)
|
||||
if !ok {
|
||||
floatVal, ok := preferenceValue.(float64)
|
||||
if !ok || floatVal != float64(int64(floatVal)) {
|
||||
return p.ErrorValueTypeMismatch()
|
||||
}
|
||||
val = int64(floatVal)
|
||||
typeSafeValue = val
|
||||
}
|
||||
if !p.IsDiscreteValues {
|
||||
if val < p.Range.Min || val > 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:
|
||||
_, ok := preferenceValue.(string)
|
||||
if !ok {
|
||||
return p.ErrorValueTypeMismatch()
|
||||
}
|
||||
case PreferenceValueTypeFloat:
|
||||
_, ok := preferenceValue.(float64)
|
||||
if !ok {
|
||||
return p.ErrorValueTypeMismatch()
|
||||
}
|
||||
case PreferenceValueTypeBoolean:
|
||||
_, ok := preferenceValue.(bool)
|
||||
if !ok {
|
||||
return p.ErrorValueTypeMismatch()
|
||||
func NewGettablePreference(preference *Preference, value any) *GettablePreference {
|
||||
return &GettablePreference{
|
||||
Preference: preference,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// check the validity of the value being part of allowed values or the range specified if any
|
||||
if p.IsDiscreteValues {
|
||||
if p.AllowedValues != nil {
|
||||
isInAllowedValues, valueMisMatchErr := p.checkIfInAllowedValues(typeSafeValue)
|
||||
|
||||
if valueMisMatchErr != nil {
|
||||
return valueMisMatchErr
|
||||
func NewStorableOrgPreference(preference *Preference, value string, orgID valuer.UUID) *StorableOrgPreference {
|
||||
return &StorableOrgPreference{
|
||||
Name: preference.Name,
|
||||
Value: value,
|
||||
OrgID: orgID,
|
||||
}
|
||||
if !isInAllowedValues {
|
||||
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "the preference value is not in the list of allowedValues: %v", p.AllowedValues)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Preference) IsEnabledForScope(scope string) bool {
|
||||
isPreferenceEnabledForGivenScope := false
|
||||
if p.AllowedScopes != nil {
|
||||
for _, allowedScope := range p.AllowedScopes {
|
||||
if allowedScope == strings.ToLower(scope) {
|
||||
isPreferenceEnabledForGivenScope = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return isPreferenceEnabledForGivenScope
|
||||
}
|
||||
|
||||
func (p *Preference) SanitizeValue(preferenceValue interface{}) interface{} {
|
||||
switch p.ValueType {
|
||||
case PreferenceValueTypeBoolean:
|
||||
if preferenceValue == "1" || preferenceValue == true || preferenceValue == "true" {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return preferenceValue
|
||||
func NewStorableUserPreference(preference *Preference, value string, userID valuer.UUID) *StorableUserPreference {
|
||||
return &StorableUserPreference{
|
||||
Name: preference.Name,
|
||||
Value: value,
|
||||
UserID: userID,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
GetByOrg(context.Context, valuer.UUID, Name) (*StorableOrgPreference, error)
|
||||
ListByOrg(context.Context, valuer.UUID) ([]*StorableOrgPreference, error)
|
||||
UpsertByOrg(context.Context, *StorableOrgPreference) error
|
||||
GetByUser(context.Context, valuer.UUID, Name) (*StorableUserPreference, error)
|
||||
ListByUser(context.Context, valuer.UUID) ([]*StorableUserPreference, error)
|
||||
UpsertByUser(context.Context, *StorableUserPreference) error
|
||||
}
|
||||
|
10
pkg/types/preferencetypes/scope.go
Normal file
10
pkg/types/preferencetypes/scope.go
Normal file
@ -0,0 +1,10 @@
|
||||
package preferencetypes
|
||||
|
||||
import "github.com/SigNoz/signoz/pkg/valuer"
|
||||
|
||||
var (
|
||||
ScopeOrg = Scope{valuer.NewString("org")}
|
||||
ScopeUser = Scope{valuer.NewString("user")}
|
||||
)
|
||||
|
||||
type Scope struct{ valuer.String }
|
@ -1,23 +1,97 @@
|
||||
package preferencetypes
|
||||
|
||||
const (
|
||||
PreferenceValueTypeInteger string = "integer"
|
||||
PreferenceValueTypeFloat string = "float"
|
||||
PreferenceValueTypeString string = "string"
|
||||
PreferenceValueTypeBoolean string = "boolean"
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
const (
|
||||
OrgAllowedScope string = "org"
|
||||
UserAllowedScope string = "user"
|
||||
var (
|
||||
ValueTypeInteger = ValueType{valuer.NewString("integer")}
|
||||
ValueTypeFloat = ValueType{valuer.NewString("float")}
|
||||
ValueTypeString = ValueType{valuer.NewString("string")}
|
||||
ValueTypeBoolean = ValueType{valuer.NewString("boolean")}
|
||||
ValueTypeArray = ValueType{valuer.NewString("array")}
|
||||
ValueTypeObject = ValueType{valuer.NewString("object")}
|
||||
)
|
||||
|
||||
type ValueType struct{ valuer.String }
|
||||
|
||||
type Range struct {
|
||||
Min int64 `json:"min"`
|
||||
Max int64 `json:"max"`
|
||||
}
|
||||
|
||||
type PreferenceWithValue struct {
|
||||
Preference
|
||||
Value interface{} `json:"value"`
|
||||
func NewPreferenceValueFromString(preference *Preference, value string) (any, error) {
|
||||
switch preference.ValueType {
|
||||
case ValueTypeInteger:
|
||||
val, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !preference.IsDiscreteValues {
|
||||
if val < preference.Range.Min || val > preference.Range.Max {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "value is not in the range specified, min: %d , max: %d", preference.Range.Min, preference.Range.Max)
|
||||
}
|
||||
}
|
||||
|
||||
if len(preference.AllowedValues) > 0 {
|
||||
for _, allowedValue := range preference.AllowedValues {
|
||||
if allowedValue == val {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "value is not one of the allowed values: %v", preference.AllowedValues)
|
||||
}
|
||||
|
||||
return val, nil
|
||||
case ValueTypeFloat:
|
||||
val, err := strconv.ParseFloat(value, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(preference.AllowedValues) > 0 {
|
||||
for _, allowedValue := range preference.AllowedValues {
|
||||
if allowedValue == val {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "value is not one of the allowed values: %v", preference.AllowedValues)
|
||||
}
|
||||
|
||||
return val, nil
|
||||
case ValueTypeString:
|
||||
if len(preference.AllowedValues) > 0 {
|
||||
for _, allowedValue := range preference.AllowedValues {
|
||||
if allowedValue == value {
|
||||
return value, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "value is not in the list of allowedValues: %v", preference.AllowedValues)
|
||||
}
|
||||
return value, nil
|
||||
case ValueTypeBoolean:
|
||||
return strconv.ParseBool(value)
|
||||
case ValueTypeArray:
|
||||
var arr []any
|
||||
err := json.Unmarshal([]byte(value), &arr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return arr, nil
|
||||
case ValueTypeObject:
|
||||
var obj map[string]any
|
||||
err := json.Unmarshal([]byte(value), &obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj, nil
|
||||
default:
|
||||
return nil, errors.Newf(errors.TypeUnsupported, errors.CodeUnsupported, "the preference value type is not supported: %s", preference.ValueType)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user