github.com/mattermost/mattermost-server/v5@v5.39.3/store/sqlstore/role_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"context"
     8  	"database/sql"
     9  	"fmt"
    10  	"strings"
    11  
    12  	sq "github.com/Masterminds/squirrel"
    13  	"github.com/mattermost/gorp"
    14  	"github.com/pkg/errors"
    15  
    16  	"github.com/mattermost/mattermost-server/v5/model"
    17  	"github.com/mattermost/mattermost-server/v5/store"
    18  )
    19  
    20  type SqlRoleStore struct {
    21  	*SqlStore
    22  }
    23  
    24  type Role struct {
    25  	Id            string
    26  	Name          string
    27  	DisplayName   string
    28  	Description   string
    29  	CreateAt      int64
    30  	UpdateAt      int64
    31  	DeleteAt      int64
    32  	Permissions   string
    33  	SchemeManaged bool
    34  	BuiltIn       bool
    35  }
    36  
    37  type channelRolesPermissions struct {
    38  	GuestRoleName                string
    39  	UserRoleName                 string
    40  	AdminRoleName                string
    41  	HigherScopedGuestPermissions string
    42  	HigherScopedUserPermissions  string
    43  	HigherScopedAdminPermissions string
    44  }
    45  
    46  func NewRoleFromModel(role *model.Role) *Role {
    47  	permissionsMap := make(map[string]bool)
    48  	permissions := ""
    49  
    50  	for _, permission := range role.Permissions {
    51  		if !permissionsMap[permission] {
    52  			permissions += fmt.Sprintf(" %v", permission)
    53  			permissionsMap[permission] = true
    54  		}
    55  	}
    56  
    57  	return &Role{
    58  		Id:            role.Id,
    59  		Name:          role.Name,
    60  		DisplayName:   role.DisplayName,
    61  		Description:   role.Description,
    62  		CreateAt:      role.CreateAt,
    63  		UpdateAt:      role.UpdateAt,
    64  		DeleteAt:      role.DeleteAt,
    65  		Permissions:   permissions,
    66  		SchemeManaged: role.SchemeManaged,
    67  		BuiltIn:       role.BuiltIn,
    68  	}
    69  }
    70  
    71  func (role Role) ToModel() *model.Role {
    72  	return &model.Role{
    73  		Id:            role.Id,
    74  		Name:          role.Name,
    75  		DisplayName:   role.DisplayName,
    76  		Description:   role.Description,
    77  		CreateAt:      role.CreateAt,
    78  		UpdateAt:      role.UpdateAt,
    79  		DeleteAt:      role.DeleteAt,
    80  		Permissions:   strings.Fields(role.Permissions),
    81  		SchemeManaged: role.SchemeManaged,
    82  		BuiltIn:       role.BuiltIn,
    83  	}
    84  }
    85  
    86  func newSqlRoleStore(sqlStore *SqlStore) store.RoleStore {
    87  	s := &SqlRoleStore{sqlStore}
    88  
    89  	for _, db := range sqlStore.GetAllConns() {
    90  		table := db.AddTableWithName(Role{}, "Roles").SetKeys(false, "Id")
    91  		table.ColMap("Id").SetMaxSize(26)
    92  		table.ColMap("Name").SetMaxSize(64).SetUnique(true)
    93  		table.ColMap("DisplayName").SetMaxSize(128)
    94  		table.ColMap("Description").SetMaxSize(1024)
    95  		table.ColMap("Permissions")
    96  	}
    97  	return s
    98  }
    99  
   100  func (s *SqlRoleStore) Save(role *model.Role) (*model.Role, error) {
   101  	// Check the role is valid before proceeding.
   102  	if !role.IsValidWithoutId() {
   103  		return nil, store.NewErrInvalidInput("Role", "<any>", fmt.Sprintf("%v", role))
   104  	}
   105  
   106  	if role.Id == "" {
   107  		transaction, err := s.GetMaster().Begin()
   108  		if err != nil {
   109  			return nil, errors.Wrap(err, "begin_transaction")
   110  		}
   111  		defer finalizeTransaction(transaction)
   112  		createdRole, err := s.createRole(role, transaction)
   113  		if err != nil {
   114  			_ = transaction.Rollback()
   115  			return nil, errors.Wrap(err, "unable to create Role")
   116  		} else if err := transaction.Commit(); err != nil {
   117  			return nil, errors.Wrap(err, "commit_transaction")
   118  		}
   119  		return createdRole, nil
   120  	}
   121  
   122  	dbRole := NewRoleFromModel(role)
   123  	dbRole.UpdateAt = model.GetMillis()
   124  	if rowsChanged, err := s.GetMaster().Update(dbRole); err != nil {
   125  		return nil, errors.Wrap(err, "failed to update Role")
   126  	} else if rowsChanged != 1 {
   127  		return nil, fmt.Errorf("invalid number of updated rows, expected 1 but got %d", rowsChanged)
   128  	}
   129  
   130  	return dbRole.ToModel(), nil
   131  }
   132  
   133  func (s *SqlRoleStore) createRole(role *model.Role, transaction *gorp.Transaction) (*model.Role, error) {
   134  	// Check the role is valid before proceeding.
   135  	if !role.IsValidWithoutId() {
   136  		return nil, store.NewErrInvalidInput("Role", "<any>", fmt.Sprintf("%v", role))
   137  	}
   138  
   139  	dbRole := NewRoleFromModel(role)
   140  
   141  	dbRole.Id = model.NewId()
   142  	dbRole.CreateAt = model.GetMillis()
   143  	dbRole.UpdateAt = dbRole.CreateAt
   144  
   145  	if err := transaction.Insert(dbRole); err != nil {
   146  		return nil, errors.Wrap(err, "failed to save Role")
   147  	}
   148  
   149  	return dbRole.ToModel(), nil
   150  }
   151  
   152  func (s *SqlRoleStore) Get(roleId string) (*model.Role, error) {
   153  	var dbRole Role
   154  
   155  	if err := s.GetReplica().SelectOne(&dbRole, "SELECT * from Roles WHERE Id = :Id", map[string]interface{}{"Id": roleId}); err != nil {
   156  		if err == sql.ErrNoRows {
   157  			return nil, store.NewErrNotFound("Role", roleId)
   158  		}
   159  		return nil, errors.Wrap(err, "failed to get Role")
   160  	}
   161  
   162  	return dbRole.ToModel(), nil
   163  }
   164  
   165  func (s *SqlRoleStore) GetAll() ([]*model.Role, error) {
   166  	var dbRoles []Role
   167  
   168  	if _, err := s.GetReplica().Select(&dbRoles, "SELECT * from Roles", map[string]interface{}{}); err != nil {
   169  		return nil, errors.Wrap(err, "failed to find Roles")
   170  	}
   171  
   172  	var roles []*model.Role
   173  	for _, dbRole := range dbRoles {
   174  		roles = append(roles, dbRole.ToModel())
   175  	}
   176  	return roles, nil
   177  }
   178  
   179  func (s *SqlRoleStore) GetByName(ctx context.Context, name string) (*model.Role, error) {
   180  	var dbRole Role
   181  	if err := s.DBFromContext(ctx).SelectOne(&dbRole, "SELECT * from Roles WHERE Name = :Name", map[string]interface{}{"Name": name}); err != nil {
   182  		if err == sql.ErrNoRows {
   183  			return nil, store.NewErrNotFound("Role", fmt.Sprintf("name=%s", name))
   184  		}
   185  		return nil, errors.Wrapf(err, "failed to find Roles with name=%s", name)
   186  	}
   187  
   188  	return dbRole.ToModel(), nil
   189  }
   190  
   191  func (s *SqlRoleStore) GetByNames(names []string) ([]*model.Role, error) {
   192  	if len(names) == 0 {
   193  		return []*model.Role{}, nil
   194  	}
   195  
   196  	query := s.getQueryBuilder().
   197  		Select("Id, Name, DisplayName, Description, CreateAt, UpdateAt, DeleteAt, Permissions, SchemeManaged, BuiltIn").
   198  		From("Roles").
   199  		Where(sq.Eq{"Name": names})
   200  	queryString, args, err := query.ToSql()
   201  	if err != nil {
   202  		return nil, errors.Wrap(err, "role_tosql")
   203  	}
   204  
   205  	rows, err := s.GetReplica().Db.Query(queryString, args...)
   206  	if err != nil {
   207  		return nil, errors.Wrap(err, "failed to find Roles")
   208  	}
   209  
   210  	var roles []*model.Role
   211  	defer rows.Close()
   212  	for rows.Next() {
   213  		var role Role
   214  		err = rows.Scan(
   215  			&role.Id, &role.Name, &role.DisplayName, &role.Description,
   216  			&role.CreateAt, &role.UpdateAt, &role.DeleteAt, &role.Permissions,
   217  			&role.SchemeManaged, &role.BuiltIn)
   218  		if err != nil {
   219  			return nil, errors.Wrap(err, "failed to scan values")
   220  		}
   221  		roles = append(roles, role.ToModel())
   222  	}
   223  	if err = rows.Err(); err != nil {
   224  		return nil, errors.Wrap(err, "unable to iterate over rows")
   225  	}
   226  
   227  	return roles, nil
   228  }
   229  
   230  func (s *SqlRoleStore) Delete(roleId string) (*model.Role, error) {
   231  	// Get the role.
   232  	var role *Role
   233  	if err := s.GetReplica().SelectOne(&role, "SELECT * from Roles WHERE Id = :Id", map[string]interface{}{"Id": roleId}); err != nil {
   234  		if err == sql.ErrNoRows {
   235  			return nil, store.NewErrNotFound("Role", roleId)
   236  		}
   237  		return nil, errors.Wrapf(err, "failed to get Role with id=%s", roleId)
   238  	}
   239  
   240  	time := model.GetMillis()
   241  	role.DeleteAt = time
   242  	role.UpdateAt = time
   243  
   244  	if rowsChanged, err := s.GetMaster().Update(role); err != nil {
   245  		return nil, errors.Wrap(err, "failed to update Role")
   246  	} else if rowsChanged != 1 {
   247  		return nil, errors.Wrapf(err, "invalid number of updated rows, expected 1 but got %d", rowsChanged)
   248  	}
   249  	return role.ToModel(), nil
   250  }
   251  
   252  func (s *SqlRoleStore) PermanentDeleteAll() error {
   253  	if _, err := s.GetMaster().Exec("DELETE FROM Roles"); err != nil {
   254  		return errors.Wrap(err, "failed to delete Roles")
   255  	}
   256  
   257  	return nil
   258  }
   259  
   260  func (s *SqlRoleStore) channelHigherScopedPermissionsQuery(roleNames []string) string {
   261  	sqlTmpl := `
   262  		SELECT
   263  			'' AS GuestRoleName,
   264  			RoleSchemes.DefaultChannelUserRole AS UserRoleName,
   265  			RoleSchemes.DefaultChannelAdminRole AS AdminRoleName,
   266  			'' AS HigherScopedGuestPermissions,
   267  			UserRoles.Permissions AS HigherScopedUserPermissions,
   268  			AdminRoles.Permissions AS HigherScopedAdminPermissions
   269  		FROM
   270  			Schemes AS RoleSchemes
   271  			JOIN Channels ON Channels.SchemeId = RoleSchemes.Id
   272  			JOIN Teams ON Teams.Id = Channels.TeamId
   273  			JOIN Schemes ON Schemes.Id = Teams.SchemeId
   274  			RIGHT JOIN Roles AS UserRoles ON UserRoles.Name = Schemes.DefaultChannelUserRole
   275  			RIGHT JOIN Roles AS AdminRoles ON AdminRoles.Name = Schemes.DefaultChannelAdminRole
   276  		WHERE
   277  			RoleSchemes.DefaultChannelUserRole IN ('%[1]s')
   278  			OR RoleSchemes.DefaultChannelAdminRole IN ('%[1]s')
   279  
   280  		UNION
   281  
   282  		SELECT
   283  			RoleSchemes.DefaultChannelGuestRole AS GuestRoleName,
   284  			'' AS UserRoleName,
   285  			'' AS AdminRoleName,
   286  			GuestRoles.Permissions AS HigherScopedGuestPermissions,
   287  			'' AS HigherScopedUserPermissions,
   288  			'' AS HigherScopedAdminPermissions
   289  		FROM
   290  			Schemes AS RoleSchemes
   291  			JOIN Channels ON Channels.SchemeId = RoleSchemes.Id
   292  			JOIN Teams ON Teams.Id = Channels.TeamId
   293  			JOIN Schemes ON Schemes.Id = Teams.SchemeId
   294  			RIGHT JOIN Roles AS GuestRoles ON GuestRoles.Name = Schemes.DefaultChannelGuestRole
   295  		WHERE
   296  			RoleSchemes.DefaultChannelGuestRole IN ('%[1]s')
   297  
   298  		UNION
   299  
   300  		SELECT
   301  			Schemes.DefaultChannelGuestRole AS GuestRoleName,
   302  			Schemes.DefaultChannelUserRole AS UserRoleName,
   303  			Schemes.DefaultChannelAdminRole AS AdminRoleName,
   304  			GuestRoles.Permissions AS HigherScopedGuestPermissions,
   305  			UserRoles.Permissions AS HigherScopedUserPermissions,
   306  			AdminRoles.Permissions AS HigherScopedAdminPermissions
   307  		FROM
   308  			Schemes
   309  			JOIN Channels ON Channels.SchemeId = Schemes.Id
   310  			JOIN Teams ON Teams.Id = Channels.TeamId
   311  			JOIN Roles AS GuestRoles ON GuestRoles.Name = '%[2]s'
   312  			JOIN Roles AS UserRoles ON UserRoles.Name = '%[3]s'
   313  			JOIN Roles AS AdminRoles ON AdminRoles.Name = '%[4]s'
   314  		WHERE
   315  			(Schemes.DefaultChannelGuestRole IN ('%[1]s')
   316  			OR Schemes.DefaultChannelUserRole IN ('%[1]s')
   317  			OR Schemes.DefaultChannelAdminRole IN ('%[1]s'))
   318  		AND (Teams.SchemeId = ''
   319  			OR Teams.SchemeId IS NULL)
   320  	`
   321  
   322  	// The below three channel role names are referenced by their name value because there is no system scheme
   323  	// record that ships with Mattermost, otherwise the system scheme would be referenced by name and the channel
   324  	// roles would be referenced by their column names.
   325  	return fmt.Sprintf(
   326  		sqlTmpl,
   327  		strings.Join(roleNames, "', '"),
   328  		model.CHANNEL_GUEST_ROLE_ID,
   329  		model.CHANNEL_USER_ROLE_ID,
   330  		model.CHANNEL_ADMIN_ROLE_ID,
   331  	)
   332  }
   333  
   334  func (s *SqlRoleStore) ChannelHigherScopedPermissions(roleNames []string) (map[string]*model.RolePermissions, error) {
   335  	query := s.channelHigherScopedPermissionsQuery(roleNames)
   336  
   337  	var rolesPermissions []*channelRolesPermissions
   338  	if _, err := s.GetReplica().Select(&rolesPermissions, query); err != nil {
   339  		return nil, errors.Wrap(err, "failed to find RolePermissions")
   340  	}
   341  
   342  	roleNameHigherScopedPermissions := map[string]*model.RolePermissions{}
   343  
   344  	for _, rp := range rolesPermissions {
   345  		roleNameHigherScopedPermissions[rp.GuestRoleName] = &model.RolePermissions{RoleID: model.CHANNEL_GUEST_ROLE_ID, Permissions: strings.Split(rp.HigherScopedGuestPermissions, " ")}
   346  		roleNameHigherScopedPermissions[rp.UserRoleName] = &model.RolePermissions{RoleID: model.CHANNEL_USER_ROLE_ID, Permissions: strings.Split(rp.HigherScopedUserPermissions, " ")}
   347  		roleNameHigherScopedPermissions[rp.AdminRoleName] = &model.RolePermissions{RoleID: model.CHANNEL_ADMIN_ROLE_ID, Permissions: strings.Split(rp.HigherScopedAdminPermissions, " ")}
   348  	}
   349  
   350  	return roleNameHigherScopedPermissions, nil
   351  }
   352  
   353  func (s *SqlRoleStore) AllChannelSchemeRoles() ([]*model.Role, error) {
   354  	query := s.getQueryBuilder().
   355  		Select("Roles.*").
   356  		From("Schemes").
   357  		Join("Roles ON Schemes.DefaultChannelGuestRole = Roles.Name OR Schemes.DefaultChannelUserRole = Roles.Name OR Schemes.DefaultChannelAdminRole = Roles.Name").
   358  		Where(sq.Eq{"Schemes.Scope": model.SCHEME_SCOPE_CHANNEL}).
   359  		Where(sq.Eq{"Roles.DeleteAt": 0}).
   360  		Where(sq.Eq{"Schemes.DeleteAt": 0})
   361  
   362  	queryString, args, err := query.ToSql()
   363  	if err != nil {
   364  		return nil, errors.Wrap(err, "role_tosql")
   365  	}
   366  
   367  	var dbRoles []*Role
   368  	if _, err = s.GetReplica().Select(&dbRoles, queryString, args...); err != nil {
   369  		return nil, errors.Wrap(err, "failed to find Roles")
   370  	}
   371  
   372  	var roles []*model.Role
   373  	for _, dbRole := range dbRoles {
   374  		roles = append(roles, dbRole.ToModel())
   375  	}
   376  
   377  	return roles, nil
   378  }
   379  
   380  // ChannelRolesUnderTeamRole finds all of the channel-scheme roles under the team of the given team-scheme role.
   381  func (s *SqlRoleStore) ChannelRolesUnderTeamRole(roleName string) ([]*model.Role, error) {
   382  	query := s.getQueryBuilder().
   383  		Select("ChannelSchemeRoles.*").
   384  		From("Roles AS HigherScopedRoles").
   385  		Join("Schemes AS HigherScopedSchemes ON (HigherScopedRoles.Name = HigherScopedSchemes.DefaultChannelGuestRole OR HigherScopedRoles.Name = HigherScopedSchemes.DefaultChannelUserRole OR HigherScopedRoles.Name = HigherScopedSchemes.DefaultChannelAdminRole)").
   386  		Join("Teams ON Teams.SchemeId = HigherScopedSchemes.Id").
   387  		Join("Channels ON Channels.TeamId = Teams.Id").
   388  		Join("Schemes AS ChannelSchemes ON Channels.SchemeId = ChannelSchemes.Id").
   389  		Join("Roles AS ChannelSchemeRoles ON (ChannelSchemeRoles.Name = ChannelSchemes.DefaultChannelGuestRole OR ChannelSchemeRoles.Name = ChannelSchemes.DefaultChannelUserRole OR ChannelSchemeRoles.Name = ChannelSchemes.DefaultChannelAdminRole)").
   390  		Where(sq.Eq{"HigherScopedSchemes.Scope": model.SCHEME_SCOPE_TEAM}).
   391  		Where(sq.Eq{"HigherScopedRoles.Name": roleName}).
   392  		Where(sq.Eq{"HigherScopedRoles.DeleteAt": 0}).
   393  		Where(sq.Eq{"HigherScopedSchemes.DeleteAt": 0}).
   394  		Where(sq.Eq{"Teams.DeleteAt": 0}).
   395  		Where(sq.Eq{"Channels.DeleteAt": 0}).
   396  		Where(sq.Eq{"ChannelSchemes.DeleteAt": 0}).
   397  		Where(sq.Eq{"ChannelSchemeRoles.DeleteAt": 0})
   398  
   399  	queryString, args, err := query.ToSql()
   400  	if err != nil {
   401  		return nil, errors.Wrap(err, "role_tosql")
   402  	}
   403  
   404  	var dbRoles []*Role
   405  	if _, err = s.GetReplica().Select(&dbRoles, queryString, args...); err != nil {
   406  		return nil, errors.Wrap(err, "failed to find Roles")
   407  	}
   408  
   409  	var roles []*model.Role
   410  	for _, dbRole := range dbRoles {
   411  		roles = append(roles, dbRole.ToModel())
   412  	}
   413  
   414  	return roles, nil
   415  }