github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/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  	"database/sql"
     8  	"fmt"
     9  	"strings"
    10  
    11  	sq "github.com/Masterminds/squirrel"
    12  	"github.com/mattermost/gorp"
    13  	"github.com/pkg/errors"
    14  
    15  	"github.com/mattermost/mattermost-server/v5/model"
    16  	"github.com/mattermost/mattermost-server/v5/store"
    17  )
    18  
    19  type SqlRoleStore struct {
    20  	*SqlStore
    21  }
    22  
    23  type Role struct {
    24  	Id            string
    25  	Name          string
    26  	DisplayName   string
    27  	Description   string
    28  	CreateAt      int64
    29  	UpdateAt      int64
    30  	DeleteAt      int64
    31  	Permissions   string
    32  	SchemeManaged bool
    33  	BuiltIn       bool
    34  }
    35  
    36  type channelRolesPermissions struct {
    37  	GuestRoleName                string
    38  	UserRoleName                 string
    39  	AdminRoleName                string
    40  	HigherScopedGuestPermissions string
    41  	HigherScopedUserPermissions  string
    42  	HigherScopedAdminPermissions string
    43  }
    44  
    45  func NewRoleFromModel(role *model.Role) *Role {
    46  	permissionsMap := make(map[string]bool)
    47  	permissions := ""
    48  
    49  	for _, permission := range role.Permissions {
    50  		if !permissionsMap[permission] {
    51  			permissions += fmt.Sprintf(" %v", permission)
    52  			permissionsMap[permission] = true
    53  		}
    54  	}
    55  
    56  	return &Role{
    57  		Id:            role.Id,
    58  		Name:          role.Name,
    59  		DisplayName:   role.DisplayName,
    60  		Description:   role.Description,
    61  		CreateAt:      role.CreateAt,
    62  		UpdateAt:      role.UpdateAt,
    63  		DeleteAt:      role.DeleteAt,
    64  		Permissions:   permissions,
    65  		SchemeManaged: role.SchemeManaged,
    66  		BuiltIn:       role.BuiltIn,
    67  	}
    68  }
    69  
    70  func (role Role) ToModel() *model.Role {
    71  	return &model.Role{
    72  		Id:            role.Id,
    73  		Name:          role.Name,
    74  		DisplayName:   role.DisplayName,
    75  		Description:   role.Description,
    76  		CreateAt:      role.CreateAt,
    77  		UpdateAt:      role.UpdateAt,
    78  		DeleteAt:      role.DeleteAt,
    79  		Permissions:   strings.Fields(role.Permissions),
    80  		SchemeManaged: role.SchemeManaged,
    81  		BuiltIn:       role.BuiltIn,
    82  	}
    83  }
    84  
    85  func newSqlRoleStore(sqlStore *SqlStore) store.RoleStore {
    86  	s := &SqlRoleStore{sqlStore}
    87  
    88  	for _, db := range sqlStore.GetAllConns() {
    89  		table := db.AddTableWithName(Role{}, "Roles").SetKeys(false, "Id")
    90  		table.ColMap("Id").SetMaxSize(26)
    91  		table.ColMap("Name").SetMaxSize(64).SetUnique(true)
    92  		table.ColMap("DisplayName").SetMaxSize(128)
    93  		table.ColMap("Description").SetMaxSize(1024)
    94  		table.ColMap("Permissions").SetMaxSize(4096)
    95  	}
    96  	return s
    97  }
    98  
    99  func (s *SqlRoleStore) Save(role *model.Role) (*model.Role, error) {
   100  	// Check the role is valid before proceeding.
   101  	if !role.IsValidWithoutId() {
   102  		return nil, store.NewErrInvalidInput("Role", "<any>", fmt.Sprintf("%v", role))
   103  	}
   104  
   105  	if role.Id == "" {
   106  		transaction, err := s.GetMaster().Begin()
   107  		if err != nil {
   108  			return nil, errors.Wrap(err, "begin_transaction")
   109  		}
   110  		defer finalizeTransaction(transaction)
   111  		createdRole, err := s.createRole(role, transaction)
   112  		if err != nil {
   113  			_ = transaction.Rollback()
   114  			return nil, errors.Wrap(err, "unable to create Role")
   115  		} else if err := transaction.Commit(); err != nil {
   116  			return nil, errors.Wrap(err, "commit_transaction")
   117  		}
   118  		return createdRole, nil
   119  	}
   120  
   121  	dbRole := NewRoleFromModel(role)
   122  	dbRole.UpdateAt = model.GetMillis()
   123  	if rowsChanged, err := s.GetMaster().Update(dbRole); err != nil {
   124  		return nil, errors.Wrap(err, "failed to update Role")
   125  	} else if rowsChanged != 1 {
   126  		return nil, fmt.Errorf("invalid number of updated rows, expected 1 but got %d", rowsChanged)
   127  	}
   128  
   129  	return dbRole.ToModel(), nil
   130  }
   131  
   132  func (s *SqlRoleStore) createRole(role *model.Role, transaction *gorp.Transaction) (*model.Role, error) {
   133  	// Check the role is valid before proceeding.
   134  	if !role.IsValidWithoutId() {
   135  		return nil, store.NewErrInvalidInput("Role", "<any>", fmt.Sprintf("%v", role))
   136  	}
   137  
   138  	dbRole := NewRoleFromModel(role)
   139  
   140  	dbRole.Id = model.NewId()
   141  	dbRole.CreateAt = model.GetMillis()
   142  	dbRole.UpdateAt = dbRole.CreateAt
   143  
   144  	if err := transaction.Insert(dbRole); err != nil {
   145  		return nil, errors.Wrap(err, "failed to save Role")
   146  	}
   147  
   148  	return dbRole.ToModel(), nil
   149  }
   150  
   151  func (s *SqlRoleStore) Get(roleId string) (*model.Role, error) {
   152  	var dbRole Role
   153  
   154  	if err := s.GetReplica().SelectOne(&dbRole, "SELECT * from Roles WHERE Id = :Id", map[string]interface{}{"Id": roleId}); err != nil {
   155  		if err == sql.ErrNoRows {
   156  			return nil, store.NewErrNotFound("Role", roleId)
   157  		}
   158  		return nil, errors.Wrap(err, "failed to get Role")
   159  	}
   160  
   161  	return dbRole.ToModel(), nil
   162  }
   163  
   164  func (s *SqlRoleStore) GetAll() ([]*model.Role, error) {
   165  	var dbRoles []Role
   166  
   167  	if _, err := s.GetReplica().Select(&dbRoles, "SELECT * from Roles", map[string]interface{}{}); err != nil {
   168  		return nil, errors.Wrap(err, "failed to find Roles")
   169  	}
   170  
   171  	var roles []*model.Role
   172  	for _, dbRole := range dbRoles {
   173  		roles = append(roles, dbRole.ToModel())
   174  	}
   175  	return roles, nil
   176  }
   177  
   178  func (s *SqlRoleStore) GetByName(name string) (*model.Role, error) {
   179  	var dbRole Role
   180  
   181  	if err := s.GetReplica().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  }