[MM-57295] Bulk export: add roles and permission schemes (#26523)

* Bulk export: add roles and permission schemes

* Update mmctl docs

* Fix log

* Update mmctl tests

* Update mmctl unit tests

* Refactor to avoid extra calls

* Update translations

* Add test case

* Fix test

* Fix test
Этот коммит содержится в:
Claudio Costa
2024-03-26 08:43:25 -06:00
коммит произвёл GitHub
родитель c7da6b4741
Коммит 4d6602aff0
16 изменённых файлов: 712 добавлений и 35 удалений

Просмотреть файл

@@ -90,6 +90,12 @@ func (a *App) BulkExport(ctx request.CTX, writer io.Writer, outPath string, job
return err
}
if opts.IncludeRolesAndSchemes {
if err := a.exportRolesAndSchemes(ctx, job, writer); err != nil {
return err
}
}
ctx.Logger().Info("Bulk export: exporting teams")
teamNames, err := a.exportAllTeams(ctx, job, writer)
if err != nil {
@@ -194,6 +200,106 @@ func (a *App) exportVersion(writer io.Writer) *model.AppError {
return a.exportWriteLine(writer, versionLine)
}
func (a *App) exportRolesAndSchemes(ctx request.CTX, job *model.Job, writer io.Writer) *model.AppError {
// We export schemes first since they'll already include their attached roles
// which we map to avoid exporting them twice later in exportRoles.
schemeRolesMap := make(map[string]bool)
roles, appErr := a.Srv().Store().Role().GetAll()
if appErr != nil {
return model.NewAppError("exportRolesAndSchemes", "app.role.get_all.app_error", nil, "", http.StatusInternalServerError).Wrap(appErr)
}
ctx.Logger().Info("Bulk export: exporting team schemes")
if err := a.exportSchemes(ctx, job, writer, model.SchemeScopeTeam, schemeRolesMap, roles); err != nil {
return err
}
ctx.Logger().Info("Bulk export: exporting channel schemes")
if err := a.exportSchemes(ctx, job, writer, model.SchemeScopeChannel, schemeRolesMap, roles); err != nil {
return err
}
ctx.Logger().Info("Bulk export: exporting roles")
if err := a.exportRoles(ctx, job, writer, schemeRolesMap, roles); err != nil {
return err
}
return nil
}
func (a *App) exportRoles(ctx request.CTX, job *model.Job, writer io.Writer, schemeRoles map[string]bool, allRoles []*model.Role) *model.AppError {
var cnt int
for _, role := range allRoles {
// We skip any roles that will be included as part of custom schemes.
if !schemeRoles[role.Name] {
if err := a.exportWriteLine(writer, ImportLineFromRole(role)); err != nil {
return err
}
cnt++
}
}
updateJobProgress(ctx.Logger(), a.Srv().Store(), job, "roles_exported", cnt)
return nil
}
func (a *App) exportSchemes(ctx request.CTX, job *model.Job, writer io.Writer, scope string, schemeRolesMap map[string]bool, allRoles []*model.Role) *model.AppError {
rolesMap := make(map[string]*model.Role, len(allRoles))
for _, role := range allRoles {
rolesMap[role.Name] = role
}
var cnt int
pageSize := 100
for {
schemes, err := a.Srv().Store().Scheme().GetAllPage(scope, cnt, pageSize)
if err != nil {
return model.NewAppError("exportSchemes", "app.scheme.get_all_page.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
for _, scheme := range schemes {
if ok := scheme.IsValid(); !ok {
return model.NewAppError("exportSchemes", "model.scheme.is_valid.app_error", nil, "", http.StatusInternalServerError)
}
if scheme.Scope == model.SchemeScopeTeam {
schemeRolesMap[scheme.DefaultTeamAdminRole] = true
schemeRolesMap[scheme.DefaultTeamUserRole] = true
schemeRolesMap[scheme.DefaultTeamGuestRole] = true
// Playbooks
// At the moment this is only needed to avoid exporting and
// importing spurious roles.
schemeRolesMap[scheme.DefaultPlaybookAdminRole] = true
schemeRolesMap[scheme.DefaultPlaybookMemberRole] = true
schemeRolesMap[scheme.DefaultRunAdminRole] = true
schemeRolesMap[scheme.DefaultRunMemberRole] = true
}
if scheme.Scope == model.SchemeScopeTeam || scheme.Scope == model.SchemeScopeChannel {
schemeRolesMap[scheme.DefaultChannelAdminRole] = true
schemeRolesMap[scheme.DefaultChannelUserRole] = true
schemeRolesMap[scheme.DefaultChannelGuestRole] = true
}
if err := a.exportWriteLine(writer, ImportLineFromScheme(scheme, rolesMap)); err != nil {
return err
}
}
cnt += len(schemes)
updateJobProgress(ctx.Logger(), a.Srv().Store(), job, fmt.Sprintf("%s_schemes_exported", scope), cnt)
if len(schemes) < pageSize {
return nil
}
}
}
func (a *App) exportAllTeams(ctx request.CTX, job *model.Job, writer io.Writer) (map[string]bool, *model.AppError) {
afterId := strings.Repeat("0", 26)
teamNames := make(map[string]bool)

Просмотреть файл

@@ -226,3 +226,46 @@ func ImportLineFromEmoji(emoji *model.Emoji, filePath string) *imports.LineImpor
},
}
}
func ImportRoleDataFromRole(role *model.Role) *imports.RoleImportData {
return &imports.RoleImportData{
Name: &role.Name,
DisplayName: &role.DisplayName,
Description: &role.Description,
Permissions: &role.Permissions,
SchemeManaged: &role.SchemeManaged,
}
}
func ImportLineFromRole(role *model.Role) *imports.LineImportData {
return &imports.LineImportData{
Type: "role",
Role: ImportRoleDataFromRole(role),
}
}
func ImportLineFromScheme(scheme *model.Scheme, rolesMap map[string]*model.Role) *imports.LineImportData {
data := &imports.SchemeImportData{
Name: &scheme.Name,
DisplayName: &scheme.DisplayName,
Description: &scheme.Description,
Scope: &scheme.Scope,
}
if scheme.Scope == model.SchemeScopeTeam {
data.DefaultTeamAdminRole = ImportRoleDataFromRole(rolesMap[scheme.DefaultTeamAdminRole])
data.DefaultTeamUserRole = ImportRoleDataFromRole(rolesMap[scheme.DefaultTeamUserRole])
data.DefaultTeamGuestRole = ImportRoleDataFromRole(rolesMap[scheme.DefaultTeamGuestRole])
}
if scheme.Scope == model.SchemeScopeTeam || scheme.Scope == model.SchemeScopeChannel {
data.DefaultChannelAdminRole = ImportRoleDataFromRole(rolesMap[scheme.DefaultChannelAdminRole])
data.DefaultChannelUserRole = ImportRoleDataFromRole(rolesMap[scheme.DefaultChannelUserRole])
data.DefaultChannelGuestRole = ImportRoleDataFromRole(rolesMap[scheme.DefaultChannelGuestRole])
}
return &imports.LineImportData{
Type: "scheme",
Scheme: data,
}
}

Просмотреть файл

@@ -804,3 +804,412 @@ func TestExportArchivedChannels(t *testing.T) {
}
require.True(t, found, "archived channel not found after import")
}
func TestExportRoles(t *testing.T) {
t.Run("defaults", func(t *testing.T) {
th1 := Setup(t).InitBasic()
defer th1.TearDown()
var b bytes.Buffer
appErr := th1.App.BulkExport(th1.Context, &b, "", nil, model.BulkExportOpts{})
require.Nil(t, appErr)
exportedRoles, appErr := th1.App.GetAllRoles()
assert.Nil(t, appErr)
assert.NotEmpty(t, exportedRoles)
th2 := Setup(t)
defer th2.TearDown()
appErr, i := th2.App.BulkImport(th2.Context, &b, nil, false, 1)
assert.Nil(t, appErr)
assert.Equal(t, 0, i)
importedRoles, appErr := th2.App.GetAllRoles()
assert.Nil(t, appErr)
assert.NotEmpty(t, importedRoles)
require.Equal(t, len(exportedRoles), len(importedRoles))
})
t.Run("modified roles", func(t *testing.T) {
th1 := Setup(t).InitBasic()
defer th1.TearDown()
exportedRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), model.TeamUserRoleId)
require.Nil(t, appErr)
exportedRole.Permissions = exportedRole.Permissions[1:]
_, appErr = th1.App.UpdateRole(exportedRole)
require.Nil(t, appErr)
var b bytes.Buffer
appErr = th1.App.BulkExport(th1.Context, &b, "", nil, model.BulkExportOpts{
IncludeRolesAndSchemes: true,
})
require.Nil(t, appErr)
th2 := Setup(t)
defer th2.TearDown()
appErr, i := th2.App.BulkImport(th2.Context, &b, nil, false, 1)
require.Nil(t, appErr)
require.Equal(t, 0, i)
importedRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), model.TeamUserRoleId)
require.Nil(t, appErr)
require.Equal(t, exportedRole.DisplayName, importedRole.DisplayName)
require.Equal(t, exportedRole.Description, importedRole.Description)
require.Equal(t, exportedRole.SchemeManaged, importedRole.SchemeManaged)
require.Equal(t, exportedRole.BuiltIn, importedRole.BuiltIn)
require.ElementsMatch(t, exportedRole.Permissions, importedRole.Permissions)
})
t.Run("custom roles", func(t *testing.T) {
th1 := Setup(t).InitBasic()
defer th1.TearDown()
exportedRoles, appErr := th1.App.GetAllRoles()
require.Nil(t, appErr)
require.NotEmpty(t, exportedRoles)
customRole, appErr := th1.App.CreateRole(&model.Role{
Name: "custom_role",
DisplayName: "custom_role",
Permissions: exportedRoles[0].Permissions,
})
require.Nil(t, appErr)
var b bytes.Buffer
appErr = th1.App.BulkExport(th1.Context, &b, "", nil, model.BulkExportOpts{
IncludeRolesAndSchemes: true,
})
require.Nil(t, appErr)
th2 := Setup(t)
defer th2.TearDown()
appErr, i := th2.App.BulkImport(th2.Context, &b, nil, false, 1)
require.Nil(t, appErr)
require.Equal(t, 0, i)
importedCustomRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), customRole.Name)
require.Nil(t, appErr)
require.Equal(t, customRole.DisplayName, importedCustomRole.DisplayName)
require.Equal(t, customRole.Description, importedCustomRole.Description)
require.Equal(t, customRole.SchemeManaged, importedCustomRole.SchemeManaged)
require.Equal(t, customRole.BuiltIn, importedCustomRole.BuiltIn)
require.ElementsMatch(t, customRole.Permissions, importedCustomRole.Permissions)
})
}
func TestExportSchemes(t *testing.T) {
t.Run("no schemes", func(t *testing.T) {
th1 := Setup(t).InitBasic()
defer th1.TearDown()
// Need to set this or working with schemes won't work until the job is
// completed which is unnecessary for the purpose of this test.
err := th1.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
schemes, err := th1.App.Srv().Store().Scheme().GetAllPage(model.SchemeScopeChannel, 0, 1)
require.NoError(t, err)
require.Empty(t, schemes)
schemes, err = th1.App.Srv().Store().Scheme().GetAllPage(model.SchemeScopeTeam, 0, 1)
require.NoError(t, err)
require.Empty(t, schemes)
var b bytes.Buffer
appErr := th1.App.BulkExport(th1.Context, &b, "", nil, model.BulkExportOpts{
IncludeRolesAndSchemes: true,
})
require.Nil(t, appErr)
// The following causes the original store to be wiped so from here on we are targeting the
// second instance where the import will be loaded.
th2 := Setup(t)
defer th2.TearDown()
err = th2.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
appErr, i := th2.App.BulkImport(th2.Context, &b, nil, false, 1)
require.Nil(t, appErr)
require.Equal(t, 0, i)
schemes, err = th2.App.Srv().Store().Scheme().GetAllPage(model.SchemeScopeChannel, 0, 1)
require.NoError(t, err)
require.Empty(t, schemes)
schemes, err = th2.App.Srv().Store().Scheme().GetAllPage(model.SchemeScopeTeam, 0, 1)
require.NoError(t, err)
require.Empty(t, schemes)
})
t.Run("skip export", func(t *testing.T) {
th1 := Setup(t).InitBasic()
defer th1.TearDown()
// Need to set this or working with schemes won't work until the job is
// completed which is unnecessary for the purpose of this test.
err := th1.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
customScheme, appErr := th1.App.CreateScheme(&model.Scheme{
Name: "custom_scheme",
DisplayName: "Custom Scheme",
Scope: model.SchemeScopeChannel,
})
require.Nil(t, appErr)
var b bytes.Buffer
appErr = th1.App.BulkExport(th1.Context, &b, "", nil, model.BulkExportOpts{})
require.Nil(t, appErr)
// The following causes the original store to be wiped so from here on we are targeting the
// second instance where the import will be loaded.
th2 := Setup(t)
defer th2.TearDown()
err = th2.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
appErr, i := th2.App.BulkImport(th2.Context, &b, nil, false, 1)
require.Nil(t, appErr)
require.Equal(t, 0, i)
// Verify the scheme doesn't exist which is the expectation as it wasn't exported.
_, appErr = th2.App.GetScheme(customScheme.Name)
require.NotNil(t, appErr)
})
t.Run("export channel scheme", func(t *testing.T) {
th1 := Setup(t).InitBasic()
defer th1.TearDown()
// Need to set this or working with schemes won't work until the job is
// completed which is unnecessary for the purpose of this test.
err := th1.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
builtInRoles := 23
defaultChannelSchemeRoles := 3
// Verify the roles count is expected prior to scheme creation.
roles, appErr := th1.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles)
customScheme, appErr := th1.App.CreateScheme(&model.Scheme{
Name: "custom_channel_scheme",
DisplayName: "Custom Channel Scheme",
Scope: model.SchemeScopeChannel,
})
require.Nil(t, appErr)
// Verify the roles count is expected after scheme creation.
roles, appErr = th1.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles+defaultChannelSchemeRoles)
// Fetch the scheme roles for later comparison
customChannelAdminRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultChannelAdminRole)
require.Nil(t, appErr)
customChannelUserRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultChannelUserRole)
require.Nil(t, appErr)
customChannelGuestRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultChannelGuestRole)
require.Nil(t, appErr)
var b bytes.Buffer
appErr = th1.App.BulkExport(th1.Context, &b, "", nil, model.BulkExportOpts{
IncludeRolesAndSchemes: true,
})
require.Nil(t, appErr)
// The following causes the original store to be wiped so from here on we are targeting the
// second instance where the import will be loaded.
th2 := Setup(t)
defer th2.TearDown()
err = th2.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
// Verify roles count before importing is as expected.
roles, appErr = th2.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles)
appErr, i := th2.App.BulkImport(th2.Context, &b, nil, false, 1)
require.Nil(t, appErr)
require.Equal(t, 0, i)
// Verify roles count after importing is as expected.
roles, appErr = th2.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles+defaultChannelSchemeRoles)
// Verify schemes match
importedScheme, appErr := th2.App.GetSchemeByName(customScheme.Name)
require.Nil(t, appErr)
require.Equal(t, customScheme.Name, importedScheme.Name)
require.Equal(t, customScheme.DisplayName, importedScheme.DisplayName)
require.Equal(t, customScheme.Description, importedScheme.Description)
require.Equal(t, customScheme.Scope, importedScheme.Scope)
// Verify scheme roles match
importedChannelAdminRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultChannelAdminRole)
require.Nil(t, appErr)
require.Equal(t, customChannelAdminRole.DisplayName, importedChannelAdminRole.DisplayName)
require.Equal(t, customChannelAdminRole.Description, importedChannelAdminRole.Description)
require.Equal(t, customChannelAdminRole.Permissions, importedChannelAdminRole.Permissions)
require.Equal(t, customChannelAdminRole.SchemeManaged, importedChannelAdminRole.SchemeManaged)
require.Equal(t, customChannelAdminRole.BuiltIn, importedChannelAdminRole.BuiltIn)
importedChannelUserRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultChannelUserRole)
require.Nil(t, appErr)
require.Equal(t, customChannelUserRole.DisplayName, importedChannelUserRole.DisplayName)
require.Equal(t, customChannelUserRole.Description, importedChannelUserRole.Description)
require.Equal(t, customChannelUserRole.Permissions, importedChannelUserRole.Permissions)
require.Equal(t, customChannelUserRole.SchemeManaged, importedChannelUserRole.SchemeManaged)
require.Equal(t, customChannelUserRole.BuiltIn, importedChannelUserRole.BuiltIn)
importedChannelGuestRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultChannelGuestRole)
require.Nil(t, appErr)
require.Equal(t, customChannelGuestRole.DisplayName, importedChannelGuestRole.DisplayName)
require.Equal(t, customChannelGuestRole.Description, importedChannelGuestRole.Description)
require.Equal(t, customChannelGuestRole.Permissions, importedChannelGuestRole.Permissions)
require.Equal(t, customChannelGuestRole.SchemeManaged, importedChannelGuestRole.SchemeManaged)
require.Equal(t, customChannelGuestRole.BuiltIn, importedChannelGuestRole.BuiltIn)
})
t.Run("export team scheme", func(t *testing.T) {
th1 := Setup(t).InitBasic()
defer th1.TearDown()
// Need to set this or working with schemes won't work until the job is
// completed which is unnecessary for the purpose of this test.
err := th1.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
builtInRoles := 23
defaultTeamSchemeRoles := 10
// Verify the roles count is expected prior to scheme creation.
roles, appErr := th1.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles)
customScheme, appErr := th1.App.CreateScheme(&model.Scheme{
Name: "custom_team_scheme",
DisplayName: "Custom Team Scheme",
Scope: model.SchemeScopeTeam,
})
require.Nil(t, appErr)
// Verify the roles count is expected after scheme creation.
roles, appErr = th1.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles+defaultTeamSchemeRoles)
customChannelAdminRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultChannelAdminRole)
require.Nil(t, appErr)
customChannelUserRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultChannelUserRole)
require.Nil(t, appErr)
customChannelGuestRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultChannelGuestRole)
require.Nil(t, appErr)
customTeamAdminRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultTeamAdminRole)
require.Nil(t, appErr)
customTeamUserRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultTeamUserRole)
require.Nil(t, appErr)
customTeamGuestRole, appErr := th1.App.GetRoleByName(th1.Context.Context(), customScheme.DefaultTeamGuestRole)
require.Nil(t, appErr)
var b bytes.Buffer
appErr = th1.App.BulkExport(th1.Context, &b, "", nil, model.BulkExportOpts{
IncludeRolesAndSchemes: true,
})
require.Nil(t, appErr)
// The following causes the original store to be wiped so from here on we are targeting the
// second instance where the import will be loaded.
th2 := Setup(t)
defer th2.TearDown()
err = th2.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
require.NoError(t, err)
// Verify roles count before importing is as expected.
roles, appErr = th2.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles)
appErr, i := th2.App.BulkImport(th2.Context, &b, nil, false, 1)
require.Nil(t, appErr)
require.Equal(t, 0, i)
// Verify roles count after importing is as expected.
roles, appErr = th2.App.GetAllRoles()
require.Nil(t, appErr)
require.Len(t, roles, builtInRoles+defaultTeamSchemeRoles)
// Verify schemes match
importedScheme, appErr := th2.App.GetSchemeByName(customScheme.Name)
require.Nil(t, appErr)
require.Equal(t, customScheme.Name, importedScheme.Name)
require.Equal(t, customScheme.DisplayName, importedScheme.DisplayName)
require.Equal(t, customScheme.Description, importedScheme.Description)
require.Equal(t, customScheme.Scope, importedScheme.Scope)
// Verify scheme roles match
importedChannelAdminRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultChannelAdminRole)
require.Nil(t, appErr)
require.Equal(t, customChannelAdminRole.DisplayName, importedChannelAdminRole.DisplayName)
require.Equal(t, customChannelAdminRole.Description, importedChannelAdminRole.Description)
require.Equal(t, customChannelAdminRole.Permissions, importedChannelAdminRole.Permissions)
require.Equal(t, customChannelAdminRole.SchemeManaged, importedChannelAdminRole.SchemeManaged)
require.Equal(t, customChannelAdminRole.BuiltIn, importedChannelAdminRole.BuiltIn)
importedChannelUserRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultChannelUserRole)
require.Nil(t, appErr)
require.Equal(t, customChannelUserRole.DisplayName, importedChannelUserRole.DisplayName)
require.Equal(t, customChannelUserRole.Description, importedChannelUserRole.Description)
require.Equal(t, customChannelUserRole.Permissions, importedChannelUserRole.Permissions)
require.Equal(t, customChannelUserRole.SchemeManaged, importedChannelUserRole.SchemeManaged)
require.Equal(t, customChannelUserRole.BuiltIn, importedChannelUserRole.BuiltIn)
importedChannelGuestRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultChannelGuestRole)
require.Nil(t, appErr)
require.Equal(t, customChannelGuestRole.DisplayName, importedChannelGuestRole.DisplayName)
require.Equal(t, customChannelGuestRole.Description, importedChannelGuestRole.Description)
require.Equal(t, customChannelGuestRole.Permissions, importedChannelGuestRole.Permissions)
require.Equal(t, customChannelGuestRole.SchemeManaged, importedChannelGuestRole.SchemeManaged)
require.Equal(t, customChannelGuestRole.BuiltIn, importedChannelGuestRole.BuiltIn)
importedTeamAdminRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultTeamAdminRole)
require.Nil(t, appErr)
require.Equal(t, customTeamAdminRole.DisplayName, importedTeamAdminRole.DisplayName)
require.Equal(t, customTeamAdminRole.Description, importedTeamAdminRole.Description)
require.Equal(t, customTeamAdminRole.Permissions, importedTeamAdminRole.Permissions)
require.Equal(t, customTeamAdminRole.SchemeManaged, importedTeamAdminRole.SchemeManaged)
require.Equal(t, customTeamAdminRole.BuiltIn, importedTeamAdminRole.BuiltIn)
importedTeamUserRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultTeamUserRole)
require.Nil(t, appErr)
require.Equal(t, customTeamUserRole.DisplayName, importedTeamUserRole.DisplayName)
require.Equal(t, customTeamUserRole.Description, importedTeamUserRole.Description)
require.Equal(t, customTeamUserRole.Permissions, importedTeamUserRole.Permissions)
require.Equal(t, customTeamUserRole.SchemeManaged, importedTeamUserRole.SchemeManaged)
require.Equal(t, customTeamUserRole.BuiltIn, importedTeamUserRole.BuiltIn)
importedTeamGuestRole, appErr := th2.App.GetRoleByName(th2.Context.Context(), importedScheme.DefaultTeamGuestRole)
require.Nil(t, appErr)
require.Equal(t, customTeamGuestRole.DisplayName, importedTeamGuestRole.DisplayName)
require.Equal(t, customTeamGuestRole.Description, importedTeamGuestRole.Description)
require.Equal(t, customTeamGuestRole.Permissions, importedTeamGuestRole.Permissions)
require.Equal(t, customTeamGuestRole.SchemeManaged, importedTeamGuestRole.SchemeManaged)
require.Equal(t, customTeamGuestRole.BuiltIn, importedTeamGuestRole.BuiltIn)
})
}

Просмотреть файл

@@ -314,6 +314,11 @@ func processImportDataFileVersionLine(line imports.LineImportData) (int, *model.
func (a *App) importLine(c request.CTX, line imports.LineImportData, dryRun bool) *model.AppError {
switch {
case line.Type == "role":
if line.Role == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_role.error", nil, "", http.StatusBadRequest)
}
return a.importRole(c, line.Role, dryRun)
case line.Type == "scheme":
if line.Scheme == nil {
return model.NewAppError("BulkImport", "app.import.import_line.null_scheme.error", nil, "", http.StatusBadRequest)

Просмотреть файл

@@ -31,9 +31,9 @@ import (
func (a *App) importScheme(rctx request.CTX, data *imports.SchemeImportData, dryRun bool) *model.AppError {
var fields []mlog.Field
if data != nil && data.Name != nil {
fields = append(fields, mlog.String("schema_name", *data.Name))
fields = append(fields, mlog.String("scheme_name", *data.Name))
}
rctx.Logger().Info("Validating schema", fields...)
rctx.Logger().Info("Validating scheme", fields...)
if err := imports.ValidateSchemeImportData(data); err != nil {
return err
@@ -44,7 +44,7 @@ func (a *App) importScheme(rctx request.CTX, data *imports.SchemeImportData, dry
return nil
}
rctx.Logger().Info("Importing schema", fields...)
rctx.Logger().Info("Importing scheme", fields...)
scheme, err := a.GetSchemeByName(*data.Name)
if err != nil {
@@ -73,44 +73,46 @@ func (a *App) importScheme(rctx request.CTX, data *imports.SchemeImportData, dry
if scheme.Scope == model.SchemeScopeTeam {
data.DefaultTeamAdminRole.Name = &scheme.DefaultTeamAdminRole
if err := a.importRole(rctx, data.DefaultTeamAdminRole, dryRun, true); err != nil {
if err := a.importRole(rctx, data.DefaultTeamAdminRole, dryRun); err != nil {
return err
}
data.DefaultTeamUserRole.Name = &scheme.DefaultTeamUserRole
if err := a.importRole(rctx, data.DefaultTeamUserRole, dryRun, true); err != nil {
if err := a.importRole(rctx, data.DefaultTeamUserRole, dryRun); err != nil {
return err
}
if data.DefaultTeamGuestRole == nil {
data.DefaultTeamGuestRole = &imports.RoleImportData{
DisplayName: model.NewString("Team Guest Role for Scheme"),
DisplayName: model.NewString("Team Guest Role for Scheme"),
SchemeManaged: model.NewBool(true),
}
}
data.DefaultTeamGuestRole.Name = &scheme.DefaultTeamGuestRole
if err := a.importRole(rctx, data.DefaultTeamGuestRole, dryRun, true); err != nil {
if err := a.importRole(rctx, data.DefaultTeamGuestRole, dryRun); err != nil {
return err
}
}
if scheme.Scope == model.SchemeScopeTeam || scheme.Scope == model.SchemeScopeChannel {
data.DefaultChannelAdminRole.Name = &scheme.DefaultChannelAdminRole
if err := a.importRole(rctx, data.DefaultChannelAdminRole, dryRun, true); err != nil {
if err := a.importRole(rctx, data.DefaultChannelAdminRole, dryRun); err != nil {
return err
}
data.DefaultChannelUserRole.Name = &scheme.DefaultChannelUserRole
if err := a.importRole(rctx, data.DefaultChannelUserRole, dryRun, true); err != nil {
if err := a.importRole(rctx, data.DefaultChannelUserRole, dryRun); err != nil {
return err
}
if data.DefaultChannelGuestRole == nil {
data.DefaultChannelGuestRole = &imports.RoleImportData{
DisplayName: model.NewString("Channel Guest Role for Scheme"),
DisplayName: model.NewString("Channel Guest Role for Scheme"),
SchemeManaged: model.NewBool(true),
}
}
data.DefaultChannelGuestRole.Name = &scheme.DefaultChannelGuestRole
if err := a.importRole(rctx, data.DefaultChannelGuestRole, dryRun, true); err != nil {
if err := a.importRole(rctx, data.DefaultChannelGuestRole, dryRun); err != nil {
return err
}
}
@@ -118,18 +120,16 @@ func (a *App) importScheme(rctx request.CTX, data *imports.SchemeImportData, dry
return nil
}
func (a *App) importRole(rctx request.CTX, data *imports.RoleImportData, dryRun bool, isSchemeRole bool) *model.AppError {
func (a *App) importRole(rctx request.CTX, data *imports.RoleImportData, dryRun bool) *model.AppError {
var fields []mlog.Field
if data != nil && data.Name != nil {
fields = append(fields, mlog.String("role_name", *data.Name))
}
if !isSchemeRole {
rctx.Logger().Info("Validating role", fields...)
rctx.Logger().Info("Validating role", fields...)
if err := imports.ValidateRoleImportData(data); err != nil {
return err
}
if err := imports.ValidateRoleImportData(data); err != nil {
return err
}
// If this is a Dry Run, do not continue any further.
@@ -158,10 +158,8 @@ func (a *App) importRole(rctx request.CTX, data *imports.RoleImportData, dryRun
role.Permissions = *data.Permissions
}
if isSchemeRole {
role.SchemeManaged = true
} else {
role.SchemeManaged = false
if data.SchemeManaged != nil {
role.SchemeManaged = *data.SchemeManaged
}
if role.Id == "" {

Просмотреть файл

@@ -413,7 +413,7 @@ func TestImportImportRole(t *testing.T) {
Name: &rid1,
}
err := th.App.importRole(th.Context, &data, true, false)
err := th.App.importRole(th.Context, &data, true)
require.NotNil(t, err, "Should have failed to import.")
_, nErr := th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
@@ -422,7 +422,7 @@ func TestImportImportRole(t *testing.T) {
// Try importing the valid role in dryRun mode.
data.DisplayName = ptrStr("display name")
err = th.App.importRole(th.Context, &data, true, false)
err = th.App.importRole(th.Context, &data, true)
require.Nil(t, err, "Should have succeeded.")
_, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
@@ -431,7 +431,7 @@ func TestImportImportRole(t *testing.T) {
// Try importing an invalid role.
data.DisplayName = nil
err = th.App.importRole(th.Context, &data, false, false)
err = th.App.importRole(th.Context, &data, false)
require.NotNil(t, err, "Should have failed to import.")
_, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
@@ -442,7 +442,7 @@ func TestImportImportRole(t *testing.T) {
data.Description = ptrStr("description")
data.Permissions = &[]string{"invite_user", "add_user_to_team"}
err = th.App.importRole(th.Context, &data, false, false)
err = th.App.importRole(th.Context, &data, false)
require.Nil(t, err, "Should have succeeded.")
role, nErr := th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
@@ -459,8 +459,9 @@ func TestImportImportRole(t *testing.T) {
data.DisplayName = ptrStr("new display name")
data.Description = ptrStr("description")
data.Permissions = &[]string{"manage_slash_commands"}
data.SchemeManaged = model.NewBool(true)
err = th.App.importRole(th.Context, &data, false, true)
err = th.App.importRole(th.Context, &data, false)
require.Nil(t, err, "Should have succeeded. %v", err)
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
@@ -479,7 +480,7 @@ func TestImportImportRole(t *testing.T) {
DisplayName: ptrStr("new display name again"),
}
err = th.App.importRole(th.Context, &data2, false, false)
err = th.App.importRole(th.Context, &data2, false)
require.Nil(t, err, "Should have succeeded.")
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
@@ -490,7 +491,7 @@ func TestImportImportRole(t *testing.T) {
assert.Equal(t, *data.Description, role.Description)
assert.Equal(t, *data.Permissions, role.Permissions)
assert.False(t, role.BuiltIn)
assert.False(t, role.SchemeManaged)
assert.True(t, role.SchemeManaged)
}
func TestImportImportTeam(t *testing.T) {

Просмотреть файл

@@ -14,6 +14,7 @@ import (
type LineImportData struct {
Type string `json:"type"`
Role *RoleImportData `json:"role,omitempty"`
Scheme *SchemeImportData `json:"scheme,omitempty"`
Team *TeamImportData `json:"team,omitempty"`
Channel *ChannelImportData `json:"channel,omitempty"`
@@ -208,10 +209,11 @@ type SchemeImportData struct {
}
type RoleImportData struct {
Name *string `json:"name"`
DisplayName *string `json:"display_name"`
Description *string `json:"description"`
Permissions *[]string `json:"permissions"`
Name *string `json:"name"`
DisplayName *string `json:"display_name"`
Description *string `json:"description"`
Permissions *[]string `json:"permissions"`
SchemeManaged *bool `json:"scheme_managed"`
}
type LineImportWorkerData struct {

Просмотреть файл

@@ -48,6 +48,11 @@ func MakeWorker(jobServer *jobs.JobServer, app AppIface) *jobs.SimpleWorker {
opts.IncludeProfilePictures = true
}
includeRolesAndSchemes, ok := job.Data["include_roles_and_schemes"]
if ok && includeRolesAndSchemes == "true" {
opts.IncludeRolesAndSchemes = true
}
outPath := *app.Config().ExportSettings.Directory
exportFilename := job.Id + "_export.zip"