[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)