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 }