Cookies: Provide a mechanism for per user control over cookies (#61566)
This commit is contained in:
@@ -7,9 +7,16 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
)
|
||||
|
||||
var ErrPrefNotFound = errors.New("preference not found")
|
||||
var ErrUnknownCookieType = errutil.NewBase(
|
||||
errutil.StatusBadRequest,
|
||||
"preferences.unknownCookieType",
|
||||
errutil.WithPublicMessage("Got an unknown cookie preference type. Expected a set containing one or more of 'functional', 'performance', or 'analytics'}"),
|
||||
)
|
||||
|
||||
type Preference struct {
|
||||
ID int64 `xorm:"pk autoincr 'id'" db:"id"`
|
||||
@@ -27,6 +34,15 @@ type Preference struct {
|
||||
JSONData *PreferenceJSONData `xorm:"json_data" db:"json_data"`
|
||||
}
|
||||
|
||||
func (p Preference) Cookies(typ string) bool {
|
||||
if p.JSONData == nil || p.JSONData.CookiePreferences == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
_, ok := p.JSONData.CookiePreferences[typ]
|
||||
return ok
|
||||
}
|
||||
|
||||
type GetPreferenceWithDefaultsQuery struct {
|
||||
Teams []int64
|
||||
OrgID int64
|
||||
@@ -44,13 +60,14 @@ type SavePreferenceCommand struct {
|
||||
OrgID int64
|
||||
TeamID int64
|
||||
|
||||
HomeDashboardID int64 `json:"homeDashboardId,omitempty"`
|
||||
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
|
||||
Timezone string `json:"timezone,omitempty"`
|
||||
WeekStart string `json:"weekStart,omitempty"`
|
||||
Theme string `json:"theme,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
|
||||
HomeDashboardID int64 `json:"homeDashboardId,omitempty"`
|
||||
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
|
||||
Timezone string `json:"timezone,omitempty"`
|
||||
WeekStart string `json:"weekStart,omitempty"`
|
||||
Theme string `json:"theme,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
|
||||
CookiePreferences []CookieType `json:"cookiePreferences,omitempty"`
|
||||
}
|
||||
|
||||
type PatchPreferenceCommand struct {
|
||||
@@ -58,18 +75,20 @@ type PatchPreferenceCommand struct {
|
||||
OrgID int64
|
||||
TeamID int64
|
||||
|
||||
HomeDashboardID *int64 `json:"homeDashboardId,omitempty"`
|
||||
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
|
||||
Timezone *string `json:"timezone,omitempty"`
|
||||
WeekStart *string `json:"weekStart,omitempty"`
|
||||
Theme *string `json:"theme,omitempty"`
|
||||
Language *string `json:"language,omitempty"`
|
||||
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
|
||||
HomeDashboardID *int64 `json:"homeDashboardId,omitempty"`
|
||||
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
|
||||
Timezone *string `json:"timezone,omitempty"`
|
||||
WeekStart *string `json:"weekStart,omitempty"`
|
||||
Theme *string `json:"theme,omitempty"`
|
||||
Language *string `json:"language,omitempty"`
|
||||
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
|
||||
CookiePreferences []CookieType `json:"cookiePreferences,omitempty"`
|
||||
}
|
||||
|
||||
type PreferenceJSONData struct {
|
||||
Language string `json:"language"`
|
||||
QueryHistory QueryHistoryPreference `json:"queryHistory"`
|
||||
Language string `json:"language"`
|
||||
QueryHistory QueryHistoryPreference `json:"queryHistory"`
|
||||
CookiePreferences map[string]struct{} `json:"cookiePreferences"`
|
||||
}
|
||||
|
||||
type QueryHistoryPreference struct {
|
||||
@@ -112,3 +131,7 @@ func (j *PreferenceJSONData) ToDB() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (p Preference) TableName() string { return "preferences" }
|
||||
|
||||
// swagger:model
|
||||
// Enum: analytics,performance,functional
|
||||
type CookieType string
|
||||
|
||||
@@ -68,6 +68,10 @@ func (s *Service) GetWithDefaults(ctx context.Context, query *pref.GetPreference
|
||||
if p.JSONData.QueryHistory.HomeTab != "" {
|
||||
res.JSONData.QueryHistory.HomeTab = p.JSONData.QueryHistory.HomeTab
|
||||
}
|
||||
|
||||
if p.JSONData.CookiePreferences != nil {
|
||||
res.JSONData.CookiePreferences = p.JSONData.CookiePreferences
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +95,11 @@ func (s *Service) Get(ctx context.Context, query *pref.GetPreferenceQuery) (*pre
|
||||
}
|
||||
|
||||
func (s *Service) Save(ctx context.Context, cmd *pref.SavePreferenceCommand) error {
|
||||
jsonData, err := preferenceData(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
preference, err := s.store.Get(ctx, &pref.Preference{
|
||||
OrgID: cmd.OrgID,
|
||||
UserID: cmd.UserID,
|
||||
@@ -108,9 +117,7 @@ func (s *Service) Save(ctx context.Context, cmd *pref.SavePreferenceCommand) err
|
||||
Theme: cmd.Theme,
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
JSONData: &pref.PreferenceJSONData{
|
||||
Language: cmd.Language,
|
||||
},
|
||||
JSONData: jsonData,
|
||||
}
|
||||
_, err = s.store.Insert(ctx, preference)
|
||||
if err != nil {
|
||||
@@ -126,13 +133,8 @@ func (s *Service) Save(ctx context.Context, cmd *pref.SavePreferenceCommand) err
|
||||
preference.Updated = time.Now()
|
||||
preference.Version += 1
|
||||
preference.HomeDashboardID = cmd.HomeDashboardID
|
||||
preference.JSONData = &pref.PreferenceJSONData{
|
||||
Language: cmd.Language,
|
||||
}
|
||||
preference.JSONData = jsonData
|
||||
|
||||
if cmd.QueryHistory != nil {
|
||||
preference.JSONData.QueryHistory = *cmd.QueryHistory
|
||||
}
|
||||
return s.store.Update(ctx, preference)
|
||||
}
|
||||
|
||||
@@ -179,6 +181,18 @@ func (s *Service) Patch(ctx context.Context, cmd *pref.PatchPreferenceCommand) e
|
||||
preference.HomeDashboardID = *cmd.HomeDashboardID
|
||||
}
|
||||
|
||||
if cmd.CookiePreferences != nil {
|
||||
cookies, err := parseCookiePreferences(cmd.CookiePreferences)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if preference.JSONData == nil {
|
||||
preference.JSONData = &pref.PreferenceJSONData{}
|
||||
}
|
||||
preference.JSONData.CookiePreferences = cookies
|
||||
}
|
||||
|
||||
if cmd.Timezone != nil {
|
||||
preference.Timezone = *cmd.Timezone
|
||||
}
|
||||
@@ -221,3 +235,40 @@ func (s *Service) GetDefaults() *pref.Preference {
|
||||
func (s *Service) DeleteByUser(ctx context.Context, userID int64) error {
|
||||
return s.store.DeleteByUser(ctx, userID)
|
||||
}
|
||||
|
||||
func parseCookiePreferences(prefs []pref.CookieType) (map[string]struct{}, error) {
|
||||
allowed := map[pref.CookieType]struct{}{
|
||||
"analytics": {},
|
||||
"performance": {},
|
||||
"functional": {},
|
||||
}
|
||||
|
||||
m := map[string]struct{}{}
|
||||
for _, c := range prefs {
|
||||
if _, ok := allowed[c]; !ok {
|
||||
return nil, pref.ErrUnknownCookieType.Errorf("'%s' is not an allowed cookie type", c)
|
||||
}
|
||||
|
||||
m[string(c)] = struct{}{}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func preferenceData(cmd *pref.SavePreferenceCommand) (*pref.PreferenceJSONData, error) {
|
||||
jsonData := &pref.PreferenceJSONData{
|
||||
Language: cmd.Language,
|
||||
}
|
||||
|
||||
if cmd.QueryHistory != nil {
|
||||
jsonData.QueryHistory = *cmd.QueryHistory
|
||||
}
|
||||
if cmd.CookiePreferences != nil {
|
||||
cookies, err := parseCookiePreferences(cmd.CookiePreferences)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jsonData.CookiePreferences = cookies
|
||||
}
|
||||
|
||||
return jsonData, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user