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  }