preference.go
preference.go - Overview
This file defines the data structures and interfaces for handling user and organization preferences within the application. It includes definitions for storing, retrieving, and validating preference values.
Detailed Documentation
Type: GettablePreference
- Purpose: Represents a preference that can be retrieved, containing the preference ID and value.
- Parameters: None
- Returns: None
type GettablePreference struct {
PreferenceID string `json:"preference_id" db:"preference_id"`
PreferenceValue interface{} `json:"preference_value" db:"preference_value"`
}
PreferenceID
: The unique identifier for the preference.PreferenceValue
: The value of the preference, which can be of any type.
Type: UpdatablePreference
- Purpose: Represents a preference that can be updated, containing only the preference value.
- Parameters: None
- Returns: None
type UpdatablePreference struct {
PreferenceValue interface{} `json:"preference_value" db:"preference_value"`
}
PreferenceValue
: The new value for the preference.
Type: StorableOrgPreference
- Purpose: Represents an organization preference stored in the database.
- Parameters: None
- Returns: None
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"`
}
bun.BaseModel
: Base model for bun ORM.types.Identifiable
: Provides a unique ID for the preference.PreferenceID
: The unique identifier for the preference.PreferenceValue
: The value of the preference, stored as a string.OrgID
: The ID of the organization to which this preference belongs.
Type: StorableUserPreference
- Purpose: Represents a user preference stored in the database.
- Parameters: None
- Returns: None
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"`
}
bun.BaseModel
: Base model for bun ORM.types.Identifiable
: Provides a unique ID for the preference.PreferenceID
: The unique identifier for the preference.PreferenceValue
: The value of the preference, stored as a string.UserID
: The ID of the user to which this preference belongs.
Type: Preference
- Purpose: Represents the definition of a preference, including its metadata and allowed values.
- Parameters: None
- Returns: None
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"`
}
Key
: The unique key for the preference.Name
: A human-readable name for the preference.Description
: A description of the preference.ValueType
: The data type of the preference value (e.g., "boolean", "string").DefaultValue
: The default value for the preference.AllowedValues
: A list of allowed values for the preference (ifIsDiscreteValues
is true).IsDiscreteValues
: A boolean indicating whether the preference has a discrete set of allowed values.Range
: Defines the acceptable range (min/max) for the preference value, applicable whenIsDiscreteValues
is false.AllowedScopes
: A list of scopes (e.g., "org", "user") where this preference can be applied.
Function: NewDefaultPreferenceMap
- Purpose: Creates and returns a map containing default preferences.
- Parameters: None
- Returns:
map[string]Preference
: A map of default preferences, where the key is the preference key.
func NewDefaultPreferenceMap() map[string]Preference {
return map[string]Preference{
"ORG_ONBOARDING": {
Key: "ORG_ONBOARDING",
Name: "Organisation Onboarding",
Description: "Organisation Onboarding",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"org"},
},
"WELCOME_CHECKLIST_DO_LATER": {
Key: "WELCOME_CHECKLIST_DO_LATER",
Name: "Welcome Checklist Do Later",
Description: "Welcome Checklist Do Later",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"user"},
},
"WELCOME_CHECKLIST_SEND_LOGS_SKIPPED": {
Key: "WELCOME_CHECKLIST_SEND_LOGS_SKIPPED",
Name: "Welcome Checklist Send Logs Skipped",
Description: "Welcome Checklist Send Logs Skipped",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"user"},
},
"WELCOME_CHECKLIST_SEND_TRACES_SKIPPED": {
Key: "WELCOME_CHECKLIST_SEND_TRACES_SKIPPED",
Name: "Welcome Checklist Send Traces Skipped",
Description: "Welcome Checklist Send Traces Skipped",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"user"},
},
"WELCOME_CHECKLIST_SEND_INFRA_METRICS_SKIPPED": {
Key: "WELCOME_CHECKLIST_SEND_INFRA_METRICS_SKIPPED",
Name: "Welcome Checklist Send Infra Metrics Skipped",
Description: "Welcome Checklist Send Infra Metrics Skipped",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"user"},
},
"WELCOME_CHECKLIST_SETUP_DASHBOARDS_SKIPPED": {
Key: "WELCOME_CHECKLIST_SETUP_DASHBOARDS_SKIPPED",
Name: "Welcome Checklist Setup Dashboards Skipped",
Description: "Welcome Checklist Setup Dashboards Skipped",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"user"},
},
"WELCOME_CHECKLIST_SETUP_ALERTS_SKIPPED": {
Key: "WELCOME_CHECKLIST_SETUP_ALERTS_SKIPPED",
Name: "Welcome Checklist Setup Alerts Skipped",
Description: "Welcome Checklist Setup Alerts Skipped",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"user"},
},
"WELCOME_CHECKLIST_SETUP_SAVED_VIEW_SKIPPED": {
Key: "WELCOME_CHECKLIST_SETUP_SAVED_VIEW_SKIPPED",
Name: "Welcome Checklist Setup Saved View Skipped",
Description: "Welcome Checklist Setup Saved View Skipped",
ValueType: "boolean",
DefaultValue: false,
AllowedValues: []interface{}{true, false},
IsDiscreteValues: true,
AllowedScopes: []string{"user"},
},
}
}
Method: (p *Preference) ErrorValueTypeMismatch
- Purpose: Returns an error indicating that the provided preference value does not match the expected type.
- Parameters: None
- Returns:
error
: An error of typeerrors.TypeInvalidInput
.
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))
}
Method: (p *Preference) checkIfInAllowedValues
- Purpose: Checks if a given preference value is within the allowed values for the preference.
- Parameters:
preferenceValue
(interface{}
): The preference value to check.
- Returns:
bool
:true
if the value is in the allowed values,false
otherwise.error
: An error if the value's type does not match the expected type, or if any internal type conversion fails.
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 allowedValue == preferenceValue {
isInAllowedValues = true
}
case PreferenceValueTypeFloat:
allowedValue, ok := value.(float64)
if !ok {
return false, p.ErrorValueTypeMismatch()
}
if allowedValue == preferenceValue {
isInAllowedValues = true
}
case PreferenceValueTypeString:
allowedValue, ok := value.(string)
if !ok {
return false, p.ErrorValueTypeMismatch()
}
if allowedValue == preferenceValue {
isInAllowedValues = true
}
case PreferenceValueTypeBoolean:
allowedValue, ok := value.(bool)
if !ok {
return false, p.ErrorValueTypeMismatch()
}
if allowedValue == preferenceValue {
isInAllowedValues = true
}
}
}
return isInAllowedValues, nil
}
Method: (p *Preference) IsValidValue
- Purpose: Validates a given preference value against the preference's definition, ensuring that the value is of the correct type and within the allowed values or range.
- Parameters:
preferenceValue
(interface{}
): The preference value to validate.
- Returns:
error
: An error if the value is invalid, ornil
if the value is valid.
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, fmt.Sprintf("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()
}
}
// 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
}
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 nil
}
Method: (p *Preference) IsEnabledForScope
- Purpose: Checks if the preference is enabled for a given scope (e.g., "org", "user").
- Parameters:
scope
(string
): The scope to check.
- Returns:
bool
:true
if the preference is enabled for the scope,false
otherwise.
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
}
Method: (p *Preference) SanitizeValue
- Purpose: Sanitizes the preference value based on its type. Currently, it only handles boolean types, converting
"1"
,true
, and"true"
totrue
, and everything else tofalse
. - Parameters:
preferenceValue
(interface{}
): The preference value to sanitize.
- Returns:
interface{}
: The sanitized preference value.
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
}
}
Interface: PreferenceStore
- Purpose: Defines the interface for interacting with the preference storage.
- Parameters: None
- Returns: None
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
}
GetOrgPreference(context.Context, string, string) (*StorableOrgPreference, error)
: Retrieves an organization preference by org ID and preference ID.GetAllOrgPreferences(context.Context, string) ([]*StorableOrgPreference, error)
: Retrieves all organization preferences for a given org ID.UpsertOrgPreference(context.Context, *StorableOrgPreference) error
: Creates or updates an organization preference.GetUserPreference(context.Context, string, string) (*StorableUserPreference, error)
: Retrieves a user preference by user ID and preference ID.GetAllUserPreferences(context.Context, string) ([]*StorableUserPreference, error)
: Retrieves all user preferences for a given user ID.UpsertUserPreference(context.Context, *StorableUserPreference) error
: Creates or updates a user preference.
Code Examples
N/A
Include in Getting Started: NO