github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/store/sqlstore/user_access_token_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  	"net/http"
     9  
    10  	"github.com/mattermost/gorp"
    11  	"github.com/vnforks/kid/v5/model"
    12  	"github.com/vnforks/kid/v5/store"
    13  )
    14  
    15  type SqlUserAccessTokenStore struct {
    16  	SqlStore
    17  }
    18  
    19  func newSqlUserAccessTokenStore(sqlStore SqlStore) store.UserAccessTokenStore {
    20  	s := &SqlUserAccessTokenStore{sqlStore}
    21  
    22  	for _, db := range sqlStore.GetAllConns() {
    23  		table := db.AddTableWithName(model.UserAccessToken{}, "UserAccessTokens").SetKeys(false, "Id")
    24  		table.ColMap("Id").SetMaxSize(26)
    25  		table.ColMap("Token").SetMaxSize(26).SetUnique(true)
    26  		table.ColMap("UserId").SetMaxSize(26)
    27  		table.ColMap("Description").SetMaxSize(512)
    28  	}
    29  
    30  	return s
    31  }
    32  
    33  func (s SqlUserAccessTokenStore) createIndexesIfNotExists() {
    34  	s.CreateIndexIfNotExists("idx_user_access_tokens_token", "UserAccessTokens", "Token")
    35  	s.CreateIndexIfNotExists("idx_user_access_tokens_user_id", "UserAccessTokens", "UserId")
    36  }
    37  
    38  func (s SqlUserAccessTokenStore) Save(token *model.UserAccessToken) (*model.UserAccessToken, *model.AppError) {
    39  	token.PreSave()
    40  
    41  	if err := token.IsValid(); err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	if err := s.GetMaster().Insert(token); err != nil {
    46  		return nil, model.NewAppError("SqlUserAccessTokenStore.Save", "store.sql_user_access_token.save.app_error", nil, "", http.StatusInternalServerError)
    47  	}
    48  	return token, nil
    49  }
    50  
    51  func (s SqlUserAccessTokenStore) Delete(tokenId string) *model.AppError {
    52  	transaction, err := s.GetMaster().Begin()
    53  	if err != nil {
    54  		return model.NewAppError("SqlUserAccessTokenStore.Delete", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError)
    55  	}
    56  
    57  	defer finalizeTransaction(transaction)
    58  
    59  	if err := s.deleteSessionsAndTokensById(transaction, tokenId); err == nil {
    60  		if err := transaction.Commit(); err != nil {
    61  			// don't need to rollback here since the transaction is already closed
    62  			return model.NewAppError("SqlUserAccessTokenStore.Delete", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError)
    63  		}
    64  	}
    65  
    66  	return nil
    67  
    68  }
    69  
    70  func (s SqlUserAccessTokenStore) deleteSessionsAndTokensById(transaction *gorp.Transaction, tokenId string) *model.AppError {
    71  
    72  	query := ""
    73  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
    74  		query = "DELETE FROM Sessions s USING UserAccessTokens o WHERE o.Token = s.Token AND o.Id = :Id"
    75  	} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
    76  		query = "DELETE s.* FROM Sessions s INNER JOIN UserAccessTokens o ON o.Token = s.Token WHERE o.Id = :Id"
    77  	}
    78  
    79  	if _, err := transaction.Exec(query, map[string]interface{}{"Id": tokenId}); err != nil {
    80  		return model.NewAppError("SqlUserAccessTokenStore.deleteSessionsById", "store.sql_user_access_token.delete.app_error", nil, "id="+tokenId+", err="+err.Error(), http.StatusInternalServerError)
    81  	}
    82  
    83  	return s.deleteTokensById(transaction, tokenId)
    84  }
    85  
    86  func (s SqlUserAccessTokenStore) deleteTokensById(transaction *gorp.Transaction, tokenId string) *model.AppError {
    87  
    88  	if _, err := transaction.Exec("DELETE FROM UserAccessTokens WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil {
    89  		return model.NewAppError("SqlUserAccessTokenStore.deleteTokensById", "store.sql_user_access_token.delete.app_error", nil, "", http.StatusInternalServerError)
    90  	}
    91  
    92  	return nil
    93  }
    94  
    95  func (s SqlUserAccessTokenStore) DeleteAllForUser(userId string) *model.AppError {
    96  	transaction, err := s.GetMaster().Begin()
    97  	if err != nil {
    98  		return model.NewAppError("SqlUserAccessTokenStore.DeleteAllForUser", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError)
    99  	}
   100  	defer finalizeTransaction(transaction)
   101  	if err := s.deleteSessionsandTokensByUser(transaction, userId); err != nil {
   102  		return err
   103  	}
   104  
   105  	if err := transaction.Commit(); err != nil {
   106  		// don't need to rollback here since the transaction is already closed
   107  		return model.NewAppError("SqlUserAccessTokenStore.DeleteAllForUser", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError)
   108  	}
   109  	return nil
   110  }
   111  
   112  func (s SqlUserAccessTokenStore) deleteSessionsandTokensByUser(transaction *gorp.Transaction, userId string) *model.AppError {
   113  	query := ""
   114  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   115  		query = "DELETE FROM Sessions s USING UserAccessTokens o WHERE o.Token = s.Token AND o.UserId = :UserId"
   116  	} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
   117  		query = "DELETE s.* FROM Sessions s INNER JOIN UserAccessTokens o ON o.Token = s.Token WHERE o.UserId = :UserId"
   118  	}
   119  
   120  	if _, err := transaction.Exec(query, map[string]interface{}{"UserId": userId}); err != nil {
   121  		return model.NewAppError("SqlUserAccessTokenStore.deleteSessionsByUser", "store.sql_user_access_token.delete.app_error", nil, "user_id="+userId+", err="+err.Error(), http.StatusInternalServerError)
   122  	}
   123  
   124  	return s.deleteTokensByUser(transaction, userId)
   125  }
   126  
   127  func (s SqlUserAccessTokenStore) deleteTokensByUser(transaction *gorp.Transaction, userId string) *model.AppError {
   128  	if _, err := transaction.Exec("DELETE FROM UserAccessTokens WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
   129  		return model.NewAppError("SqlUserAccessTokenStore.deleteTokensByUser", "store.sql_user_access_token.delete.app_error", nil, "", http.StatusInternalServerError)
   130  	}
   131  
   132  	return nil
   133  }
   134  
   135  func (s SqlUserAccessTokenStore) Get(tokenId string) (*model.UserAccessToken, *model.AppError) {
   136  	token := model.UserAccessToken{}
   137  
   138  	if err := s.GetReplica().SelectOne(&token, "SELECT * FROM UserAccessTokens WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil {
   139  		if err == sql.ErrNoRows {
   140  			return nil, model.NewAppError("SqlUserAccessTokenStore.Get", "store.sql_user_access_token.get.app_error", nil, err.Error(), http.StatusNotFound)
   141  		}
   142  		return nil, model.NewAppError("SqlUserAccessTokenStore.Get", "store.sql_user_access_token.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   143  	}
   144  
   145  	return &token, nil
   146  }
   147  
   148  func (s SqlUserAccessTokenStore) GetAll(offset, limit int) ([]*model.UserAccessToken, *model.AppError) {
   149  	tokens := []*model.UserAccessToken{}
   150  
   151  	if _, err := s.GetReplica().Select(&tokens, "SELECT * FROM UserAccessTokens LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil {
   152  		return nil, model.NewAppError("SqlUserAccessTokenStore.GetAll", "store.sql_user_access_token.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   153  	}
   154  
   155  	return tokens, nil
   156  }
   157  
   158  func (s SqlUserAccessTokenStore) GetByToken(tokenString string) (*model.UserAccessToken, *model.AppError) {
   159  	token := model.UserAccessToken{}
   160  
   161  	if err := s.GetReplica().SelectOne(&token, "SELECT * FROM UserAccessTokens WHERE Token = :Token", map[string]interface{}{"Token": tokenString}); err != nil {
   162  		if err == sql.ErrNoRows {
   163  			return nil, model.NewAppError("SqlUserAccessTokenStore.GetByToken", "store.sql_user_access_token.get_by_token.app_error", nil, err.Error(), http.StatusNotFound)
   164  		}
   165  		return nil, model.NewAppError("SqlUserAccessTokenStore.GetByToken", "store.sql_user_access_token.get_by_token.app_error", nil, err.Error(), http.StatusInternalServerError)
   166  	}
   167  
   168  	return &token, nil
   169  }
   170  
   171  func (s SqlUserAccessTokenStore) GetByUser(userId string, offset, limit int) ([]*model.UserAccessToken, *model.AppError) {
   172  	tokens := []*model.UserAccessToken{}
   173  
   174  	if _, err := s.GetReplica().Select(&tokens, "SELECT * FROM UserAccessTokens WHERE UserId = :UserId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"UserId": userId, "Offset": offset, "Limit": limit}); err != nil {
   175  		return nil, model.NewAppError("SqlUserAccessTokenStore.GetByUser", "store.sql_user_access_token.get_by_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   176  	}
   177  
   178  	return tokens, nil
   179  }
   180  
   181  func (s SqlUserAccessTokenStore) Search(term string) ([]*model.UserAccessToken, *model.AppError) {
   182  	term = sanitizeSearchTerm(term, "\\")
   183  	tokens := []*model.UserAccessToken{}
   184  	params := map[string]interface{}{"Term": term + "%"}
   185  	query := `
   186  		SELECT
   187  			uat.*
   188  		FROM UserAccessTokens uat
   189  		INNER JOIN Users u
   190  			ON uat.UserId = u.Id
   191  		WHERE uat.Id LIKE :Term OR uat.UserId LIKE :Term OR u.Username LIKE :Term`
   192  
   193  	if _, err := s.GetReplica().Select(&tokens, query, params); err != nil {
   194  		return nil, model.NewAppError("SqlUserAccessTokenStore.Search", "store.sql_user_access_token.search.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError)
   195  	}
   196  
   197  	return tokens, nil
   198  }
   199  
   200  func (s SqlUserAccessTokenStore) UpdateTokenEnable(tokenId string) *model.AppError {
   201  	if _, err := s.GetMaster().Exec("UPDATE UserAccessTokens SET IsActive = TRUE WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil {
   202  		return model.NewAppError("SqlUserAccessTokenStore.UpdateTokenEnable", "store.sql_user_access_token.update_token_enable.app_error", nil, "id="+tokenId+", "+err.Error(), http.StatusInternalServerError)
   203  	}
   204  	return nil
   205  }
   206  
   207  func (s SqlUserAccessTokenStore) UpdateTokenDisable(tokenId string) *model.AppError {
   208  	transaction, err := s.GetMaster().Begin()
   209  	if err != nil {
   210  		return model.NewAppError("SqlUserAccessTokenStore.UpdateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, err.Error(), http.StatusInternalServerError)
   211  	}
   212  	defer finalizeTransaction(transaction)
   213  
   214  	if err := s.deleteSessionsAndDisableToken(transaction, tokenId); err != nil {
   215  		return err
   216  	}
   217  	if err := transaction.Commit(); err != nil {
   218  		// don't need to rollback here since the transaction is already closed
   219  		return model.NewAppError("SqlUserAccessTokenStore.UpdateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, err.Error(), http.StatusInternalServerError)
   220  	}
   221  	return nil
   222  }
   223  
   224  func (s SqlUserAccessTokenStore) deleteSessionsAndDisableToken(transaction *gorp.Transaction, tokenId string) *model.AppError {
   225  	query := ""
   226  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   227  		query = "DELETE FROM Sessions s USING UserAccessTokens o WHERE o.Token = s.Token AND o.Id = :Id"
   228  	} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
   229  		query = "DELETE s.* FROM Sessions s INNER JOIN UserAccessTokens o ON o.Token = s.Token WHERE o.Id = :Id"
   230  	}
   231  
   232  	if _, err := transaction.Exec(query, map[string]interface{}{"Id": tokenId}); err != nil {
   233  		return model.NewAppError("SqlUserAccessTokenStore.deleteSessionsAndDisableToken", "store.sql_user_access_token.update_token_disable.app_error", nil, "id="+tokenId+", err="+err.Error(), http.StatusInternalServerError)
   234  	}
   235  
   236  	return s.updateTokenDisable(transaction, tokenId)
   237  }
   238  
   239  func (s SqlUserAccessTokenStore) updateTokenDisable(transaction *gorp.Transaction, tokenId string) *model.AppError {
   240  	if _, err := transaction.Exec("UPDATE UserAccessTokens SET IsActive = FALSE WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil {
   241  		return model.NewAppError("SqlUserAccessTokenStore.updateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, "", http.StatusInternalServerError)
   242  	}
   243  
   244  	return nil
   245  }