1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2// See LICENSE.txt for license information. 3 4package model 5 6import ( 7 "encoding/json" 8 "io" 9 "net/http" 10 "strings" 11) 12 13const ( 14 COMMAND_METHOD_POST = "P" 15 COMMAND_METHOD_GET = "G" 16 MIN_TRIGGER_LENGTH = 1 17 MAX_TRIGGER_LENGTH = 128 18) 19 20type Command struct { 21 Id string `json:"id"` 22 Token string `json:"token"` 23 CreateAt int64 `json:"create_at"` 24 UpdateAt int64 `json:"update_at"` 25 DeleteAt int64 `json:"delete_at"` 26 CreatorId string `json:"creator_id"` 27 TeamId string `json:"team_id"` 28 Trigger string `json:"trigger"` 29 Method string `json:"method"` 30 Username string `json:"username"` 31 IconURL string `json:"icon_url"` 32 AutoComplete bool `json:"auto_complete"` 33 AutoCompleteDesc string `json:"auto_complete_desc"` 34 AutoCompleteHint string `json:"auto_complete_hint"` 35 DisplayName string `json:"display_name"` 36 Description string `json:"description"` 37 URL string `json:"url"` 38 // PluginId records the id of the plugin that created this Command. If it is blank, the Command 39 // was not created by a plugin. 40 PluginId string `json:"plugin_id"` 41 AutocompleteData *AutocompleteData `db:"-" json:"autocomplete_data,omitempty"` 42 // AutocompleteIconData is a base64 encoded svg 43 AutocompleteIconData string `db:"-" json:"autocomplete_icon_data,omitempty"` 44} 45 46func (o *Command) ToJson() string { 47 b, _ := json.Marshal(o) 48 return string(b) 49} 50 51func CommandFromJson(data io.Reader) *Command { 52 var o *Command 53 json.NewDecoder(data).Decode(&o) 54 return o 55} 56 57func CommandListToJson(l []*Command) string { 58 b, _ := json.Marshal(l) 59 return string(b) 60} 61 62func CommandListFromJson(data io.Reader) []*Command { 63 var o []*Command 64 json.NewDecoder(data).Decode(&o) 65 return o 66} 67 68func (o *Command) IsValid() *AppError { 69 70 if !IsValidId(o.Id) { 71 return NewAppError("Command.IsValid", "model.command.is_valid.id.app_error", nil, "", http.StatusBadRequest) 72 } 73 74 if len(o.Token) != 26 { 75 return NewAppError("Command.IsValid", "model.command.is_valid.token.app_error", nil, "", http.StatusBadRequest) 76 } 77 78 if o.CreateAt == 0 { 79 return NewAppError("Command.IsValid", "model.command.is_valid.create_at.app_error", nil, "", http.StatusBadRequest) 80 } 81 82 if o.UpdateAt == 0 { 83 return NewAppError("Command.IsValid", "model.command.is_valid.update_at.app_error", nil, "", http.StatusBadRequest) 84 } 85 86 // If the CreatorId is blank, this should be a command created by a plugin. 87 if o.CreatorId == "" && !IsValidPluginId(o.PluginId) { 88 return NewAppError("Command.IsValid", "model.command.is_valid.plugin_id.app_error", nil, "", http.StatusBadRequest) 89 } 90 91 // If the PluginId is blank, this should be a command associated with a userId. 92 if o.PluginId == "" && !IsValidId(o.CreatorId) { 93 return NewAppError("Command.IsValid", "model.command.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) 94 } 95 96 if o.CreatorId != "" && o.PluginId != "" { 97 return NewAppError("Command.IsValid", "model.command.is_valid.plugin_id.app_error", nil, "command cannot have both a CreatorId and a PluginId", http.StatusBadRequest) 98 } 99 100 if !IsValidId(o.TeamId) { 101 return NewAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "", http.StatusBadRequest) 102 } 103 104 if len(o.Trigger) < MIN_TRIGGER_LENGTH || len(o.Trigger) > MAX_TRIGGER_LENGTH || strings.Index(o.Trigger, "/") == 0 || strings.Contains(o.Trigger, " ") { 105 return NewAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "", http.StatusBadRequest) 106 } 107 108 if len(o.URL) == 0 || len(o.URL) > 1024 { 109 return NewAppError("Command.IsValid", "model.command.is_valid.url.app_error", nil, "", http.StatusBadRequest) 110 } 111 112 if !IsValidHttpUrl(o.URL) { 113 return NewAppError("Command.IsValid", "model.command.is_valid.url_http.app_error", nil, "", http.StatusBadRequest) 114 } 115 116 if !(o.Method == COMMAND_METHOD_GET || o.Method == COMMAND_METHOD_POST) { 117 return NewAppError("Command.IsValid", "model.command.is_valid.method.app_error", nil, "", http.StatusBadRequest) 118 } 119 120 if len(o.DisplayName) > 64 { 121 return NewAppError("Command.IsValid", "model.command.is_valid.display_name.app_error", nil, "", http.StatusBadRequest) 122 } 123 124 if len(o.Description) > 128 { 125 return NewAppError("Command.IsValid", "model.command.is_valid.description.app_error", nil, "", http.StatusBadRequest) 126 } 127 128 if o.AutocompleteData != nil { 129 if err := o.AutocompleteData.IsValid(); err != nil { 130 return NewAppError("Command.IsValid", "model.command.is_valid.autocomplete_data.app_error", nil, err.Error(), http.StatusBadRequest) 131 } 132 } 133 134 return nil 135} 136 137func (o *Command) PreSave() { 138 if o.Id == "" { 139 o.Id = NewId() 140 } 141 142 if o.Token == "" { 143 o.Token = NewId() 144 } 145 146 o.CreateAt = GetMillis() 147 o.UpdateAt = o.CreateAt 148} 149 150func (o *Command) PreUpdate() { 151 o.UpdateAt = GetMillis() 152} 153 154func (o *Command) Sanitize() { 155 o.Token = "" 156 o.CreatorId = "" 157 o.Method = "" 158 o.URL = "" 159 o.Username = "" 160 o.IconURL = "" 161} 162