diff --git a/server/channels/api4/team.go b/server/channels/api4/team.go index 1a568d4e15..7c29c32658 100644 --- a/server/channels/api4/team.go +++ b/server/channels/api4/team.go @@ -867,6 +867,12 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { } } + if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionAddUserToTeam) { + c.SetPermissionError(model.PermissionAddUserToTeam) + return + } + + canInviteGuests := c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionInviteGuest) var userIDs []string for _, member := range members { if member.TeamId != c.Params.TeamId { @@ -879,14 +885,21 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { return } + // if user cannot invite guests, check if any users are guest users. + if !canInviteGuests { + user, err := c.App.GetUser(member.UserId) + if err != nil { + c.Err = model.NewAppError("addTeamMembers", "api.team.user.missing_account", nil, "", http.StatusNotFound).Wrap(err) + return + } + if user.IsGuest() { + c.SetPermissionError(model.PermissionInviteGuest) + return + } + } userIDs = append(userIDs, member.UserId) } - if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionAddUserToTeam) { - c.SetPermissionError(model.PermissionAddUserToTeam) - return - } - membersWithErrors, appErr := c.App.AddTeamMembers(c.AppContext, c.Params.TeamId, userIDs, c.AppContext.Session().UserId, graceful) if len(membersWithErrors) != 0 { diff --git a/server/channels/api4/team_test.go b/server/channels/api4/team_test.go index d4f0a572b5..79e4481f04 100644 --- a/server/channels/api4/team_test.go +++ b/server/channels/api4/team_test.go @@ -2498,6 +2498,12 @@ func TestAddTeamMembers(t *testing.T) { otherUser.Id, } + guestUser := th.CreateUser() + th.App.UpdateUserRoles(th.Context, guestUser.Id, model.SystemGuestRoleId, false) + guestList := []string{ + guestUser.Id, + } + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableBotAccountCreation = true }) @@ -2526,6 +2532,23 @@ func TestAddTeamMembers(t *testing.T) { require.Equal(t, tm[0].TeamId, team.Id, "team ids should have matched") + // Check the appropriate permissions are enforced. + defaultRolePermissions := th.SaveDefaultRolePermissions() + defer func() { + th.RestoreDefaultRolePermissions(defaultRolePermissions) + }() + + // Regular user can add a guest member to a team they belong to. + th.AddPermissionToRole(model.PermissionInviteGuest.Id, model.TeamUserRoleId) + tm, resp, err = client.AddTeamMembers(context.Background(), team.Id, guestList) + require.NoError(t, err) + CheckCreatedStatus(t, resp) + + // Check all the returned data. + require.NotNil(t, tm[0], "should have returned team member") + require.Equal(t, tm[0].UserId, guestUser.Id, "user ids should have matched") + require.Equal(t, tm[0].TeamId, team.Id, "team ids should have matched") + // Check with various invalid requests. _, resp, err = client.AddTeamMembers(context.Background(), "junk", userList) require.Error(t, err) @@ -2550,12 +2573,6 @@ func TestAddTeamMembers(t *testing.T) { client.Logout(context.Background()) - // Check the appropriate permissions are enforced. - defaultRolePermissions := th.SaveDefaultRolePermissions() - defer func() { - th.RestoreDefaultRolePermissions(defaultRolePermissions) - }() - // Set the config so that only team admins can add a user to a team. th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId) th.AddPermissionToRole(model.PermissionAddUserToTeam.Id, model.TeamAdminRoleId) @@ -2592,6 +2609,13 @@ func TestAddTeamMembers(t *testing.T) { _, _, err = client.AddTeamMembers(context.Background(), team.Id, userList) require.NoError(t, err) + // remove invite guests + th.RemovePermissionFromRole(model.PermissionInviteGuest.Id, model.TeamUserRoleId) + // Regular user can no longer add a guest member to a team they belong to. + _, resp, err = client.AddTeamMembers(context.Background(), team.Id, guestList) + require.Error(t, err) + CheckForbiddenStatus(t, resp) + // Set a team to group-constrained team.GroupConstrained = model.NewBool(true) _, appErr = th.App.UpdateTeam(team) diff --git a/server/i18n/en.json b/server/i18n/en.json index 5513087c40..2fd8456d43 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -3378,6 +3378,10 @@ "id": "api.team.update_team_scheme.scheme_scope.error", "translation": "Unable to set the scheme to the team because the supplied scheme is not a team scheme." }, + { + "id": "api.team.user.missing_account", + "translation": "Unable to find the user." + }, { "id": "api.templates.cloud_renewal.button", "translation": "Renew now" diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json index 8c8475a8f7..779580fda5 100644 --- a/webapp/channels/src/i18n/en.json +++ b/webapp/channels/src/i18n/en.json @@ -1674,7 +1674,7 @@ "admin.permissions.permission.edit_post.name": "Edit Own Posts", "admin.permissions.permission.import_team.description": "Import team", "admin.permissions.permission.import_team.name": "Import team", - "admin.permissions.permission.invite_guest.description": "Invite guests to channels and send guest email invites.", + "admin.permissions.permission.invite_guest.description": "Invite guests to teams and send guest email invites.", "admin.permissions.permission.invite_guest.name": "Invite guests", "admin.permissions.permission.list_team_channels.description": "List team channels", "admin.permissions.permission.list_team_channels.name": "List team channels",