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 }