github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/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_CLASS_CONVERTED = "class_converted" 20 WEBSOCKET_EVENT_CLASS_CREATED = "class_created" 21 WEBSOCKET_EVENT_CLASS_DELETED = "class_deleted" 22 WEBSOCKET_EVENT_CLASS_RESTORED = "class_restored" 23 WEBSOCKET_EVENT_CLASS_UPDATED = "class_updated" 24 WEBSOCKET_EVENT_CLASS_MEMBER_UPDATED = "class_member_updated" 25 WEBSOCKET_EVENT_CLASS_SCHEME_UPDATED = "class_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_BRANCH = "added_to_branch" 30 WEBSOCKET_EVENT_LEAVE_BRANCH = "leave_branch" 31 WEBSOCKET_EVENT_UPDATE_BRANCH = "update_branch" 32 WEBSOCKET_EVENT_DELETE_BRANCH = "delete_branch" 33 WEBSOCKET_EVENT_RESTORE_BRANCH = "restore_branch" 34 WEBSOCKET_EVENT_USER_ADDED = "user_added" 35 WEBSOCKET_EVENT_USER_UPDATED = "user_updated" 36 WEBSOCKET_EVENT_USER_ROLE_UPDATED = "user_role_updated" 37 WEBSOCKET_EVENT_MEMBERROLE_UPDATED = "memberrole_updated" 38 WEBSOCKET_EVENT_USER_REMOVED = "user_removed" 39 WEBSOCKET_EVENT_PREFERENCE_CHANGED = "preference_changed" 40 WEBSOCKET_EVENT_PREFERENCES_CHANGED = "preferences_changed" 41 WEBSOCKET_EVENT_PREFERENCES_DELETED = "preferences_deleted" 42 WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message" 43 WEBSOCKET_EVENT_STATUS_CHANGE = "status_change" 44 WEBSOCKET_EVENT_HELLO = "hello" 45 WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge" 46 WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added" 47 WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed" 48 WEBSOCKET_EVENT_RESPONSE = "response" 49 WEBSOCKET_EVENT_EMOJI_ADDED = "emoji_added" 50 WEBSOCKET_EVENT_CLASS_VIEWED = "class_viewed" 51 WEBSOCKET_EVENT_PLUGIN_STATUSES_CHANGED = "plugin_statuses_changed" 52 WEBSOCKET_EVENT_PLUGIN_ENABLED = "plugin_enabled" 53 WEBSOCKET_EVENT_PLUGIN_DISABLED = "plugin_disabled" 54 WEBSOCKET_EVENT_ROLE_UPDATED = "role_updated" 55 WEBSOCKET_EVENT_LICENSE_CHANGED = "license_changed" 56 WEBSOCKET_EVENT_CONFIG_CHANGED = "config_changed" 57 WEBSOCKET_EVENT_OPEN_DIALOG = "open_dialog" 58 WEBSOCKET_EVENT_GUESTS_DEACTIVATED = "guests_deactivated" 59 ) 60 61 type WebSocketMessage interface { 62 ToJson() string 63 IsValid() bool 64 EventType() string 65 } 66 67 type WebsocketBroadcast struct { 68 OmitUsers map[string]bool `json:"omit_users"` // broadcast is omitted for users listed here 69 UserId string `json:"user_id"` // broadcast only occurs for this user 70 ClassId string `json:"class_id"` // broadcast only occurs for users in this class 71 BranchId string `json:"branch_id"` // broadcast only occurs for users in this branch 72 ContainsSanitizedData bool `json:"-"` 73 ContainsSensitiveData bool `json:"-"` 74 } 75 76 type precomputedWebSocketEventJSON struct { 77 Event json.RawMessage 78 Data json.RawMessage 79 Broadcast json.RawMessage 80 } 81 82 // webSocketEventJSON mirrors WebSocketEvent to make some of its unexported fields serializable 83 type webSocketEventJSON struct { 84 Event string `json:"event"` 85 Data map[string]interface{} `json:"data"` 86 Broadcast *WebsocketBroadcast `json:"broadcast"` 87 Sequence int64 `json:"seq"` 88 } 89 90 // **NOTE**: Direct access to WebSocketEvent fields is deprecated. They will be 91 // made unexported in next major version release. Provided getter functions should be used instead. 92 type WebSocketEvent struct { 93 Event string // Deprecated: use EventType() 94 Data map[string]interface{} // Deprecated: use GetData() 95 Broadcast *WebsocketBroadcast // Deprecated: use GetBroadcast() 96 Sequence int64 // Deprecated: use GetSequence() 97 precomputedJSON *precomputedWebSocketEventJSON 98 } 99 100 // PrecomputeJSON precomputes and stores the serialized JSON for all fields other than Sequence. 101 // This makes ToJson much more efficient when sending the same event to multiple connections. 102 func (ev *WebSocketEvent) PrecomputeJSON() *WebSocketEvent { 103 copy := ev.Copy() 104 event, _ := json.Marshal(copy.Event) 105 data, _ := json.Marshal(copy.Data) 106 broadcast, _ := json.Marshal(copy.Broadcast) 107 copy.precomputedJSON = &precomputedWebSocketEventJSON{ 108 Event: json.RawMessage(event), 109 Data: json.RawMessage(data), 110 Broadcast: json.RawMessage(broadcast), 111 } 112 return copy 113 } 114 115 func (ev *WebSocketEvent) Add(key string, value interface{}) { 116 ev.Data[key] = value 117 } 118 119 func NewWebSocketEvent(event, branchId, classId, userId string, omitUsers map[string]bool) *WebSocketEvent { 120 return &WebSocketEvent{Event: event, Data: make(map[string]interface{}), 121 Broadcast: &WebsocketBroadcast{BranchId: branchId, ClassId: classId, UserId: userId, OmitUsers: omitUsers}} 122 } 123 124 func (ev *WebSocketEvent) Copy() *WebSocketEvent { 125 copy := &WebSocketEvent{ 126 Event: ev.Event, 127 Data: ev.Data, 128 Broadcast: ev.Broadcast, 129 Sequence: ev.Sequence, 130 precomputedJSON: ev.precomputedJSON, 131 } 132 return copy 133 } 134 135 func (ev *WebSocketEvent) GetData() map[string]interface{} { 136 return ev.Data 137 } 138 139 func (ev *WebSocketEvent) GetBroadcast() *WebsocketBroadcast { 140 return ev.Broadcast 141 } 142 143 func (ev *WebSocketEvent) GetSequence() int64 { 144 return ev.Sequence 145 } 146 147 func (ev *WebSocketEvent) SetEvent(event string) *WebSocketEvent { 148 copy := ev.Copy() 149 copy.Event = event 150 return copy 151 } 152 153 func (ev *WebSocketEvent) SetData(data map[string]interface{}) *WebSocketEvent { 154 copy := ev.Copy() 155 copy.Data = data 156 return copy 157 } 158 159 func (ev *WebSocketEvent) SetBroadcast(broadcast *WebsocketBroadcast) *WebSocketEvent { 160 copy := ev.Copy() 161 copy.Broadcast = broadcast 162 return copy 163 } 164 165 func (ev *WebSocketEvent) SetSequence(seq int64) *WebSocketEvent { 166 copy := ev.Copy() 167 copy.Sequence = seq 168 return copy 169 } 170 171 func (ev *WebSocketEvent) IsValid() bool { 172 return ev.Event != "" 173 } 174 175 func (ev *WebSocketEvent) EventType() string { 176 return ev.Event 177 } 178 179 func (ev *WebSocketEvent) ToJson() string { 180 if ev.precomputedJSON != nil { 181 return fmt.Sprintf(`{"event": %s, "data": %s, "broadcast": %s, "seq": %d}`, ev.precomputedJSON.Event, ev.precomputedJSON.Data, ev.precomputedJSON.Broadcast, ev.Sequence) 182 } 183 b, _ := json.Marshal(webSocketEventJSON{ 184 ev.Event, 185 ev.Data, 186 ev.Broadcast, 187 ev.Sequence, 188 }) 189 return string(b) 190 } 191 192 func WebSocketEventFromJson(data io.Reader) *WebSocketEvent { 193 var ev WebSocketEvent 194 var o webSocketEventJSON 195 if err := json.NewDecoder(data).Decode(&o); err != nil { 196 return nil 197 } 198 ev.Event = o.Event 199 if u, ok := o.Data["user"]; ok { 200 // We need to convert to and from JSON again 201 // because the user is in the form of a map[string]interface{}. 202 buf, err := json.Marshal(u) 203 if err != nil { 204 return nil 205 } 206 o.Data["user"] = UserFromJson(bytes.NewReader(buf)) 207 } 208 ev.Data = o.Data 209 ev.Broadcast = o.Broadcast 210 ev.Sequence = o.Sequence 211 return &ev 212 } 213 214 // WebSocketResponse represents a response received through the WebSocket 215 // for a request made to the server. This is available through the ResponseClass 216 // class in WebSocketClient. 217 type WebSocketResponse struct { 218 Status string `json:"status"` // The status of the response. For example: OK, FAIL. 219 SeqReply int64 `json:"seq_reply,omitempty"` // A counter which is incremented for every response sent. 220 Data map[string]interface{} `json:"data,omitempty"` // The data contained in the response. 221 Error *AppError `json:"error,omitempty"` // A field that is set if any error has occurred. 222 } 223 224 func (m *WebSocketResponse) Add(key string, value interface{}) { 225 m.Data[key] = value 226 } 227 228 func NewWebSocketResponse(status string, seqReply int64, data map[string]interface{}) *WebSocketResponse { 229 return &WebSocketResponse{Status: status, SeqReply: seqReply, Data: data} 230 } 231 232 func NewWebSocketError(seqReply int64, err *AppError) *WebSocketResponse { 233 return &WebSocketResponse{Status: STATUS_FAIL, SeqReply: seqReply, Error: err} 234 } 235 236 func (m *WebSocketResponse) IsValid() bool { 237 return m.Status != "" 238 } 239 240 func (m *WebSocketResponse) EventType() string { 241 return WEBSOCKET_EVENT_RESPONSE 242 } 243 244 func (m *WebSocketResponse) ToJson() string { 245 b, _ := json.Marshal(m) 246 return string(b) 247 } 248 249 func WebSocketResponseFromJson(data io.Reader) *WebSocketResponse { 250 var o *WebSocketResponse 251 json.NewDecoder(data).Decode(&o) 252 return o 253 }