diff --git a/api4/api.go b/api4/api.go index d5a9c3aa5f..f033824adb 100644 --- a/api4/api.go +++ b/api4/api.go @@ -131,6 +131,8 @@ type Routes struct { RemoteCluster *mux.Router // 'api/v4/remotecluster' SharedChannels *mux.Router // 'api/v4/sharedchannels' + + Permissions *mux.Router // 'api/v4/permissions' } type API struct { @@ -250,6 +252,8 @@ func Init(configservice configservice.ConfigService, globalOptionsFunc app.AppOp api.BaseRoutes.RemoteCluster = api.BaseRoutes.ApiRoot.PathPrefix("/remotecluster").Subrouter() api.BaseRoutes.SharedChannels = api.BaseRoutes.ApiRoot.PathPrefix("/sharedchannels").Subrouter() + api.BaseRoutes.Permissions = api.BaseRoutes.ApiRoot.PathPrefix("/permissions").Subrouter() + api.InitUser() api.InitBot() api.InitTeam() @@ -289,6 +293,7 @@ func Init(configservice configservice.ConfigService, globalOptionsFunc app.AppOp api.InitImport() api.InitRemoteCluster() api.InitSharedChannels() + api.InitPermissions() api.InitExport() root.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404)) diff --git a/api4/permission.go b/api4/permission.go new file mode 100644 index 0000000000..d37a9abae2 --- /dev/null +++ b/api4/permission.go @@ -0,0 +1,33 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package api4 + +import ( + "encoding/json" + "net/http" + "strings" + + "github.com/mattermost/mattermost-server/v5/model" +) + +func (api *API) InitPermissions() { + api.BaseRoutes.Permissions.Handle("/ancillary", api.ApiSessionRequired(appendAncillaryPermissions)).Methods("GET") +} + +func appendAncillaryPermissions(c *Context, w http.ResponseWriter, r *http.Request) { + keys, ok := r.URL.Query()["subsection_permissions"] + + if !ok || len(keys[0]) < 1 { + c.SetInvalidUrlParam("subsection_permissions") + return + } + + permissions := strings.Split(keys[0], ",") + b, err := json.Marshal(model.AddAncillaryPermissions(permissions)) + if err != nil { + c.SetJSONEncodingError() + return + } + w.Write(b) +} diff --git a/api4/permissions_test.go b/api4/permissions_test.go new file mode 100644 index 0000000000..c82c1a1eef --- /dev/null +++ b/api4/permissions_test.go @@ -0,0 +1,42 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package api4 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/mattermost/mattermost-server/v5/model" +) + +func TestGetAncillaryPermissions(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + var subsectionPermissions []string + var expectedAncillaryPermissions []string + t.Run("Valid Case, Passing in SubSection Permissions", func(t *testing.T) { + subsectionPermissions = []string{model.PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS.Id} + expectedAncillaryPermissions = []string{model.PERMISSION_GET_ANALYTICS.Id} + actualAncillaryPermissions, resp := th.Client.GetAncillaryPermissions(subsectionPermissions) + CheckNoError(t, resp) + assert.Equal(t, append(subsectionPermissions, expectedAncillaryPermissions...), actualAncillaryPermissions) + }) + + t.Run("Invalid Case, Passing in SubSection Permissions That Don't Exist", func(t *testing.T) { + subsectionPermissions = []string{"All", "The", "Things", "She", "Said", "Running", "Through", "My", "Head"} + expectedAncillaryPermissions = []string{} + actualAncillaryPermissions, resp := th.Client.GetAncillaryPermissions(subsectionPermissions) + CheckNoError(t, resp) + assert.Equal(t, append(subsectionPermissions, expectedAncillaryPermissions...), actualAncillaryPermissions) + }) + + t.Run("Invalid Case, Passing in nothing", func(t *testing.T) { + subsectionPermissions = []string{} + expectedAncillaryPermissions = []string{} + _, resp := th.Client.GetAncillaryPermissions(subsectionPermissions) + CheckBadRequestStatus(t, resp) + }) +} diff --git a/api4/role.go b/api4/role.go index 8d231c0c0c..4c179a172c 100644 --- a/api4/role.go +++ b/api4/role.go @@ -163,9 +163,6 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { } } - ancillaryPermissions := model.AddAncillaryPermissions(*patch.Permissions) - *patch.Permissions = append(*patch.Permissions, ancillaryPermissions...) - *patch.Permissions = model.UniqueStrings(*patch.Permissions) } diff --git a/model/client4.go b/model/client4.go index 6898f7720a..8f523b1f6c 100644 --- a/model/client4.go +++ b/model/client4.go @@ -573,6 +573,10 @@ func (c *Client4) GetSharedChannelsRoute() string { return "/sharedchannels" } +func (c *Client4) GetPermissionsRoute() string { + return "/permissions" +} + func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) { return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag) } @@ -6312,3 +6316,16 @@ func (c *Client4) GetRemoteClusterInfo(remoteID string) (RemoteClusterInfo, *Res return rci, BuildResponse(r) } + +func (c *Client4) GetAncillaryPermissions(subsectionPermissions []string) ([]string, *Response) { + var returnedPermissions []string + url := fmt.Sprintf("%s/ancillary?subsection_permissions=%s", c.GetPermissionsRoute(), strings.Join(subsectionPermissions, ",")) + r, appErr := c.DoApiGet(url, "") + if appErr != nil { + return returnedPermissions, BuildErrorResponse(r, appErr) + } + defer closeBody(r) + + json.NewDecoder(r.Body).Decode(&returnedPermissions) + return returnedPermissions, BuildResponse(r) +}