github.com/levb/mattermost-server@v5.3.1+incompatible/store/sqlstore/scheme_supplier.go (about)

     1  // Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"context"
     8  	"database/sql"
     9  	"fmt"
    10  	"net/http"
    11  	"strings"
    12  
    13  	"github.com/mattermost/gorp"
    14  
    15  	"github.com/mattermost/mattermost-server/model"
    16  	"github.com/mattermost/mattermost-server/store"
    17  )
    18  
    19  func initSqlSupplierSchemes(sqlStore SqlStore) {
    20  	for _, db := range sqlStore.GetAllConns() {
    21  		table := db.AddTableWithName(model.Scheme{}, "Schemes").SetKeys(false, "Id")
    22  		table.ColMap("Id").SetMaxSize(26)
    23  		table.ColMap("Name").SetMaxSize(model.SCHEME_NAME_MAX_LENGTH).SetUnique(true)
    24  		table.ColMap("DisplayName").SetMaxSize(model.SCHEME_DISPLAY_NAME_MAX_LENGTH)
    25  		table.ColMap("Description").SetMaxSize(model.SCHEME_DESCRIPTION_MAX_LENGTH)
    26  		table.ColMap("Scope").SetMaxSize(32)
    27  		table.ColMap("DefaultTeamAdminRole").SetMaxSize(64)
    28  		table.ColMap("DefaultTeamUserRole").SetMaxSize(64)
    29  		table.ColMap("DefaultChannelAdminRole").SetMaxSize(64)
    30  		table.ColMap("DefaultChannelUserRole").SetMaxSize(64)
    31  	}
    32  }
    33  
    34  func (s *SqlSupplier) SchemeSave(ctx context.Context, scheme *model.Scheme, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
    35  	result := store.NewSupplierResult()
    36  
    37  	if len(scheme.Id) == 0 {
    38  		if transaction, err := s.GetMaster().Begin(); err != nil {
    39  			result.Err = model.NewAppError("SqlSchemeStore.SaveScheme", "store.sql_scheme.save.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
    40  		} else {
    41  			result = s.createScheme(ctx, scheme, transaction, hints...)
    42  
    43  			if result.Err != nil {
    44  				transaction.Rollback()
    45  			} else if err := transaction.Commit(); err != nil {
    46  				result.Err = model.NewAppError("SqlSchemeStore.SchemeSave", "store.sql_scheme.save_scheme.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
    47  			}
    48  		}
    49  	} else {
    50  		if !scheme.IsValid() {
    51  			result.Err = model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.invalid_scheme.app_error", nil, "schemeId="+scheme.Id, http.StatusBadRequest)
    52  			return result
    53  		}
    54  
    55  		scheme.UpdateAt = model.GetMillis()
    56  
    57  		if rowsChanged, err := s.GetMaster().Update(scheme); err != nil {
    58  			result.Err = model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.update.app_error", nil, err.Error(), http.StatusInternalServerError)
    59  		} else if rowsChanged != 1 {
    60  			result.Err = model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.update.app_error", nil, "no record to update", http.StatusInternalServerError)
    61  		}
    62  
    63  		result.Data = scheme
    64  	}
    65  
    66  	return result
    67  }
    68  
    69  func (s *SqlSupplier) createScheme(ctx context.Context, scheme *model.Scheme, transaction *gorp.Transaction, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
    70  	result := store.NewSupplierResult()
    71  
    72  	// Fetch the default system scheme roles to populate default permissions.
    73  	defaultRoleNames := []string{model.TEAM_ADMIN_ROLE_ID, model.TEAM_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID, model.CHANNEL_USER_ROLE_ID}
    74  	defaultRoles := make(map[string]*model.Role)
    75  	if rolesResult := s.RoleGetByNames(ctx, defaultRoleNames); rolesResult.Err != nil {
    76  		result.Err = rolesResult.Err
    77  		return result
    78  	} else {
    79  		for _, role := range rolesResult.Data.([]*model.Role) {
    80  			switch role.Name {
    81  			case model.TEAM_ADMIN_ROLE_ID:
    82  				defaultRoles[model.TEAM_ADMIN_ROLE_ID] = role
    83  			case model.TEAM_USER_ROLE_ID:
    84  				defaultRoles[model.TEAM_USER_ROLE_ID] = role
    85  			case model.CHANNEL_ADMIN_ROLE_ID:
    86  				defaultRoles[model.CHANNEL_ADMIN_ROLE_ID] = role
    87  			case model.CHANNEL_USER_ROLE_ID:
    88  				defaultRoles[model.CHANNEL_USER_ROLE_ID] = role
    89  			}
    90  		}
    91  
    92  		if len(defaultRoles) != 4 {
    93  			result.Err = model.NewAppError("SqlSchemeStore.SaveScheme", "store.sql_scheme.save.retrieve_default_scheme_roles.app_error", nil, "", http.StatusInternalServerError)
    94  			return result
    95  		}
    96  	}
    97  
    98  	// Create the appropriate default roles for the scheme.
    99  	if scheme.Scope == model.SCHEME_SCOPE_TEAM {
   100  		// Team Admin Role
   101  		teamAdminRole := &model.Role{
   102  			Name:          model.NewId(),
   103  			DisplayName:   fmt.Sprintf("Team Admin Role for Scheme %s", scheme.Name),
   104  			Permissions:   defaultRoles[model.TEAM_ADMIN_ROLE_ID].Permissions,
   105  			SchemeManaged: true,
   106  		}
   107  
   108  		if saveRoleResult := s.createRole(ctx, teamAdminRole, transaction); saveRoleResult.Err != nil {
   109  			result.Err = saveRoleResult.Err
   110  			return result
   111  		} else {
   112  			scheme.DefaultTeamAdminRole = saveRoleResult.Data.(*model.Role).Name
   113  		}
   114  
   115  		// Team User Role
   116  		teamUserRole := &model.Role{
   117  			Name:          model.NewId(),
   118  			DisplayName:   fmt.Sprintf("Team User Role for Scheme %s", scheme.Name),
   119  			Permissions:   defaultRoles[model.TEAM_USER_ROLE_ID].Permissions,
   120  			SchemeManaged: true,
   121  		}
   122  
   123  		if saveRoleResult := s.createRole(ctx, teamUserRole, transaction); saveRoleResult.Err != nil {
   124  			result.Err = saveRoleResult.Err
   125  			return result
   126  		} else {
   127  			scheme.DefaultTeamUserRole = saveRoleResult.Data.(*model.Role).Name
   128  		}
   129  	}
   130  	if scheme.Scope == model.SCHEME_SCOPE_TEAM || scheme.Scope == model.SCHEME_SCOPE_CHANNEL {
   131  		// Channel Admin Role
   132  		channelAdminRole := &model.Role{
   133  			Name:          model.NewId(),
   134  			DisplayName:   fmt.Sprintf("Channel Admin Role for Scheme %s", scheme.Name),
   135  			Permissions:   defaultRoles[model.CHANNEL_ADMIN_ROLE_ID].Permissions,
   136  			SchemeManaged: true,
   137  		}
   138  
   139  		if saveRoleResult := s.createRole(ctx, channelAdminRole, transaction); saveRoleResult.Err != nil {
   140  			result.Err = saveRoleResult.Err
   141  			return result
   142  		} else {
   143  			scheme.DefaultChannelAdminRole = saveRoleResult.Data.(*model.Role).Name
   144  		}
   145  
   146  		// Channel User Role
   147  		channelUserRole := &model.Role{
   148  			Name:          model.NewId(),
   149  			DisplayName:   fmt.Sprintf("Channel User Role for Scheme %s", scheme.Name),
   150  			Permissions:   defaultRoles[model.CHANNEL_USER_ROLE_ID].Permissions,
   151  			SchemeManaged: true,
   152  		}
   153  
   154  		if saveRoleResult := s.createRole(ctx, channelUserRole, transaction); saveRoleResult.Err != nil {
   155  			result.Err = saveRoleResult.Err
   156  			return result
   157  		} else {
   158  			scheme.DefaultChannelUserRole = saveRoleResult.Data.(*model.Role).Name
   159  		}
   160  	}
   161  
   162  	scheme.Id = model.NewId()
   163  	if len(scheme.Name) == 0 {
   164  		scheme.Name = model.NewId()
   165  	}
   166  	scheme.CreateAt = model.GetMillis()
   167  	scheme.UpdateAt = scheme.CreateAt
   168  
   169  	// Validate the scheme
   170  	if !scheme.IsValidForCreate() {
   171  		result.Err = model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.invalid_scheme.app_error", nil, "", http.StatusBadRequest)
   172  		return result
   173  	}
   174  
   175  	if err := transaction.Insert(scheme); err != nil {
   176  		result.Err = model.NewAppError("SqlSchemeStore.Save", "store.sql_scheme.save.insert.app_error", nil, err.Error(), http.StatusInternalServerError)
   177  	}
   178  
   179  	result.Data = scheme
   180  
   181  	return result
   182  }
   183  
   184  func (s *SqlSupplier) SchemeGet(ctx context.Context, schemeId string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
   185  	result := store.NewSupplierResult()
   186  
   187  	var scheme model.Scheme
   188  
   189  	if err := s.GetReplica().SelectOne(&scheme, "SELECT * from Schemes WHERE Id = :Id", map[string]interface{}{"Id": schemeId}); err != nil {
   190  		if err == sql.ErrNoRows {
   191  			result.Err = model.NewAppError("SqlSchemeStore.Get", "store.sql_scheme.get.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusNotFound)
   192  		} else {
   193  			result.Err = model.NewAppError("SqlSchemeStore.Get", "store.sql_scheme.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   194  		}
   195  	}
   196  
   197  	result.Data = &scheme
   198  
   199  	return result
   200  }
   201  
   202  func (s *SqlSupplier) SchemeGetByName(ctx context.Context, schemeName string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
   203  	result := store.NewSupplierResult()
   204  
   205  	var scheme model.Scheme
   206  
   207  	if err := s.GetReplica().SelectOne(&scheme, "SELECT * from Schemes WHERE Name = :Name", map[string]interface{}{"Name": schemeName}); err != nil {
   208  		if err == sql.ErrNoRows {
   209  			result.Err = model.NewAppError("SqlSchemeStore.GetByName", "store.sql_scheme.get.app_error", nil, "Name="+schemeName+", "+err.Error(), http.StatusNotFound)
   210  		} else {
   211  			result.Err = model.NewAppError("SqlSchemeStore.GetByName", "store.sql_scheme.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   212  		}
   213  	}
   214  
   215  	result.Data = &scheme
   216  
   217  	return result
   218  }
   219  
   220  func (s *SqlSupplier) SchemeDelete(ctx context.Context, schemeId string, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
   221  	result := store.NewSupplierResult()
   222  
   223  	// Get the scheme
   224  	var scheme model.Scheme
   225  	if err := s.GetReplica().SelectOne(&scheme, "SELECT * from Schemes WHERE Id = :Id", map[string]interface{}{"Id": schemeId}); err != nil {
   226  		if err == sql.ErrNoRows {
   227  			result.Err = model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.get.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusNotFound)
   228  		} else {
   229  			result.Err = model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.get.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError)
   230  		}
   231  
   232  		return result
   233  	}
   234  
   235  	// Update any teams or channels using this scheme to the default scheme.
   236  	if scheme.Scope == model.SCHEME_SCOPE_TEAM {
   237  		if _, err := s.GetMaster().Exec("UPDATE Teams SET SchemeId = '' WHERE SchemeId = :SchemeId", map[string]interface{}{"SchemeId": schemeId}); err != nil {
   238  			result.Err = model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.reset_teams.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError)
   239  			return result
   240  		}
   241  	} else if scheme.Scope == model.SCHEME_SCOPE_CHANNEL {
   242  		if _, err := s.GetMaster().Exec("UPDATE Channels SET SchemeId = '' WHERE SchemeId = :SchemeId", map[string]interface{}{"SchemeId": schemeId}); err != nil {
   243  			result.Err = model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.reset_channels.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError)
   244  			return result
   245  		}
   246  
   247  		// Blow away the channel caches.
   248  		s.Channel().ClearCaches()
   249  	}
   250  
   251  	// Delete the roles belonging to the scheme.
   252  	roleNames := []string{scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole}
   253  	if scheme.Scope == model.SCHEME_SCOPE_TEAM {
   254  		roleNames = append(roleNames, scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole)
   255  	}
   256  
   257  	var inQueryList []string
   258  	queryArgs := make(map[string]interface{})
   259  	for i, roleId := range roleNames {
   260  		inQueryList = append(inQueryList, fmt.Sprintf(":RoleName%v", i))
   261  		queryArgs[fmt.Sprintf("RoleName%v", i)] = roleId
   262  	}
   263  	inQuery := strings.Join(inQueryList, ", ")
   264  
   265  	time := model.GetMillis()
   266  	queryArgs["UpdateAt"] = time
   267  	queryArgs["DeleteAt"] = time
   268  
   269  	if _, err := s.GetMaster().Exec("UPDATE Roles SET UpdateAt = :UpdateAt, DeleteAt = :DeleteAt WHERE Name IN ("+inQuery+")", queryArgs); err != nil {
   270  		result.Err = model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.delete.role_update.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError)
   271  		return result
   272  	}
   273  
   274  	// Delete the scheme itself.
   275  	scheme.UpdateAt = time
   276  	scheme.DeleteAt = time
   277  
   278  	if rowsChanged, err := s.GetMaster().Update(&scheme); err != nil {
   279  		result.Err = model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.delete.update.app_error", nil, "Id="+schemeId+", "+err.Error(), http.StatusInternalServerError)
   280  	} else if rowsChanged != 1 {
   281  		result.Err = model.NewAppError("SqlSchemeStore.Delete", "store.sql_scheme.delete.update.app_error", nil, "no record to update", http.StatusInternalServerError)
   282  	} else {
   283  		result.Data = &scheme
   284  	}
   285  
   286  	return result
   287  }
   288  
   289  func (s *SqlSupplier) SchemeGetAllPage(ctx context.Context, scope string, offset int, limit int, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
   290  	result := store.NewSupplierResult()
   291  
   292  	var schemes []*model.Scheme
   293  
   294  	scopeClause := ""
   295  	if len(scope) > 0 {
   296  		scopeClause = " AND Scope=:Scope "
   297  	}
   298  
   299  	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 {
   300  		result.Err = model.NewAppError("SqlSchemeStore.Get", "store.sql_scheme.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   301  	}
   302  
   303  	result.Data = schemes
   304  
   305  	return result
   306  }
   307  
   308  func (s *SqlSupplier) SchemePermanentDeleteAll(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
   309  	result := store.NewSupplierResult()
   310  
   311  	if _, err := s.GetMaster().Exec("DELETE from Schemes"); err != nil {
   312  		result.Err = model.NewAppError("SqlSchemeStore.PermanentDeleteAll", "store.sql_scheme.permanent_delete_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   313  	}
   314  
   315  	return result
   316  }