github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/store/sqlstore/scheme_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 "net/http" 10 "strings" 11 12 "github.com/mattermost/gorp" 13 14 "github.com/vnforks/kid/v5/model" 15 "github.com/vnforks/kid/v5/store" 16 ) 17 18 type SqlSchemeStore struct { 19 SqlStore 20 } 21 22 func newSqlSchemeStore(sqlStore SqlStore) store.SchemeStore { 23 s := &SqlSchemeStore{sqlStore} 24 25 for _, db := range sqlStore.GetAllConns() { 26 table := db.AddTableWithName(model.Scheme{}, "Schemes").SetKeys(false, "Id") 27 table.ColMap("Id").SetMaxSize(26) 28 table.ColMap("Name").SetMaxSize(model.SCHEME_NAME_MAX_LENGTH).SetUnique(true) 29 table.ColMap("DisplayName").SetMaxSize(model.SCHEME_DISPLAY_NAME_MAX_LENGTH) 30 table.ColMap("Description").SetMaxSize(model.SCHEME_DESCRIPTION_MAX_LENGTH) 31 table.ColMap("Scope").SetMaxSize(32) 32 table.ColMap("DefaultBranchAdminRole").SetMaxSize(64) 33 table.ColMap("DefaultBranchUserRole").SetMaxSize(64) 34 table.ColMap("DefaultClassAdminRole").SetMaxSize(64) 35 table.ColMap("DefaultClassUserRole").SetMaxSize(64) 36 } 37 38 return s 39 } 40 41 func (s SqlSchemeStore) createIndexesIfNotExists() { 42 s.CreateIndexIfNotExists("idx_schemes_class_user_role", "Schemes", "DefaultClassUserRole") 43 s.CreateIndexIfNotExists("idx_schemes_class_admin_role", "Schemes", "DefaultClassAdminRole") 44 } 45 46 func (s *SqlSchemeStore) Save(scheme *model.Scheme) (*model.Scheme, *model.AppError) { 47 if len(scheme.Id) == 0 { 48 transaction, err := s.GetMaster().Begin() 49 if err != nil { 50 return nil, model.NewAppError("SqlSchemeStore.SaveScheme", "store.sql_scheme.save.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 51 } 52 defer finalizeTransaction(transaction) 53 54 newScheme, appErr := s.createScheme(scheme, transaction) 55 if appErr != nil { 56 return nil, appErr 57 } 58 if err := transaction.Commit(); err != nil { 59 return nil, model.NewAppError("SqlSchemeStore.SchemeSave", "store.sql_scheme.save_scheme.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 60 } 61 return newScheme, nil 62 } 63 64 if !scheme.IsValid() { 65 return nil, model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.invalid_scheme.app_error", nil, "schemeId="+scheme.Id, http.StatusBadRequest) 66 } 67 68 scheme.UpdateAt = model.GetMillis() 69 70 rowsChanged, err := s.GetMaster().Update(scheme) 71 if err != nil { 72 return nil, model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.update.app_error", nil, err.Error(), http.StatusInternalServerError) 73 } 74 if rowsChanged != 1 { 75 return nil, model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.update.app_error", nil, "no record to update", http.StatusInternalServerError) 76 } 77 78 return scheme, nil 79 } 80 81 func (s *SqlSchemeStore) createScheme(scheme *model.Scheme, transaction *gorp.Transaction) (*model.Scheme, *model.AppError) { 82 // Fetch the default system scheme roles to populate default permissions. 83 defaultRoleNames := []string{model.BRANCH_ADMIN_ROLE_ID, model.BRANCH_USER_ROLE_ID, model.CLASS_ADMIN_ROLE_ID, model.CLASS_USER_ROLE_ID} 84 defaultRoles := make(map[string]*model.Role) 85 roles, err := s.SqlStore.Role().GetByNames(defaultRoleNames) 86 if err != nil { 87 return nil, err 88 } 89 90 for _, role := range roles { 91 switch role.Name { 92 case model.BRANCH_ADMIN_ROLE_ID: 93 defaultRoles[model.BRANCH_ADMIN_ROLE_ID] = role 94 case model.BRANCH_USER_ROLE_ID: 95 defaultRoles[model.BRANCH_USER_ROLE_ID] = role 96 case model.CLASS_ADMIN_ROLE_ID: 97 defaultRoles[model.CLASS_ADMIN_ROLE_ID] = role 98 case model.CLASS_USER_ROLE_ID: 99 defaultRoles[model.CLASS_USER_ROLE_ID] = role 100 } 101 } 102 103 if len(defaultRoles) != 6 { 104 return nil, model.NewAppError("SqlSchemeStore.SaveScheme", "store.sql_scheme.save.retrieve_default_scheme_roles.app_error", nil, "", http.StatusInternalServerError) 105 } 106 107 // Create the appropriate default roles for the scheme. 108 if scheme.Scope == model.SCHEME_SCOPE_BRANCH { 109 // Branch Admin Role 110 branchAdminRole := &model.Role{ 111 Name: model.NewId(), 112 DisplayName: fmt.Sprintf("Branch Admin Role for Scheme %s", scheme.Name), 113 Permissions: defaultRoles[model.BRANCH_ADMIN_ROLE_ID].Permissions, 114 SchemeManaged: true, 115 } 116 117 savedRole, err := s.SqlStore.Role().(*SqlRoleStore).createRole(branchAdminRole, transaction) 118 if err != nil { 119 return nil, err 120 } 121 scheme.DefaultBranchAdminRole = savedRole.Name 122 123 // Branch User Role 124 branchUserRole := &model.Role{ 125 Name: model.NewId(), 126 DisplayName: fmt.Sprintf("Branch User Role for Scheme %s", scheme.Name), 127 Permissions: defaultRoles[model.BRANCH_USER_ROLE_ID].Permissions, 128 SchemeManaged: true, 129 } 130 131 savedRole, err = s.SqlStore.Role().(*SqlRoleStore).createRole(branchUserRole, transaction) 132 if err != nil { 133 return nil, err 134 } 135 scheme.DefaultBranchUserRole = savedRole.Name 136 137 } 138 139 if scheme.Scope == model.SCHEME_SCOPE_BRANCH || scheme.Scope == model.SCHEME_SCOPE_CLASS { 140 // Class Admin Role 141 classAdminRole := &model.Role{ 142 Name: model.NewId(), 143 DisplayName: fmt.Sprintf("Class Admin Role for Scheme %s", scheme.Name), 144 Permissions: defaultRoles[model.CLASS_ADMIN_ROLE_ID].Permissions, 145 SchemeManaged: true, 146 } 147 148 if scheme.Scope == model.SCHEME_SCOPE_CLASS { 149 classAdminRole.Permissions = []string{} 150 } 151 152 savedRole, err := s.SqlStore.Role().(*SqlRoleStore).createRole(classAdminRole, transaction) 153 if err != nil { 154 return nil, err 155 } 156 scheme.DefaultClassAdminRole = savedRole.Name 157 158 // Class User Role 159 classUserRole := &model.Role{ 160 Name: model.NewId(), 161 DisplayName: fmt.Sprintf("Class User Role for Scheme %s", scheme.Name), 162 Permissions: defaultRoles[model.CLASS_USER_ROLE_ID].Permissions, 163 SchemeManaged: true, 164 } 165 166 if scheme.Scope == model.SCHEME_SCOPE_CLASS { 167 classUserRole.Permissions = filterModerated(classUserRole.Permissions) 168 } 169 170 savedRole, err = s.SqlStore.Role().(*SqlRoleStore).createRole(classUserRole, transaction) 171 if err != nil { 172 return nil, err 173 } 174 scheme.DefaultClassUserRole = savedRole.Name 175 176 } 177 178 scheme.Id = model.NewId() 179 if len(scheme.Name) == 0 { 180 scheme.Name = model.NewId() 181 } 182 scheme.CreateAt = model.GetMillis() 183 scheme.UpdateAt = scheme.CreateAt 184 185 // Validate the scheme 186 if !scheme.IsValidForCreate() { 187 return nil, model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.invalid_scheme.app_error", nil, "", http.StatusBadRequest) 188 } 189 190 if err := transaction.Insert(scheme); err != nil { 191 return nil, model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.insert.app_error", nil, err.Error(), http.StatusInternalServerError) 192 } 193 194 return scheme, nil 195 } 196 197 func filterModerated(permissions []string) []string { 198 filteredPermissions := []string{} 199 for _, perm := range permissions { 200 if _, ok := model.CLASS_MODERATED_PERMISSIONS_MAP[perm]; ok { 201 filteredPermissions = append(filteredPermissions, perm) 202 } 203 } 204 return filteredPermissions 205 } 206 207 func (s *SqlSchemeStore) Get(schemeId string) (*model.Scheme, *model.AppError) { 208 var scheme model.Scheme 209 if err := s.GetReplica().SelectOne(&scheme, "SELECT * from Schemes WHERE Id = :Id", map[string]interface{}{"Id": schemeId}); err != nil { 210 if err == sql.ErrNoRows { 211 return nil, model.NewAppError("SqlSchemeStore.Get", "store.sql_scheme.get.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusNotFound) 212 } 213 return nil, model.NewAppError("SqlSchemeStore.Get", "store.sql_scheme.get.app_error", nil, err.Error(), http.StatusInternalServerError) 214 } 215 216 return &scheme, nil 217 } 218 219 func (s *SqlSchemeStore) GetByName(schemeName string) (*model.Scheme, *model.AppError) { 220 var scheme model.Scheme 221 222 if err := s.GetReplica().SelectOne(&scheme, "SELECT * from Schemes WHERE Name = :Name", map[string]interface{}{"Name": schemeName}); err != nil { 223 if err == sql.ErrNoRows { 224 return nil, model.NewAppError("SqlSchemeStore.GetByName", "store.sql_scheme.get.app_error", nil, "Name="+schemeName+", "+err.Error(), http.StatusNotFound) 225 } 226 return nil, model.NewAppError("SqlSchemeStore.GetByName", "store.sql_scheme.get.app_error", nil, err.Error(), http.StatusInternalServerError) 227 } 228 229 return &scheme, nil 230 } 231 232 func (s *SqlSchemeStore) Delete(schemeId string) (*model.Scheme, *model.AppError) { 233 // Get the scheme 234 var scheme model.Scheme 235 if err := s.GetReplica().SelectOne(&scheme, "SELECT * from Schemes WHERE Id = :Id", map[string]interface{}{"Id": schemeId}); err != nil { 236 if err == sql.ErrNoRows { 237 return nil, model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.get.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusNotFound) 238 } 239 return nil, model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.get.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError) 240 } 241 242 // Update any branches or classes using this scheme to the default scheme. 243 if scheme.Scope == model.SCHEME_SCOPE_BRANCH { 244 if _, err := s.GetMaster().Exec("UPDATE Branches SET SchemeId = '' WHERE SchemeId = :SchemeId", map[string]interface{}{"SchemeId": schemeId}); err != nil { 245 return nil, model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.reset_branches.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError) 246 } 247 } else if scheme.Scope == model.SCHEME_SCOPE_CLASS { 248 if _, err := s.GetMaster().Exec("UPDATE Classes SET SchemeId = '' WHERE SchemeId = :SchemeId", map[string]interface{}{"SchemeId": schemeId}); err != nil { 249 return nil, model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.reset_classes.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError) 250 } 251 252 // Blow away the class caches. 253 s.Class().ClearCaches() 254 } 255 256 // Delete the roles belonging to the scheme. 257 roleNames := []string{scheme.DefaultClassUserRole, scheme.DefaultClassAdminRole} 258 if scheme.Scope == model.SCHEME_SCOPE_BRANCH { 259 roleNames = append(roleNames, scheme.DefaultBranchUserRole, scheme.DefaultBranchAdminRole) 260 } 261 262 var inQueryList []string 263 queryArgs := make(map[string]interface{}) 264 for i, roleId := range roleNames { 265 inQueryList = append(inQueryList, fmt.Sprintf(":RoleName%v", i)) 266 queryArgs[fmt.Sprintf("RoleName%v", i)] = roleId 267 } 268 inQuery := strings.Join(inQueryList, ", ") 269 270 time := model.GetMillis() 271 queryArgs["UpdateAt"] = time 272 queryArgs["DeleteAt"] = time 273 274 if _, err := s.GetMaster().Exec("UPDATE Roles SET UpdateAt = :UpdateAt, DeleteAt = :DeleteAt WHERE Name IN ("+inQuery+")", queryArgs); err != nil { 275 return nil, model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.delete.role_update.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError) 276 } 277 278 // Delete the scheme itself. 279 scheme.UpdateAt = time 280 scheme.DeleteAt = time 281 282 rowsChanged, err := s.GetMaster().Update(&scheme) 283 if err != nil { 284 return nil, model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.delete.update.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError) 285 } 286 if rowsChanged != 1 { 287 return nil, model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.delete.update.app_error", nil, "no record to update", http.StatusInternalServerError) 288 } 289 return &scheme, nil 290 } 291 292 func (s *SqlSchemeStore) GetAllPage(scope string, offset int, limit int) ([]*model.Scheme, *model.AppError) { 293 var schemes []*model.Scheme 294 295 scopeClause := "" 296 if len(scope) > 0 { 297 scopeClause = " AND Scope=:Scope " 298 } 299 300 if _, err := s.GetReplica().Select(&schemes, "SELECT * from Schemes WHERE DeleteAt = 0 "+scopeClause+" ORDER BY CreateAt DESC LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Limit": limit, "Offset": offset, "Scope": scope}); err != nil { 301 return nil, model.NewAppError("SqlSchemeStore.Get", "store.sql_scheme.get.app_error", nil, err.Error(), http.StatusInternalServerError) 302 } 303 304 return schemes, nil 305 } 306 307 func (s *SqlSchemeStore) PermanentDeleteAll() *model.AppError { 308 if _, err := s.GetMaster().Exec("DELETE from Schemes"); err != nil { 309 return model.NewAppError("SqlSchemeStore.PermanentDeleteAll", "store.sql_scheme.permanent_delete_all.app_error", nil, err.Error(), http.StatusInternalServerError) 310 } 311 312 return nil 313 } 314 315 func (s *SqlSchemeStore) CountByScope(scope string) (int64, *model.AppError) { 316 count, err := s.GetReplica().SelectInt("SELECT count(*) FROM Schemes WHERE Scope = :Scope AND DeleteAt = 0", map[string]interface{}{"Scope": scope}) 317 if err != nil { 318 return int64(0), model.NewAppError("SqlSchemeStore.CountByScope", "store.select_error", nil, err.Error(), http.StatusInternalServerError) 319 } 320 return count, nil 321 } 322 323 func (s *SqlSchemeStore) CountWithoutPermission(schemeScope, permissionID string, roleScope model.RoleScope, roleType model.RoleType) (int64, *model.AppError) { 324 joinCol := fmt.Sprintf("Default%s%sRole", roleScope, roleType) 325 query := fmt.Sprintf(` 326 SELECT 327 count(*) 328 FROM Schemes 329 JOIN Roles ON Roles.Name = Schemes.%s 330 WHERE 331 Schemes.DeleteAt = 0 AND 332 Schemes.Scope = '%s' AND 333 Roles.Permissions NOT LIKE '%%%s%%' 334 `, joinCol, schemeScope, permissionID) 335 count, err := s.GetReplica().SelectInt(query) 336 if err != nil { 337 return int64(0), model.NewAppError("SqlSchemeStore.CountWithoutPermission", "store.select_error", nil, err.Error(), http.StatusInternalServerError) 338 } 339 return count, nil 340 }