github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/store/sqlstore/role_store.go (about)

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