github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/model/preference.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package model 5 6 import ( 7 "encoding/json" 8 "io" 9 "net/http" 10 "regexp" 11 "strings" 12 "unicode/utf8" 13 ) 14 15 const ( 16 PREFERENCE_CATEGORY_DIRECT_CLASS_SHOW = "direct_class_show" 17 PREFERENCE_CATEGORY_TUTORIAL_STEPS = "tutorial_step" 18 PREFERENCE_CATEGORY_ADVANCED_SETTINGS = "advanced_settings" 19 PREFERENCE_CATEGORY_FLAGGED_POST = "flagged_post" 20 PREFERENCE_CATEGORY_FAVORITE_CLASS = "favorite_class" 21 PREFERENCE_CATEGORY_SIDEBAR_SETTINGS = "sidebar_settings" 22 23 PREFERENCE_CATEGORY_DISPLAY_SETTINGS = "display_settings" 24 PREFERENCE_NAME_CLASS_DISPLAY_MODE = "class_display_mode" 25 PREFERENCE_NAME_COLLAPSE_SETTING = "collapse_previews" 26 PREFERENCE_NAME_MESSAGE_DISPLAY = "message_display" 27 PREFERENCE_NAME_NAME_FORMAT = "name_format" 28 PREFERENCE_NAME_USE_MILITARY_TIME = "use_military_time" 29 30 PREFERENCE_CATEGORY_THEME = "theme" 31 // the name for theme props is the branch id 32 33 PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP = "oauth_app" 34 // the name for oauth_app is the client_id and value is the current scope 35 36 PREFERENCE_CATEGORY_LAST = "last" 37 PREFERENCE_NAME_LAST_CLASS = "class" 38 PREFERENCE_NAME_LAST_BRANCH = "branch" 39 40 PREFERENCE_CATEGORY_NOTIFICATIONS = "notifications" 41 PREFERENCE_NAME_EMAIL_INTERVAL = "email_interval" 42 43 PREFERENCE_EMAIL_INTERVAL_NO_BATCHING_SECONDS = "30" // the "immediate" setting is actually 30s 44 PREFERENCE_EMAIL_INTERVAL_BATCHING_SECONDS = "900" // fifteen minutes is 900 seconds 45 PREFERENCE_EMAIL_INTERVAL_IMMEDIATELY = "immediately" 46 PREFERENCE_EMAIL_INTERVAL_FIFTEEN = "fifteen" 47 PREFERENCE_EMAIL_INTERVAL_FIFTEEN_AS_SECONDS = "900" 48 PREFERENCE_EMAIL_INTERVAL_HOUR = "hour" 49 PREFERENCE_EMAIL_INTERVAL_HOUR_AS_SECONDS = "3600" 50 ) 51 52 type Preference struct { 53 UserId string `json:"user_id"` 54 Category string `json:"category"` 55 Name string `json:"name"` 56 Value string `json:"value"` 57 } 58 59 func (o *Preference) ToJson() string { 60 b, _ := json.Marshal(o) 61 return string(b) 62 } 63 64 func PreferenceFromJson(data io.Reader) *Preference { 65 var o *Preference 66 json.NewDecoder(data).Decode(&o) 67 return o 68 } 69 70 func (o *Preference) IsValid() *AppError { 71 if len(o.UserId) != 26 { 72 return NewAppError("Preference.IsValid", "model.preference.is_valid.id.app_error", nil, "user_id="+o.UserId, http.StatusBadRequest) 73 } 74 75 if len(o.Category) == 0 || len(o.Category) > 32 { 76 return NewAppError("Preference.IsValid", "model.preference.is_valid.category.app_error", nil, "category="+o.Category, http.StatusBadRequest) 77 } 78 79 if len(o.Name) > 32 { 80 return NewAppError("Preference.IsValid", "model.preference.is_valid.name.app_error", nil, "name="+o.Name, http.StatusBadRequest) 81 } 82 83 if utf8.RuneCountInString(o.Value) > 2000 { 84 return NewAppError("Preference.IsValid", "model.preference.is_valid.value.app_error", nil, "value="+o.Value, http.StatusBadRequest) 85 } 86 87 if o.Category == PREFERENCE_CATEGORY_THEME { 88 var unused map[string]string 89 if err := json.NewDecoder(strings.NewReader(o.Value)).Decode(&unused); err != nil { 90 return NewAppError("Preference.IsValid", "model.preference.is_valid.theme.app_error", nil, "value="+o.Value, http.StatusBadRequest) 91 } 92 } 93 94 return nil 95 } 96 97 func (o *Preference) PreUpdate() { 98 if o.Category == PREFERENCE_CATEGORY_THEME { 99 // decode the value of theme (a map of strings to string) and eliminate any invalid values 100 var props map[string]string 101 if err := json.NewDecoder(strings.NewReader(o.Value)).Decode(&props); err != nil { 102 // just continue, the invalid preference value should get caught by IsValid before saving 103 return 104 } 105 106 colorPattern := regexp.MustCompile(`^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$`) 107 108 // blank out any invalid theme values 109 for name, value := range props { 110 if name == "image" || name == "type" || name == "codeTheme" { 111 continue 112 } 113 114 if !colorPattern.MatchString(value) { 115 props[name] = "#ffffff" 116 } 117 } 118 119 if b, err := json.Marshal(props); err == nil { 120 o.Value = string(b) 121 } 122 } 123 }