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