mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
https://mattermost.atlassian.net/browse/MM-52532 - Replace golint with revive - Add makezero linter - Fix all the required linter failures Some issues in enterprise and public modules are yet to be fixed. We send this to expediate things.
290 lines
9.5 KiB
Go
290 lines
9.5 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package app
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/v8/channels/app/request"
|
|
"github.com/mattermost/mattermost/server/v8/channels/product"
|
|
)
|
|
|
|
const permissionsExportBatchSize = 100
|
|
const systemSchemeName = "00000000-0000-0000-0000-000000000000" // Prevents collisions with user-created schemes.
|
|
|
|
// Ensure permissions service wrapper implements `product.PermissionService`
|
|
var _ product.PermissionService = (*permissionsServiceWrapper)(nil)
|
|
|
|
// permissionsServiceWrapper provides an implementation of `product.PermissionService` for use by products.
|
|
type permissionsServiceWrapper struct {
|
|
app AppIface
|
|
}
|
|
|
|
func (s *permissionsServiceWrapper) HasPermissionTo(userID string, permission *model.Permission) bool {
|
|
return s.app.HasPermissionTo(userID, permission)
|
|
}
|
|
|
|
func (s *permissionsServiceWrapper) HasPermissionToTeam(userID string, teamID string, permission *model.Permission) bool {
|
|
return s.app.HasPermissionToTeam(userID, teamID, permission)
|
|
}
|
|
|
|
func (s *permissionsServiceWrapper) HasPermissionToChannel(askingUserID string, channelID string, permission *model.Permission) bool {
|
|
return s.app.HasPermissionToChannel(request.EmptyContext(s.app.Log()), askingUserID, channelID, permission)
|
|
}
|
|
|
|
func (s *permissionsServiceWrapper) RolesGrantPermission(roleNames []string, permissionId string) bool {
|
|
return s.app.RolesGrantPermission(roleNames, permissionId)
|
|
}
|
|
|
|
func (a *App) ResetPermissionsSystem() *model.AppError {
|
|
// Reset all Teams to not have a scheme.
|
|
if err := a.Srv().Store().Team().ResetAllTeamSchemes(); err != nil {
|
|
return model.NewAppError("ResetPermissionsSystem", "app.team.reset_all_team_schemes.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Reset all Channels to not have a scheme.
|
|
if err := a.Srv().Store().Channel().ResetAllChannelSchemes(); err != nil {
|
|
return model.NewAppError("ResetPermissionsSystem", "app.channel.reset_all_channel_schemes.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Reset all Custom Role assignments to Users.
|
|
if err := a.Srv().Store().User().ClearAllCustomRoleAssignments(); err != nil {
|
|
return model.NewAppError("ResetPermissionsSystem", "app.user.clear_all_custom_role_assignments.select.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Reset all Custom Role assignments to TeamMembers.
|
|
if err := a.Srv().Store().Team().ClearAllCustomRoleAssignments(); err != nil {
|
|
return model.NewAppError("ResetPermissionsSystem", "app.team.clear_all_custom_role_assignments.select.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Reset all Custom Role assignments to ChannelMembers.
|
|
if err := a.Srv().Store().Channel().ClearAllCustomRoleAssignments(); err != nil {
|
|
return model.NewAppError("ResetPermissionsSystem", "app.channel.clear_all_custom_role_assignments.select.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Purge all schemes from the database.
|
|
if err := a.Srv().Store().Scheme().PermanentDeleteAll(); err != nil {
|
|
return model.NewAppError("ResetPermissionsSystem", "app.scheme.permanent_delete_all.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Purge all roles from the database.
|
|
if err := a.Srv().Store().Role().PermanentDeleteAll(); err != nil {
|
|
return model.NewAppError("ResetPermissionsSystem", "app.role.permanent_delete_all.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Remove the "System" table entry that marks the advanced permissions migration as done.
|
|
if _, err := a.Srv().Store().System().PermanentDeleteByName(model.AdvancedPermissionsMigrationKey); err != nil {
|
|
return model.NewAppError("ResetPermissionSystem", "app.system.permanent_delete_by_name.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Remove the "System" table entry that marks the emoji permissions migration as done.
|
|
if _, err := a.Srv().Store().System().PermanentDeleteByName(EmojisPermissionsMigrationKey); err != nil {
|
|
return model.NewAppError("ResetPermissionSystem", "app.system.permanent_delete_by_name.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Remove the "System" table entry that marks the guest roles permissions migration as done.
|
|
if _, err := a.Srv().Store().System().PermanentDeleteByName(GuestRolesCreationMigrationKey); err != nil {
|
|
return model.NewAppError("ResetPermissionSystem", "app.system.permanent_delete_by_name.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
}
|
|
|
|
// Now that the permissions system has been reset, re-run the migration to reinitialise it.
|
|
a.DoAppMigrations()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (a *App) ExportPermissions(w io.Writer) error {
|
|
|
|
next := a.SchemesIterator("", permissionsExportBatchSize)
|
|
var schemeBatch []*model.Scheme
|
|
|
|
for schemeBatch = next(); len(schemeBatch) > 0; schemeBatch = next() {
|
|
|
|
for _, scheme := range schemeBatch {
|
|
|
|
roleNames := []string{
|
|
scheme.DefaultTeamAdminRole,
|
|
scheme.DefaultTeamUserRole,
|
|
scheme.DefaultTeamGuestRole,
|
|
scheme.DefaultChannelAdminRole,
|
|
scheme.DefaultChannelUserRole,
|
|
scheme.DefaultChannelGuestRole,
|
|
}
|
|
|
|
roles := []*model.Role{}
|
|
for _, roleName := range roleNames {
|
|
if roleName == "" {
|
|
continue
|
|
}
|
|
role, err := a.GetRoleByName(context.Background(), roleName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
roles = append(roles, role)
|
|
}
|
|
|
|
schemeExport, err := json.Marshal(&model.SchemeConveyor{
|
|
Name: scheme.Name,
|
|
DisplayName: scheme.DisplayName,
|
|
Description: scheme.Description,
|
|
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 {
|
|
return err
|
|
}
|
|
|
|
schemeExport = append(schemeExport, []byte("\n")...)
|
|
|
|
_, err = w.Write(schemeExport)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
defaultRoleNames := []string{}
|
|
for _, dr := range model.MakeDefaultRoles() {
|
|
defaultRoleNames = append(defaultRoleNames, dr.Name)
|
|
}
|
|
|
|
roles, appErr := a.GetRolesByNames(defaultRoleNames)
|
|
if appErr != nil {
|
|
return errors.New(appErr.Message)
|
|
}
|
|
|
|
schemeExport, err := json.Marshal(&model.SchemeConveyor{
|
|
Name: systemSchemeName,
|
|
Roles: roles,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
schemeExport = append(schemeExport, []byte("\n")...)
|
|
|
|
_, err = w.Write(schemeExport)
|
|
return err
|
|
}
|
|
|
|
func (a *App) ImportPermissions(jsonl io.Reader) error {
|
|
createdSchemeIDs := []string{}
|
|
|
|
scanner := bufio.NewScanner(jsonl)
|
|
|
|
for scanner.Scan() {
|
|
var schemeConveyor *model.SchemeConveyor
|
|
err := json.Unmarshal(scanner.Bytes(), &schemeConveyor)
|
|
if err != nil {
|
|
rollback(a, createdSchemeIDs)
|
|
return err
|
|
}
|
|
|
|
if schemeConveyor.Name == systemSchemeName {
|
|
for _, roleIn := range schemeConveyor.Roles {
|
|
dbRole, err := a.GetRoleByName(context.Background(), roleIn.Name)
|
|
if err != nil {
|
|
rollback(a, createdSchemeIDs)
|
|
return errors.New(err.Message)
|
|
}
|
|
_, err = a.PatchRole(dbRole, &model.RolePatch{
|
|
Permissions: &roleIn.Permissions,
|
|
})
|
|
if err != nil {
|
|
rollback(a, createdSchemeIDs)
|
|
return err
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
// Create the new Scheme. The new Roles are created automatically.
|
|
var appErr *model.AppError
|
|
schemeCreated, appErr := a.CreateScheme(schemeConveyor.Scheme())
|
|
if appErr != nil {
|
|
rollback(a, createdSchemeIDs)
|
|
return errors.New(appErr.Message)
|
|
}
|
|
createdSchemeIDs = append(createdSchemeIDs, schemeCreated.Id)
|
|
|
|
schemeIn := schemeConveyor.Scheme()
|
|
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 roleNameTuple[0] == "" || roleNameTuple[1] == "" {
|
|
continue
|
|
}
|
|
|
|
err = updateRole(a, schemeConveyor, roleNameTuple[0], roleNameTuple[1])
|
|
if err != nil {
|
|
// Delete the new Schemes. The new Roles are deleted automatically.
|
|
rollback(a, createdSchemeIDs)
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
rollback(a, createdSchemeIDs)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func rollback(a *App, createdSchemeIDs []string) {
|
|
for _, schemeID := range createdSchemeIDs {
|
|
a.DeleteScheme(schemeID)
|
|
}
|
|
}
|
|
|
|
func updateRole(a *App, sc *model.SchemeConveyor, roleCreatedName, defaultRoleName string) error {
|
|
var err *model.AppError
|
|
|
|
roleCreated, err := a.GetRoleByName(context.Background(), roleCreatedName)
|
|
if err != nil {
|
|
return errors.New(err.Message)
|
|
}
|
|
|
|
var roleIn *model.Role
|
|
for _, role := range sc.Roles {
|
|
if role.Name == defaultRoleName {
|
|
roleIn = role
|
|
break
|
|
}
|
|
}
|
|
|
|
roleCreated.DisplayName = roleIn.DisplayName
|
|
roleCreated.Description = roleIn.Description
|
|
roleCreated.Permissions = roleIn.Permissions
|
|
|
|
_, err = a.UpdateRole(roleCreated)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update role: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|