diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 77a7ecd24b..0d2c13303e 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -104,8 +104,7 @@ func setupTestHelper(enterprise bool, updateConfig func(*model.Config)) *TestHel web.New(th.Server, th.Server.AppOptions, th.App.Srv.Router) wsapi.Init(th.App, th.App.Srv.WebSocketRouter) th.App.Srv.Store.MarkSystemRanUnitTests() - th.App.DoAdvancedPermissionsMigration() - th.App.DoEmojisPermissionsMigration() + th.App.DoAppMigrations() th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true }) diff --git a/api4/channel.go b/api4/channel.go index 1dfafd394d..56d0caa6c1 100644 --- a/api4/channel.go +++ b/api4/channel.go @@ -1041,7 +1041,7 @@ func updateChannelMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.R return } - if _, err := c.App.UpdateChannelMemberSchemeRoles(c.Params.ChannelId, c.Params.UserId, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil { + if _, err := c.App.UpdateChannelMemberSchemeRoles(c.Params.ChannelId, c.Params.UserId, schemeRoles.SchemeGuest, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil { c.Err = err return } diff --git a/api4/channel_test.go b/api4/channel_test.go index 1670f1f499..ea1c26d02c 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -1767,52 +1767,82 @@ func TestUpdateChannelMemberSchemeRoles(t *testing.T) { s1 := &model.SchemeRoles{ SchemeAdmin: false, SchemeUser: false, + SchemeGuest: 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.SchemeGuest) assert.Equal(t, false, tm1.SchemeUser) assert.Equal(t, false, tm1.SchemeAdmin) s2 := &model.SchemeRoles{ SchemeAdmin: false, SchemeUser: true, + SchemeGuest: false, } _, 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, false, tm2.SchemeGuest) assert.Equal(t, true, tm2.SchemeUser) assert.Equal(t, false, tm2.SchemeAdmin) s3 := &model.SchemeRoles{ SchemeAdmin: true, SchemeUser: false, + SchemeGuest: 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.SchemeGuest) assert.Equal(t, false, tm3.SchemeUser) assert.Equal(t, true, tm3.SchemeAdmin) s4 := &model.SchemeRoles{ SchemeAdmin: true, SchemeUser: true, + SchemeGuest: false, } _, 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, false, tm4.SchemeGuest) assert.Equal(t, true, tm4.SchemeUser) assert.Equal(t, true, tm4.SchemeAdmin) - _, resp := SystemAdminClient.UpdateChannelMemberSchemeRoles(model.NewId(), th.BasicUser.Id, s4) + s5 := &model.SchemeRoles{ + SchemeAdmin: false, + SchemeUser: false, + SchemeGuest: true, + } + _, r5 := SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.BasicUser.Id, s5) + CheckNoError(t, r5) + + tm5, rtm5 := SystemAdminClient.GetChannelMember(th.BasicChannel.Id, th.BasicUser.Id, "") + CheckNoError(t, rtm5) + assert.Equal(t, true, tm5.SchemeGuest) + assert.Equal(t, false, tm5.SchemeUser) + assert.Equal(t, false, tm5.SchemeAdmin) + + s6 := &model.SchemeRoles{ + SchemeAdmin: false, + SchemeUser: true, + SchemeGuest: true, + } + _, resp := SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, th.BasicUser.Id, s6) + CheckBadRequestStatus(t, resp) + + _, resp = SystemAdminClient.UpdateChannelMemberSchemeRoles(model.NewId(), th.BasicUser.Id, s4) CheckForbiddenStatus(t, resp) _, resp = SystemAdminClient.UpdateChannelMemberSchemeRoles(th.BasicChannel.Id, model.NewId(), s4) diff --git a/api4/scheme_test.go b/api4/scheme_test.go index 3fac57bb20..8d23dd6b9a 100644 --- a/api4/scheme_test.go +++ b/api4/scheme_test.go @@ -41,8 +41,10 @@ func TestCreateScheme(t *testing.T) { assert.Equal(t, s1.Scope, scheme1.Scope) assert.NotZero(t, len(s1.DefaultTeamAdminRole)) assert.NotZero(t, len(s1.DefaultTeamUserRole)) + assert.NotZero(t, len(s1.DefaultTeamGuestRole)) assert.NotZero(t, len(s1.DefaultChannelAdminRole)) assert.NotZero(t, len(s1.DefaultChannelUserRole)) + assert.NotZero(t, len(s1.DefaultChannelGuestRole)) // Check the default roles have been created. _, roleRes1 := th.SystemAdminClient.GetRoleByName(s1.DefaultTeamAdminRole) @@ -53,6 +55,10 @@ func TestCreateScheme(t *testing.T) { CheckNoError(t, roleRes3) _, roleRes4 := th.SystemAdminClient.GetRoleByName(s1.DefaultChannelUserRole) CheckNoError(t, roleRes4) + _, roleRes5 := th.SystemAdminClient.GetRoleByName(s1.DefaultTeamGuestRole) + CheckNoError(t, roleRes5) + _, roleRes6 := th.SystemAdminClient.GetRoleByName(s1.DefaultChannelGuestRole) + CheckNoError(t, roleRes6) // Basic Test of a Channel scheme. scheme2 := &model.Scheme{ @@ -74,14 +80,18 @@ func TestCreateScheme(t *testing.T) { assert.Equal(t, s2.Scope, scheme2.Scope) assert.Zero(t, len(s2.DefaultTeamAdminRole)) assert.Zero(t, len(s2.DefaultTeamUserRole)) + assert.Zero(t, len(s2.DefaultTeamGuestRole)) assert.NotZero(t, len(s2.DefaultChannelAdminRole)) assert.NotZero(t, len(s2.DefaultChannelUserRole)) + assert.NotZero(t, len(s2.DefaultChannelGuestRole)) // Check the default roles have been created. - _, roleRes5 := th.SystemAdminClient.GetRoleByName(s2.DefaultChannelAdminRole) - CheckNoError(t, roleRes5) - _, roleRes6 := th.SystemAdminClient.GetRoleByName(s2.DefaultChannelUserRole) - CheckNoError(t, roleRes6) + _, roleRes7 := th.SystemAdminClient.GetRoleByName(s2.DefaultChannelAdminRole) + CheckNoError(t, roleRes7) + _, roleRes8 := th.SystemAdminClient.GetRoleByName(s2.DefaultChannelUserRole) + CheckNoError(t, roleRes8) + _, roleRes9 := th.SystemAdminClient.GetRoleByName(s2.DefaultChannelGuestRole) + CheckNoError(t, roleRes9) // Try and create a scheme with an invalid scope. scheme3 := &model.Scheme{ @@ -178,8 +188,10 @@ func TestGetScheme(t *testing.T) { assert.Equal(t, s1.Scope, scheme1.Scope) assert.NotZero(t, len(s1.DefaultTeamAdminRole)) assert.NotZero(t, len(s1.DefaultTeamUserRole)) + assert.NotZero(t, len(s1.DefaultTeamGuestRole)) assert.NotZero(t, len(s1.DefaultChannelAdminRole)) assert.NotZero(t, len(s1.DefaultChannelUserRole)) + assert.NotZero(t, len(s1.DefaultChannelGuestRole)) s2, r2 := th.SystemAdminClient.GetScheme(s1.Id) CheckNoError(t, r2) @@ -490,8 +502,10 @@ func TestPatchScheme(t *testing.T) { assert.Equal(t, s1.Scope, scheme1.Scope) assert.NotZero(t, len(s1.DefaultTeamAdminRole)) assert.NotZero(t, len(s1.DefaultTeamUserRole)) + assert.NotZero(t, len(s1.DefaultTeamGuestRole)) assert.NotZero(t, len(s1.DefaultChannelAdminRole)) assert.NotZero(t, len(s1.DefaultChannelUserRole)) + assert.NotZero(t, len(s1.DefaultChannelGuestRole)) s2, r2 := th.SystemAdminClient.GetScheme(s1.Id) CheckNoError(t, r2) @@ -596,11 +610,17 @@ func TestDeleteScheme(t *testing.T) { CheckNoError(t, roleRes3) role4, roleRes4 := th.SystemAdminClient.GetRoleByName(s1.DefaultChannelUserRole) CheckNoError(t, roleRes4) + role5, roleRes5 := th.SystemAdminClient.GetRoleByName(s1.DefaultTeamGuestRole) + CheckNoError(t, roleRes5) + role6, roleRes6 := th.SystemAdminClient.GetRoleByName(s1.DefaultChannelGuestRole) + CheckNoError(t, roleRes6) assert.Zero(t, role1.DeleteAt) assert.Zero(t, role2.DeleteAt) assert.Zero(t, role3.DeleteAt) assert.Zero(t, role4.DeleteAt) + assert.Zero(t, role5.DeleteAt) + assert.Zero(t, role6.DeleteAt) // Make sure this scheme is in use by a team. team, err := th.App.Srv.Store.Team().Save(&model.Team{ @@ -625,11 +645,17 @@ func TestDeleteScheme(t *testing.T) { CheckNoError(t, roleRes3) role4, roleRes4 = th.SystemAdminClient.GetRoleByName(s1.DefaultChannelUserRole) CheckNoError(t, roleRes4) + role5, roleRes5 = th.SystemAdminClient.GetRoleByName(s1.DefaultTeamGuestRole) + CheckNoError(t, roleRes5) + role6, roleRes6 = th.SystemAdminClient.GetRoleByName(s1.DefaultChannelGuestRole) + CheckNoError(t, roleRes6) assert.NotZero(t, role1.DeleteAt) assert.NotZero(t, role2.DeleteAt) assert.NotZero(t, role3.DeleteAt) assert.NotZero(t, role4.DeleteAt) + assert.NotZero(t, role5.DeleteAt) + assert.NotZero(t, role6.DeleteAt) // Check the team now uses the default scheme c2, resp := th.SystemAdminClient.GetTeam(team.Id, "") @@ -658,9 +684,12 @@ func TestDeleteScheme(t *testing.T) { CheckNoError(t, roleRes3) role4, roleRes4 := th.SystemAdminClient.GetRoleByName(s1.DefaultChannelUserRole) CheckNoError(t, roleRes4) + role6, roleRes6 := th.SystemAdminClient.GetRoleByName(s1.DefaultChannelGuestRole) + CheckNoError(t, roleRes6) assert.Zero(t, role3.DeleteAt) assert.Zero(t, role4.DeleteAt) + assert.Zero(t, role6.DeleteAt) // Make sure this scheme is in use by a team. res := <-th.App.Srv.Store.Channel().Save(&model.Channel{ @@ -682,9 +711,12 @@ func TestDeleteScheme(t *testing.T) { CheckNoError(t, roleRes3) role4, roleRes4 = th.SystemAdminClient.GetRoleByName(s1.DefaultChannelUserRole) CheckNoError(t, roleRes4) + role6, roleRes6 = th.SystemAdminClient.GetRoleByName(s1.DefaultChannelGuestRole) + CheckNoError(t, roleRes6) assert.NotZero(t, role3.DeleteAt) assert.NotZero(t, role4.DeleteAt) + assert.NotZero(t, role6.DeleteAt) // Check the channel now uses the default scheme c2, resp := th.SystemAdminClient.GetChannelByName(channel.Name, channel.TeamId, "") diff --git a/api4/team.go b/api4/team.go index 3e1824692c..415b2d5fb2 100644 --- a/api4/team.go +++ b/api4/team.go @@ -701,7 +701,7 @@ func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Requ return } - if _, err := c.App.UpdateTeamMemberSchemeRoles(c.Params.TeamId, c.Params.UserId, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil { + if _, err := c.App.UpdateTeamMemberSchemeRoles(c.Params.TeamId, c.Params.UserId, schemeRoles.SchemeGuest, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil { c.Err = err return } diff --git a/api4/team_test.go b/api4/team_test.go index 8fd93f1465..8f23535f41 100644 --- a/api4/team_test.go +++ b/api4/team_test.go @@ -1933,52 +1933,82 @@ func TestUpdateTeamMemberSchemeRoles(t *testing.T) { s1 := &model.SchemeRoles{ SchemeAdmin: false, SchemeUser: false, + SchemeGuest: 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.SchemeGuest) assert.Equal(t, false, tm1.SchemeUser) assert.Equal(t, false, tm1.SchemeAdmin) s2 := &model.SchemeRoles{ SchemeAdmin: false, SchemeUser: true, + SchemeGuest: false, } _, 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, false, tm2.SchemeGuest) assert.Equal(t, true, tm2.SchemeUser) assert.Equal(t, false, tm2.SchemeAdmin) s3 := &model.SchemeRoles{ SchemeAdmin: true, SchemeUser: false, + SchemeGuest: 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.SchemeGuest) assert.Equal(t, false, tm3.SchemeUser) assert.Equal(t, true, tm3.SchemeAdmin) s4 := &model.SchemeRoles{ SchemeAdmin: true, SchemeUser: true, + SchemeGuest: false, } _, 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, false, tm4.SchemeGuest) assert.Equal(t, true, tm4.SchemeUser) assert.Equal(t, true, tm4.SchemeAdmin) - _, resp := SystemAdminClient.UpdateTeamMemberSchemeRoles(model.NewId(), th.BasicUser.Id, s4) + s5 := &model.SchemeRoles{ + SchemeAdmin: false, + SchemeUser: false, + SchemeGuest: true, + } + _, r5 := SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.BasicUser.Id, s5) + CheckNoError(t, r5) + + tm5, rtm5 := SystemAdminClient.GetTeamMember(th.BasicTeam.Id, th.BasicUser.Id, "") + CheckNoError(t, rtm5) + assert.Equal(t, true, tm5.SchemeGuest) + assert.Equal(t, false, tm5.SchemeUser) + assert.Equal(t, false, tm5.SchemeAdmin) + + s6 := &model.SchemeRoles{ + SchemeAdmin: false, + SchemeUser: true, + SchemeGuest: true, + } + _, resp := SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, th.BasicUser.Id, s6) + CheckBadRequestStatus(t, resp) + + _, resp = SystemAdminClient.UpdateTeamMemberSchemeRoles(model.NewId(), th.BasicUser.Id, s4) CheckNotFoundStatus(t, resp) _, resp = SystemAdminClient.UpdateTeamMemberSchemeRoles(th.BasicTeam.Id, model.NewId(), s4) diff --git a/app/channel.go b/app/channel.go index 2e461b69f2..8b6d0cd020 100644 --- a/app/channel.go +++ b/app/channel.go @@ -71,7 +71,8 @@ func (a *App) JoinDefaultChannels(teamId string, user *model.User, shouldBeAdmin cm := &model.ChannelMember{ ChannelId: channel.Id, UserId: user.Id, - SchemeUser: true, + SchemeGuest: user.IsGuest(), + SchemeUser: !user.IsGuest(), SchemeAdmin: shouldBeAdmin, NotifyProps: model.GetDefaultChannelNotifyProps(), } @@ -213,10 +214,16 @@ func (a *App) CreateChannel(channel *model.Channel, addMember bool) (*model.Chan sc := result.Data.(*model.Channel) if addMember { + user, err := a.Srv.Store.User().Get(channel.CreatorId) + if err != nil { + return nil, err + } + cm := &model.ChannelMember{ ChannelId: sc.Id, - UserId: channel.CreatorId, - SchemeUser: true, + UserId: user.Id, + SchemeGuest: user.IsGuest(), + SchemeUser: !user.IsGuest(), SchemeAdmin: true, NotifyProps: model.GetDefaultChannelNotifyProps(), } @@ -450,7 +457,8 @@ func (a *App) createGroupChannel(userIds []string, creatorId string) (*model.Cha UserId: user.Id, ChannelId: group.Id, NotifyProps: model.GetDefaultChannelNotifyProps(), - SchemeUser: true, + SchemeGuest: user.IsGuest(), + SchemeUser: !user.IsGuest(), } if result := <-a.Srv.Store.Channel().SaveMember(cm); result.Err != nil { @@ -616,35 +624,35 @@ func (a *App) PatchChannel(channel *model.Channel, patch *model.ChannelPatch, us return channel, nil } -func (a *App) GetSchemeRolesForChannel(channelId string) (string, string, *model.AppError) { +func (a *App) GetSchemeRolesForChannel(channelId string) (string, string, string, *model.AppError) { channel, err := a.GetChannel(channelId) if err != nil { - return "", "", err + return "", "", "", err } if channel.SchemeId != nil && len(*channel.SchemeId) != 0 { var scheme *model.Scheme scheme, err = a.GetScheme(*channel.SchemeId) if err != nil { - return "", "", err + return "", "", "", err } - return scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole, nil + return scheme.DefaultChannelGuestRole, scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole, nil } team, err := a.GetTeam(channel.TeamId) if err != nil { - return "", "", err + return "", "", "", err } if team.SchemeId != nil && len(*team.SchemeId) != 0 { scheme, err := a.GetScheme(*team.SchemeId) if err != nil { - return "", "", err + return "", "", "", err } - return scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole, nil + return scheme.DefaultChannelGuestRole, scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole, nil } - return model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID, nil + return model.CHANNEL_GUEST_ROLE_ID, model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID, nil } func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles string) (*model.ChannelMember, *model.AppError) { @@ -654,12 +662,15 @@ func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles return nil, err } - schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForChannel(channelId) + schemeGuestRole, schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForChannel(channelId) if err != nil { return nil, err } + prevSchemeGuestValue := member.SchemeGuest + var newExplicitRoles []string + member.SchemeGuest = false member.SchemeUser = false member.SchemeAdmin = false @@ -680,6 +691,8 @@ func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles member.SchemeAdmin = true case schemeUserRole: member.SchemeUser = true + case schemeGuestRole: + member.SchemeGuest = true default: // If not part of the scheme for this channel, then it is not allowed to apply it as an explicit role. return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest) @@ -687,6 +700,14 @@ func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles } } + if member.SchemeUser && member.SchemeGuest { + return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) + } + + if prevSchemeGuestValue != member.SchemeGuest { + return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.changing_guest_role.app_error", nil, "", http.StatusBadRequest) + } + member.ExplicitRoles = strings.Join(newExplicitRoles, " ") result := <-a.Srv.Store.Channel().UpdateMember(member) @@ -699,7 +720,7 @@ 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) { +func (a *App) UpdateChannelMemberSchemeRoles(channelId string, userId string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError) { member, err := a.GetChannelMember(channelId, userId) if err != nil { return nil, err @@ -707,10 +728,15 @@ func (a *App) UpdateChannelMemberSchemeRoles(channelId string, userId string, is member.SchemeAdmin = isSchemeAdmin member.SchemeUser = isSchemeUser + member.SchemeGuest = isSchemeGuest + + if member.SchemeUser && member.SchemeGuest { + return nil, model.NewAppError("UpdateChannelMemberSchemeRoles", "api.channel.update_channel_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) + } // 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) + member.ExplicitRoles = RemoveRoles([]string{model.CHANNEL_GUEST_ROLE_ID, model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID}, member.ExplicitRoles) } result := <-a.Srv.Store.Channel().UpdateMember(member) @@ -871,7 +897,8 @@ func (a *App) addUserToChannel(user *model.User, channel *model.Channel, teamMem ChannelId: channel.Id, UserId: user.Id, NotifyProps: model.GetDefaultChannelNotifyProps(), - SchemeUser: true, + SchemeGuest: user.IsGuest(), + SchemeUser: !user.IsGuest(), } if result := <-a.Srv.Store.Channel().SaveMember(newMember); result.Err != nil { mlog.Error(fmt.Sprintf("Failed to add member user_id=%v channel_id=%v err=%v", user.Id, channel.Id, result.Err), mlog.String("user_id", user.Id)) diff --git a/app/channel_test.go b/app/channel_test.go index 09073bd6b6..a303475c5a 100644 --- a/app/channel_test.go +++ b/app/channel_test.go @@ -812,3 +812,86 @@ func TestGetPublicChannelsForTeam(t *testing.T) { channels := append(*channelList, *channelList2...) assert.ElementsMatch(t, expectedChannels, channels) } + +func TestUpdateChannelMemberRolesChangingGuest(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + t.Run("from guest to user", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateGuest(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + _, err = th.App.AddUserToChannel(ruser, th.BasicChannel) + require.Nil(t, err) + + if _, err := th.App.UpdateChannelMemberRoles(th.BasicChannel.Id, ruser.Id, "channel_user"); err == nil { + t.Fatal("Should fail when try to modify the guest role") + } + }) + + t.Run("from user to guest", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateUser(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + _, err = th.App.AddUserToChannel(ruser, th.BasicChannel) + require.Nil(t, err) + + if _, err := th.App.UpdateChannelMemberRoles(th.BasicChannel.Id, ruser.Id, "channel_guest"); err == nil { + t.Fatal("Should fail when try to modify the guest role") + } + }) + + t.Run("from user to admin", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateUser(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + _, err = th.App.AddUserToChannel(ruser, th.BasicChannel) + require.Nil(t, err) + + if _, err := th.App.UpdateChannelMemberRoles(th.BasicChannel.Id, ruser.Id, "channel_user channel_admin"); err != nil { + t.Fatal("Should work when you not modify guest role") + } + }) + + t.Run("from guest to guest plus custom", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateGuest(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + _, err = th.App.AddUserToChannel(ruser, th.BasicChannel) + require.Nil(t, err) + + _, err = th.App.CreateRole(&model.Role{Name: "custom", DisplayName: "custom", Description: "custom"}) + require.Nil(t, err) + + if _, err := th.App.UpdateChannelMemberRoles(th.BasicChannel.Id, ruser.Id, "channel_guest custom"); err != nil { + t.Fatal("Should work when you not modify guest role") + } + }) + + t.Run("a guest cant have user role", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateGuest(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + _, err = th.App.AddUserToChannel(ruser, th.BasicChannel) + require.Nil(t, err) + + if _, err := th.App.UpdateChannelMemberRoles(th.BasicChannel.Id, ruser.Id, "channel_guest channel_user"); err == nil { + t.Fatal("Should work when you not modify guest role") + } + }) +} diff --git a/app/diagnostics.go b/app/diagnostics.go index c68bbe76e3..676a6f73d6 100644 --- a/app/diagnostics.go +++ b/app/diagnostics.go @@ -739,6 +739,11 @@ func (a *App) trackPermissions() { teamUserPermissions = strings.Join(role.Permissions, " ") } + teamGuestPermissions := "" + if role, err := a.GetRoleByName(model.TEAM_GUEST_ROLE_ID); err == nil { + teamGuestPermissions = strings.Join(role.Permissions, " ") + } + channelAdminPermissions := "" if role, err := a.GetRoleByName(model.CHANNEL_ADMIN_ROLE_ID); err == nil { channelAdminPermissions = strings.Join(role.Permissions, " ") @@ -746,7 +751,12 @@ func (a *App) trackPermissions() { channelUserPermissions := "" if role, err := a.GetRoleByName(model.CHANNEL_USER_ROLE_ID); err == nil { - systemAdminPermissions = strings.Join(role.Permissions, " ") + channelUserPermissions = strings.Join(role.Permissions, " ") + } + + channelGuestPermissions := "" + if role, err := a.GetRoleByName(model.CHANNEL_GUEST_ROLE_ID); err == nil { + channelGuestPermissions = strings.Join(role.Permissions, " ") } a.SendDiagnostic(TRACK_PERMISSIONS_SYSTEM_SCHEME, map[string]interface{}{ @@ -754,8 +764,10 @@ func (a *App) trackPermissions() { "system_user_permissions": systemUserPermissions, "team_admin_permissions": teamAdminPermissions, "team_user_permissions": teamUserPermissions, + "team_guest_permissions": teamGuestPermissions, "channel_admin_permissions": channelAdminPermissions, "channel_user_permissions": channelUserPermissions, + "channel_guest_permissions": channelGuestPermissions, }) if schemes, err := a.GetSchemes(model.SCHEME_SCOPE_TEAM, 0, 100); err == nil { @@ -770,6 +782,11 @@ func (a *App) trackPermissions() { teamUserPermissions = strings.Join(role.Permissions, " ") } + teamGuestPermissions := "" + if role, err := a.GetRoleByName(scheme.DefaultTeamGuestRole); err == nil { + teamGuestPermissions = strings.Join(role.Permissions, " ") + } + channelAdminPermissions := "" if role, err := a.GetRoleByName(scheme.DefaultChannelAdminRole); err == nil { channelAdminPermissions = strings.Join(role.Permissions, " ") @@ -777,7 +794,12 @@ func (a *App) trackPermissions() { channelUserPermissions := "" if role, err := a.GetRoleByName(scheme.DefaultChannelUserRole); err == nil { - systemAdminPermissions = strings.Join(role.Permissions, " ") + channelUserPermissions = strings.Join(role.Permissions, " ") + } + + channelGuestPermissions := "" + if role, err := a.GetRoleByName(scheme.DefaultChannelGuestRole); err == nil { + channelGuestPermissions = strings.Join(role.Permissions, " ") } var count int64 = 0 @@ -789,8 +811,10 @@ func (a *App) trackPermissions() { "scheme_id": scheme.Id, "team_admin_permissions": teamAdminPermissions, "team_user_permissions": teamUserPermissions, + "team_guest_permissions": teamGuestPermissions, "channel_admin_permissions": channelAdminPermissions, "channel_user_permissions": channelUserPermissions, + "channel_guest_permissions": channelGuestPermissions, "team_count": count, }) } diff --git a/app/export_converters.go b/app/export_converters.go index a29fde2e81..452e2a5613 100644 --- a/app/export_converters.go +++ b/app/export_converters.go @@ -91,6 +91,9 @@ func ImportUserTeamDataFromTeamMember(member *model.TeamMemberForExport) *UserTe if member.SchemeUser { rolesList = append(rolesList, model.TEAM_USER_ROLE_ID) } + if member.SchemeGuest { + rolesList = append(rolesList, model.TEAM_GUEST_ROLE_ID) + } roles := strings.Join(rolesList, " ") return &UserTeamImportData{ Name: &member.TeamName, @@ -106,6 +109,9 @@ func ImportUserChannelDataFromChannelMemberAndPreferences(member *model.ChannelM if member.SchemeUser { rolesList = append(rolesList, model.CHANNEL_USER_ROLE_ID) } + if member.SchemeGuest { + rolesList = append(rolesList, model.CHANNEL_GUEST_ROLE_ID) + } props := member.NotifyProps notifyProps := UserChannelNotifyPropsImportData{} diff --git a/app/helper_test.go b/app/helper_test.go index 6ba78486a9..f006c11f41 100644 --- a/app/helper_test.go +++ b/app/helper_test.go @@ -144,6 +144,14 @@ func (me *TestHelper) CreateTeam() *model.Team { } func (me *TestHelper) CreateUser() *model.User { + return me.CreateUserOrGuest(false) +} + +func (me *TestHelper) CreateGuest() *model.User { + return me.CreateUserOrGuest(true) +} + +func (me *TestHelper) CreateUserOrGuest(guest bool) *model.User { id := model.NewId() user := &model.User{ @@ -156,11 +164,20 @@ func (me *TestHelper) CreateUser() *model.User { utils.DisableDebugLogForTest() var err *model.AppError - if user, err = me.App.CreateUser(user); err != nil { - mlog.Error(err.Error()) + if guest { + if user, err = me.App.CreateGuest(user); err != nil { + mlog.Error(err.Error()) - time.Sleep(time.Second) - panic(err) + time.Sleep(time.Second) + panic(err) + } + } else { + if user, err = me.App.CreateUser(user); err != nil { + mlog.Error(err.Error()) + + time.Sleep(time.Second) + panic(err) + } } utils.EnableDebugLogForTest() return user @@ -316,8 +333,10 @@ func (me *TestHelper) CreateScheme() (*model.Scheme, []*model.Role) { roleNames := []string{ scheme.DefaultTeamAdminRole, scheme.DefaultTeamUserRole, + scheme.DefaultTeamGuestRole, scheme.DefaultChannelAdminRole, scheme.DefaultChannelUserRole, + scheme.DefaultChannelGuestRole, } var roles []*model.Role diff --git a/app/import_functions.go b/app/import_functions.go index c1e469c13d..037402b5af 100644 --- a/app/import_functions.go +++ b/app/import_functions.go @@ -68,6 +68,16 @@ func (a *App) ImportScheme(data *SchemeImportData, dryRun bool) *model.AppError if err := a.ImportRole(data.DefaultTeamUserRole, dryRun, true); err != nil { return err } + + if data.DefaultTeamGuestRole == nil { + data.DefaultTeamGuestRole = &RoleImportData{ + DisplayName: model.NewString("Team Guest Role for Scheme"), + } + } + data.DefaultTeamGuestRole.Name = &scheme.DefaultTeamGuestRole + if err := a.ImportRole(data.DefaultTeamGuestRole, dryRun, true); err != nil { + return err + } } if scheme.Scope == model.SCHEME_SCOPE_TEAM || scheme.Scope == model.SCHEME_SCOPE_CHANNEL { @@ -80,6 +90,16 @@ func (a *App) ImportScheme(data *SchemeImportData, dryRun bool) *model.AppError if err := a.ImportRole(data.DefaultChannelUserRole, dryRun, true); err != nil { return err } + + if data.DefaultChannelGuestRole == nil { + data.DefaultChannelGuestRole = &RoleImportData{ + DisplayName: model.NewString("Channel Guest Role for Scheme"), + } + } + data.DefaultChannelGuestRole.Name = &scheme.DefaultChannelGuestRole + if err := a.ImportRole(data.DefaultChannelGuestRole, dryRun, true); err != nil { + return err + } } return nil @@ -647,6 +667,7 @@ func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *mod } var roles string + isSchemeGuest := false isSchemeUser := true isSchemeAdmin := false @@ -656,7 +677,10 @@ func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *mod rawRoles := *tdata.Roles explicitRoles := []string{} for _, role := range strings.Fields(rawRoles) { - if role == model.TEAM_USER_ROLE_ID { + if role == model.TEAM_GUEST_ROLE_ID { + isSchemeGuest = true + isSchemeUser = false + } else if role == model.TEAM_USER_ROLE_ID { isSchemeUser = true } else if role == model.TEAM_ADMIN_ROLE_ID { isSchemeAdmin = true @@ -678,8 +702,8 @@ func (a *App) ImportUserTeams(user *model.User, data *[]UserTeamImportData) *mod } } - if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser { - a.UpdateTeamMemberSchemeRoles(team.Id, user.Id, isSchemeUser, isSchemeAdmin) + if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser || member.SchemeGuest != isSchemeGuest { + a.UpdateTeamMemberSchemeRoles(team.Id, user.Id, isSchemeGuest, isSchemeUser, isSchemeAdmin) } defaultChannel, err := a.GetChannelByName(model.DEFAULT_CHANNEL, team.Id, true) @@ -720,6 +744,7 @@ func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember } var roles string + isSchemeGuest := false isSchemeUser := true isSchemeAdmin := false @@ -729,7 +754,10 @@ func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember rawRoles := *cdata.Roles explicitRoles := []string{} for _, role := range strings.Fields(rawRoles) { - if role == model.CHANNEL_USER_ROLE_ID { + if role == model.CHANNEL_GUEST_ROLE_ID { + isSchemeGuest = true + isSchemeUser = false + } else if role == model.CHANNEL_USER_ROLE_ID { isSchemeUser = true } else if role == model.CHANNEL_ADMIN_ROLE_ID { isSchemeAdmin = true @@ -755,8 +783,8 @@ func (a *App) ImportUserChannels(user *model.User, team *model.Team, teamMember } } - if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser { - a.UpdateChannelMemberSchemeRoles(channel.Id, user.Id, isSchemeUser, isSchemeAdmin) + if member.SchemeAdmin != isSchemeAdmin || member.SchemeUser != isSchemeUser || member.SchemeGuest != isSchemeGuest { + a.UpdateChannelMemberSchemeRoles(channel.Id, user.Id, isSchemeGuest, isSchemeUser, isSchemeAdmin) } if cdata.NotifyProps != nil { diff --git a/app/import_functions_test.go b/app/import_functions_test.go index 7ea6f54a5d..43ef3f4d09 100644 --- a/app/import_functions_test.go +++ b/app/import_functions_test.go @@ -28,6 +28,239 @@ func TestImportImportScheme(t *testing.T) { <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2) }() + // Try importing an invalid scheme in dryRun mode. + data := SchemeImportData{ + Name: ptrStr(model.NewId()), + Scope: ptrStr("team"), + DefaultTeamGuestRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, + DefaultTeamUserRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, + DefaultTeamAdminRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, + DefaultChannelGuestRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, + DefaultChannelUserRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, + DefaultChannelAdminRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, + Description: ptrStr("description"), + } + + if err := th.App.ImportScheme(&data, true); err == nil { + t.Fatalf("Should have failed to import.") + } + + if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil { + t.Fatalf("Scheme should not have imported.") + } + + // Try importing a valid scheme in dryRun mode. + data.DisplayName = ptrStr("display name") + + if err := th.App.ImportScheme(&data, true); err != nil { + t.Fatalf("Should have succeeded.") + } + + if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil { + t.Fatalf("Scheme should not have imported.") + } + + // Try importing an invalid scheme. + data.DisplayName = nil + + if err := th.App.ImportScheme(&data, false); err == nil { + t.Fatalf("Should have failed to import.") + } + + if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err == nil { + t.Fatalf("Scheme should not have imported.") + } + + // Try importing a valid scheme with all params set. + data.DisplayName = ptrStr("display name") + + if err := th.App.ImportScheme(&data, false); err != nil { + t.Fatalf("Should have succeeded.") + } + + if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil { + t.Fatalf("Failed to import scheme: %v", res.Err) + } else { + scheme := res.Data.(*model.Scheme) + assert.Equal(t, *data.Name, scheme.Name) + assert.Equal(t, *data.DisplayName, scheme.DisplayName) + assert.Equal(t, *data.Description, scheme.Description) + assert.Equal(t, *data.Scope, scheme.Scope) + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamAdminRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamUserRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelUserRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + } + + // Try modifying all the fields and re-importing. + data.DisplayName = ptrStr("new display name") + data.Description = ptrStr("new description") + + if err := th.App.ImportScheme(&data, false); err != nil { + t.Fatalf("Should have succeeded: %v", err) + } + + if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil { + t.Fatalf("Failed to import scheme: %v", res.Err) + } else { + scheme := res.Data.(*model.Scheme) + assert.Equal(t, *data.Name, scheme.Name) + assert.Equal(t, *data.DisplayName, scheme.DisplayName) + assert.Equal(t, *data.Description, scheme.Description) + assert.Equal(t, *data.Scope, scheme.Scope) + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamAdminRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamUserRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelUserRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + } + + // Try changing the scope of the scheme and reimporting. + data.Scope = ptrStr("channel") + + if err := th.App.ImportScheme(&data, false); err == nil { + t.Fatalf("Should have failed to import.") + } + + if res := <-th.App.Srv.Store.Scheme().GetByName(*data.Name); res.Err != nil { + t.Fatalf("Failed to import scheme: %v", res.Err) + } else { + scheme := res.Data.(*model.Scheme) + assert.Equal(t, *data.Name, scheme.Name) + assert.Equal(t, *data.DisplayName, scheme.DisplayName) + assert.Equal(t, *data.Description, scheme.Description) + assert.Equal(t, "team", scheme.Scope) + } +} + +func TestImportImportSchemeWithoutGuestRoles(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + // Mark the phase 2 permissions migration as completed. + <-th.App.Srv.Store.System().Save(&model.System{Name: model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2, Value: "true"}) + + defer func() { + <-th.App.Srv.Store.System().PermanentDeleteByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2) + }() + // Try importing an invalid scheme in dryRun mode. data := SchemeImportData{ Name: ptrStr(model.NewId()), @@ -115,6 +348,15 @@ func TestImportImportScheme(t *testing.T) { assert.True(t, role.SchemeManaged) } + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil { t.Fatalf("Should have found the imported role.") } else { @@ -132,6 +374,15 @@ func TestImportImportScheme(t *testing.T) { assert.False(t, role.BuiltIn) assert.True(t, role.SchemeManaged) } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } } // Try modifying all the fields and re-importing. @@ -169,6 +420,15 @@ func TestImportImportScheme(t *testing.T) { assert.True(t, role.SchemeManaged) } + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultTeamGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelAdminRole); res.Err != nil { t.Fatalf("Should have found the imported role.") } else { @@ -186,6 +446,15 @@ func TestImportImportScheme(t *testing.T) { assert.False(t, role.BuiltIn) assert.True(t, role.SchemeManaged) } + + if res := <-th.App.Srv.Store.Role().GetByName(scheme.DefaultChannelGuestRole); res.Err != nil { + t.Fatalf("Should have found the imported role.") + } else { + role := res.Data.(*model.Role) + assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName) + assert.False(t, role.BuiltIn) + assert.True(t, role.SchemeManaged) + } } // Try changing the scope of the scheme and reimporting. @@ -1273,6 +1542,10 @@ func TestImportImportUser(t *testing.T) { Name: ptrStr(model.NewId()), DisplayName: ptrStr(model.NewId()), Scope: ptrStr("team"), + DefaultTeamGuestRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, DefaultTeamUserRole: &RoleImportData{ Name: ptrStr(model.NewId()), DisplayName: ptrStr(model.NewId()), @@ -1281,6 +1554,10 @@ func TestImportImportUser(t *testing.T) { Name: ptrStr(model.NewId()), DisplayName: ptrStr(model.NewId()), }, + DefaultChannelGuestRole: &RoleImportData{ + Name: ptrStr(model.NewId()), + DisplayName: ptrStr(model.NewId()), + }, DefaultChannelUserRole: &RoleImportData{ Name: ptrStr(model.NewId()), DisplayName: ptrStr(model.NewId()), @@ -1363,6 +1640,7 @@ func TestImportImportUser(t *testing.T) { } assert.True(t, teamMember.SchemeAdmin) assert.True(t, teamMember.SchemeUser) + assert.False(t, teamMember.SchemeGuest) assert.Equal(t, "", teamMember.ExplicitRoles) channelMember, err = th.App.GetChannelMember(channel.Id, user.Id) @@ -1371,6 +1649,7 @@ func TestImportImportUser(t *testing.T) { } assert.True(t, channelMember.SchemeAdmin) assert.True(t, channelMember.SchemeUser) + assert.False(t, channelMember.SchemeGuest) assert.Equal(t, "", channelMember.ExplicitRoles) // Test importing deleted user with a valid team & valid channel name in apply mode. @@ -1406,7 +1685,9 @@ func TestImportImportUser(t *testing.T) { t.Fatalf("Failed to get the team member") } + assert.False(t, teamMember.SchemeAdmin) assert.True(t, teamMember.SchemeUser) + assert.False(t, teamMember.SchemeGuest) assert.Equal(t, "", teamMember.ExplicitRoles) channelMember, err = th.App.GetChannelMember(channel.Id, user.Id) @@ -1414,9 +1695,58 @@ func TestImportImportUser(t *testing.T) { t.Fatalf("Failed to get the channel member") } + assert.False(t, teamMember.SchemeAdmin) assert.True(t, channelMember.SchemeUser) + assert.False(t, teamMember.SchemeGuest) assert.Equal(t, "", channelMember.ExplicitRoles) + // Test importing deleted guest with a valid team & valid channel name in apply mode. + username = model.NewId() + deleteAt = model.GetMillis() + deletedGuestData := &UserImportData{ + Username: &username, + DeleteAt: &deleteAt, + Email: ptrStr(model.NewId() + "@example.com"), + Teams: &[]UserTeamImportData{ + { + Name: &team.Name, + Roles: ptrStr("team_guest"), + Channels: &[]UserChannelImportData{ + { + Name: &channel.Name, + Roles: ptrStr("channel_guest"), + }, + }, + }, + }, + } + err = th.App.ImportUser(deletedGuestData, false) + assert.Nil(t, err) + + user, err = th.App.GetUserByUsername(*deletedGuestData.Username) + if err != nil { + t.Fatalf("Failed to get user from database.") + } + + teamMember, err = th.App.GetTeamMember(team.Id, user.Id) + if err != nil { + t.Fatalf("Failed to get the team member") + } + + assert.False(t, teamMember.SchemeAdmin) + assert.False(t, teamMember.SchemeUser) + assert.True(t, teamMember.SchemeGuest) + assert.Equal(t, "", teamMember.ExplicitRoles) + + channelMember, err = th.App.GetChannelMember(channel.Id, user.Id) + if err != nil { + t.Fatalf("Failed to get the channel member") + } + + assert.False(t, teamMember.SchemeAdmin) + assert.False(t, channelMember.SchemeUser) + assert.True(t, teamMember.SchemeGuest) + assert.Equal(t, "", channelMember.ExplicitRoles) } func TestImportUserDefaultNotifyProps(t *testing.T) { diff --git a/app/import_types.go b/app/import_types.go index d286d925bb..26c0e69d22 100644 --- a/app/import_types.go +++ b/app/import_types.go @@ -167,8 +167,10 @@ type SchemeImportData struct { Scope *string `json:"scope"` DefaultTeamAdminRole *RoleImportData `json:"default_team_admin_role"` DefaultTeamUserRole *RoleImportData `json:"default_team_user_role"` + DefaultTeamGuestRole *RoleImportData `json:"default_team_guest_role"` DefaultChannelAdminRole *RoleImportData `json:"default_channel_admin_role"` DefaultChannelUserRole *RoleImportData `json:"default_channel_user_role"` + DefaultChannelGuestRole *RoleImportData `json:"default_channel_guest_role"` } type RoleImportData struct { diff --git a/app/import_validators.go b/app/import_validators.go index e0282666c0..ec966f33da 100644 --- a/app/import_validators.go +++ b/app/import_validators.go @@ -56,6 +56,12 @@ func validateSchemeImportData(data *SchemeImportData) *model.AppError { } } + if data.DefaultTeamGuestRole != nil { + if err := validateRoleImportData(data.DefaultTeamGuestRole); err != nil { + return err + } + } + if data.DefaultChannelAdminRole != nil { if err := validateRoleImportData(data.DefaultChannelAdminRole); err != nil { return err @@ -68,6 +74,12 @@ func validateSchemeImportData(data *SchemeImportData) *model.AppError { } } + if data.DefaultChannelGuestRole != nil { + if err := validateRoleImportData(data.DefaultChannelGuestRole); err != nil { + return err + } + } + return nil } diff --git a/app/import_validators_test.go b/app/import_validators_test.go index 08ef674e0c..891702e9d9 100644 --- a/app/import_validators_test.go +++ b/app/import_validators_test.go @@ -29,6 +29,11 @@ func TestImportValidateSchemeImportData(t *testing.T) { DisplayName: ptrStr("display name"), Permissions: &[]string{"invite_user"}, }, + DefaultTeamGuestRole: &RoleImportData{ + Name: ptrStr("name"), + DisplayName: ptrStr("display name"), + Permissions: &[]string{"invite_user"}, + }, DefaultChannelAdminRole: &RoleImportData{ Name: ptrStr("name"), DisplayName: ptrStr("display name"), @@ -39,6 +44,11 @@ func TestImportValidateSchemeImportData(t *testing.T) { DisplayName: ptrStr("display name"), Permissions: &[]string{"invite_user"}, }, + DefaultChannelGuestRole: &RoleImportData{ + Name: ptrStr("name"), + DisplayName: ptrStr("display name"), + Permissions: &[]string{"invite_user"}, + }, } if err := validateSchemeImportData(&data); err != nil { t.Fatal("Validation failed but should have been valid.", err) @@ -164,6 +174,18 @@ func TestImportValidateSchemeImportData(t *testing.T) { t.Fatal("Should have failed due to spurious role.") } + data.DefaultTeamUserRole = &RoleImportData{ + Name: ptrStr("name"), + DisplayName: ptrStr("display name"), + Permissions: &[]string{"invite_user"}, + } + data.DefaultTeamGuestRole = nil + if err := validateSchemeImportData(&data); err == nil { + t.Fatal("Should have failed due to spurious role.") + } + + data.DefaultTeamGuestRole = nil + data.DefaultTeamUserRole = nil data.DefaultTeamAdminRole = nil if err := validateSchemeImportData(&data); err != nil { t.Fatal("Should have succeeded.") diff --git a/app/migrations.go b/app/migrations.go index 2d668f101f..bd5014be1b 100644 --- a/app/migrations.go +++ b/app/migrations.go @@ -14,6 +14,7 @@ import ( const ADVANCED_PERMISSIONS_MIGRATION_KEY = "AdvancedPermissionsMigrationComplete" const EMOJIS_PERMISSIONS_MIGRATION_KEY = "EmojisPermissionsMigrationComplete" +const GUEST_ROLES_CREATION_MIGRATION_KEY = "GuestRolesCreationMigrationComplete" // This function migrates the default built in roles from code/config to the database. func (a *App) DoAdvancedPermissionsMigration() { @@ -156,3 +157,108 @@ func (a *App) DoEmojisPermissionsMigration() { mlog.Critical(fmt.Sprint(result.Err)) } } + +func (a *App) DoGuestRolesCreationMigration() { + // If the migration is already marked as completed, don't do it again. + if result := <-a.Srv.Store.System().GetByName(GUEST_ROLES_CREATION_MIGRATION_KEY); result.Err == nil { + return + } + + roles := model.MakeDefaultRoles() + + allSucceeded := true + if result := <-a.Srv.Store.Role().GetByName(model.CHANNEL_GUEST_ROLE_ID); result.Err != nil { + if result := <-a.Srv.Store.Role().Save(roles[model.CHANNEL_GUEST_ROLE_ID]); result.Err != nil { + mlog.Critical("Failed to create new guest role to database.") + mlog.Critical(fmt.Sprint(result.Err)) + allSucceeded = false + } + } + if result := <-a.Srv.Store.Role().GetByName(model.TEAM_GUEST_ROLE_ID); result.Err != nil { + if result := <-a.Srv.Store.Role().Save(roles[model.TEAM_GUEST_ROLE_ID]); result.Err != nil { + mlog.Critical("Failed to create new guest role to database.") + mlog.Critical(fmt.Sprint(result.Err)) + allSucceeded = false + } + } + if result := <-a.Srv.Store.Role().GetByName(model.SYSTEM_GUEST_ROLE_ID); result.Err != nil { + if result := <-a.Srv.Store.Role().Save(roles[model.SYSTEM_GUEST_ROLE_ID]); result.Err != nil { + mlog.Critical("Failed to create new guest role to database.") + mlog.Critical(fmt.Sprint(result.Err)) + allSucceeded = false + } + } + + resultSchemes := <-a.Srv.Store.Scheme().GetAllPage("", 0, 1000000) + if resultSchemes.Err != nil { + mlog.Critical("Failed to get all schemes.") + mlog.Critical(fmt.Sprint(resultSchemes.Err)) + allSucceeded = false + } + schemes := resultSchemes.Data.([]*model.Scheme) + for _, scheme := range schemes { + if scheme.DefaultTeamGuestRole == "" || scheme.DefaultChannelGuestRole == "" { + // Team Guest Role + teamGuestRole := &model.Role{ + Name: model.NewId(), + DisplayName: fmt.Sprintf("Team Guest Role for Scheme %s", scheme.Name), + Permissions: roles[model.TEAM_GUEST_ROLE_ID].Permissions, + SchemeManaged: true, + } + + if saveRoleResult := <-a.Srv.Store.Role().Save(teamGuestRole); saveRoleResult.Err != nil { + mlog.Critical("Failed to create new guest role for custom scheme.") + mlog.Critical(fmt.Sprint(saveRoleResult.Err)) + allSucceeded = false + } else { + scheme.DefaultTeamGuestRole = saveRoleResult.Data.(*model.Role).Name + } + + // Channel Guest Role + channelGuestRole := &model.Role{ + Name: model.NewId(), + DisplayName: fmt.Sprintf("Channel Guest Role for Scheme %s", scheme.Name), + Permissions: roles[model.CHANNEL_GUEST_ROLE_ID].Permissions, + SchemeManaged: true, + } + + if saveRoleResult := <-a.Srv.Store.Role().Save(channelGuestRole); saveRoleResult.Err != nil { + mlog.Critical("Failed to create new guest role for custom scheme.") + mlog.Critical(fmt.Sprint(saveRoleResult.Err)) + allSucceeded = false + } else { + scheme.DefaultChannelGuestRole = saveRoleResult.Data.(*model.Role).Name + } + + result := <-a.Srv.Store.Scheme().Save(scheme) + if result.Err != nil { + mlog.Critical("Failed to update custom scheme.") + mlog.Critical(fmt.Sprint(result.Err)) + allSucceeded = false + } + } + } + + if !allSucceeded { + return + } + + system := model.System{ + Name: GUEST_ROLES_CREATION_MIGRATION_KEY, + Value: "true", + } + + if result := <-a.Srv.Store.System().Save(&system); result.Err != nil { + mlog.Critical("Failed to mark guest roles creation migration as completed.") + mlog.Critical(fmt.Sprint(result.Err)) + } +} + +func (a *App) DoAppMigrations() { + a.DoAdvancedPermissionsMigration() + a.DoEmojisPermissionsMigration() + a.DoGuestRolesCreationMigration() + // This migration always must be the last, because can be based on previous + // migrations. For example, it needs the guest roles migration. + a.DoPermissionsMigrations() +} diff --git a/app/permissions.go b/app/permissions.go index a05a81a10c..e9fb6e25c7 100644 --- a/app/permissions.go +++ b/app/permissions.go @@ -58,9 +58,7 @@ func (a *App) ResetPermissionsSystem() *model.AppError { } // Now that the permissions system has been reset, re-run the migration to reinitialise it. - a.DoAdvancedPermissionsMigration() - a.DoEmojisPermissionsMigration() - a.DoPermissionsMigrations() + a.DoAppMigrations() return nil } @@ -77,8 +75,10 @@ func (a *App) ExportPermissions(w io.Writer) error { roleNames := []string{ scheme.DefaultTeamAdminRole, scheme.DefaultTeamUserRole, + scheme.DefaultTeamGuestRole, scheme.DefaultChannelAdminRole, scheme.DefaultChannelUserRole, + scheme.DefaultChannelGuestRole, } roles := []*model.Role{} @@ -100,8 +100,10 @@ func (a *App) ExportPermissions(w io.Writer) error { Scope: scheme.Scope, TeamAdmin: scheme.DefaultTeamAdminRole, TeamUser: scheme.DefaultTeamUserRole, + TeamGuest: scheme.DefaultTeamGuestRole, ChannelAdmin: scheme.DefaultChannelAdminRole, ChannelUser: scheme.DefaultChannelUserRole, + ChannelGuest: scheme.DefaultChannelGuestRole, Roles: roles, }) if err != nil { @@ -186,8 +188,10 @@ func (a *App) ImportPermissions(jsonl io.Reader) error { roleNameTuples := [][]string{ {schemeCreated.DefaultTeamAdminRole, schemeIn.DefaultTeamAdminRole}, {schemeCreated.DefaultTeamUserRole, schemeIn.DefaultTeamUserRole}, + {schemeCreated.DefaultTeamGuestRole, schemeIn.DefaultTeamGuestRole}, {schemeCreated.DefaultChannelAdminRole, schemeIn.DefaultChannelAdminRole}, {schemeCreated.DefaultChannelUserRole, schemeIn.DefaultChannelUserRole}, + {schemeCreated.DefaultChannelGuestRole, schemeIn.DefaultChannelGuestRole}, } for _, roleNameTuple := range roleNameTuples { if len(roleNameTuple[0]) == 0 || len(roleNameTuple[1]) == 0 { diff --git a/app/permissions_test.go b/app/permissions_test.go index d9d31ea176..b6db159b4a 100644 --- a/app/permissions_test.go +++ b/app/permissions_test.go @@ -69,8 +69,10 @@ func TestExportPermissions(t *testing.T) { scheme.Scope: func(str string) string { return row["scope"].(string) }, scheme.DefaultTeamAdminRole: func(str string) string { return getRoleByName(str) }, scheme.DefaultTeamUserRole: func(str string) string { return getRoleByName(str) }, + scheme.DefaultTeamGuestRole: func(str string) string { return getRoleByName(str) }, scheme.DefaultChannelAdminRole: func(str string) string { return getRoleByName(str) }, scheme.DefaultChannelUserRole: func(str string) string { return getRoleByName(str) }, + scheme.DefaultChannelGuestRole: func(str string) string { return getRoleByName(str) }, } for key, valF := range expectations { @@ -137,6 +139,11 @@ func TestImportPermissions(t *testing.T) { t.Error(appErr) } + channelGuestRole, appErr := th.App.GetRoleByName(newScheme.DefaultChannelGuestRole) + if appErr != nil { + t.Error(appErr) + } + expectations := map[string]string{ newScheme.DisplayName: displayName, newScheme.Name: name, @@ -144,8 +151,10 @@ func TestImportPermissions(t *testing.T) { newScheme.Scope: scope, newScheme.DefaultTeamAdminRole: "", newScheme.DefaultTeamUserRole: "", + newScheme.DefaultTeamGuestRole: "", channelAdminRole.Name: newScheme.DefaultChannelAdminRole, channelUserRole.Name: newScheme.DefaultChannelUserRole, + channelGuestRole.Name: newScheme.DefaultChannelGuestRole, } for actual, expected := range expectations { diff --git a/app/scheme.go b/app/scheme.go index b3bbb2614c..ea476c620a 100644 --- a/app/scheme.go +++ b/app/scheme.go @@ -61,8 +61,10 @@ func (a *App) CreateScheme(scheme *model.Scheme) (*model.Scheme, *model.AppError // Clear any user-provided values for trusted properties. scheme.DefaultTeamAdminRole = "" scheme.DefaultTeamUserRole = "" + scheme.DefaultTeamGuestRole = "" scheme.DefaultChannelAdminRole = "" scheme.DefaultChannelUserRole = "" + scheme.DefaultChannelGuestRole = "" scheme.CreateAt = 0 scheme.UpdateAt = 0 scheme.DeleteAt = 0 diff --git a/app/server_app_adapters.go b/app/server_app_adapters.go index 89ddbd8516..34afdd891a 100644 --- a/app/server_app_adapters.go +++ b/app/server_app_adapters.go @@ -137,9 +137,7 @@ func (s *Server) RunOldAppInitalization() error { s.FakeApp().LoadLicense() } - s.FakeApp().DoAdvancedPermissionsMigration() - s.FakeApp().DoEmojisPermissionsMigration() - s.FakeApp().DoPermissionsMigrations() + s.FakeApp().DoAppMigrations() s.FakeApp().InitPostMetadata() diff --git a/app/team.go b/app/team.go index 1c091abd1b..ca9d95beb0 100644 --- a/app/team.go +++ b/app/team.go @@ -229,21 +229,21 @@ func (a *App) sendTeamEvent(team *model.Team, event string) { a.Publish(message) } -func (a *App) GetSchemeRolesForTeam(teamId string) (string, string, *model.AppError) { +func (a *App) GetSchemeRolesForTeam(teamId string) (string, string, string, *model.AppError) { team, err := a.GetTeam(teamId) if err != nil { - return "", "", err + return "", "", "", err } if team.SchemeId != nil && len(*team.SchemeId) != 0 { scheme, err := a.GetScheme(*team.SchemeId) if err != nil { - return "", "", err + return "", "", "", err } - return scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole, nil + return scheme.DefaultTeamGuestRole, scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole, nil } - return model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID, nil + return model.TEAM_GUEST_ROLE_ID, model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID, nil } func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) { @@ -258,12 +258,15 @@ func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles strin return nil, err } - schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForTeam(teamId) + schemeGuestRole, schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForTeam(teamId) if err != nil { return nil, err } + prevSchemeGuestValue := member.SchemeGuest + var newExplicitRoles []string + member.SchemeGuest = false member.SchemeUser = false member.SchemeAdmin = false @@ -283,13 +286,23 @@ func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles strin member.SchemeAdmin = true case schemeUserRole: member.SchemeUser = true + case schemeGuestRole: + member.SchemeGuest = true default: - // If not part of the scheme for this channel, then it is not allowed to apply it as an explicit role. + // If not part of the scheme for this team, then it is not allowed to apply it as an explicit role. return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest) } } } + if member.SchemeGuest && member.SchemeUser { + return nil, model.NewAppError("UpdateTeamMemberRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) + } + + if prevSchemeGuestValue != member.SchemeGuest { + return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.changing_guest_role.app_error", nil, "", http.StatusBadRequest) + } + member.ExplicitRoles = strings.Join(newExplicitRoles, " ") result = <-a.Srv.Store.Team().UpdateMember(member) @@ -305,7 +318,7 @@ 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) { +func (a *App) UpdateTeamMemberSchemeRoles(teamId string, userId string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.TeamMember, *model.AppError) { member, err := a.GetTeamMember(teamId, userId) if err != nil { return nil, err @@ -313,10 +326,15 @@ func (a *App) UpdateTeamMemberSchemeRoles(teamId string, userId string, isScheme member.SchemeAdmin = isSchemeAdmin member.SchemeUser = isSchemeUser + member.SchemeGuest = isSchemeGuest + + if member.SchemeUser && member.SchemeGuest { + return nil, model.NewAppError("UpdateTeamMemberSchemeRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) + } // 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) + member.ExplicitRoles = RemoveRoles([]string{model.TEAM_GUEST_ROLE_ID, model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID}, member.ExplicitRoles) } result := <-a.Srv.Store.Team().UpdateMember(member) @@ -474,9 +492,10 @@ func (a *App) AddUserToTeamByInviteId(inviteId string, userId string) (*model.Te // 3. a pointer to an AppError if something went wrong. func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMember, bool, *model.AppError) { tm := &model.TeamMember{ - TeamId: team.Id, - UserId: user.Id, - SchemeUser: true, + TeamId: team.Id, + UserId: user.Id, + SchemeGuest: user.IsGuest(), + SchemeUser: !user.IsGuest(), } if team.Email == user.Email { diff --git a/app/team_test.go b/app/team_test.go index f18ec81d59..72945b1dfe 100644 --- a/app/team_test.go +++ b/app/team_test.go @@ -780,3 +780,71 @@ func TestGetTeamStats(t *testing.T) { require.Nil(t, err) assert.Equal(t, int64(len(members)), teamStats.TotalMemberCount) } + +func TestUpdateTeamMemberRolesChangingGuest(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + t.Run("from guest to user", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateGuest(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + if _, err := th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, "team_user"); err == nil { + t.Fatal("Should fail when try to modify the guest role") + } + }) + + t.Run("from user to guest", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateUser(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + if _, err := th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, "team_guest"); err == nil { + t.Fatal("Should fail when try to modify the guest role") + } + }) + + t.Run("from user to admin", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateUser(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + if _, err := th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, "team_user team_admin"); err != nil { + t.Fatal("Should work when you not modify guest role") + } + }) + + t.Run("from guest to guest plus custom", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateGuest(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + _, err = th.App.CreateRole(&model.Role{Name: "custom", DisplayName: "custom", Description: "custom"}) + require.Nil(t, err) + + if _, err := th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, "team_guest custom"); err != nil { + t.Fatal("Should work when you not modify guest role") + } + }) + + t.Run("a guest cant have user role", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateGuest(&user) + + _, err := th.App.AddUserToTeam(th.BasicTeam.Id, ruser.Id, "") + require.Nil(t, err) + + if _, err := th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, "team_guest team_user"); err == nil { + t.Fatal("Should work when you not modify guest role") + } + }) +} diff --git a/app/user.go b/app/user.go index fafde29633..0e31237414 100644 --- a/app/user.go +++ b/app/user.go @@ -223,11 +223,24 @@ func (a *App) indexUserFromId(userId string) *model.AppError { // CreateUser creates a user and sets several fields of the returned User struct to // their zero values. func (a *App) CreateUser(user *model.User) (*model.User, *model.AppError) { + return a.createUserOrGuest(user, false) +} + +// CreateGuest creates a guest and sets several fields of the returned User struct to +// their zero values. +func (a *App) CreateGuest(user *model.User) (*model.User, *model.AppError) { + return a.createUserOrGuest(user, true) +} + +func (a *App) createUserOrGuest(user *model.User, guest bool) (*model.User, *model.AppError) { if !user.IsLDAPUser() && !user.IsSAMLUser() && !CheckUserDomain(user, *a.Config().TeamSettings.RestrictCreationToDomains) { return nil, model.NewAppError("CreateUser", "api.user.create_user.accepted_domain.app_error", nil, "", http.StatusBadRequest) } user.Roles = model.SYSTEM_USER_ROLE_ID + if guest { + user.Roles = model.SYSTEM_GUEST_ROLE_ID + } // Below is a special case where the first user in the entire // system is granted the system_admin role diff --git a/cmd/mattermost/commands/init.go b/cmd/mattermost/commands/init.go index f36149db9d..812e3337a1 100644 --- a/cmd/mattermost/commands/init.go +++ b/cmd/mattermost/commands/init.go @@ -22,9 +22,7 @@ func InitDBCommandContextCobra(command *cobra.Command) (*app.App, error) { } a.InitPlugins(*a.Config().PluginSettings.Directory, *a.Config().PluginSettings.ClientDirectory) - a.DoAdvancedPermissionsMigration() - a.DoEmojisPermissionsMigration() - a.DoPermissionsMigrations() + a.DoAppMigrations() return a, nil } diff --git a/cmd/mattermost/commands/sampledata.go b/cmd/mattermost/commands/sampledata.go index 25ea4591e0..3a5c41f1a0 100644 --- a/cmd/mattermost/commands/sampledata.go +++ b/cmd/mattermost/commands/sampledata.go @@ -31,6 +31,7 @@ func init() { SampleDataCmd.Flags().IntP("teams", "t", 2, "The number of sample teams.") SampleDataCmd.Flags().Int("channels-per-team", 10, "The number of sample channels per team.") SampleDataCmd.Flags().IntP("users", "u", 15, "The number of sample users.") + SampleDataCmd.Flags().IntP("guests", "g", 1, "The number of sample guests.") SampleDataCmd.Flags().Int("team-memberships", 2, "The number of sample team memberships per user.") SampleDataCmd.Flags().Int("channel-memberships", 5, "The number of sample channel memberships per user in a team.") SampleDataCmd.Flags().Int("posts-per-channel", 100, "The number of sample post per channel.") @@ -164,6 +165,10 @@ func sampleDataCmdF(command *cobra.Command, args []string) error { if err != nil || users < 0 { return errors.New("Invalid users parameter") } + guests, err := command.Flags().GetInt("guests") + if err != nil || guests < 0 { + return errors.New("Invalid guests parameter") + } teamMemberships, err := command.Flags().GetInt("team-memberships") if err != nil || teamMemberships < 0 { return errors.New("Invalid team-memberships parameter") @@ -278,7 +283,12 @@ func sampleDataCmdF(command *cobra.Command, args []string) error { allUsers := []string{} for i := 0; i < users; i++ { - userLine := createUser(i, teamMemberships, channelMemberships, teamsAndChannels, profileImages) + userLine := createUser(i, teamMemberships, channelMemberships, teamsAndChannels, profileImages, false) + encoder.Encode(userLine) + allUsers = append(allUsers, *userLine.User.Username) + } + for i := 0; i < guests; i++ { + userLine := createUser(i, teamMemberships, channelMemberships, teamsAndChannels, profileImages, true) encoder.Encode(userLine) allUsers = append(allUsers, *userLine.User.Username) } @@ -345,22 +355,35 @@ func sampleDataCmdF(command *cobra.Command, args []string) error { return nil } -func createUser(idx int, teamMemberships int, channelMemberships int, teamsAndChannels map[string][]string, profileImages []string) app.LineImportData { +func createUser(idx int, teamMemberships int, channelMemberships int, teamsAndChannels map[string][]string, profileImages []string, guest bool) app.LineImportData { password := fmt.Sprintf("user-%d", idx) email := fmt.Sprintf("user-%d@sample.mattermost.com", idx) + if guest { + password = fmt.Sprintf("guest-%d", idx) + email = fmt.Sprintf("guest-%d@sample.mattermost.com", idx) + } firstName := fake.FirstName() lastName := fake.LastName() username := fmt.Sprintf("%s.%s", strings.ToLower(firstName), strings.ToLower(lastName)) - if idx == 0 { + if guest { + if idx == 0 { + username = "guest" + password = "guest" + email = "guest@sample.mattermost.com" + } + } else if idx == 0 { username = "sysadmin" password = "sysadmin" email = "sysadmin@sample.mattermost.com" } else if idx == 1 { username = "user-1" } + position := fake.JobTitle() roles := "system_user" - if idx%5 == 0 { + if guest { + roles = "system_guest" + } else if idx%5 == 0 { roles = "system_admin system_user" } @@ -427,7 +450,7 @@ func createUser(idx int, teamMemberships int, channelMemberships int, teamsAndCh team := possibleTeams[position] possibleTeams = append(possibleTeams[:position], possibleTeams[position+1:]...) if teamChannels, err := teamsAndChannels[team]; err { - teams = append(teams, createTeamMembership(channelMemberships, teamChannels, &team)) + teams = append(teams, createTeamMembership(channelMemberships, teamChannels, &team, guest)) } } @@ -454,9 +477,11 @@ func createUser(idx int, teamMemberships int, channelMemberships int, teamsAndCh } } -func createTeamMembership(numOfchannels int, teamChannels []string, teamName *string) app.UserTeamImportData { +func createTeamMembership(numOfchannels int, teamChannels []string, teamName *string, guest bool) app.UserTeamImportData { roles := "team_user" - if rand.Intn(5) == 0 { + if guest { + roles = "team_guest" + } else if rand.Intn(5) == 0 { roles = "team_user team_admin" } channels := []app.UserChannelImportData{} @@ -468,7 +493,7 @@ func createTeamMembership(numOfchannels int, teamChannels []string, teamName *st position := rand.Intn(len(teamChannelsCopy)) channelName := teamChannelsCopy[position] teamChannelsCopy = append(teamChannelsCopy[:position], teamChannelsCopy[position+1:]...) - channels = append(channels, createChannelMembership(channelName)) + channels = append(channels, createChannelMembership(channelName, guest)) } return app.UserTeamImportData{ @@ -478,9 +503,11 @@ func createTeamMembership(numOfchannels int, teamChannels []string, teamName *st } } -func createChannelMembership(channelName string) app.UserChannelImportData { +func createChannelMembership(channelName string, guest bool) app.UserChannelImportData { roles := "channel_user" - if rand.Intn(5) == 0 { + if guest { + roles = "channel_guest" + } else if rand.Intn(5) == 0 { roles = "channel_user channel_admin" } favorite := rand.Intn(5) == 0 diff --git a/i18n/en.json b/i18n/en.json index 4a1342984c..4555ffc133 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -319,6 +319,14 @@ "id": "api.channel.update_channel.tried.app_error", "translation": "Tried to perform an invalid update of the default channel {{.Channel}}" }, + { + "id": "api.channel.update_channel_member_roles.changing_guest_role.app_error", + "translation": "Invalid channel member update: You can't add or remove the guest role manually" + }, + { + "id": "api.channel.update_channel_member_roles.guest_and_user.app_error", + "translation": "Invalid channel member update: A user must be a guest or a user but not both." + }, { "id": "api.channel.update_channel_member_roles.scheme_role.app_error", "translation": "The provided role is managed by a Scheme and therefore cannot be applied directly to a Channel Member" @@ -331,6 +339,10 @@ "id": "api.channel.update_channel_scheme.scheme_scope.error", "translation": "Unable to set the scheme to the channel because the supplied scheme is not a channel scheme." }, + { + "id": "api.channel.update_team_member_roles.changing_guest_role.app_error", + "translation": "Invalid team member update: You can't add or remove the guest role manually" + }, { "id": "api.channel.update_team_member_roles.scheme_role.app_error", "translation": "The provided role is managed by a Scheme and therefore cannot be applied directly to a Team Member" @@ -1930,6 +1942,10 @@ "id": "api.team.update_restricted_domains.mismatch.app_error", "translation": "Restricting team to {{ .Domain }} is not allowed by the system config. Please contact your system administrator." }, + { + "id": "api.team.update_team_member_roles.guest_and_user.app_error", + "translation": "Invalid team member update: A user must be a guest or a user but not both." + }, { "id": "api.team.update_team_scheme.license.error", "translation": "Your license does not support updating a team's scheme" diff --git a/migrations/helper_test.go b/migrations/helper_test.go index 82d8cb176e..9bda859720 100644 --- a/migrations/helper_test.go +++ b/migrations/helper_test.go @@ -63,8 +63,7 @@ func setupTestHelper(enterprise bool) *TestHelper { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress }) - th.App.DoAdvancedPermissionsMigration() - th.App.DoEmojisPermissionsMigration() + th.App.DoAppMigrations() th.App.Srv.Store.MarkSystemRanUnitTests() diff --git a/model/channel_member.go b/model/channel_member.go index f2c49efac1..6bfa9bf656 100644 --- a/model/channel_member.go +++ b/model/channel_member.go @@ -40,6 +40,7 @@ type ChannelMember struct { MentionCount int64 `json:"mention_count"` NotifyProps StringMap `json:"notify_props"` LastUpdateAt int64 `json:"last_update_at"` + SchemeGuest bool `json:"scheme_guest"` SchemeUser bool `json:"scheme_user"` SchemeAdmin bool `json:"scheme_admin"` ExplicitRoles string `json:"explicit_roles"` diff --git a/model/role.go b/model/role.go index eb8ad5c84f..86dcd85499 100644 --- a/model/role.go +++ b/model/role.go @@ -10,17 +10,20 @@ import ( ) const ( + SYSTEM_GUEST_ROLE_ID = "system_guest" SYSTEM_USER_ROLE_ID = "system_user" SYSTEM_ADMIN_ROLE_ID = "system_admin" SYSTEM_POST_ALL_ROLE_ID = "system_post_all" SYSTEM_POST_ALL_PUBLIC_ROLE_ID = "system_post_all_public" SYSTEM_USER_ACCESS_TOKEN_ROLE_ID = "system_user_access_token" + TEAM_GUEST_ROLE_ID = "team_guest" TEAM_USER_ROLE_ID = "team_user" TEAM_ADMIN_ROLE_ID = "team_admin" TEAM_POST_ALL_ROLE_ID = "team_post_all" TEAM_POST_ALL_PUBLIC_ROLE_ID = "team_post_all_public" + CHANNEL_GUEST_ROLE_ID = "channel_guest" CHANNEL_USER_ROLE_ID = "channel_user" CHANNEL_ADMIN_ROLE_ID = "channel_admin" @@ -173,6 +176,23 @@ func IsValidRoleName(roleName string) bool { func MakeDefaultRoles() map[string]*Role { roles := make(map[string]*Role) + roles[CHANNEL_GUEST_ROLE_ID] = &Role{ + Name: "channel_guest", + DisplayName: "authentication.roles.channel_guest.name", + Description: "authentication.roles.channel_guest.description", + Permissions: []string{ + PERMISSION_READ_CHANNEL.Id, + PERMISSION_ADD_REACTION.Id, + PERMISSION_REMOVE_REACTION.Id, + PERMISSION_UPLOAD_FILE.Id, + PERMISSION_EDIT_POST.Id, + PERMISSION_CREATE_POST.Id, + PERMISSION_USE_SLASH_COMMANDS.Id, + }, + SchemeManaged: true, + BuiltIn: true, + } + roles[CHANNEL_USER_ROLE_ID] = &Role{ Name: "channel_user", DisplayName: "authentication.roles.channel_user.name", @@ -202,6 +222,17 @@ func MakeDefaultRoles() map[string]*Role { BuiltIn: true, } + roles[TEAM_GUEST_ROLE_ID] = &Role{ + Name: "team_guest", + DisplayName: "authentication.roles.team_guest.name", + Description: "authentication.roles.team_guest.description", + Permissions: []string{ + PERMISSION_VIEW_TEAM.Id, + }, + SchemeManaged: true, + BuiltIn: true, + } + roles[TEAM_USER_ROLE_ID] = &Role{ Name: "team_user", DisplayName: "authentication.roles.team_user.name", @@ -259,6 +290,18 @@ func MakeDefaultRoles() map[string]*Role { BuiltIn: true, } + roles[SYSTEM_GUEST_ROLE_ID] = &Role{ + Name: "system_guest", + DisplayName: "authentication.roles.global_guest.name", + Description: "authentication.roles.global_guest.description", + Permissions: []string{ + PERMISSION_CREATE_DIRECT_CHANNEL.Id, + PERMISSION_CREATE_GROUP_CHANNEL.Id, + }, + SchemeManaged: true, + BuiltIn: true, + } + roles[SYSTEM_USER_ROLE_ID] = &Role{ Name: "system_user", DisplayName: "authentication.roles.global_user.name", diff --git a/model/scheme.go b/model/scheme.go index 0c38b560f9..f40a9599c3 100644 --- a/model/scheme.go +++ b/model/scheme.go @@ -29,8 +29,10 @@ type Scheme struct { Scope string `json:"scope"` DefaultTeamAdminRole string `json:"default_team_admin_role"` DefaultTeamUserRole string `json:"default_team_user_role"` + DefaultTeamGuestRole string `json:"default_team_guest_role"` DefaultChannelAdminRole string `json:"default_channel_admin_role"` DefaultChannelUserRole string `json:"default_channel_user_role"` + DefaultChannelGuestRole string `json:"default_channel_guest_role"` } type SchemePatch struct { @@ -51,8 +53,10 @@ type SchemeConveyor struct { Scope string `json:"scope"` TeamAdmin string `json:"default_team_admin_role"` TeamUser string `json:"default_team_user_role"` + TeamGuest string `json:"default_team_guest_role"` ChannelAdmin string `json:"default_channel_admin_role"` ChannelUser string `json:"default_channel_user_role"` + ChannelGuest string `json:"default_channel_guest_role"` Roles []*Role `json:"roles"` } @@ -64,14 +68,17 @@ func (sc *SchemeConveyor) Scheme() *Scheme { Scope: sc.Scope, DefaultTeamAdminRole: sc.TeamAdmin, DefaultTeamUserRole: sc.TeamUser, + DefaultTeamGuestRole: sc.TeamGuest, DefaultChannelAdminRole: sc.ChannelAdmin, DefaultChannelUserRole: sc.ChannelUser, + DefaultChannelGuestRole: sc.ChannelGuest, } } type SchemeRoles struct { SchemeAdmin bool `json:"scheme_admin"` SchemeUser bool `json:"scheme_user"` + SchemeGuest bool `json:"scheme_guest"` } func (scheme *Scheme) ToJson() string { @@ -134,6 +141,10 @@ func (scheme *Scheme) IsValidForCreate() bool { return false } + if !IsValidRoleName(scheme.DefaultChannelGuestRole) { + return false + } + if scheme.Scope == SCHEME_SCOPE_TEAM { if !IsValidRoleName(scheme.DefaultTeamAdminRole) { return false @@ -142,6 +153,10 @@ func (scheme *Scheme) IsValidForCreate() bool { if !IsValidRoleName(scheme.DefaultTeamUserRole) { return false } + + if !IsValidRoleName(scheme.DefaultTeamGuestRole) { + return false + } } if scheme.Scope == SCHEME_SCOPE_CHANNEL { @@ -152,6 +167,10 @@ func (scheme *Scheme) IsValidForCreate() bool { if len(scheme.DefaultTeamUserRole) != 0 { return false } + + if len(scheme.DefaultTeamGuestRole) != 0 { + return false + } } return true diff --git a/model/team_member.go b/model/team_member.go index 3bae3d7e95..4b33c1410a 100644 --- a/model/team_member.go +++ b/model/team_member.go @@ -15,6 +15,7 @@ type TeamMember struct { UserId string `json:"user_id"` Roles string `json:"roles"` DeleteAt int64 `json:"delete_at"` + SchemeGuest bool `json:"scheme_guest"` SchemeUser bool `json:"scheme_user"` SchemeAdmin bool `json:"scheme_admin"` ExplicitRoles string `json:"explicit_roles"` diff --git a/model/user.go b/model/user.go index 83eef18ee5..4e24c0b158 100644 --- a/model/user.go +++ b/model/user.go @@ -565,6 +565,12 @@ func IsValidUserRoles(userRoles string) bool { return true } +// Make sure you acually want to use this function. In context.go there are functions to check permissions +// This function should not be used to check permissions. +func (u *User) IsGuest() bool { + return IsInRole(u.Roles, SYSTEM_GUEST_ROLE_ID) +} + // Make sure you acually want to use this function. In context.go there are functions to check permissions // This function should not be used to check permissions. func (u *User) IsInRole(inRole string) bool { diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go index bf67e96c37..a05d9d37c0 100644 --- a/store/sqlstore/channel_store.go +++ b/store/sqlstore/channel_store.go @@ -49,6 +49,7 @@ type channelMember struct { MentionCount int64 NotifyProps model.StringMap LastUpdateAt int64 + SchemeGuest sql.NullBool SchemeUser sql.NullBool SchemeAdmin sql.NullBool } @@ -63,6 +64,7 @@ func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember { MentionCount: cm.MentionCount, NotifyProps: cm.NotifyProps, LastUpdateAt: cm.LastUpdateAt, + SchemeGuest: sql.NullBool{Valid: true, Bool: cm.SchemeGuest}, SchemeUser: sql.NullBool{Valid: true, Bool: cm.SchemeUser}, SchemeAdmin: sql.NullBool{Valid: true, Bool: cm.SchemeAdmin}, } @@ -77,10 +79,13 @@ type channelMemberWithSchemeRoles struct { MentionCount int64 NotifyProps model.StringMap LastUpdateAt int64 + SchemeGuest sql.NullBool SchemeUser sql.NullBool SchemeAdmin sql.NullBool + TeamSchemeDefaultGuestRole sql.NullString TeamSchemeDefaultUserRole sql.NullString TeamSchemeDefaultAdminRole sql.NullString + ChannelSchemeDefaultGuestRole sql.NullString ChannelSchemeDefaultUserRole sql.NullString ChannelSchemeDefaultAdminRole sql.NullString } @@ -93,11 +98,16 @@ func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember { // Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated, // and exclude them from ExplicitRoles field. + schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool for _, role := range strings.Fields(db.Roles) { isImplicit := false - if role == model.CHANNEL_USER_ROLE_ID { + if role == model.CHANNEL_GUEST_ROLE_ID { + // We have an implicit role via the system scheme. Override the "schemeGuest" field to true. + schemeGuest = true + isImplicit = true + } else if role == model.CHANNEL_USER_ROLE_ID { // We have an implicit role via the system scheme. Override the "schemeUser" field to true. schemeUser = true isImplicit = true @@ -116,6 +126,15 @@ func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember { // Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add // them to the Roles field for backwards compatibility reasons. var schemeImpliedRoles []string + if db.SchemeGuest.Valid && db.SchemeGuest.Bool { + if db.ChannelSchemeDefaultGuestRole.Valid && db.ChannelSchemeDefaultGuestRole.String != "" { + schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultGuestRole.String) + } else if db.TeamSchemeDefaultGuestRole.Valid && db.TeamSchemeDefaultGuestRole.String != "" { + schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultGuestRole.String) + } else { + schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_GUEST_ROLE_ID) + } + } if db.SchemeUser.Valid && db.SchemeUser.Bool { if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" { schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String) @@ -157,6 +176,7 @@ func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember { LastUpdateAt: db.LastUpdateAt, SchemeAdmin: schemeAdmin, SchemeUser: schemeUser, + SchemeGuest: schemeGuest, ExplicitRoles: strings.Join(explicitRoles, " "), } } @@ -174,10 +194,13 @@ func (db channelMemberWithSchemeRolesList) ToModel() *model.ChannelMembers { type allChannelMember struct { ChannelId string Roles string + SchemeGuest sql.NullBool SchemeUser sql.NullBool SchemeAdmin sql.NullBool + TeamSchemeDefaultGuestRole sql.NullString TeamSchemeDefaultUserRole sql.NullString TeamSchemeDefaultAdminRole sql.NullString + ChannelSchemeDefaultGuestRole sql.NullString ChannelSchemeDefaultUserRole sql.NullString ChannelSchemeDefaultAdminRole sql.NullString } @@ -190,6 +213,15 @@ func (db allChannelMember) Process() (string, string) { // Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add // them to the Roles field for backwards compatibility reasons. var schemeImpliedRoles []string + if db.SchemeGuest.Valid && db.SchemeGuest.Bool { + if db.ChannelSchemeDefaultGuestRole.Valid && db.ChannelSchemeDefaultGuestRole.String != "" { + schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultGuestRole.String) + } else if db.TeamSchemeDefaultGuestRole.Valid && db.TeamSchemeDefaultGuestRole.String != "" { + schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultGuestRole.String) + } else { + schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_GUEST_ROLE_ID) + } + } if db.SchemeUser.Valid && db.SchemeUser.Bool { if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" { schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String) @@ -1266,8 +1298,10 @@ func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int) store. var CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY = ` SELECT ChannelMembers.*, + TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole, TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole, TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole, + ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole, ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole, ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole FROM @@ -1464,8 +1498,10 @@ func (s SqlChannelStore) GetMemberForPost(postId string, userId string) store.St ` SELECT ChannelMembers.*, + TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole, TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole, TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole, + ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole, ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole, ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole FROM @@ -1518,9 +1554,12 @@ func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCac var data allChannelMembers _, err := s.GetReplica().Select(&data, ` SELECT - ChannelMembers.ChannelId, ChannelMembers.Roles, ChannelMembers.SchemeUser, ChannelMembers.SchemeAdmin, + ChannelMembers.ChannelId, ChannelMembers.Roles, + ChannelMembers.SchemeGuest, ChannelMembers.SchemeUser, ChannelMembers.SchemeAdmin, + TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole, TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole, TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole, + ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole, ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole, ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole FROM @@ -2336,11 +2375,16 @@ func (s SqlChannelStore) MigrateChannelMembers(fromChannelId string, fromUserId if !member.SchemeUser.Valid { member.SchemeUser = sql.NullBool{Bool: false, Valid: true} } + if !member.SchemeGuest.Valid { + member.SchemeGuest = sql.NullBool{Bool: false, Valid: true} + } for _, role := range roles { if role == model.CHANNEL_ADMIN_ROLE_ID { member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true} } else if role == model.CHANNEL_USER_ROLE_ID { member.SchemeUser = sql.NullBool{Bool: true, Valid: true} + } else if role == model.CHANNEL_GUEST_ROLE_ID { + member.SchemeGuest = sql.NullBool{Bool: true, Valid: true} } else { newRoles = append(newRoles, role) } @@ -2492,7 +2536,17 @@ func (s SqlChannelStore) GetChannelMembersForExport(userId string, teamId string var members []*model.ChannelMemberForExport _, err := s.GetReplica().Select(&members, ` SELECT - ChannelMembers.*, + ChannelMembers.ChannelId, + ChannelMembers.UserId, + ChannelMembers.Roles, + ChannelMembers.LastViewedAt, + ChannelMembers.MsgCount, + ChannelMembers.MentionCount, + ChannelMembers.NotifyProps, + ChannelMembers.LastUpdateAt, + ChannelMembers.SchemeUser, + ChannelMembers.SchemeAdmin, + (ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) as SchemeGuest, Channels.Name as ChannelName FROM ChannelMembers @@ -2543,7 +2597,7 @@ func (s SqlChannelStore) GetAllDirectChannelsForExportAfter(limit int, afterId s channelIds = append(channelIds, channel.Id) } query = s.getQueryBuilder(). - Select("*"). + Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest"). From("ChannelMembers cm"). Join("Users u ON ( u.Id = cm.UserId )"). Where(sq.And{ diff --git a/store/sqlstore/channel_store_test.go b/store/sqlstore/channel_store_test.go index 5eb84afcdb..0ba334643e 100644 --- a/store/sqlstore/channel_store_test.go +++ b/store/sqlstore/channel_store_test.go @@ -33,6 +33,7 @@ func testNewChannelMemberFromModel(t *testing.T) { MentionCount: 1, NotifyProps: model.StringMap{"key": "value"}, LastUpdateAt: 54321, + SchemeGuest: false, SchemeUser: true, SchemeAdmin: true, ExplicitRoles: "custom_role", @@ -47,8 +48,10 @@ func testNewChannelMemberFromModel(t *testing.T) { assert.Equal(t, m.MentionCount, db.MentionCount) assert.Equal(t, m.NotifyProps, db.NotifyProps) assert.Equal(t, m.LastUpdateAt, db.LastUpdateAt) + assert.Equal(t, true, db.SchemeGuest.Valid) assert.Equal(t, true, db.SchemeUser.Valid) assert.Equal(t, true, db.SchemeAdmin.Valid) + assert.Equal(t, m.SchemeGuest, db.SchemeGuest.Bool) assert.Equal(t, m.SchemeUser, db.SchemeUser.Bool) assert.Equal(t, m.SchemeAdmin, db.SchemeAdmin.Bool) assert.Equal(t, m.ExplicitRoles, db.Roles) @@ -66,10 +69,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { MentionCount: 1, NotifyProps: model.StringMap{"key": "value"}, LastUpdateAt: 54321, + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -84,6 +90,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { assert.Equal(t, db.MentionCount, m.MentionCount) assert.Equal(t, db.NotifyProps, m.NotifyProps) assert.Equal(t, db.LastUpdateAt, m.LastUpdateAt) + assert.Equal(t, db.SchemeGuest.Bool, m.SchemeGuest) assert.Equal(t, db.SchemeUser.Bool, m.SchemeUser) assert.Equal(t, db.SchemeAdmin.Bool, m.SchemeAdmin) assert.Equal(t, db.Roles, m.ExplicitRoles) @@ -93,10 +100,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_User", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "channel_user", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -104,6 +114,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "channel_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -112,10 +123,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_Admin", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "channel_admin channel_user", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -123,6 +137,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "channel_admin channel_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -131,10 +146,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_CustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -150,10 +168,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_UserAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "channel_user custom_role", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -161,6 +182,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "channel_user custom_role", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -169,10 +191,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_AdminAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "channel_user channel_admin custom_role", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -180,6 +205,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "channel_user channel_admin custom_role", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -188,10 +214,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_NoRoles", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -199,6 +228,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -208,10 +238,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_User", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -219,6 +252,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "channel_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -227,10 +261,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_Admin", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -238,18 +275,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "channel_user channel_admin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) }) + t.Run("Migrated_NoScheme_Guest", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + cm := db.ToModel() + + assert.Equal(t, "channel_guest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "", cm.ExplicitRoles) + }) + t.Run("Migrated_NoScheme_CustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -257,6 +321,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -265,6 +330,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_UserAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, @@ -276,6 +342,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role channel_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -284,10 +351,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_AdminAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -295,18 +365,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role channel_user channel_admin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) }) + t.Run("Migrated_NoScheme_GuestAndCustomRole", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + cm := db.ToModel() + + assert.Equal(t, "custom_role channel_guest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "custom_role", cm.ExplicitRoles) + }) + t.Run("Migrated_NoScheme_NoRoles", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -314,6 +411,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -323,10 +421,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_ChannelScheme_User", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -334,6 +435,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "cscheme_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -342,10 +444,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_ChannelScheme_Admin", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -353,18 +458,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "cscheme_user cscheme_admin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) }) + t.Run("Migrated_ChannelScheme_Guest", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, + } + + cm := db.ToModel() + + assert.Equal(t, "cscheme_guest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "", cm.ExplicitRoles) + }) + t.Run("Migrated_ChannelScheme_CustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -372,6 +504,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -380,10 +513,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_ChannelScheme_UserAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -391,6 +527,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role cscheme_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -399,10 +536,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_ChannelScheme_AdminAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -410,18 +550,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role cscheme_user cscheme_admin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) }) + t.Run("Migrated_ChannelScheme_GuestAndCustomRole", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, + } + + cm := db.ToModel() + + assert.Equal(t, "custom_role cscheme_guest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "custom_role", cm.ExplicitRoles) + }) + t.Run("Migrated_ChannelScheme_NoRoles", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -429,6 +596,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -438,10 +606,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_User", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -449,6 +620,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "tscheme_channeluser", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -457,10 +629,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_Admin", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -468,18 +643,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "tscheme_channeluser tscheme_channeladmin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) }) + t.Run("Migrated_TeamScheme_Guest", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + cm := db.ToModel() + + assert.Equal(t, "tscheme_channelguest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "", cm.ExplicitRoles) + }) + t.Run("Migrated_TeamScheme_CustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -487,6 +689,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -495,10 +698,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_UserAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -506,6 +712,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role tscheme_channeluser", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -514,10 +721,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_AdminAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -525,18 +735,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role tscheme_channeluser tscheme_channeladmin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) }) + t.Run("Migrated_TeamScheme_GuestAndCustomRole", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + cm := db.ToModel() + + assert.Equal(t, "custom_role tscheme_channelguest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "custom_role", cm.ExplicitRoles) + }) + t.Run("Migrated_TeamScheme_NoRoles", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -544,6 +781,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -553,10 +791,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamAndChannelScheme_User", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -564,6 +805,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "cscheme_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -572,10 +814,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamAndChannelScheme_Admin", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -583,18 +828,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "cscheme_user cscheme_admin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) }) + t.Run("Migrated_TeamAndChannelScheme_Guest", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, + } + + cm := db.ToModel() + + assert.Equal(t, "cscheme_guest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "", cm.ExplicitRoles) + }) + t.Run("Migrated_TeamAndChannelScheme_CustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -602,6 +874,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -610,10 +883,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamAndChannelScheme_UserAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -621,6 +897,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role cscheme_user", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) @@ -629,10 +906,13 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamAndChannelScheme_AdminAndCustomRole", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -640,18 +920,45 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "custom_role cscheme_user cscheme_admin", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, true, cm.SchemeUser) assert.Equal(t, true, cm.SchemeAdmin) assert.Equal(t, "custom_role", cm.ExplicitRoles) }) + t.Run("Migrated_TeamAndChannelScheme_GuestAndCustomRole", func(t *testing.T) { + db := channelMemberWithSchemeRoles{ + Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, + } + + cm := db.ToModel() + + assert.Equal(t, "custom_role cscheme_guest", cm.Roles) + assert.Equal(t, true, cm.SchemeGuest) + assert.Equal(t, false, cm.SchemeUser) + assert.Equal(t, false, cm.SchemeAdmin) + assert.Equal(t, "custom_role", cm.ExplicitRoles) + }) + t.Run("Migrated_TeamAndChannelScheme_NoRoles", func(t *testing.T) { db := channelMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -659,6 +966,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) { cm := db.ToModel() assert.Equal(t, "", cm.Roles) + assert.Equal(t, false, cm.SchemeGuest) assert.Equal(t, false, cm.SchemeUser) assert.Equal(t, false, cm.SchemeAdmin) assert.Equal(t, "", cm.ExplicitRoles) @@ -669,10 +977,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("Unmigrated_User", func(t *testing.T) { db := allChannelMember{ Roles: "channel_user", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -685,10 +996,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("Unmigrated_Admin", func(t *testing.T) { db := allChannelMember{ Roles: "channel_user channel_admin", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -698,13 +1012,16 @@ func testAllChannelMemberProcess(t *testing.T) { assert.Equal(t, "channel_user channel_admin", roles) }) - t.Run("Unmigrated_Neither", func(t *testing.T) { + t.Run("Unmigrated_None", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -717,10 +1034,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("Unmigrated_Custom", func(t *testing.T) { db := allChannelMember{ Roles: "custom", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -733,10 +1053,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedNoScheme_User", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -749,10 +1072,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedNoScheme_Admin", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -762,13 +1088,35 @@ func testAllChannelMemberProcess(t *testing.T) { assert.Equal(t, "channel_user channel_admin", roles) }) - t.Run("MigratedNoScheme_Neither", func(t *testing.T) { + t.Run("MigratedNoScheme_Guest", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + _, roles := db.Process() + + assert.Equal(t, "channel_guest", roles) + }) + + t.Run("MigratedNoScheme_None", func(t *testing.T) { + db := allChannelMember{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -781,10 +1129,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedChannelScheme_User", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -797,10 +1148,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedChannelScheme_Admin", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -810,13 +1164,35 @@ func testAllChannelMemberProcess(t *testing.T) { assert.Equal(t, "cscheme_user cscheme_admin", roles) }) - t.Run("MigratedChannelScheme_Neither", func(t *testing.T) { + t.Run("MigratedChannelScheme_Guest", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, + } + + _, roles := db.Process() + + assert.Equal(t, "cscheme_guest", roles) + }) + + t.Run("MigratedChannelScheme_None", func(t *testing.T) { + db := allChannelMember{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -829,10 +1205,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedTeamScheme_User", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -845,10 +1224,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedTeamScheme_Admin", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -858,13 +1240,35 @@ func testAllChannelMemberProcess(t *testing.T) { assert.Equal(t, "tscheme_channeluser tscheme_channeladmin", roles) }) - t.Run("MigratedTeamScheme_Neither", func(t *testing.T) { + t.Run("MigratedTeamScheme_Guest", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + _, roles := db.Process() + + assert.Equal(t, "tscheme_channelguest", roles) + }) + + t.Run("MigratedTeamScheme_None", func(t *testing.T) { + db := allChannelMember{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -877,10 +1281,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedTeamAndChannelScheme_User", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -893,10 +1300,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("MigratedTeamAndChannelScheme_Admin", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -906,13 +1316,35 @@ func testAllChannelMemberProcess(t *testing.T) { assert.Equal(t, "cscheme_user cscheme_admin", roles) }) - t.Run("MigratedTeamAndChannelScheme_Neither", func(t *testing.T) { + t.Run("MigratedTeamAndChannelScheme_Guest", func(t *testing.T) { db := allChannelMember{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, + ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, + ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, + } + + _, roles := db.Process() + + assert.Equal(t, "cscheme_guest", roles) + }) + + t.Run("MigratedTeamAndChannelScheme_None", func(t *testing.T) { + db := allChannelMember{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_channelguest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_channeluser"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_channeladmin"}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "cscheme_guest"}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: true, String: "cscheme_user"}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "cscheme_admin"}, } @@ -925,10 +1357,13 @@ func testAllChannelMemberProcess(t *testing.T) { t.Run("DeduplicationCheck", func(t *testing.T) { db := allChannelMember{ Roles: "channel_user", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + ChannelSchemeDefaultGuestRole: sql.NullString{Valid: false}, ChannelSchemeDefaultUserRole: sql.NullString{Valid: false}, ChannelSchemeDefaultAdminRole: sql.NullString{Valid: false}, } diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go index b515563501..9d8c761975 100644 --- a/store/sqlstore/post_store.go +++ b/store/sqlstore/post_store.go @@ -1401,7 +1401,7 @@ func (s *SqlPostStore) GetDirectPostParentsForExportAfter(limit int, afterId str channelIds = append(channelIds, post.ChannelId) } query = s.getQueryBuilder(). - Select("*"). + Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest"). From("ChannelMembers cm"). Join("Users u ON ( u.Id = cm.UserId )"). Where(sq.Eq{ diff --git a/store/sqlstore/scheme_supplier.go b/store/sqlstore/scheme_supplier.go index b3ca7154b1..5fd23fed32 100644 --- a/store/sqlstore/scheme_supplier.go +++ b/store/sqlstore/scheme_supplier.go @@ -26,8 +26,10 @@ func initSqlSupplierSchemes(sqlStore SqlStore) { table.ColMap("Scope").SetMaxSize(32) table.ColMap("DefaultTeamAdminRole").SetMaxSize(64) table.ColMap("DefaultTeamUserRole").SetMaxSize(64) + table.ColMap("DefaultTeamGuestRole").SetMaxSize(64) table.ColMap("DefaultChannelAdminRole").SetMaxSize(64) table.ColMap("DefaultChannelUserRole").SetMaxSize(64) + table.ColMap("DefaultChannelGuestRole").SetMaxSize(64) } } @@ -71,7 +73,7 @@ func (s *SqlSupplier) createScheme(ctx context.Context, scheme *model.Scheme, tr result := store.NewSupplierResult() // Fetch the default system scheme roles to populate default permissions. - defaultRoleNames := []string{model.TEAM_ADMIN_ROLE_ID, model.TEAM_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID, model.CHANNEL_USER_ROLE_ID} + defaultRoleNames := []string{model.TEAM_ADMIN_ROLE_ID, model.TEAM_USER_ROLE_ID, model.TEAM_GUEST_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID, model.CHANNEL_USER_ROLE_ID, model.CHANNEL_GUEST_ROLE_ID} defaultRoles := make(map[string]*model.Role) if rolesResult := s.RoleGetByNames(ctx, defaultRoleNames); rolesResult.Err != nil { result.Err = rolesResult.Err @@ -83,14 +85,18 @@ func (s *SqlSupplier) createScheme(ctx context.Context, scheme *model.Scheme, tr defaultRoles[model.TEAM_ADMIN_ROLE_ID] = role case model.TEAM_USER_ROLE_ID: defaultRoles[model.TEAM_USER_ROLE_ID] = role + case model.TEAM_GUEST_ROLE_ID: + defaultRoles[model.TEAM_GUEST_ROLE_ID] = role case model.CHANNEL_ADMIN_ROLE_ID: defaultRoles[model.CHANNEL_ADMIN_ROLE_ID] = role case model.CHANNEL_USER_ROLE_ID: defaultRoles[model.CHANNEL_USER_ROLE_ID] = role + case model.CHANNEL_GUEST_ROLE_ID: + defaultRoles[model.CHANNEL_GUEST_ROLE_ID] = role } } - if len(defaultRoles) != 4 { + if len(defaultRoles) != 6 { result.Err = model.NewAppError("SqlSchemeStore.SaveScheme", "store.sql_scheme.save.retrieve_default_scheme_roles.app_error", nil, "", http.StatusInternalServerError) return result } @@ -127,6 +133,21 @@ func (s *SqlSupplier) createScheme(ctx context.Context, scheme *model.Scheme, tr } else { scheme.DefaultTeamUserRole = saveRoleResult.Data.(*model.Role).Name } + + // Team Guest Role + teamGuestRole := &model.Role{ + Name: model.NewId(), + DisplayName: fmt.Sprintf("Team Guest Role for Scheme %s", scheme.Name), + Permissions: defaultRoles[model.TEAM_GUEST_ROLE_ID].Permissions, + SchemeManaged: true, + } + + if saveRoleResult := s.createRole(ctx, teamGuestRole, transaction); saveRoleResult.Err != nil { + result.Err = saveRoleResult.Err + return result + } else { + scheme.DefaultTeamGuestRole = saveRoleResult.Data.(*model.Role).Name + } } if scheme.Scope == model.SCHEME_SCOPE_TEAM || scheme.Scope == model.SCHEME_SCOPE_CHANNEL { // Channel Admin Role @@ -158,6 +179,21 @@ func (s *SqlSupplier) createScheme(ctx context.Context, scheme *model.Scheme, tr } else { scheme.DefaultChannelUserRole = saveRoleResult.Data.(*model.Role).Name } + + // Channel Guest Role + channelGuestRole := &model.Role{ + Name: model.NewId(), + DisplayName: fmt.Sprintf("Channel Guest Role for Scheme %s", scheme.Name), + Permissions: defaultRoles[model.CHANNEL_GUEST_ROLE_ID].Permissions, + SchemeManaged: true, + } + + if saveRoleResult := s.createRole(ctx, channelGuestRole, transaction); saveRoleResult.Err != nil { + result.Err = saveRoleResult.Err + return result + } else { + scheme.DefaultChannelGuestRole = saveRoleResult.Data.(*model.Role).Name + } } scheme.Id = model.NewId() @@ -250,9 +286,9 @@ func (s *SqlSupplier) SchemeDelete(ctx context.Context, schemeId string, hints . } // Delete the roles belonging to the scheme. - roleNames := []string{scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole} + roleNames := []string{scheme.DefaultChannelGuestRole, scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole} if scheme.Scope == model.SCHEME_SCOPE_TEAM { - roleNames = append(roleNames, scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole) + roleNames = append(roleNames, scheme.DefaultTeamGuestRole, scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole) } var inQueryList []string diff --git a/store/sqlstore/team_store.go b/store/sqlstore/team_store.go index 90620a27a6..32f63c5ce0 100644 --- a/store/sqlstore/team_store.go +++ b/store/sqlstore/team_store.go @@ -34,6 +34,7 @@ type teamMember struct { UserId string Roles string DeleteAt int64 + SchemeGuest sql.NullBool SchemeUser sql.NullBool SchemeAdmin sql.NullBool } @@ -44,6 +45,7 @@ func NewTeamMemberFromModel(tm *model.TeamMember) *teamMember { UserId: tm.UserId, Roles: tm.ExplicitRoles, DeleteAt: tm.DeleteAt, + SchemeGuest: sql.NullBool{Valid: true, Bool: tm.SchemeGuest}, SchemeUser: sql.NullBool{Valid: true, Bool: tm.SchemeUser}, SchemeAdmin: sql.NullBool{Valid: true, Bool: tm.SchemeAdmin}, } @@ -54,8 +56,10 @@ type teamMemberWithSchemeRoles struct { UserId string Roles string DeleteAt int64 + SchemeGuest sql.NullBool SchemeUser sql.NullBool SchemeAdmin sql.NullBool + TeamSchemeDefaultGuestRole sql.NullString TeamSchemeDefaultUserRole sql.NullString TeamSchemeDefaultAdminRole sql.NullString } @@ -68,11 +72,16 @@ func (db teamMemberWithSchemeRoles) ToModel() *model.TeamMember { // Identify any scheme derived roles that are in "Roles" field due to not yet being migrated, and exclude // them from ExplicitRoles field. + schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool for _, role := range strings.Fields(db.Roles) { isImplicit := false - if role == model.TEAM_USER_ROLE_ID { + if role == model.TEAM_GUEST_ROLE_ID { + // We have an implicit role via the system scheme. Override the "schemeGuest" field to true. + schemeGuest = true + isImplicit = true + } else if role == model.TEAM_USER_ROLE_ID { // We have an implicit role via the system scheme. Override the "schemeUser" field to true. schemeUser = true isImplicit = true @@ -91,6 +100,13 @@ func (db teamMemberWithSchemeRoles) ToModel() *model.TeamMember { // Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add // them to the Roles field for backwards compatibility reasons. var schemeImpliedRoles []string + if db.SchemeGuest.Valid && db.SchemeGuest.Bool { + if db.TeamSchemeDefaultGuestRole.Valid && db.TeamSchemeDefaultGuestRole.String != "" { + schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultGuestRole.String) + } else { + schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_GUEST_ROLE_ID) + } + } if db.SchemeUser.Valid && db.SchemeUser.Bool { if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" { schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String) @@ -122,6 +138,7 @@ func (db teamMemberWithSchemeRoles) ToModel() *model.TeamMember { UserId: db.UserId, Roles: strings.Join(roles, " "), DeleteAt: db.DeleteAt, + SchemeGuest: schemeGuest, SchemeUser: schemeUser, SchemeAdmin: schemeAdmin, ExplicitRoles: strings.Join(explicitRoles, " "), @@ -475,6 +492,7 @@ func (s SqlTeamStore) getTeamMembersWithSchemeSelectQuery() sq.SelectBuilder { return s.getQueryBuilder(). Select( "TeamMembers.*", + "TeamScheme.DefaultTeamGuestRole TeamSchemeDefaultGuestRole", "TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole", "TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole", ). @@ -887,11 +905,16 @@ func (s SqlTeamStore) MigrateTeamMembers(fromTeamId string, fromUserId string) s if !member.SchemeUser.Valid { member.SchemeUser = sql.NullBool{Bool: false, Valid: true} } + if !member.SchemeGuest.Valid { + member.SchemeGuest = sql.NullBool{Bool: false, Valid: true} + } for _, role := range roles { if role == model.TEAM_ADMIN_ROLE_ID { member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true} } else if role == model.TEAM_USER_ROLE_ID { member.SchemeUser = sql.NullBool{Bool: true, Valid: true} + } else if role == model.TEAM_GUEST_ROLE_ID { + member.SchemeGuest = sql.NullBool{Bool: true, Valid: true} } else { newRoles = append(newRoles, role) } @@ -1082,16 +1105,22 @@ func (s SqlTeamStore) GetTeamMembersForExport(userId string) store.StoreChannel return store.Do(func(result *store.StoreResult) { var members []*model.TeamMemberForExport _, err := s.GetReplica().Select(&members, ` - SELECT - TeamMembers.*, - Teams.Name as TeamName - FROM - TeamMembers - INNER JOIN - Teams ON TeamMembers.TeamId = Teams.Id - WHERE - TeamMembers.UserId = :UserId - AND Teams.DeleteAt = 0`, + SELECT + TeamMembers.TeamId, + TeamMembers.UserId, + TeamMembers.Roles, + TeamMembers.DeleteAt, + (TeamMembers.SchemeGuest IS NOT NULL AND TeamMembers.SchemeGuest) as SchemeGuest, + TeamMembers.SchemeUser, + TeamMembers.SchemeAdmin, + Teams.Name as TeamName + FROM + TeamMembers + INNER JOIN + Teams ON TeamMembers.TeamId = Teams.Id + WHERE + TeamMembers.UserId = :UserId + AND Teams.DeleteAt = 0`, map[string]interface{}{"UserId": userId}) if err != nil { result.Err = model.NewAppError("SqlTeamStore.GetTeamMembersForExport", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) diff --git a/store/sqlstore/team_store_test.go b/store/sqlstore/team_store_test.go index 4aaefd1a6f..0c3b70fd57 100644 --- a/store/sqlstore/team_store_test.go +++ b/store/sqlstore/team_store_test.go @@ -28,6 +28,7 @@ func testNewTeamMemberFromModel(t *testing.T) { UserId: model.NewId(), Roles: "team_user team_admin custom_role", DeleteAt: 12345, + SchemeGuest: false, SchemeUser: true, SchemeAdmin: true, ExplicitRoles: "custom_role", @@ -38,8 +39,10 @@ func testNewTeamMemberFromModel(t *testing.T) { assert.Equal(t, m.TeamId, db.TeamId) assert.Equal(t, m.UserId, db.UserId) assert.Equal(t, m.DeleteAt, db.DeleteAt) + assert.Equal(t, true, db.SchemeGuest.Valid) assert.Equal(t, true, db.SchemeUser.Valid) assert.Equal(t, true, db.SchemeAdmin.Valid) + assert.Equal(t, m.SchemeGuest, db.SchemeGuest.Bool) assert.Equal(t, m.SchemeUser, db.SchemeUser.Bool) assert.Equal(t, m.SchemeAdmin, db.SchemeAdmin.Bool) assert.Equal(t, m.ExplicitRoles, db.Roles) @@ -53,8 +56,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { UserId: model.NewId(), Roles: "custom_role", DeleteAt: 12345, + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -65,6 +70,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { assert.Equal(t, db.UserId, m.UserId) assert.Equal(t, "custom_role team_user team_admin", m.Roles) assert.Equal(t, db.DeleteAt, m.DeleteAt) + assert.Equal(t, db.SchemeGuest.Bool, m.SchemeGuest) assert.Equal(t, db.SchemeUser.Bool, m.SchemeUser) assert.Equal(t, db.SchemeAdmin.Bool, m.SchemeAdmin) assert.Equal(t, db.Roles, m.ExplicitRoles) @@ -74,8 +80,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_User", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "team_user", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -83,6 +91,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "team_user", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) @@ -91,8 +100,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_Admin", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "team_user team_admin", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -100,6 +111,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "team_user team_admin", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, true, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) @@ -108,8 +120,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_CustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -117,6 +131,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "custom_role", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, false, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) @@ -125,8 +140,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_UserAndCustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "team_user custom_role", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -134,6 +151,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "team_user custom_role", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) @@ -142,8 +160,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_AdminAndCustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "team_user team_admin custom_role", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -151,6 +171,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "team_user team_admin custom_role", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, true, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) @@ -159,8 +180,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Unmigrated_NoScheme_NoRoles", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: false, Bool: false}, SchemeUser: sql.NullBool{Valid: false, Bool: false}, SchemeAdmin: sql.NullBool{Valid: false, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -168,6 +191,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, false, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) @@ -177,8 +201,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_User", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -186,6 +212,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "team_user", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) @@ -194,8 +221,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_Admin", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -203,16 +232,39 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "team_user team_admin", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, true, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) }) + t.Run("Migrated_NoScheme_Guest", func(t *testing.T) { + db := teamMemberWithSchemeRoles{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + m := db.ToModel() + + assert.Equal(t, "team_guest", m.Roles) + assert.Equal(t, true, m.SchemeGuest) + assert.Equal(t, false, m.SchemeUser) + assert.Equal(t, false, m.SchemeAdmin) + assert.Equal(t, "", m.ExplicitRoles) + }) + t.Run("Migrated_NoScheme_CustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -220,6 +272,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "custom_role", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, false, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) @@ -228,8 +281,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_UserAndCustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -237,6 +292,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "custom_role team_user", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) @@ -245,8 +301,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_NoScheme_AdminAndCustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -254,16 +312,39 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "custom_role team_user team_admin", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, true, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) }) + t.Run("Migrated_NoScheme_GuestAndCustomRole", func(t *testing.T) { + db := teamMemberWithSchemeRoles{ + Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, + } + + m := db.ToModel() + + assert.Equal(t, "custom_role team_guest", m.Roles) + assert.Equal(t, true, m.SchemeGuest) + assert.Equal(t, false, m.SchemeUser) + assert.Equal(t, false, m.SchemeAdmin) + assert.Equal(t, "custom_role", m.ExplicitRoles) + }) + t.Run("Migrated_NoScheme_NoRoles", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: false}, TeamSchemeDefaultUserRole: sql.NullString{Valid: false}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: false}, } @@ -271,6 +352,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, false, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) @@ -280,8 +362,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_User", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, } @@ -289,6 +373,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "tscheme_user", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) @@ -297,8 +382,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_Admin", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, } @@ -306,16 +393,39 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "tscheme_user tscheme_admin", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, true, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) }) + t.Run("Migrated_TeamScheme_Guest", func(t *testing.T) { + db := teamMemberWithSchemeRoles{ + Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, + } + + m := db.ToModel() + + assert.Equal(t, "tscheme_guest", m.Roles) + assert.Equal(t, true, m.SchemeGuest) + assert.Equal(t, false, m.SchemeUser) + assert.Equal(t, false, m.SchemeAdmin) + assert.Equal(t, "", m.ExplicitRoles) + }) + t.Run("Migrated_TeamScheme_CustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, } @@ -323,6 +433,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "custom_role", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, false, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) @@ -331,8 +442,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_UserAndCustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, } @@ -340,6 +453,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "custom_role tscheme_user", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) @@ -348,8 +462,10 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { t.Run("Migrated_TeamScheme_AdminAndCustomRole", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: true}, SchemeAdmin: sql.NullBool{Valid: true, Bool: true}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, } @@ -357,16 +473,39 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "custom_role tscheme_user tscheme_admin", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, true, m.SchemeUser) assert.Equal(t, true, m.SchemeAdmin) assert.Equal(t, "custom_role", m.ExplicitRoles) }) + t.Run("Migrated_TeamScheme_GuestAndCustomRole", func(t *testing.T) { + db := teamMemberWithSchemeRoles{ + Roles: "custom_role", + SchemeGuest: sql.NullBool{Valid: true, Bool: true}, + SchemeUser: sql.NullBool{Valid: true, Bool: false}, + SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, + TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, + TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, + } + + m := db.ToModel() + + assert.Equal(t, "custom_role tscheme_guest", m.Roles) + assert.Equal(t, true, m.SchemeGuest) + assert.Equal(t, false, m.SchemeUser) + assert.Equal(t, false, m.SchemeAdmin) + assert.Equal(t, "custom_role", m.ExplicitRoles) + }) + t.Run("Migrated_TeamScheme_NoRoles", func(t *testing.T) { db := teamMemberWithSchemeRoles{ Roles: "", + SchemeGuest: sql.NullBool{Valid: true, Bool: false}, SchemeUser: sql.NullBool{Valid: true, Bool: false}, SchemeAdmin: sql.NullBool{Valid: true, Bool: false}, + TeamSchemeDefaultGuestRole: sql.NullString{Valid: true, String: "tscheme_guest"}, TeamSchemeDefaultUserRole: sql.NullString{Valid: true, String: "tscheme_user"}, TeamSchemeDefaultAdminRole: sql.NullString{Valid: true, String: "tscheme_admin"}, } @@ -374,6 +513,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) { m := db.ToModel() assert.Equal(t, "", m.Roles) + assert.Equal(t, false, m.SchemeGuest) assert.Equal(t, false, m.SchemeUser) assert.Equal(t, false, m.SchemeAdmin) assert.Equal(t, "", m.ExplicitRoles) diff --git a/store/sqlstore/upgrade.go b/store/sqlstore/upgrade.go index a079d45585..475d3d54db 100644 --- a/store/sqlstore/upgrade.go +++ b/store/sqlstore/upgrade.go @@ -154,6 +154,7 @@ func UpgradeDatabase(sqlStore SqlStore, currentModelVersionString string) error UpgradeDatabaseToVersion59(sqlStore) UpgradeDatabaseToVersion510(sqlStore) UpgradeDatabaseToVersion511(sqlStore) + UpgradeDatabaseToVersion512(sqlStore) return nil } @@ -677,3 +678,16 @@ func UpgradeDatabaseToVersion511(sqlStore SqlStore) { // saveSchemaVersion(sqlStore, VERSION_5_11_0) // } } + +func UpgradeDatabaseToVersion512(sqlStore SqlStore) { + // TODO: Uncomment following condition when version 5.12.0 is released + // if shouldPerformUpgrade(sqlStore, VERSION_5_11_0, VERSION_5_12_0) { + sqlStore.CreateColumnIfNotExistsNoDefault("TeamMembers", "SchemeGuest", "boolean", "boolean") + sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeGuest", "boolean", "boolean") + sqlStore.CreateColumnIfNotExistsNoDefault("Schemes", "DefaultTeamGuestRole", "text", "VARCHAR(64)") + sqlStore.CreateColumnIfNotExistsNoDefault("Schemes", "DefaultChannelGuestRole", "text", "VARCHAR(64)") + sqlStore.GetMaster().Exec("UPDATE Schemes SET DefaultTeamGuestRole = '', DefaultChannelGuestRole = ''") + + // saveSchemaVersion(sqlStore, VERSION_5_12_0) + // } +} diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go index 230e4e3d69..f4b2bb1aab 100644 --- a/store/storetest/channel_store.go +++ b/store/storetest/channel_store.go @@ -4,6 +4,7 @@ package storetest import ( + "fmt" "sort" "strconv" "strings" @@ -2722,6 +2723,9 @@ func testChannelStoreGetChannelsByScheme(t *testing.T, ss store.Store) { Scope: model.SCHEME_SCOPE_CHANNEL, } + result := <-ss.Scheme().Save(s1) + fmt.Println(result.Err) + s1 = result.Data.(*model.Scheme) s1 = (<-ss.Scheme().Save(s1)).Data.(*model.Scheme) s2 = (<-ss.Scheme().Save(s2)).Data.(*model.Scheme) @@ -2826,18 +2830,21 @@ func testChannelStoreMigrateChannelMembers(t *testing.T, ss store.Store) { cm1b, err := ss.Channel().GetMember(cm1.ChannelId, cm1.UserId) assert.Nil(t, err) assert.Equal(t, "", cm1b.ExplicitRoles) + assert.False(t, cm1b.SchemeGuest) assert.True(t, cm1b.SchemeUser) assert.True(t, cm1b.SchemeAdmin) cm2b, err := ss.Channel().GetMember(cm2.ChannelId, cm2.UserId) assert.Nil(t, err) assert.Equal(t, "", cm2b.ExplicitRoles) + assert.False(t, cm1b.SchemeGuest) assert.True(t, cm2b.SchemeUser) assert.False(t, cm2b.SchemeAdmin) cm3b, err := ss.Channel().GetMember(cm3.ChannelId, cm3.UserId) assert.Nil(t, err) assert.Equal(t, "something_else", cm3b.ExplicitRoles) + assert.False(t, cm1b.SchemeGuest) assert.False(t, cm3b.SchemeUser) assert.False(t, cm3b.SchemeAdmin) } diff --git a/store/storetest/scheme_store.go b/store/storetest/scheme_store.go index 2c920fa605..c3d88d82c9 100644 --- a/store/storetest/scheme_store.go +++ b/store/storetest/scheme_store.go @@ -42,6 +42,14 @@ func createDefaultRoles(t *testing.T, ss store.Store) { }, }) + <-ss.Role().Save(&model.Role{ + Name: model.TEAM_GUEST_ROLE_ID, + DisplayName: model.TEAM_GUEST_ROLE_ID, + Permissions: []string{ + model.PERMISSION_VIEW_TEAM.Id, + }, + }) + <-ss.Role().Save(&model.Role{ Name: model.CHANNEL_ADMIN_ROLE_ID, DisplayName: model.CHANNEL_ADMIN_ROLE_ID, @@ -59,6 +67,15 @@ func createDefaultRoles(t *testing.T, ss store.Store) { model.PERMISSION_CREATE_POST.Id, }, }) + + <-ss.Role().Save(&model.Role{ + Name: model.CHANNEL_GUEST_ROLE_ID, + DisplayName: model.CHANNEL_GUEST_ROLE_ID, + Permissions: []string{ + model.PERMISSION_READ_CHANNEL.Id, + model.PERMISSION_CREATE_POST.Id, + }, + }) } func testSchemeStoreSave(t *testing.T, ss store.Store) { @@ -84,8 +101,10 @@ func testSchemeStoreSave(t *testing.T, ss store.Store) { assert.Equal(t, s1.Scope, d1.Scope) assert.Len(t, d1.DefaultTeamAdminRole, 26) assert.Len(t, d1.DefaultTeamUserRole, 26) + assert.Len(t, d1.DefaultTeamGuestRole, 26) assert.Len(t, d1.DefaultChannelAdminRole, 26) assert.Len(t, d1.DefaultChannelUserRole, 26) + assert.Len(t, d1.DefaultChannelGuestRole, 26) // Check the default roles were created correctly. roleRes1 := <-ss.Role().GetByName(d1.DefaultTeamAdminRole) @@ -112,6 +131,18 @@ func testSchemeStoreSave(t *testing.T, ss store.Store) { assert.Equal(t, role4.Permissions, []string{"read_channel", "create_post"}) assert.True(t, role4.SchemeManaged) + roleRes5 := <-ss.Role().GetByName(d1.DefaultTeamGuestRole) + assert.Nil(t, roleRes5.Err) + role5 := roleRes5.Data.(*model.Role) + assert.Equal(t, role5.Permissions, []string{"view_team"}) + assert.True(t, role5.SchemeManaged) + + roleRes6 := <-ss.Role().GetByName(d1.DefaultChannelGuestRole) + assert.Nil(t, roleRes6.Err) + role6 := roleRes6.Data.(*model.Role) + assert.Equal(t, role6.Permissions, []string{"read_channel", "create_post"}) + assert.True(t, role6.SchemeManaged) + // Change the scheme description and update. d1.Description = model.NewId() @@ -128,8 +159,10 @@ func testSchemeStoreSave(t *testing.T, ss store.Store) { assert.Equal(t, s1.Scope, d2.Scope) assert.Equal(t, d1.DefaultTeamAdminRole, d2.DefaultTeamAdminRole) assert.Equal(t, d1.DefaultTeamUserRole, d2.DefaultTeamUserRole) + assert.Equal(t, d1.DefaultTeamGuestRole, d2.DefaultTeamGuestRole) assert.Equal(t, d1.DefaultChannelAdminRole, d2.DefaultChannelAdminRole) assert.Equal(t, d1.DefaultChannelUserRole, d2.DefaultChannelUserRole) + assert.Equal(t, d1.DefaultChannelGuestRole, d2.DefaultChannelGuestRole) // Try saving one with an invalid ID set. s3 := &model.Scheme{ @@ -172,8 +205,10 @@ func testSchemeStoreGet(t *testing.T, ss store.Store) { assert.Equal(t, s1.Scope, d2.Scope) assert.Equal(t, d1.DefaultTeamAdminRole, d2.DefaultTeamAdminRole) assert.Equal(t, d1.DefaultTeamUserRole, d2.DefaultTeamUserRole) + assert.Equal(t, d1.DefaultTeamGuestRole, d2.DefaultTeamGuestRole) assert.Equal(t, d1.DefaultChannelAdminRole, d2.DefaultChannelAdminRole) assert.Equal(t, d1.DefaultChannelUserRole, d2.DefaultChannelUserRole) + assert.Equal(t, d1.DefaultChannelGuestRole, d2.DefaultChannelGuestRole) // Get an invalid scheme res3 := <-ss.Scheme().Get(model.NewId()) @@ -208,8 +243,10 @@ func testSchemeStoreGetByName(t *testing.T, ss store.Store) { assert.Equal(t, s1.Scope, d2.Scope) assert.Equal(t, d1.DefaultTeamAdminRole, d2.DefaultTeamAdminRole) assert.Equal(t, d1.DefaultTeamUserRole, d2.DefaultTeamUserRole) + assert.Equal(t, d1.DefaultTeamGuestRole, d2.DefaultTeamGuestRole) assert.Equal(t, d1.DefaultChannelAdminRole, d2.DefaultChannelAdminRole) assert.Equal(t, d1.DefaultChannelUserRole, d2.DefaultChannelUserRole) + assert.Equal(t, d1.DefaultChannelGuestRole, d2.DefaultChannelGuestRole) // Get an invalid scheme res3 := <-ss.Scheme().GetByName(model.NewId()) @@ -307,8 +344,10 @@ func testSchemeStoreDelete(t *testing.T, ss store.Store) { assert.Equal(t, s1.Scope, d1.Scope) assert.Len(t, d1.DefaultTeamAdminRole, 26) assert.Len(t, d1.DefaultTeamUserRole, 26) + assert.Len(t, d1.DefaultTeamGuestRole, 26) assert.Len(t, d1.DefaultChannelAdminRole, 26) assert.Len(t, d1.DefaultChannelUserRole, 26) + assert.Len(t, d1.DefaultChannelGuestRole, 26) // Check the default roles were created correctly. roleRes1 := <-ss.Role().GetByName(d1.DefaultTeamAdminRole) @@ -335,6 +374,18 @@ func testSchemeStoreDelete(t *testing.T, ss store.Store) { assert.Equal(t, role4.Permissions, []string{"read_channel", "create_post"}) assert.True(t, role4.SchemeManaged) + roleRes5 := <-ss.Role().GetByName(d1.DefaultTeamGuestRole) + assert.Nil(t, roleRes5.Err) + role5 := roleRes5.Data.(*model.Role) + assert.Equal(t, role5.Permissions, []string{"view_team"}) + assert.True(t, role5.SchemeManaged) + + roleRes6 := <-ss.Role().GetByName(d1.DefaultChannelGuestRole) + assert.Nil(t, roleRes6.Err) + role6 := roleRes6.Data.(*model.Role) + assert.Equal(t, role6.Permissions, []string{"read_channel", "create_post"}) + assert.True(t, role6.SchemeManaged) + // Delete the scheme. res2 := <-ss.Scheme().Delete(d1.Id) if !assert.Nil(t, res2.Err) { @@ -344,26 +395,36 @@ func testSchemeStoreDelete(t *testing.T, ss store.Store) { assert.NotZero(t, d2.DeleteAt) // Check that the roles are deleted too. - roleRes5 := <-ss.Role().GetByName(d1.DefaultTeamAdminRole) - assert.Nil(t, roleRes5.Err) - role5 := roleRes5.Data.(*model.Role) - assert.NotZero(t, role5.DeleteAt) - - roleRes6 := <-ss.Role().GetByName(d1.DefaultTeamUserRole) - assert.Nil(t, roleRes6.Err) - role6 := roleRes6.Data.(*model.Role) - assert.NotZero(t, role6.DeleteAt) - - roleRes7 := <-ss.Role().GetByName(d1.DefaultChannelAdminRole) + roleRes7 := <-ss.Role().GetByName(d1.DefaultTeamAdminRole) assert.Nil(t, roleRes7.Err) role7 := roleRes7.Data.(*model.Role) assert.NotZero(t, role7.DeleteAt) - roleRes8 := <-ss.Role().GetByName(d1.DefaultChannelUserRole) + roleRes8 := <-ss.Role().GetByName(d1.DefaultTeamUserRole) assert.Nil(t, roleRes8.Err) role8 := roleRes8.Data.(*model.Role) assert.NotZero(t, role8.DeleteAt) + roleRes9 := <-ss.Role().GetByName(d1.DefaultChannelAdminRole) + assert.Nil(t, roleRes9.Err) + role9 := roleRes9.Data.(*model.Role) + assert.NotZero(t, role9.DeleteAt) + + roleRes10 := <-ss.Role().GetByName(d1.DefaultChannelUserRole) + assert.Nil(t, roleRes10.Err) + role10 := roleRes10.Data.(*model.Role) + assert.NotZero(t, role10.DeleteAt) + + roleRes11 := <-ss.Role().GetByName(d1.DefaultTeamGuestRole) + assert.Nil(t, roleRes11.Err) + role11 := roleRes11.Data.(*model.Role) + assert.NotZero(t, role11.DeleteAt) + + roleRes12 := <-ss.Role().GetByName(d1.DefaultChannelGuestRole) + assert.Nil(t, roleRes12.Err) + role12 := roleRes12.Data.(*model.Role) + assert.NotZero(t, role12.DeleteAt) + // Try deleting a scheme that does not exist. res3 := <-ss.Scheme().Delete(model.NewId()) assert.NotNil(t, res3.Err) diff --git a/store/storetest/team_store.go b/store/storetest/team_store.go index aeb01e6da1..55924c3314 100644 --- a/store/storetest/team_store.go +++ b/store/storetest/team_store.go @@ -1100,6 +1100,15 @@ func testGetTeamMember(t *testing.T, ss store.Store) { t.Log(m3) assert.Equal(t, s2.DefaultTeamUserRole, m3.Roles) + + m4 := &model.TeamMember{TeamId: t2.Id, UserId: model.NewId(), SchemeGuest: true} + store.Must(ss.Team().SaveMember(m4, -1)) + + r3 := <-ss.Team().GetMember(m4.TeamId, m4.UserId) + require.Nil(t, r3.Err) + m5 := r3.Data.(*model.TeamMember) + + assert.Equal(t, s2.DefaultTeamGuestRole, m5.Roles) } func testGetTeamMembersByIds(t *testing.T, ss store.Store) { diff --git a/web/web_test.go b/web/web_test.go index 22f9826a30..91e1f94633 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -70,8 +70,7 @@ func Setup() *TestHelper { URL = fmt.Sprintf("http://localhost:%v", a.Srv.ListenAddr.Port) ApiClient = model.NewAPIv4Client(URL) - a.DoAdvancedPermissionsMigration() - a.DoEmojisPermissionsMigration() + a.DoAppMigrations() a.Srv.Store.MarkSystemRanUnitTests()