From cef5028cbeed93b6493f6d1f379afe4ca85535c8 Mon Sep 17 00:00:00 2001 From: Ruzette Tanyag Date: Tue, 28 Feb 2017 04:14:16 -0500 Subject: Implemented preferences endpoints for apiv4 (#5531) * implemented preferences endpoints for apiv4 * added user id in preferences endpoints --- api4/api.go | 3 +- api4/context.go | 24 ++++ api4/params.go | 38 ++++--- api4/preference.go | 153 ++++++++++++++++++++++++++ api4/preference_test.go | 287 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 490 insertions(+), 15 deletions(-) create mode 100644 api4/preference.go create mode 100644 api4/preference_test.go (limited to 'api4') diff --git a/api4/api.go b/api4/api.go index ca43e7275..c8c0e170b 100644 --- a/api4/api.go +++ b/api4/api.go @@ -130,7 +130,7 @@ func InitApi(full bool) { BaseRoutes.OAuth = BaseRoutes.ApiRoot.PathPrefix("/oauth").Subrouter() BaseRoutes.Admin = BaseRoutes.ApiRoot.PathPrefix("/admin").Subrouter() BaseRoutes.System = BaseRoutes.ApiRoot.PathPrefix("/system").Subrouter() - BaseRoutes.Preferences = BaseRoutes.ApiRoot.PathPrefix("/preferences").Subrouter() + BaseRoutes.Preferences = BaseRoutes.User.PathPrefix("/preferences").Subrouter() BaseRoutes.License = BaseRoutes.ApiRoot.PathPrefix("/license").Subrouter() BaseRoutes.Public = BaseRoutes.ApiRoot.PathPrefix("/public").Subrouter() @@ -146,6 +146,7 @@ func InitApi(full bool) { InitFile() InitSystem() InitWebhook() + InitPreference() app.Srv.Router.Handle("/api/v4/{anything:.*}", http.HandlerFunc(Handle404)) diff --git a/api4/context.go b/api4/context.go index f0d8b0c5c..c30a975f2 100644 --- a/api4/context.go +++ b/api4/context.go @@ -431,3 +431,27 @@ func (c *Context) RequireEmail() *Context { return c } + +func (c *Context) RequireCategory() *Context { + if c.Err != nil { + return c + } + + if !model.IsValidAlphaNum(c.Params.Category, true) { + c.SetInvalidUrlParam("category") + } + + return c +} + +func (c *Context) RequirePreferenceName() *Context { + if c.Err != nil { + return c + } + + if !model.IsValidAlphaNum(c.Params.PreferenceName, true) { + c.SetInvalidUrlParam("preference_name") + } + + return c +} diff --git a/api4/params.go b/api4/params.go index 9b371e71a..b1688a859 100644 --- a/api4/params.go +++ b/api4/params.go @@ -17,20 +17,22 @@ const ( ) type ApiParams struct { - UserId string - TeamId string - ChannelId string - PostId string - FileId string - CommandId string - HookId string - EmojiId string - Email string - Username string - TeamName string - ChannelName string - Page int - PerPage int + UserId string + TeamId string + ChannelId string + PostId string + FileId string + CommandId string + HookId string + EmojiId string + Email string + Username string + TeamName string + ChannelName string + PreferenceName string + Category string + Page int + PerPage int } func ApiParamsFromRequest(r *http.Request) *ApiParams { @@ -86,6 +88,14 @@ func ApiParamsFromRequest(r *http.Request) *ApiParams { params.ChannelName = val } + if val, ok := props["category"]; ok { + params.Category = val + } + + if val, ok := props["preference_name"]; ok { + params.PreferenceName = val + } + if val, err := strconv.Atoi(r.URL.Query().Get("page")); err != nil { params.Page = PAGE_DEFAULT } else { diff --git a/api4/preference.go b/api4/preference.go new file mode 100644 index 000000000..9ba6b85d2 --- /dev/null +++ b/api4/preference.go @@ -0,0 +1,153 @@ +// // Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// // See License.txt for license information. + +package api4 + +import ( + "net/http" + + l4g "github.com/alecthomas/log4go" + "github.com/mattermost/platform/app" + "github.com/mattermost/platform/model" + "github.com/mattermost/platform/utils" +) + +func InitPreference() { + l4g.Debug(utils.T("api.preference.init.debug")) + + BaseRoutes.Preferences.Handle("", ApiSessionRequired(getPreferences)).Methods("GET") + BaseRoutes.Preferences.Handle("", ApiSessionRequired(updatePreferences)).Methods("PUT") + BaseRoutes.Preferences.Handle("/delete", ApiSessionRequired(deletePreferences)).Methods("POST") + BaseRoutes.Preferences.Handle("/{category:[A-Za-z0-9_]+}", ApiSessionRequired(getPreferencesByCategory)).Methods("GET") + BaseRoutes.Preferences.Handle("/{category:[A-Za-z0-9_]+}/name/{preference_name:[A-Za-z0-9_]+}", ApiSessionRequired(getPreferenceByCategoryAndName)).Methods("GET") +} + +func getPreferences(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId() + if c.Err != nil { + return + } + + if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + if preferences, err := app.GetPreferencesForUser(c.Params.UserId); err != nil { + c.Err = err + return + } else { + w.Write([]byte(preferences.ToJson())) + return + } +} + +func getPreferencesByCategory(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId().RequireCategory() + if c.Err != nil { + return + } + + if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + if preferences, err := app.GetPreferenceByCategoryForUser(c.Params.UserId, c.Params.Category); err != nil { + c.Err = err + return + } else { + w.Write([]byte(preferences.ToJson())) + return + } +} + +func getPreferenceByCategoryAndName(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId().RequireCategory().RequirePreferenceName() + if c.Err != nil { + return + } + + if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + if preferences, err := app.GetPreferenceByCategoryAndNameForUser(c.Params.UserId, c.Params.Category, c.Params.PreferenceName); err != nil { + c.Err = err + return + } else { + w.Write([]byte(preferences.ToJson())) + return + } +} + +func updatePreferences(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId() + if c.Err != nil { + return + } + + if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + preferences, err := model.PreferencesFromJson(r.Body) + if err != nil { + c.SetInvalidParam("preferences") + 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 { + c.Err = err + return + } + + ReturnStatusOK(w) +} + +func deletePreferences(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId() + if c.Err != nil { + return + } + + if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + preferences, err := model.PreferencesFromJson(r.Body) + if err != nil { + c.SetInvalidParam("preferences") + 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 { + c.Err = err + return + } + + ReturnStatusOK(w) +} diff --git a/api4/preference_test.go b/api4/preference_test.go new file mode 100644 index 000000000..02df99b9b --- /dev/null +++ b/api4/preference_test.go @@ -0,0 +1,287 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api4 + +import ( + "github.com/mattermost/platform/model" + "testing" +) + +func TestGetPreferences(t *testing.T) { + th := Setup().InitBasic() + defer TearDown() + Client := th.Client + + th.LoginBasic() + user1 := th.BasicUser + + category := model.NewId() + preferences1 := model.Preferences{ + { + UserId: user1.Id, + Category: category, + Name: model.NewId(), + }, + { + UserId: user1.Id, + Category: category, + Name: model.NewId(), + }, + { + UserId: user1.Id, + Category: model.NewId(), + Name: model.NewId(), + }, + } + + Client.UpdatePreferences(user1.Id, &preferences1) + + prefs, resp := Client.GetPreferences(user1.Id) + CheckNoError(t, resp) + if len(prefs) != 4 { + t.Fatal("received the wrong number of preferences") + } + + for _, preference := range prefs { + if preference.UserId != th.BasicUser.Id { + t.Fatal("user id does not match") + } + } + + th.LoginBasic2() + + prefs, resp = Client.GetPreferences(th.BasicUser2.Id) + CheckNoError(t, resp) + + if len(prefs) == 0 { + t.Fatal("received the wrong number of preferences") + } + + _, resp = Client.GetPreferences(th.BasicUser.Id) + CheckForbiddenStatus(t, resp) + + Client.Logout() + _, resp = Client.GetPreferences(th.BasicUser2.Id) + CheckUnauthorizedStatus(t, resp) +} + +func TestGetPreferencesByCategory(t *testing.T) { + th := Setup().InitBasic() + defer TearDown() + Client := th.Client + + th.LoginBasic() + user1 := th.BasicUser + + category := model.NewId() + preferences1 := model.Preferences{ + { + UserId: user1.Id, + Category: category, + Name: model.NewId(), + }, + { + UserId: user1.Id, + Category: category, + Name: model.NewId(), + }, + { + UserId: user1.Id, + Category: model.NewId(), + Name: model.NewId(), + }, + } + + Client.UpdatePreferences(user1.Id, &preferences1) + + prefs, resp := Client.GetPreferencesByCategory(user1.Id, category) + CheckNoError(t, resp) + + if len(prefs) != 2 { + t.Fatalf("received the wrong number of preferences %v:%v", len(prefs), 2) + } + + prefs, resp = Client.GetPreferencesByCategory(user1.Id, "junk") + CheckNotFoundStatus(t, resp) + + th.LoginBasic2() + + prefs, resp = Client.GetPreferencesByCategory(th.BasicUser2.Id, category) + CheckNotFoundStatus(t, resp) + + prefs, resp = Client.GetPreferencesByCategory(user1.Id, category) + CheckForbiddenStatus(t, resp) + + prefs, resp = Client.GetPreferencesByCategory(th.BasicUser2.Id, "junk") + CheckNotFoundStatus(t, resp) + + if len(prefs) != 0 { + t.Fatal("received the wrong number of preferences") + } + + Client.Logout() + _, resp = Client.GetPreferencesByCategory(th.BasicUser2.Id, category) + CheckUnauthorizedStatus(t, resp) +} + +func TestGetPreferenceByCategoryAndName(t *testing.T) { + th := Setup().InitBasic() + defer TearDown() + Client := th.Client + + th.LoginBasic() + user := th.BasicUser + name := model.NewId() + value := model.NewId() + + preferences := model.Preferences{ + { + UserId: user.Id, + Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, + Name: name, + Value: value, + }, + { + UserId: user.Id, + Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, + Name: model.NewId(), + Value: model.NewId(), + }, + } + + Client.UpdatePreferences(user.Id, &preferences) + + pref, resp := Client.GetPreferenceByCategoryAndName(user.Id, model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, name) + CheckNoError(t, resp) + + if (pref.UserId != preferences[0].UserId) && (pref.Category != preferences[0].Category) && (pref.Name != preferences[0].Name) { + t.Fatal("preference saved incorrectly") + } + + preferences[0].Value = model.NewId() + Client.UpdatePreferences(user.Id, &preferences) + + _, resp = Client.GetPreferenceByCategoryAndName(user.Id, "junk", preferences[0].Name) + CheckBadRequestStatus(t, resp) + + _, resp = Client.GetPreferenceByCategoryAndName(user.Id, preferences[0].Category, "junk") + CheckBadRequestStatus(t, resp) + + _, resp = Client.GetPreferenceByCategoryAndName(th.BasicUser2.Id, preferences[0].Category, "junk") + CheckForbiddenStatus(t, resp) + + _, resp = Client.GetPreferenceByCategoryAndName(user.Id, preferences[0].Category, preferences[0].Name) + CheckNoError(t, resp) + + Client.Logout() + _, resp = Client.GetPreferenceByCategoryAndName(user.Id, preferences[0].Category, preferences[0].Name) + CheckUnauthorizedStatus(t, resp) + +} + +func TestUpdatePreferences(t *testing.T) { + th := Setup().InitBasic() + defer TearDown() + Client := th.Client + + th.LoginBasic() + user1 := th.BasicUser + + category := model.NewId() + preferences1 := model.Preferences{ + { + UserId: user1.Id, + Category: category, + Name: model.NewId(), + }, + { + UserId: user1.Id, + Category: category, + Name: model.NewId(), + }, + { + UserId: user1.Id, + Category: model.NewId(), + Name: model.NewId(), + }, + } + + _, resp := Client.UpdatePreferences(user1.Id, &preferences1) + CheckNoError(t, resp) + + preferences := model.Preferences{ + { + UserId: model.NewId(), + Category: category, + Name: model.NewId(), + }, + } + + _, resp = Client.UpdatePreferences(user1.Id, &preferences) + CheckForbiddenStatus(t, resp) + + preferences = model.Preferences{ + { + UserId: user1.Id, + Name: model.NewId(), + }, + } + + _, resp = Client.UpdatePreferences(user1.Id, &preferences) + CheckBadRequestStatus(t, resp) + + _, resp = Client.UpdatePreferences(th.BasicUser2.Id, &preferences) + CheckForbiddenStatus(t, resp) + + Client.Logout() + _, resp = Client.UpdatePreferences(user1.Id, &preferences1) + CheckUnauthorizedStatus(t, resp) +} + +func TestDeletePreferences(t *testing.T) { + th := Setup().InitBasic() + defer TearDown() + Client := th.Client + + th.LoginBasic() + + prefs, resp := Client.GetPreferences(th.BasicUser.Id) + originalCount := len(prefs) + + // save 10 preferences + var preferences model.Preferences + for i := 0; i < 10; i++ { + preference := model.Preference{ + UserId: th.BasicUser.Id, + Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, + Name: model.NewId(), + } + preferences = append(preferences, preference) + } + + Client.UpdatePreferences(th.BasicUser.Id, &preferences) + + // delete 10 preferences + th.LoginBasic2() + + _, resp = Client.DeletePreferences(th.BasicUser2.Id, &preferences) + CheckForbiddenStatus(t, resp) + + th.LoginBasic() + + _, resp = Client.DeletePreferences(th.BasicUser.Id, &preferences) + CheckNoError(t, resp) + + _, resp = Client.DeletePreferences(th.BasicUser2.Id, &preferences) + CheckForbiddenStatus(t, resp) + + prefs, resp = Client.GetPreferences(th.BasicUser.Id) + if len(prefs) != originalCount { + t.Fatal("should've deleted preferences") + } + + Client.Logout() + _, resp = Client.DeletePreferences(th.BasicUser.Id, &preferences) + CheckUnauthorizedStatus(t, resp) +} -- cgit v1.2.3-1-g7c22