summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarrison Healey <harrisonmhealey@gmail.com>2017-04-20 08:57:31 -0400
committerGeorge Goldberg <george@gberg.me>2017-04-20 13:57:31 +0100
commit1a0f8d1b3c7451eac43bfdc5971de060caabf441 (patch)
tree3bf83f3f8da16a257a1539d0a20cf7febb95fba8
parentb79439e92b11a53c972bbd1169f4c3aaede9b8ce (diff)
downloadchat-1a0f8d1b3c7451eac43bfdc5971de060caabf441.tar.gz
chat-1a0f8d1b3c7451eac43bfdc5971de060caabf441.tar.bz2
chat-1a0f8d1b3c7451eac43bfdc5971de060caabf441.zip
PLT-1384 Added websocket event when preferences are updated/deleted (#6107)
-rw-r--r--api/preference.go31
-rw-r--r--api4/api.go2
-rw-r--r--api4/preference.go24
-rw-r--r--api4/preference_test.go118
-rw-r--r--app/preference.go35
-rw-r--r--i18n/en.json4
-rw-r--r--model/websocket_message.go48
7 files changed, 179 insertions, 83 deletions
diff --git a/api/preference.go b/api/preference.go
index 9fdc0279c..d3dc2b174 100644
--- a/api/preference.go
+++ b/api/preference.go
@@ -40,18 +40,8 @@ func savePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- for _, preference := range preferences {
- if c.Session.UserId != preference.UserId {
- c.Err = model.NewLocAppError("savePreferences", "api.preference.save_preferences.set.app_error", nil,
- c.T("api.preference.save_preferences.set_details.app_error",
- map[string]interface{}{"SessionUserId": c.Session.UserId, "PreferenceUserId": preference.UserId}))
- c.Err.StatusCode = http.StatusForbidden
- return
- }
- }
-
- if result := <-app.Srv.Store.Preference().Save(&preferences); result.Err != nil {
- c.Err = result.Err
+ if err := app.UpdatePreferences(c.Session.UserId, preferences); err != nil {
+ c.Err = err
return
}
@@ -92,20 +82,9 @@ func deletePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- for _, preference := range preferences {
- if c.Session.UserId != preference.UserId {
- c.Err = model.NewLocAppError("deletePreferences", "api.preference.delete_preferences.user_id.app_error",
- nil, "session.user_id="+c.Session.UserId+",preference.user_id="+preference.UserId)
- c.Err.StatusCode = http.StatusForbidden
- return
- }
- }
-
- for _, preference := range preferences {
- if result := <-app.Srv.Store.Preference().Delete(c.Session.UserId, preference.Category, preference.Name); result.Err != nil {
- c.Err = result.Err
- return
- }
+ if err := app.DeletePreferences(c.Session.UserId, preferences); err != nil {
+ c.Err = err
+ return
}
ReturnStatusOK(w)
diff --git a/api4/api.go b/api4/api.go
index 18e1e4022..8d03d91d1 100644
--- a/api4/api.go
+++ b/api4/api.go
@@ -76,7 +76,7 @@ type Routes struct {
System *mux.Router // 'api/v4/system'
- Preferences *mux.Router // 'api/v4/preferences'
+ Preferences *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/preferences'
License *mux.Router // 'api/v4/license'
diff --git a/api4/preference.go b/api4/preference.go
index f9a5bfba6..371f8054b 100644
--- a/api4/preference.go
+++ b/api4/preference.go
@@ -99,17 +99,7 @@ func updatePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- for _, preference := range preferences {
- if c.Params.UserId != preference.UserId {
- c.Err = model.NewAppError("savePreferences", "api.preference.update_preferences.set.app_error", nil,
- c.T("api.preference.update_preferences.set_details.app_error",
- map[string]interface{}{"SessionUserId": c.Params.UserId, "PreferenceUserId": preference.UserId}),
- http.StatusForbidden)
- return
- }
- }
-
- if _, err := app.UpdatePreferences(preferences); err != nil {
+ if err := app.UpdatePreferences(c.Params.UserId, preferences); err != nil {
c.Err = err
return
}
@@ -134,17 +124,7 @@ func deletePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- for _, preference := range preferences {
- if c.Params.UserId != preference.UserId {
- c.Err = model.NewAppError("deletePreferences", "api.preference.delete_preferences.delete.app_error", nil,
- c.T("api.preference.delete_preferences.delete.app_error",
- map[string]interface{}{"SessionUserId": c.Params.UserId, "PreferenceUserId": preference.UserId}),
- http.StatusForbidden)
- return
- }
- }
-
- if _, err := app.DeletePreferences(c.Params.UserId, preferences); err != nil {
+ if err := app.DeletePreferences(c.Params.UserId, preferences); err != nil {
c.Err = err
return
}
diff --git a/api4/preference_test.go b/api4/preference_test.go
index 6efc96ff3..ecf3acbd7 100644
--- a/api4/preference_test.go
+++ b/api4/preference_test.go
@@ -4,8 +4,11 @@
package api4
import (
- "github.com/mattermost/platform/model"
+ "strings"
"testing"
+ "time"
+
+ "github.com/mattermost/platform/model"
)
func TestGetPreferences(t *testing.T) {
@@ -239,6 +242,61 @@ func TestUpdatePreferences(t *testing.T) {
CheckUnauthorizedStatus(t, resp)
}
+func TestUpdatePreferencesWebsocket(t *testing.T) {
+ th := Setup().InitBasic()
+
+ WebSocketClient, err := th.CreateWebSocketClient()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ WebSocketClient.Listen()
+
+ userId := th.BasicUser.Id
+ preferences := &model.Preferences{
+ {
+ UserId: userId,
+ Category: model.NewId(),
+ Name: model.NewId(),
+ },
+ {
+ UserId: userId,
+ Category: model.NewId(),
+ Name: model.NewId(),
+ },
+ }
+ _, resp := th.Client.UpdatePreferences(userId, preferences)
+ CheckNoError(t, resp)
+
+ timeout := time.After(300 * time.Millisecond)
+
+ waiting := true
+ for waiting {
+ select {
+ case event := <-WebSocketClient.EventChannel:
+ if event.Event != model.WEBSOCKET_EVENT_PREFERENCES_CHANGED {
+ // Ignore any other events
+ continue
+ }
+
+ received, err := model.PreferencesFromJson(strings.NewReader(event.Data["preferences"].(string)))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i, preference := range *preferences {
+ if preference.UserId != received[i].UserId || preference.Category != received[i].Category || preference.Name != received[i].Name {
+ t.Fatal("received incorrect preference")
+ }
+ }
+
+ waiting = false
+ case <-timeout:
+ t.Fatal("timed out waiting for preference update event")
+ }
+ }
+}
+
func TestDeletePreferences(t *testing.T) {
th := Setup().InitBasic()
defer TearDown()
@@ -285,3 +343,61 @@ func TestDeletePreferences(t *testing.T) {
_, resp = Client.DeletePreferences(th.BasicUser.Id, &preferences)
CheckUnauthorizedStatus(t, resp)
}
+
+func TestDeletePreferencesWebsocket(t *testing.T) {
+ th := Setup().InitBasic()
+
+ userId := th.BasicUser.Id
+ preferences := &model.Preferences{
+ {
+ UserId: userId,
+ Category: model.NewId(),
+ Name: model.NewId(),
+ },
+ {
+ UserId: userId,
+ Category: model.NewId(),
+ Name: model.NewId(),
+ },
+ }
+ _, resp := th.Client.UpdatePreferences(userId, preferences)
+ CheckNoError(t, resp)
+
+ WebSocketClient, err := th.CreateWebSocketClient()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ WebSocketClient.Listen()
+
+ _, resp = th.Client.DeletePreferences(userId, preferences)
+ CheckNoError(t, resp)
+
+ timeout := time.After(30000 * time.Millisecond)
+
+ waiting := true
+ for waiting {
+ select {
+ case event := <-WebSocketClient.EventChannel:
+ if event.Event != model.WEBSOCKET_EVENT_PREFERENCES_DELETED {
+ // Ignore any other events
+ continue
+ }
+
+ received, err := model.PreferencesFromJson(strings.NewReader(event.Data["preferences"].(string)))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i, preference := range *preferences {
+ if preference.UserId != received[i].UserId || preference.Category != received[i].Category || preference.Name != received[i].Name {
+ t.Fatal("received incorrect preference")
+ }
+ }
+
+ waiting = false
+ case <-timeout:
+ t.Fatal("timed out waiting for preference delete event")
+ }
+ }
+}
diff --git a/app/preference.go b/app/preference.go
index 793f1802b..425b88d29 100644
--- a/app/preference.go
+++ b/app/preference.go
@@ -39,22 +39,45 @@ func GetPreferenceByCategoryAndNameForUser(userId string, category string, prefe
}
}
-func UpdatePreferences(preferences model.Preferences) (bool, *model.AppError) {
+func UpdatePreferences(userId string, preferences model.Preferences) *model.AppError {
+ for _, preference := range preferences {
+ if userId != preference.UserId {
+ return model.NewAppError("savePreferences", "api.preference.update_preferences.set.app_error", nil,
+ "userId="+userId+", preference.UserId="+preference.UserId, http.StatusForbidden)
+ }
+ }
+
if result := <-Srv.Store.Preference().Save(&preferences); result.Err != nil {
result.Err.StatusCode = http.StatusBadRequest
- return false, result.Err
+ return result.Err
}
- return true, nil
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCES_CHANGED, "", "", userId, nil)
+ message.Add("preferences", preferences.ToJson())
+ go Publish(message)
+
+ return nil
}
-func DeletePreferences(userId string, preferences model.Preferences) (bool, *model.AppError) {
+func DeletePreferences(userId string, preferences model.Preferences) *model.AppError {
+ for _, preference := range preferences {
+ if userId != preference.UserId {
+ err := model.NewAppError("deletePreferences", "api.preference.delete_preferences.delete.app_error", nil,
+ "userId="+userId+", preference.UserId="+preference.UserId, http.StatusForbidden)
+ return err
+ }
+ }
+
for _, preference := range preferences {
if result := <-Srv.Store.Preference().Delete(userId, preference.Category, preference.Name); result.Err != nil {
result.Err.StatusCode = http.StatusBadRequest
- return false, result.Err
+ return result.Err
}
}
- return true, nil
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCES_DELETED, "", "", userId, nil)
+ message.Add("preferences", preferences.ToJson())
+ go Publish(message)
+
+ return nil
}
diff --git a/i18n/en.json b/i18n/en.json
index 731679b8a..07895025c 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1688,10 +1688,6 @@
"translation": "Unable to set preferences for other user"
},
{
- "id": "api.preference.save_preferences.set_details.app_error",
- "translation": "session.user_id={{.SessionUserId}}, preference.user_id={{.PreferenceUserId}}"
- },
- {
"id": "api.reaction.delete_reaction.mismatched_channel_id.app_error",
"translation": "Failed to delete reaction because channel ID does not match post ID in the URL"
},
diff --git a/model/websocket_message.go b/model/websocket_message.go
index 0ed056cfe..23977eec5 100644
--- a/model/websocket_message.go
+++ b/model/websocket_message.go
@@ -9,29 +9,31 @@ import (
)
const (
- WEBSOCKET_EVENT_TYPING = "typing"
- WEBSOCKET_EVENT_POSTED = "posted"
- WEBSOCKET_EVENT_POST_EDITED = "post_edited"
- WEBSOCKET_EVENT_POST_DELETED = "post_deleted"
- WEBSOCKET_EVENT_CHANNEL_DELETED = "channel_deleted"
- WEBSOCKET_EVENT_CHANNEL_CREATED = "channel_created"
- WEBSOCKET_EVENT_DIRECT_ADDED = "direct_added"
- WEBSOCKET_EVENT_GROUP_ADDED = "group_added"
- WEBSOCKET_EVENT_NEW_USER = "new_user"
- WEBSOCKET_EVENT_ADDED_TO_TEAM = "added_to_team"
- WEBSOCKET_EVENT_LEAVE_TEAM = "leave_team"
- WEBSOCKET_EVENT_UPDATE_TEAM = "update_team"
- WEBSOCKET_EVENT_USER_ADDED = "user_added"
- WEBSOCKET_EVENT_USER_UPDATED = "user_updated"
- WEBSOCKET_EVENT_USER_REMOVED = "user_removed"
- WEBSOCKET_EVENT_PREFERENCE_CHANGED = "preference_changed"
- WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message"
- WEBSOCKET_EVENT_STATUS_CHANGE = "status_change"
- WEBSOCKET_EVENT_HELLO = "hello"
- WEBSOCKET_EVENT_WEBRTC = "webrtc"
- WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge"
- WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added"
- WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed"
+ WEBSOCKET_EVENT_TYPING = "typing"
+ WEBSOCKET_EVENT_POSTED = "posted"
+ WEBSOCKET_EVENT_POST_EDITED = "post_edited"
+ WEBSOCKET_EVENT_POST_DELETED = "post_deleted"
+ WEBSOCKET_EVENT_CHANNEL_DELETED = "channel_deleted"
+ WEBSOCKET_EVENT_CHANNEL_CREATED = "channel_created"
+ WEBSOCKET_EVENT_DIRECT_ADDED = "direct_added"
+ WEBSOCKET_EVENT_GROUP_ADDED = "group_added"
+ WEBSOCKET_EVENT_NEW_USER = "new_user"
+ WEBSOCKET_EVENT_ADDED_TO_TEAM = "added_to_team"
+ WEBSOCKET_EVENT_LEAVE_TEAM = "leave_team"
+ WEBSOCKET_EVENT_UPDATE_TEAM = "update_team"
+ WEBSOCKET_EVENT_USER_ADDED = "user_added"
+ WEBSOCKET_EVENT_USER_UPDATED = "user_updated"
+ WEBSOCKET_EVENT_USER_REMOVED = "user_removed"
+ WEBSOCKET_EVENT_PREFERENCE_CHANGED = "preference_changed"
+ WEBSOCKET_EVENT_PREFERENCES_CHANGED = "preferences_changed"
+ WEBSOCKET_EVENT_PREFERENCES_DELETED = "preferences_deleted"
+ WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message"
+ WEBSOCKET_EVENT_STATUS_CHANGE = "status_change"
+ WEBSOCKET_EVENT_HELLO = "hello"
+ WEBSOCKET_EVENT_WEBRTC = "webrtc"
+ WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge"
+ WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added"
+ WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed"
)
type WebSocketMessage interface {