github.com/mad-app/mattermost-server@v5.11.1+incompatible/store/sqlstore/user_access_token_store.go (about) 1 // Copyright (c) 2017 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/mattermost/mattermost-server/model" 12 "github.com/mattermost/mattermost-server/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) store.StoreChannel { 39 return store.Do(func(result *store.StoreResult) { 40 token.PreSave() 41 42 if result.Err = token.IsValid(); result.Err != nil { 43 return 44 } 45 46 if err := s.GetMaster().Insert(token); err != nil { 47 result.Err = model.NewAppError("SqlUserAccessTokenStore.Save", "store.sql_user_access_token.save.app_error", nil, "", http.StatusInternalServerError) 48 } else { 49 result.Data = token 50 } 51 }) 52 } 53 54 func (s SqlUserAccessTokenStore) Delete(tokenId string) store.StoreChannel { 55 return store.Do(func(result *store.StoreResult) { 56 transaction, err := s.GetMaster().Begin() 57 if err != nil { 58 result.Err = model.NewAppError("SqlUserAccessTokenStore.Delete", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 59 } else { 60 defer finalizeTransaction(transaction) 61 if extrasResult := s.deleteSessionsAndTokensById(transaction, tokenId); extrasResult.Err != nil { 62 *result = extrasResult 63 } 64 65 if result.Err == nil { 66 if err := transaction.Commit(); err != nil { 67 // don't need to rollback here since the transaction is already closed 68 result.Err = model.NewAppError("SqlUserAccessTokenStore.Delete", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 69 } 70 } 71 } 72 }) 73 } 74 75 func (s SqlUserAccessTokenStore) deleteSessionsAndTokensById(transaction *gorp.Transaction, tokenId string) store.StoreResult { 76 result := store.StoreResult{} 77 78 query := "" 79 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 80 query = "DELETE FROM Sessions s USING UserAccessTokens o WHERE o.Token = s.Token AND o.Id = :Id" 81 } else if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 82 query = "DELETE s.* FROM Sessions s INNER JOIN UserAccessTokens o ON o.Token = s.Token WHERE o.Id = :Id" 83 } 84 85 if _, err := transaction.Exec(query, map[string]interface{}{"Id": tokenId}); err != nil { 86 result.Err = model.NewAppError("SqlUserAccessTokenStore.deleteSessionsById", "store.sql_user_access_token.delete.app_error", nil, "id="+tokenId+", err="+err.Error(), http.StatusInternalServerError) 87 return result 88 } 89 90 return s.deleteTokensById(transaction, tokenId) 91 } 92 93 func (s SqlUserAccessTokenStore) deleteTokensById(transaction *gorp.Transaction, tokenId string) store.StoreResult { 94 result := store.StoreResult{} 95 96 if _, err := transaction.Exec("DELETE FROM UserAccessTokens WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil { 97 result.Err = model.NewAppError("SqlUserAccessTokenStore.deleteTokensById", "store.sql_user_access_token.delete.app_error", nil, "", http.StatusInternalServerError) 98 } 99 100 return result 101 } 102 103 func (s SqlUserAccessTokenStore) DeleteAllForUser(userId string) store.StoreChannel { 104 return store.Do(func(result *store.StoreResult) { 105 transaction, err := s.GetMaster().Begin() 106 if err != nil { 107 result.Err = model.NewAppError("SqlUserAccessTokenStore.DeleteAllForUser", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 108 } else { 109 defer finalizeTransaction(transaction) 110 if extrasResult := s.deleteSessionsandTokensByUser(transaction, userId); extrasResult.Err != nil { 111 *result = extrasResult 112 } 113 114 if result.Err == nil { 115 if err := transaction.Commit(); err != nil { 116 // don't need to rollback here since the transaction is already closed 117 result.Err = model.NewAppError("SqlUserAccessTokenStore.DeleteAllForUser", "store.sql_user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 118 } 119 } 120 } 121 }) 122 } 123 124 func (s SqlUserAccessTokenStore) deleteSessionsandTokensByUser(transaction *gorp.Transaction, userId string) store.StoreResult { 125 result := store.StoreResult{} 126 127 query := "" 128 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 129 query = "DELETE FROM Sessions s USING UserAccessTokens o WHERE o.Token = s.Token AND o.UserId = :UserId" 130 } else if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 131 query = "DELETE s.* FROM Sessions s INNER JOIN UserAccessTokens o ON o.Token = s.Token WHERE o.UserId = :UserId" 132 } 133 134 if _, err := transaction.Exec(query, map[string]interface{}{"UserId": userId}); err != nil { 135 result.Err = model.NewAppError("SqlUserAccessTokenStore.deleteSessionsByUser", "store.sql_user_access_token.delete.app_error", nil, "user_id="+userId+", err="+err.Error(), http.StatusInternalServerError) 136 return result 137 } 138 139 return s.deleteTokensByUser(transaction, userId) 140 } 141 142 func (s SqlUserAccessTokenStore) deleteTokensByUser(transaction *gorp.Transaction, userId string) store.StoreResult { 143 result := store.StoreResult{} 144 145 if _, err := transaction.Exec("DELETE FROM UserAccessTokens WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil { 146 result.Err = model.NewAppError("SqlUserAccessTokenStore.deleteTokensByUser", "store.sql_user_access_token.delete.app_error", nil, "", http.StatusInternalServerError) 147 } 148 149 return result 150 } 151 152 func (s SqlUserAccessTokenStore) Get(tokenId string) store.StoreChannel { 153 return store.Do(func(result *store.StoreResult) { 154 token := model.UserAccessToken{} 155 156 if err := s.GetReplica().SelectOne(&token, "SELECT * FROM UserAccessTokens WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil { 157 if err == sql.ErrNoRows { 158 result.Err = model.NewAppError("SqlUserAccessTokenStore.Get", "store.sql_user_access_token.get.app_error", nil, err.Error(), http.StatusNotFound) 159 } else { 160 result.Err = model.NewAppError("SqlUserAccessTokenStore.Get", "store.sql_user_access_token.get.app_error", nil, err.Error(), http.StatusInternalServerError) 161 } 162 } 163 164 result.Data = &token 165 }) 166 } 167 168 func (s SqlUserAccessTokenStore) GetAll(offset, limit int) store.StoreChannel { 169 return store.Do(func(result *store.StoreResult) { 170 tokens := []*model.UserAccessToken{} 171 172 if _, err := s.GetReplica().Select(&tokens, "SELECT * FROM UserAccessTokens LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil { 173 result.Err = model.NewAppError("SqlUserAccessTokenStore.GetAll", "store.sql_user_access_token.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 174 } 175 176 result.Data = tokens 177 }) 178 } 179 180 func (s SqlUserAccessTokenStore) GetByToken(tokenString string) store.StoreChannel { 181 return store.Do(func(result *store.StoreResult) { 182 token := model.UserAccessToken{} 183 184 if err := s.GetReplica().SelectOne(&token, "SELECT * FROM UserAccessTokens WHERE Token = :Token", map[string]interface{}{"Token": tokenString}); err != nil { 185 if err == sql.ErrNoRows { 186 result.Err = model.NewAppError("SqlUserAccessTokenStore.GetByToken", "store.sql_user_access_token.get_by_token.app_error", nil, err.Error(), http.StatusNotFound) 187 } else { 188 result.Err = model.NewAppError("SqlUserAccessTokenStore.GetByToken", "store.sql_user_access_token.get_by_token.app_error", nil, err.Error(), http.StatusInternalServerError) 189 } 190 } 191 192 result.Data = &token 193 }) 194 } 195 196 func (s SqlUserAccessTokenStore) GetByUser(userId string, offset, limit int) store.StoreChannel { 197 return store.Do(func(result *store.StoreResult) { 198 tokens := []*model.UserAccessToken{} 199 200 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 { 201 result.Err = model.NewAppError("SqlUserAccessTokenStore.GetByUser", "store.sql_user_access_token.get_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 202 } 203 204 result.Data = tokens 205 }) 206 } 207 208 func (s SqlUserAccessTokenStore) Search(term string) store.StoreChannel { 209 return store.Do(func(result *store.StoreResult) { 210 tokens := []*model.UserAccessToken{} 211 params := map[string]interface{}{"Term": term + "%"} 212 query := ` 213 SELECT 214 uat.* 215 FROM UserAccessTokens uat 216 INNER JOIN Users u 217 ON uat.UserId = u.Id 218 WHERE uat.Id LIKE :Term OR uat.UserId LIKE :Term OR u.Username LIKE :Term` 219 220 if _, err := s.GetReplica().Select(&tokens, query, params); err != nil { 221 result.Err = model.NewAppError("SqlUserAccessTokenStore.Search", "store.sql_user_access_token.search.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError) 222 } 223 224 result.Data = tokens 225 }) 226 } 227 228 func (s SqlUserAccessTokenStore) UpdateTokenEnable(tokenId string) store.StoreChannel { 229 return store.Do(func(result *store.StoreResult) { 230 if _, err := s.GetMaster().Exec("UPDATE UserAccessTokens SET IsActive = TRUE WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil { 231 result.Err = model.NewAppError("SqlUserAccessTokenStore.UpdateTokenEnable", "store.sql_user_access_token.update_token_enable.app_error", nil, "id="+tokenId+", "+err.Error(), http.StatusInternalServerError) 232 } else { 233 result.Data = tokenId 234 } 235 }) 236 } 237 238 func (s SqlUserAccessTokenStore) UpdateTokenDisable(tokenId string) store.StoreChannel { 239 return store.Do(func(result *store.StoreResult) { 240 transaction, err := s.GetMaster().Begin() 241 if err != nil { 242 result.Err = model.NewAppError("SqlUserAccessTokenStore.UpdateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, err.Error(), http.StatusInternalServerError) 243 } else { 244 defer finalizeTransaction(transaction) 245 if extrasResult := s.deleteSessionsAndDisableToken(transaction, tokenId); extrasResult.Err != nil { 246 *result = extrasResult 247 } 248 249 if result.Err == nil { 250 if err := transaction.Commit(); err != nil { 251 // don't need to rollback here since the transaction is already closed 252 result.Err = model.NewAppError("SqlUserAccessTokenStore.UpdateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, err.Error(), http.StatusInternalServerError) 253 } 254 } 255 } 256 }) 257 } 258 259 func (s SqlUserAccessTokenStore) deleteSessionsAndDisableToken(transaction *gorp.Transaction, tokenId string) store.StoreResult { 260 result := store.StoreResult{} 261 262 query := "" 263 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 264 query = "DELETE FROM Sessions s USING UserAccessTokens o WHERE o.Token = s.Token AND o.Id = :Id" 265 } else if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 266 query = "DELETE s.* FROM Sessions s INNER JOIN UserAccessTokens o ON o.Token = s.Token WHERE o.Id = :Id" 267 } 268 269 if _, err := transaction.Exec(query, map[string]interface{}{"Id": tokenId}); err != nil { 270 result.Err = model.NewAppError("SqlUserAccessTokenStore.deleteSessionsAndDisableToken", "store.sql_user_access_token.update_token_disable.app_error", nil, "id="+tokenId+", err="+err.Error(), http.StatusInternalServerError) 271 return result 272 } 273 274 return s.updateTokenDisable(transaction, tokenId) 275 } 276 277 func (s SqlUserAccessTokenStore) updateTokenDisable(transaction *gorp.Transaction, tokenId string) store.StoreResult { 278 result := store.StoreResult{} 279 280 if _, err := transaction.Exec("UPDATE UserAccessTokens SET IsActive = FALSE WHERE Id = :Id", map[string]interface{}{"Id": tokenId}); err != nil { 281 result.Err = model.NewAppError("SqlUserAccessTokenStore.updateTokenDisable", "store.sql_user_access_token.update_token_disable.app_error", nil, "", http.StatusInternalServerError) 282 } 283 284 return result 285 }