diff options
-rw-r--r-- | api/preference.go | 31 | ||||
-rw-r--r-- | api4/api.go | 2 | ||||
-rw-r--r-- | api4/preference.go | 24 | ||||
-rw-r--r-- | api4/preference_test.go | 118 | ||||
-rw-r--r-- | app/preference.go | 35 | ||||
-rw-r--r-- | i18n/en.json | 4 | ||||
-rw-r--r-- | model/websocket_message.go | 48 |
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 { |