github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/model/websocket_message.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 "bytes" 8 "encoding/json" 9 "fmt" 10 "io" 11 ) 12 13 const ( 14 WEBSOCKET_EVENT_TYPING = "typing" 15 WEBSOCKET_EVENT_POSTED = "posted" 16 WEBSOCKET_EVENT_POST_EDITED = "post_edited" 17 WEBSOCKET_EVENT_POST_DELETED = "post_deleted" 18 WEBSOCKET_EVENT_POST_UNREAD = "post_unread" 19 WEBSOCKET_EVENT_CHANNEL_CONVERTED = "channel_converted" 20 WEBSOCKET_EVENT_CHANNEL_CREATED = "channel_created" 21 WEBSOCKET_EVENT_CHANNEL_DELETED = "channel_deleted" 22 WEBSOCKET_EVENT_CHANNEL_RESTORED = "channel_restored" 23 WEBSOCKET_EVENT_CHANNEL_UPDATED = "channel_updated" 24 WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED = "channel_member_updated" 25 WEBSOCKET_EVENT_CHANNEL_SCHEME_UPDATED = "channel_scheme_updated" 26 WEBSOCKET_EVENT_DIRECT_ADDED = "direct_added" 27 WEBSOCKET_EVENT_GROUP_ADDED = "group_added" 28 WEBSOCKET_EVENT_NEW_USER = "new_user" 29 WEBSOCKET_EVENT_ADDED_TO_TEAM = "added_to_team" 30 WEBSOCKET_EVENT_LEAVE_TEAM = "leave_team" 31 WEBSOCKET_EVENT_UPDATE_TEAM = "update_team" 32 WEBSOCKET_EVENT_DELETE_TEAM = "delete_team" 33 WEBSOCKET_EVENT_RESTORE_TEAM = "restore_team" 34 WEBSOCKET_EVENT_UPDATE_TEAM_SCHEME = "update_team_scheme" 35 WEBSOCKET_EVENT_USER_ADDED = "user_added" 36 WEBSOCKET_EVENT_USER_UPDATED = "user_updated" 37 WEBSOCKET_EVENT_USER_ROLE_UPDATED = "user_role_updated" 38 WEBSOCKET_EVENT_MEMBERROLE_UPDATED = "memberrole_updated" 39 WEBSOCKET_EVENT_USER_REMOVED = "user_removed" 40 WEBSOCKET_EVENT_PREFERENCE_CHANGED = "preference_changed" 41 WEBSOCKET_EVENT_PREFERENCES_CHANGED = "preferences_changed" 42 WEBSOCKET_EVENT_PREFERENCES_DELETED = "preferences_deleted" 43 WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message" 44 WEBSOCKET_EVENT_STATUS_CHANGE = "status_change" 45 WEBSOCKET_EVENT_HELLO = "hello" 46 WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge" 47 WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added" 48 WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed" 49 WEBSOCKET_EVENT_RESPONSE = "response" 50 WEBSOCKET_EVENT_EMOJI_ADDED = "emoji_added" 51 WEBSOCKET_EVENT_CHANNEL_VIEWED = "channel_viewed" 52 WEBSOCKET_EVENT_PLUGIN_STATUSES_CHANGED = "plugin_statuses_changed" 53 WEBSOCKET_EVENT_PLUGIN_ENABLED = "plugin_enabled" 54 WEBSOCKET_EVENT_PLUGIN_DISABLED = "plugin_disabled" 55 WEBSOCKET_EVENT_ROLE_UPDATED = "role_updated" 56 WEBSOCKET_EVENT_LICENSE_CHANGED = "license_changed" 57 WEBSOCKET_EVENT_CONFIG_CHANGED = "config_changed" 58 WEBSOCKET_EVENT_OPEN_DIALOG = "open_dialog" 59 WEBSOCKET_EVENT_GUESTS_DEACTIVATED = "guests_deactivated" 60 WEBSOCKET_EVENT_RECEIVED_GROUP = "received_group" 61 WEBSOCKET_EVENT_RECEIVED_GROUP_ASSOCIATED_TO_TEAM = "received_group_associated_to_team" 62 WEBSOCKET_EVENT_RECEIVED_GROUP_NOT_ASSOCIATED_TO_TEAM = "received_group_not_associated_to_team" 63 WEBSOCKET_EVENT_RECEIVED_GROUP_ASSOCIATED_TO_CHANNEL = "received_group_associated_to_channel" 64 WEBSOCKET_EVENT_RECEIVED_GROUP_NOT_ASSOCIATED_TO_CHANNEL = "received_group_not_associated_to_channel" 65 WEBSOCKET_EVENT_SIDEBAR_CATEGORY_CREATED = "sidebar_category_created" 66 WEBSOCKET_EVENT_SIDEBAR_CATEGORY_UPDATED = "sidebar_category_updated" 67 WEBSOCKET_EVENT_SIDEBAR_CATEGORY_DELETED = "sidebar_category_deleted" 68 WEBSOCKET_EVENT_SIDEBAR_CATEGORY_ORDER_UPDATED = "sidebar_category_order_updated" 69 WEBSOCKET_WARN_METRIC_STATUS_RECEIVED = "warn_metric_status_received" 70 WEBSOCKET_WARN_METRIC_STATUS_REMOVED = "warn_metric_status_removed" 71 ) 72 73 type WebSocketMessage interface { 74 ToJson() string 75 IsValid() bool 76 EventType() string 77 } 78 79 type WebsocketBroadcast struct { 80 OmitUsers map[string]bool `json:"omit_users"` // broadcast is omitted for users listed here 81 UserId string `json:"user_id"` // broadcast only occurs for this user 82 ChannelId string `json:"channel_id"` // broadcast only occurs for users in this channel 83 TeamId string `json:"team_id"` // broadcast only occurs for users in this team 84 ContainsSanitizedData bool `json:"-"` 85 ContainsSensitiveData bool `json:"-"` 86 } 87 88 type precomputedWebSocketEventJSON struct { 89 Event json.RawMessage 90 Data json.RawMessage 91 Broadcast json.RawMessage 92 } 93 94 // webSocketEventJSON mirrors WebSocketEvent to make some of its unexported fields serializable 95 type webSocketEventJSON struct { 96 Event string `json:"event"` 97 Data map[string]interface{} `json:"data"` 98 Broadcast *WebsocketBroadcast `json:"broadcast"` 99 Sequence int64 `json:"seq"` 100 } 101 102 // **NOTE**: Direct access to WebSocketEvent fields is deprecated. They will be 103 // made unexported in next major version release. Provided getter functions should be used instead. 104 type WebSocketEvent struct { 105 Event string // Deprecated: use EventType() 106 Data map[string]interface{} // Deprecated: use GetData() 107 Broadcast *WebsocketBroadcast // Deprecated: use GetBroadcast() 108 Sequence int64 // Deprecated: use GetSequence() 109 precomputedJSON *precomputedWebSocketEventJSON 110 } 111 112 // PrecomputeJSON precomputes and stores the serialized JSON for all fields other than Sequence. 113 // This makes ToJson much more efficient when sending the same event to multiple connections. 114 func (ev *WebSocketEvent) PrecomputeJSON() *WebSocketEvent { 115 copy := ev.Copy() 116 event, _ := json.Marshal(copy.Event) 117 data, _ := json.Marshal(copy.Data) 118 broadcast, _ := json.Marshal(copy.Broadcast) 119 copy.precomputedJSON = &precomputedWebSocketEventJSON{ 120 Event: json.RawMessage(event), 121 Data: json.RawMessage(data), 122 Broadcast: json.RawMessage(broadcast), 123 } 124 return copy 125 } 126 127 func (ev *WebSocketEvent) Add(key string, value interface{}) { 128 ev.Data[key] = value 129 } 130 131 func NewWebSocketEvent(event, teamId, channelId, userId string, omitUsers map[string]bool) *WebSocketEvent { 132 return &WebSocketEvent{Event: event, Data: make(map[string]interface{}), 133 Broadcast: &WebsocketBroadcast{TeamId: teamId, ChannelId: channelId, UserId: userId, OmitUsers: omitUsers}} 134 } 135 136 func (ev *WebSocketEvent) Copy() *WebSocketEvent { 137 copy := &WebSocketEvent{ 138 Event: ev.Event, 139 Data: ev.Data, 140 Broadcast: ev.Broadcast, 141 Sequence: ev.Sequence, 142 precomputedJSON: ev.precomputedJSON, 143 } 144 return copy 145 } 146 147 func (ev *WebSocketEvent) GetData() map[string]interface{} { 148 return ev.Data 149 } 150 151 func (ev *WebSocketEvent) GetBroadcast() *WebsocketBroadcast { 152 return ev.Broadcast 153 } 154 155 func (ev *WebSocketEvent) GetSequence() int64 { 156 return ev.Sequence 157 } 158 159 func (ev *WebSocketEvent) SetEvent(event string) *WebSocketEvent { 160 copy := ev.Copy() 161 copy.Event = event 162 return copy 163 } 164 165 func (ev *WebSocketEvent) SetData(data map[string]interface{}) *WebSocketEvent { 166 copy := ev.Copy() 167 copy.Data = data 168 return copy 169 } 170 171 func (ev *WebSocketEvent) SetBroadcast(broadcast *WebsocketBroadcast) *WebSocketEvent { 172 copy := ev.Copy() 173 copy.Broadcast = broadcast 174 return copy 175 } 176 177 func (ev *WebSocketEvent) SetSequence(seq int64) *WebSocketEvent { 178 copy := ev.Copy() 179 copy.Sequence = seq 180 return copy 181 } 182 183 func (ev *WebSocketEvent) IsValid() bool { 184 return ev.Event != "" 185 } 186 187 func (ev *WebSocketEvent) EventType() string { 188 return ev.Event 189 } 190 191 func (ev *WebSocketEvent) ToJson() string { 192 if ev.precomputedJSON != nil { 193 return fmt.Sprintf(`{"event": %s, "data": %s, "broadcast": %s, "seq": %d}`, ev.precomputedJSON.Event, ev.precomputedJSON.Data, ev.precomputedJSON.Broadcast, ev.Sequence) 194 } 195 b, _ := json.Marshal(webSocketEventJSON{ 196 ev.Event, 197 ev.Data, 198 ev.Broadcast, 199 ev.Sequence, 200 }) 201 return string(b) 202 } 203 204 func WebSocketEventFromJson(data io.Reader) *WebSocketEvent { 205 var ev WebSocketEvent 206 var o webSocketEventJSON 207 if err := json.NewDecoder(data).Decode(&o); err != nil { 208 return nil 209 } 210 ev.Event = o.Event 211 if u, ok := o.Data["user"]; ok { 212 // We need to convert to and from JSON again 213 // because the user is in the form of a map[string]interface{}. 214 buf, err := json.Marshal(u) 215 if err != nil { 216 return nil 217 } 218 o.Data["user"] = UserFromJson(bytes.NewReader(buf)) 219 } 220 ev.Data = o.Data 221 ev.Broadcast = o.Broadcast 222 ev.Sequence = o.Sequence 223 return &ev 224 } 225 226 // WebSocketResponse represents a response received through the WebSocket 227 // for a request made to the server. This is available through the ResponseChannel 228 // channel in WebSocketClient. 229 type WebSocketResponse struct { 230 Status string `json:"status"` // The status of the response. For example: OK, FAIL. 231 SeqReply int64 `json:"seq_reply,omitempty"` // A counter which is incremented for every response sent. 232 Data map[string]interface{} `json:"data,omitempty"` // The data contained in the response. 233 Error *AppError `json:"error,omitempty"` // A field that is set if any error has occurred. 234 } 235 236 func (m *WebSocketResponse) Add(key string, value interface{}) { 237 m.Data[key] = value 238 } 239 240 func NewWebSocketResponse(status string, seqReply int64, data map[string]interface{}) *WebSocketResponse { 241 return &WebSocketResponse{Status: status, SeqReply: seqReply, Data: data} 242 } 243 244 func NewWebSocketError(seqReply int64, err *AppError) *WebSocketResponse { 245 return &WebSocketResponse{Status: STATUS_FAIL, SeqReply: seqReply, Error: err} 246 } 247 248 func (m *WebSocketResponse) IsValid() bool { 249 return m.Status != "" 250 } 251 252 func (m *WebSocketResponse) EventType() string { 253 return WEBSOCKET_EVENT_RESPONSE 254 } 255 256 func (m *WebSocketResponse) ToJson() string { 257 b, _ := json.Marshal(m) 258 return string(b) 259 } 260 261 func WebSocketResponseFromJson(data io.Reader) *WebSocketResponse { 262 var o *WebSocketResponse 263 json.NewDecoder(data).Decode(&o) 264 return o 265 }