summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api4/channel.go26
-rw-r--r--api4/channel_test.go76
-rw-r--r--api4/team.go27
-rw-r--r--api4/team_test.go75
-rw-r--r--app/channel.go24
-rw-r--r--app/role.go24
-rw-r--r--app/team.go27
-rw-r--r--model/client4.go20
-rw-r--r--model/scheme.go16
9 files changed, 312 insertions, 3 deletions
diff --git a/api4/channel.go b/api4/channel.go
index e5101ada8..b2c920ddb 100644
--- a/api4/channel.go
+++ b/api4/channel.go
@@ -45,6 +45,7 @@ func (api *API) InitChannel() {
api.BaseRoutes.ChannelMember.Handle("", api.ApiSessionRequired(getChannelMember)).Methods("GET")
api.BaseRoutes.ChannelMember.Handle("", api.ApiSessionRequired(removeChannelMember)).Methods("DELETE")
api.BaseRoutes.ChannelMember.Handle("/roles", api.ApiSessionRequired(updateChannelMemberRoles)).Methods("PUT")
+ api.BaseRoutes.ChannelMember.Handle("/schemeRoles", api.ApiSessionRequired(updateChannelMemberSchemeRoles)).Methods("PUT")
api.BaseRoutes.ChannelMember.Handle("/notify_props", api.ApiSessionRequired(updateChannelMemberNotifyProps)).Methods("PUT")
}
@@ -811,6 +812,31 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request
ReturnStatusOK(w)
}
+func updateChannelMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireChannelId().RequireUserId()
+ if c.Err != nil {
+ return
+ }
+
+ schemeRoles := model.SchemeRolesFromJson(r.Body)
+ if schemeRoles == nil {
+ c.SetInvalidParam("scheme_roles")
+ return
+ }
+
+ if !c.App.SessionHasPermissionToChannel(c.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_CHANNEL_ROLES) {
+ c.SetPermissionError(model.PERMISSION_MANAGE_CHANNEL_ROLES)
+ return
+ }
+
+ if _, err := c.App.UpdateChannelMemberSchemeRoles(c.Params.ChannelId, c.Params.UserId, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil {
+ c.Err = err
+ return
+ }
+
+ ReturnStatusOK(w)
+}
+
func updateChannelMemberNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireChannelId().RequireUserId()
if c.Err != nil {
diff --git a/api4/channel_test.go b/api4/channel_test.go
index 7b677f77f..d66c2a640 100644
--- a/api4/channel_test.go
+++ b/api4/channel_test.go
@@ -15,6 +15,7 @@ import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
+ "github.com/stretchr/testify/assert"
)
func TestCreateChannel(t *testing.T) {
@@ -1537,6 +1538,81 @@ func TestUpdateChannelRoles(t *testing.T) {
CheckForbiddenStatus(t, resp)
}
+func TestUpdateChannelMemberSchemeRoles(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer th.TearDown()
+ SystemAdminClient := th.SystemAdminClient
+ th.LoginBasic()
+
+ s1 := &model.SchemeRoles{
+ SchemeAdmin: false,
+ SchemeUser: false,
+ }
+ _, r1 := SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.BasicUser.Id, s1)
+ CheckNoError(t, r1)
+
+ tm1, rtm1 := SystemAdminClient.GetChannelMember(th.BasicChannel.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm1)
+ assert.Equal(t, false, tm1.SchemeUser)
+ assert.Equal(t, false, tm1.SchemeAdmin)
+
+ s2 := &model.SchemeRoles{
+ SchemeAdmin: false,
+ SchemeUser: true,
+ }
+ _, r2 := SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.BasicUser.Id, s2)
+ CheckNoError(t, r2)
+
+ tm2, rtm2 := SystemAdminClient.GetChannelMember(th.BasicChannel.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm2)
+ assert.Equal(t, true, tm2.SchemeUser)
+ assert.Equal(t, false, tm2.SchemeAdmin)
+
+ s3 := &model.SchemeRoles{
+ SchemeAdmin: true,
+ SchemeUser: false,
+ }
+ _, r3 := SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.BasicUser.Id, s3)
+ CheckNoError(t, r3)
+
+ tm3, rtm3 := SystemAdminClient.GetChannelMember(th.BasicChannel.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm3)
+ assert.Equal(t, false, tm3.SchemeUser)
+ assert.Equal(t, true, tm3.SchemeAdmin)
+
+ s4 := &model.SchemeRoles{
+ SchemeAdmin: true,
+ SchemeUser: true,
+ }
+ _, r4 := SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.BasicUser.Id, s4)
+ CheckNoError(t, r4)
+
+ tm4, rtm4 := SystemAdminClient.GetChannelMember(th.BasicChannel.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm4)
+ assert.Equal(t, true, tm4.SchemeUser)
+ assert.Equal(t, true, tm4.SchemeAdmin)
+
+ _, resp := SystemAdminClient.UpdateChannelMemberSchemeRoles(model.NewId(), th.BasicUser.Id, s4)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, model.NewId(), s4)
+ CheckNotFoundStatus(t, resp)
+
+ _, resp = SystemAdminClient.UpdateChannelMemberSchemeRoles("ASDF", th.BasicUser.Id, s4)
+ CheckBadRequestStatus(t, resp)
+
+ _, resp = SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, "ASDF", s4)
+ CheckBadRequestStatus(t, resp)
+
+ th.LoginBasic2()
+ _, resp = th.Client.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.BasicUser.Id, s4)
+ CheckForbiddenStatus(t, resp)
+
+ SystemAdminClient.Logout()
+ _, resp = SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.SystemAdminUser.Id, s4)
+ CheckUnauthorizedStatus(t, resp)
+}
+
func TestUpdateChannelNotifyProps(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
diff --git a/api4/team.go b/api4/team.go
index 74b385122..adb8ae355 100644
--- a/api4/team.go
+++ b/api4/team.go
@@ -49,7 +49,7 @@ func (api *API) InitTeam() {
api.BaseRoutes.TeamMember.Handle("", api.ApiSessionRequired(getTeamMember)).Methods("GET")
api.BaseRoutes.TeamByName.Handle("/exists", api.ApiSessionRequired(teamExists)).Methods("GET")
api.BaseRoutes.TeamMember.Handle("/roles", api.ApiSessionRequired(updateTeamMemberRoles)).Methods("PUT")
-
+ api.BaseRoutes.TeamMember.Handle("/schemeRoles", api.ApiSessionRequired(updateTeamMemberSchemeRoles)).Methods("PUT")
api.BaseRoutes.Team.Handle("/import", api.ApiSessionRequired(importTeam)).Methods("POST")
api.BaseRoutes.Team.Handle("/invite/email", api.ApiSessionRequired(inviteUsersToTeam)).Methods("POST")
api.BaseRoutes.Teams.Handle("/invite/{invite_id:[A-Za-z0-9]+}", api.ApiHandler(getInviteInfo)).Methods("GET")
@@ -539,6 +539,31 @@ func updateTeamMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
ReturnStatusOK(w)
}
+func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireTeamId().RequireUserId()
+ if c.Err != nil {
+ return
+ }
+
+ schemeRoles := model.SchemeRolesFromJson(r.Body)
+ if schemeRoles == nil {
+ c.SetInvalidParam("scheme_roles")
+ return
+ }
+
+ if !c.App.SessionHasPermissionToTeam(c.Session, c.Params.TeamId, model.PERMISSION_MANAGE_TEAM_ROLES) {
+ c.SetPermissionError(model.PERMISSION_MANAGE_TEAM_ROLES)
+ return
+ }
+
+ if _, err := c.App.UpdateTeamMemberSchemeRoles(c.Params.TeamId, c.Params.UserId, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil {
+ c.Err = err
+ return
+ }
+
+ ReturnStatusOK(w)
+}
+
func getAllTeams(c *Context, w http.ResponseWriter, r *http.Request) {
var teams []*model.Team
var err *model.AppError
diff --git a/api4/team_test.go b/api4/team_test.go
index 079ba37ec..48e3404eb 100644
--- a/api4/team_test.go
+++ b/api4/team_test.go
@@ -1712,6 +1712,81 @@ func TestUpdateTeamMemberRoles(t *testing.T) {
CheckNoError(t, resp)
}
+func TestUpdateTeamMemberSchemeRoles(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer th.TearDown()
+ SystemAdminClient := th.SystemAdminClient
+ th.LoginBasic()
+
+ s1 := &model.SchemeRoles{
+ SchemeAdmin: false,
+ SchemeUser: false,
+ }
+ _, r1 := SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.BasicUser.Id, s1)
+ CheckNoError(t, r1)
+
+ tm1, rtm1 := SystemAdminClient.GetTeamMember(th.BasicTeam.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm1)
+ assert.Equal(t, false, tm1.SchemeUser)
+ assert.Equal(t, false, tm1.SchemeAdmin)
+
+ s2 := &model.SchemeRoles{
+ SchemeAdmin: false,
+ SchemeUser: true,
+ }
+ _, r2 := SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.BasicUser.Id, s2)
+ CheckNoError(t, r2)
+
+ tm2, rtm2 := SystemAdminClient.GetTeamMember(th.BasicTeam.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm2)
+ assert.Equal(t, true, tm2.SchemeUser)
+ assert.Equal(t, false, tm2.SchemeAdmin)
+
+ s3 := &model.SchemeRoles{
+ SchemeAdmin: true,
+ SchemeUser: false,
+ }
+ _, r3 := SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.BasicUser.Id, s3)
+ CheckNoError(t, r3)
+
+ tm3, rtm3 := SystemAdminClient.GetTeamMember(th.BasicTeam.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm3)
+ assert.Equal(t, false, tm3.SchemeUser)
+ assert.Equal(t, true, tm3.SchemeAdmin)
+
+ s4 := &model.SchemeRoles{
+ SchemeAdmin: true,
+ SchemeUser: true,
+ }
+ _, r4 := SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.BasicUser.Id, s4)
+ CheckNoError(t, r4)
+
+ tm4, rtm4 := SystemAdminClient.GetTeamMember(th.BasicTeam.Id, th.BasicUser.Id, "")
+ CheckNoError(t, rtm4)
+ assert.Equal(t, true, tm4.SchemeUser)
+ assert.Equal(t, true, tm4.SchemeAdmin)
+
+ _, resp := SystemAdminClient.UpdateTeamMemberSchemeRoles(model.NewId(), th.BasicUser.Id, s4)
+ CheckNotFoundStatus(t, resp)
+
+ _, resp = SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, model.NewId(), s4)
+ CheckNotFoundStatus(t, resp)
+
+ _, resp = SystemAdminClient.UpdateTeamMemberSchemeRoles("ASDF", th.BasicUser.Id, s4)
+ CheckBadRequestStatus(t, resp)
+
+ _, resp = SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, "ASDF", s4)
+ CheckBadRequestStatus(t, resp)
+
+ th.LoginBasic2()
+ _, resp = th.Client.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.BasicUser.Id, s4)
+ CheckForbiddenStatus(t, resp)
+
+ SystemAdminClient.Logout()
+ _, resp = SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.SystemAdminUser.Id, s4)
+ CheckUnauthorizedStatus(t, resp)
+}
+
func TestGetMyTeamsUnread(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown()
diff --git a/app/channel.go b/app/channel.go
index 55a5008d4..7637e9d21 100644
--- a/app/channel.go
+++ b/app/channel.go
@@ -540,6 +540,30 @@ func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles
return member, nil
}
+func (a *App) UpdateChannelMemberSchemeRoles(channelId string, userId string, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError) {
+ member, err := a.GetChannelMember(channelId, userId)
+ if err != nil {
+ return nil, err
+ }
+
+ member.SchemeAdmin = isSchemeAdmin
+ member.SchemeUser = isSchemeUser
+
+ // If the migration is not completed, we also need to check the default channel_admin/channel_user roles are not present in the roles field.
+ if err = a.IsPhase2MigrationCompleted(); err != nil {
+ member.ExplicitRoles = RemoveRoles([]string{model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID}, member.ExplicitRoles)
+ }
+
+ if result := <-a.Srv.Store.Channel().UpdateMember(member); result.Err != nil {
+ return nil, result.Err
+ } else {
+ member = result.Data.(*model.ChannelMember)
+ }
+
+ a.InvalidateCacheForUser(userId)
+ return member, nil
+}
+
func (a *App) UpdateChannelMemberNotifyProps(data map[string]string, channelId string, userId string) (*model.ChannelMember, *model.AppError) {
var member *model.ChannelMember
var err *model.AppError
diff --git a/app/role.go b/app/role.go
index c9278e0bd..72cf43fe7 100644
--- a/app/role.go
+++ b/app/role.go
@@ -4,9 +4,9 @@
package app
import (
- "reflect"
-
"net/http"
+ "reflect"
+ "strings"
"github.com/mattermost/mattermost-server/model"
)
@@ -90,3 +90,23 @@ func (a *App) sendUpdatedRoleEvent(role *model.Role) {
a.Publish(message)
})
}
+
+func RemoveRoles(rolesToRemove []string, roles string) string {
+ roleList := strings.Fields(roles)
+ newRoles := make([]string, 0)
+
+ for _, role := range roleList {
+ shouldRemove := false
+ for _, roleToRemove := range rolesToRemove {
+ if role == roleToRemove {
+ shouldRemove = true
+ break
+ }
+ }
+ if !shouldRemove {
+ newRoles = append(newRoles, role)
+ }
+ }
+
+ return strings.Join(newRoles, " ")
+}
diff --git a/app/team.go b/app/team.go
index 2833e2eed..d6245b6df 100644
--- a/app/team.go
+++ b/app/team.go
@@ -237,6 +237,33 @@ func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles strin
return member, nil
}
+func (a *App) UpdateTeamMemberSchemeRoles(teamId string, userId string, isSchemeUser bool, isSchemeAdmin bool) (*model.TeamMember, *model.AppError) {
+ member, err := a.GetTeamMember(teamId, userId)
+ if err != nil {
+ return nil, err
+ }
+
+ member.SchemeAdmin = isSchemeAdmin
+ member.SchemeUser = isSchemeUser
+
+ // If the migration is not completed, we also need to check the default team_admin/team_user roles are not present in the roles field.
+ if err = a.IsPhase2MigrationCompleted(); err != nil {
+ member.ExplicitRoles = RemoveRoles([]string{model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID}, member.ExplicitRoles)
+ }
+
+ if result := <-a.Srv.Store.Team().UpdateMember(member); result.Err != nil {
+ return nil, result.Err
+ } else {
+ member = result.Data.(*model.TeamMember)
+ }
+
+ a.ClearSessionCacheForUser(userId)
+
+ a.sendUpdatedMemberRoleEvent(userId, member)
+
+ return member, nil
+}
+
func (a *App) sendUpdatedMemberRoleEvent(userId string, member *model.TeamMember) {
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", userId, nil)
message.Add("member", member.ToJson())
diff --git a/model/client4.go b/model/client4.go
index c2b6ba948..fb4d1375c 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -1320,6 +1320,16 @@ func (c *Client4) UpdateTeamMemberRoles(teamId, userId, newRoles string) (bool,
}
}
+// UpdateTeamMemberSchemeRoles will update the scheme-derived roles on a team for a user.
+func (c *Client4) UpdateTeamMemberSchemeRoles(teamId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) {
+ if r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/schemeRoles", schemeRoles.ToJson()); err != nil {
+ return false, BuildErrorResponse(r, err)
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
// UpdateTeam will update a team.
func (c *Client4) UpdateTeam(team *Team) (*Team, *Response) {
if r, err := c.DoApiPut(c.GetTeamRoute(team.Id), team.ToJson()); err != nil {
@@ -1849,6 +1859,16 @@ func (c *Client4) UpdateChannelRoles(channelId, userId, roles string) (bool, *Re
}
}
+// UpdateChannelMemberSchemeRoles will update the scheme-derived roles on a channel for a user.
+func (c *Client4) UpdateChannelMemberSchemeRoles(channelId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) {
+ if r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/schemeRoles", schemeRoles.ToJson()); err != nil {
+ return false, BuildErrorResponse(r, err)
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
// UpdateChannelNotifyProps will update the notification properties on a channel for a user.
func (c *Client4) UpdateChannelNotifyProps(channelId, userId string, props map[string]string) (bool, *Response) {
if r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/notify_props", MapToJson(props)); err != nil {
diff --git a/model/scheme.go b/model/scheme.go
index 959b80c24..2247717eb 100644
--- a/model/scheme.go
+++ b/model/scheme.go
@@ -69,6 +69,11 @@ func (sc *SchemeConveyor) Scheme() *Scheme {
}
}
+type SchemeRoles struct {
+ SchemeAdmin bool `json:"scheme_admin"`
+ SchemeUser bool `json:"scheme_user"`
+}
+
func (scheme *Scheme) ToJson() string {
b, _ := json.Marshal(scheme)
return string(b)
@@ -190,3 +195,14 @@ func IsValidSchemeName(name string) bool {
re := regexp.MustCompile(fmt.Sprintf("^[a-z0-9_]{0,%d}$", SCHEME_NAME_MAX_LENGTH))
return re.MatchString(name)
}
+
+func (schemeRoles *SchemeRoles) ToJson() string {
+ b, _ := json.Marshal(schemeRoles)
+ return string(b)
+}
+
+func SchemeRolesFromJson(data io.Reader) *SchemeRoles {
+ var schemeRoles *SchemeRoles
+ json.NewDecoder(data).Decode(&schemeRoles)
+ return schemeRoles
+}