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