github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/session.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "context" 8 "errors" 9 "fmt" 10 "math" 11 "net/http" 12 "os" 13 "sync" 14 "time" 15 16 "github.com/mattermost/mattermost-server/v5/audit" 17 "github.com/mattermost/mattermost-server/v5/mlog" 18 "github.com/mattermost/mattermost-server/v5/model" 19 "github.com/mattermost/mattermost-server/v5/store" 20 ) 21 22 func (a *App) CreateSession(session *model.Session) (*model.Session, *model.AppError) { 23 session.Token = "" 24 25 session, err := a.Srv().Store.Session().Save(session) 26 if err != nil { 27 var invErr *store.ErrInvalidInput 28 switch { 29 case errors.As(err, &invErr): 30 return nil, model.NewAppError("CreateSession", "app.session.save.existing.app_error", nil, invErr.Error(), http.StatusBadRequest) 31 default: 32 return nil, model.NewAppError("CreateSession", "app.session.save.app_error", nil, err.Error(), http.StatusInternalServerError) 33 } 34 } 35 36 a.AddSessionToCache(session) 37 38 return session, nil 39 } 40 41 func ReturnSessionToPool(session *model.Session) { 42 if session != nil { 43 session.Id = "" 44 userSessionPool.Put(session) 45 } 46 } 47 48 var userSessionPool = sync.Pool{ 49 New: func() interface{} { 50 return &model.Session{} 51 }, 52 } 53 54 func (a *App) GetCloudSession(token string) (*model.Session, *model.AppError) { 55 apiKey := os.Getenv("MM_CLOUD_API_KEY") 56 if apiKey != "" && apiKey == token { 57 // Need a bare-bones session object for later checks 58 session := &model.Session{ 59 Token: token, 60 IsOAuth: false, 61 } 62 63 session.AddProp(model.SESSION_PROP_TYPE, model.SESSION_TYPE_CLOUD_KEY) 64 return session, nil 65 } 66 return nil, model.NewAppError("GetCloudSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": ""}, "The provided token is invalid", http.StatusUnauthorized) 67 } 68 69 func (a *App) GetSession(token string) (*model.Session, *model.AppError) { 70 metrics := a.Metrics() 71 72 var session = userSessionPool.Get().(*model.Session) 73 74 var err *model.AppError 75 if err := a.Srv().sessionCache.Get(token, session); err == nil { 76 if metrics != nil { 77 metrics.IncrementMemCacheHitCounterSession() 78 } 79 } else { 80 if metrics != nil { 81 metrics.IncrementMemCacheMissCounterSession() 82 } 83 } 84 85 if session.Id == "" { 86 var nErr error 87 if session, nErr = a.Srv().Store.Session().Get(token); nErr == nil { 88 if session != nil { 89 if session.Token != token { 90 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": ""}, "session token is different from the one in DB", http.StatusUnauthorized) 91 } 92 93 if !session.IsExpired() { 94 a.AddSessionToCache(session) 95 } 96 } 97 } else if nfErr := new(store.ErrNotFound); !errors.As(nErr, &nfErr) { 98 return nil, model.NewAppError("GetSession", "app.session.get.app_error", nil, nErr.Error(), http.StatusInternalServerError) 99 } 100 } 101 102 if session == nil || session.Id == "" { 103 session, err = a.createSessionForUserAccessToken(token) 104 if err != nil { 105 detailedError := "" 106 statusCode := http.StatusUnauthorized 107 if err.Id != "app.user_access_token.invalid_or_missing" { 108 detailedError = err.Error() 109 statusCode = err.StatusCode 110 } else { 111 mlog.Warn("Error while creating session for user access token", mlog.Err(err)) 112 } 113 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": detailedError}, "", statusCode) 114 } 115 } 116 117 if session.Id == "" || session.IsExpired() { 118 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": ""}, "session is either nil or expired", http.StatusUnauthorized) 119 } 120 121 if *a.Config().ServiceSettings.SessionIdleTimeoutInMinutes > 0 && 122 !session.IsOAuth && !session.IsMobileApp() && 123 session.Props[model.SESSION_PROP_TYPE] != model.SESSION_TYPE_USER_ACCESS_TOKEN && 124 !*a.Config().ServiceSettings.ExtendSessionLengthWithActivity { 125 126 timeout := int64(*a.Config().ServiceSettings.SessionIdleTimeoutInMinutes) * 1000 * 60 127 if (model.GetMillis() - session.LastActivityAt) > timeout { 128 // Revoking the session is an asynchronous task anyways since we are not checking 129 // for the return value of the call before returning the error. 130 // So moving this to a goroutine has 2 advantages: 131 // 1. We are treating this as a proper asynchronous task. 132 // 2. This also fixes a race condition in the web hub, where GetSession 133 // gets called from (*WebConn).isMemberOfTeam and revoking a session involves 134 // clearing the webconn cache, which needs the hub again. 135 a.Srv().Go(func() { 136 err := a.RevokeSessionById(session.Id) 137 if err != nil { 138 mlog.Warn("Error while revoking session", mlog.Err(err)) 139 } 140 }) 141 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": ""}, "idle timeout", http.StatusUnauthorized) 142 } 143 } 144 145 return session, nil 146 } 147 148 func (a *App) GetSessions(userID string) ([]*model.Session, *model.AppError) { 149 150 sessions, err := a.Srv().Store.Session().GetSessions(userID) 151 if err != nil { 152 return nil, model.NewAppError("GetSessions", "app.session.get_sessions.app_error", nil, err.Error(), http.StatusInternalServerError) 153 } 154 155 return sessions, nil 156 } 157 158 func (a *App) UpdateSessionsIsGuest(userID string, isGuest bool) { 159 sessions, err := a.Srv().Store.Session().GetSessions(userID) 160 if err != nil { 161 mlog.Error("Unable to get user sessions", mlog.String("user_id", userID), mlog.Err(err)) 162 return 163 } 164 165 for _, session := range sessions { 166 session.AddProp(model.SESSION_PROP_IS_GUEST, fmt.Sprintf("%t", isGuest)) 167 err := a.Srv().Store.Session().UpdateProps(session) 168 if err != nil { 169 mlog.Warn("Unable to update isGuest session", mlog.Err(err)) 170 continue 171 } 172 a.AddSessionToCache(session) 173 } 174 } 175 176 func (a *App) RevokeAllSessions(userID string) *model.AppError { 177 sessions, err := a.Srv().Store.Session().GetSessions(userID) 178 if err != nil { 179 return model.NewAppError("RevokeAllSessions", "app.session.get_sessions.app_error", nil, err.Error(), http.StatusInternalServerError) 180 } 181 for _, session := range sessions { 182 if session.IsOAuth { 183 a.RevokeAccessToken(session.Token) 184 } else { 185 if err := a.Srv().Store.Session().Remove(session.Id); err != nil { 186 return model.NewAppError("RevokeAllSessions", "app.session.remove.app_error", nil, err.Error(), http.StatusInternalServerError) 187 } 188 } 189 } 190 191 a.ClearSessionCacheForUser(userID) 192 193 return nil 194 } 195 196 // RevokeSessionsFromAllUsers will go through all the sessions active 197 // in the server and revoke them 198 func (a *App) RevokeSessionsFromAllUsers() *model.AppError { 199 // revoke tokens before sessions so they can't be used to relogin 200 nErr := a.Srv().Store.OAuth().RemoveAllAccessData() 201 if nErr != nil { 202 return model.NewAppError("RevokeSessionsFromAllUsers", "app.oauth.remove_access_data.app_error", nil, nErr.Error(), http.StatusInternalServerError) 203 } 204 err := a.Srv().Store.Session().RemoveAllSessions() 205 if err != nil { 206 return model.NewAppError("RevokeSessionsFromAllUsers", "app.session.remove_all_sessions_for_team.app_error", nil, err.Error(), http.StatusInternalServerError) 207 } 208 a.ClearSessionCacheForAllUsers() 209 210 return nil 211 } 212 213 func (a *App) ClearSessionCacheForUser(userID string) { 214 a.ClearSessionCacheForUserSkipClusterSend(userID) 215 216 if a.Cluster() != nil { 217 msg := &model.ClusterMessage{ 218 Event: model.CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER, 219 SendType: model.CLUSTER_SEND_RELIABLE, 220 Data: userID, 221 } 222 a.Cluster().SendClusterMessage(msg) 223 } 224 } 225 226 func (a *App) ClearSessionCacheForAllUsers() { 227 a.ClearSessionCacheForAllUsersSkipClusterSend() 228 229 if a.Cluster() != nil { 230 msg := &model.ClusterMessage{ 231 Event: model.CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_ALL_USERS, 232 SendType: model.CLUSTER_SEND_RELIABLE, 233 } 234 a.Cluster().SendClusterMessage(msg) 235 } 236 } 237 238 func (a *App) ClearSessionCacheForUserSkipClusterSend(userID string) { 239 if keys, err := a.Srv().sessionCache.Keys(); err == nil { 240 var session *model.Session 241 for _, key := range keys { 242 if err := a.Srv().sessionCache.Get(key, &session); err == nil { 243 if session.UserId == userID { 244 a.Srv().sessionCache.Remove(key) 245 if a.Metrics() != nil { 246 a.Metrics().IncrementMemCacheInvalidationCounterSession() 247 } 248 } 249 } 250 } 251 } 252 253 a.InvalidateWebConnSessionCacheForUser(userID) 254 } 255 256 func (a *App) ClearSessionCacheForAllUsersSkipClusterSend() { 257 mlog.Info("Purging sessions cache") 258 a.Srv().sessionCache.Purge() 259 } 260 261 func (a *App) AddSessionToCache(session *model.Session) { 262 a.Srv().sessionCache.SetWithExpiry(session.Token, session, time.Duration(int64(*a.Config().ServiceSettings.SessionCacheInMinutes))*time.Minute) 263 } 264 265 func (a *App) SessionCacheLength() int { 266 if l, err := a.Srv().sessionCache.Len(); err == nil { 267 return l 268 } 269 return 0 270 } 271 272 func (a *App) RevokeSessionsForDeviceId(userID string, deviceId string, currentSessionId string) *model.AppError { 273 sessions, err := a.Srv().Store.Session().GetSessions(userID) 274 if err != nil { 275 return model.NewAppError("RevokeSessionsForDeviceId", "app.session.get_sessions.app_error", nil, err.Error(), http.StatusInternalServerError) 276 } 277 for _, session := range sessions { 278 if session.DeviceId == deviceId && session.Id != currentSessionId { 279 mlog.Debug("Revoking sessionId for userId. Re-login with the same device Id", mlog.String("session_id", session.Id), mlog.String("user_id", userID)) 280 if err := a.RevokeSession(session); err != nil { 281 mlog.Warn("Could not revoke session for device", mlog.String("device_id", deviceId), mlog.Err(err)) 282 } 283 } 284 } 285 286 return nil 287 } 288 289 func (a *App) GetSessionById(sessionId string) (*model.Session, *model.AppError) { 290 session, err := a.Srv().Store.Session().Get(sessionId) 291 if err != nil { 292 return nil, model.NewAppError("GetSessionById", "app.session.get.app_error", nil, err.Error(), http.StatusBadRequest) 293 } 294 295 return session, nil 296 } 297 298 func (a *App) RevokeSessionById(sessionId string) *model.AppError { 299 session, err := a.Srv().Store.Session().Get(sessionId) 300 if err != nil { 301 return model.NewAppError("RevokeSessionById", "app.session.get.app_error", nil, err.Error(), http.StatusBadRequest) 302 } 303 return a.RevokeSession(session) 304 305 } 306 307 func (a *App) RevokeSession(session *model.Session) *model.AppError { 308 if session.IsOAuth { 309 if err := a.RevokeAccessToken(session.Token); err != nil { 310 return err 311 } 312 } else { 313 if err := a.Srv().Store.Session().Remove(session.Id); err != nil { 314 return model.NewAppError("RevokeSession", "app.session.remove.app_error", nil, err.Error(), http.StatusInternalServerError) 315 } 316 } 317 318 a.ClearSessionCacheForUser(session.UserId) 319 320 return nil 321 } 322 323 func (a *App) AttachDeviceId(sessionId string, deviceId string, expiresAt int64) *model.AppError { 324 _, err := a.Srv().Store.Session().UpdateDeviceId(sessionId, deviceId, expiresAt) 325 if err != nil { 326 return model.NewAppError("AttachDeviceId", "app.session.update_device_id.app_error", nil, err.Error(), http.StatusInternalServerError) 327 } 328 329 return nil 330 } 331 332 func (a *App) UpdateLastActivityAtIfNeeded(session model.Session) { 333 now := model.GetMillis() 334 335 a.UpdateWebConnUserActivity(session, now) 336 337 if now-session.LastActivityAt < model.SESSION_ACTIVITY_TIMEOUT { 338 return 339 } 340 341 if err := a.Srv().Store.Session().UpdateLastActivityAt(session.Id, now); err != nil { 342 mlog.Warn("Failed to update LastActivityAt", mlog.String("user_id", session.UserId), mlog.String("session_id", session.Id), mlog.Err(err)) 343 } 344 345 session.LastActivityAt = now 346 a.AddSessionToCache(&session) 347 } 348 349 // ExtendSessionExpiryIfNeeded extends Session.ExpiresAt based on session lengths in config. 350 // A new ExpiresAt is only written if enough time has elapsed since last update. 351 // Returns true only if the session was extended. 352 func (a *App) ExtendSessionExpiryIfNeeded(session *model.Session) bool { 353 if session == nil || session.IsExpired() { 354 return false 355 } 356 357 sessionLength := a.GetSessionLengthInMillis(session) 358 359 // Only extend the expiry if the lessor of 1% or 1 day has elapsed within the 360 // current session duration. 361 threshold := int64(math.Min(float64(sessionLength)*0.01, float64(24*60*60*1000))) 362 // Minimum session length is 1 day as of this writing, therefore a minimum ~14 minutes threshold. 363 // However we'll add a sanity check here in case that changes. Minimum 5 minute threshold, 364 // meaning we won't write a new expiry more than every 5 minutes. 365 if threshold < 5*60*1000 { 366 threshold = 5 * 60 * 1000 367 } 368 369 now := model.GetMillis() 370 elapsed := now - (session.ExpiresAt - sessionLength) 371 if elapsed < threshold { 372 return false 373 } 374 375 auditRec := a.MakeAuditRecord("extendSessionExpiry", audit.Fail) 376 defer a.LogAuditRec(auditRec, nil) 377 auditRec.AddMeta("session", session) 378 379 newExpiry := now + sessionLength 380 if err := a.Srv().Store.Session().UpdateExpiresAt(session.Id, newExpiry); err != nil { 381 mlog.Error("Failed to update ExpiresAt", mlog.String("user_id", session.UserId), mlog.String("session_id", session.Id), mlog.Err(err)) 382 auditRec.AddMeta("err", err.Error()) 383 return false 384 } 385 386 // Update local cache. No need to invalidate cache for cluster as the session cache timeout 387 // ensures each node will get an extended expiry within the next 10 minutes. 388 // Worst case is another node may generate a redundant expiry update. 389 session.ExpiresAt = newExpiry 390 a.AddSessionToCache(session) 391 392 mlog.Debug("Session extended", mlog.String("user_id", session.UserId), mlog.String("session_id", session.Id), 393 mlog.Int64("newExpiry", newExpiry), mlog.Int64("session_length", sessionLength)) 394 395 auditRec.Success() 396 auditRec.AddMeta("extended_session", session) 397 return true 398 } 399 400 // GetSessionLengthInMillis returns the session length, in milliseconds, 401 // based on the type of session (Mobile, SSO, Web/LDAP). 402 func (a *App) GetSessionLengthInMillis(session *model.Session) int64 { 403 if session == nil { 404 return 0 405 } 406 407 var days int 408 if session.IsMobileApp() { 409 days = *a.Config().ServiceSettings.SessionLengthMobileInDays 410 } else if session.IsSSOLogin() { 411 days = *a.Config().ServiceSettings.SessionLengthSSOInDays 412 } else { 413 days = *a.Config().ServiceSettings.SessionLengthWebInDays 414 } 415 return int64(days * 24 * 60 * 60 * 1000) 416 } 417 418 // SetSessionExpireInDays sets the session's expiry the specified number of days 419 // relative to either the session creation date or the current time, depending 420 // on the `ExtendSessionOnActivity` config setting. 421 func (a *App) SetSessionExpireInDays(session *model.Session, days int) { 422 if session.CreateAt == 0 || *a.Config().ServiceSettings.ExtendSessionLengthWithActivity { 423 session.ExpiresAt = model.GetMillis() + (1000 * 60 * 60 * 24 * int64(days)) 424 } else { 425 session.ExpiresAt = session.CreateAt + (1000 * 60 * 60 * 24 * int64(days)) 426 } 427 } 428 429 func (a *App) CreateUserAccessToken(token *model.UserAccessToken) (*model.UserAccessToken, *model.AppError) { 430 431 user, nErr := a.Srv().Store.User().Get(context.Background(), token.UserId) 432 if nErr != nil { 433 var nfErr *store.ErrNotFound 434 switch { 435 case errors.As(nErr, &nfErr): 436 return nil, model.NewAppError("CreateUserAccessToken", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) 437 default: 438 return nil, model.NewAppError("CreateUserAccessToken", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError) 439 } 440 } 441 442 if !*a.Config().ServiceSettings.EnableUserAccessTokens && !user.IsBot { 443 return nil, model.NewAppError("CreateUserAccessToken", "app.user_access_token.disabled", nil, "", http.StatusNotImplemented) 444 } 445 446 token.Token = model.NewId() 447 448 token, nErr = a.Srv().Store.UserAccessToken().Save(token) 449 if nErr != nil { 450 var appErr *model.AppError 451 switch { 452 case errors.As(nErr, &appErr): 453 return nil, appErr 454 default: 455 return nil, model.NewAppError("CreateUserAccessToken", "app.user_access_token.save.app_error", nil, nErr.Error(), http.StatusInternalServerError) 456 } 457 } 458 459 // Don't send emails to bot users. 460 if !user.IsBot { 461 if err := a.Srv().EmailService.sendUserAccessTokenAddedEmail(user.Email, user.Locale, a.GetSiteURL()); err != nil { 462 a.Log().Error("Unable to send user access token added email", mlog.Err(err), mlog.String("user_id", user.Id)) 463 } 464 } 465 466 return token, nil 467 468 } 469 470 func (a *App) createSessionForUserAccessToken(tokenString string) (*model.Session, *model.AppError) { 471 token, nErr := a.Srv().Store.UserAccessToken().GetByToken(tokenString) 472 if nErr != nil { 473 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, nErr.Error(), http.StatusUnauthorized) 474 } 475 476 if !token.IsActive { 477 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, "inactive_token", http.StatusUnauthorized) 478 } 479 480 user, nErr := a.Srv().Store.User().Get(context.Background(), token.UserId) 481 if nErr != nil { 482 var nfErr *store.ErrNotFound 483 switch { 484 case errors.As(nErr, &nfErr): 485 return nil, model.NewAppError("createSessionForUserAccessToken", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound) 486 default: 487 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError) 488 } 489 } 490 491 if !*a.Config().ServiceSettings.EnableUserAccessTokens && !user.IsBot { 492 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, "EnableUserAccessTokens=false", http.StatusUnauthorized) 493 } 494 495 if user.DeleteAt != 0 { 496 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, "inactive_user_id="+user.Id, http.StatusUnauthorized) 497 } 498 499 session := &model.Session{ 500 Token: token.Token, 501 UserId: user.Id, 502 Roles: user.GetRawRoles(), 503 IsOAuth: false, 504 } 505 506 session.AddProp(model.SESSION_PROP_USER_ACCESS_TOKEN_ID, token.Id) 507 session.AddProp(model.SESSION_PROP_TYPE, model.SESSION_TYPE_USER_ACCESS_TOKEN) 508 if user.IsBot { 509 session.AddProp(model.SESSION_PROP_IS_BOT, model.SESSION_PROP_IS_BOT_VALUE) 510 } 511 if user.IsGuest() { 512 session.AddProp(model.SESSION_PROP_IS_GUEST, "true") 513 } else { 514 session.AddProp(model.SESSION_PROP_IS_GUEST, "false") 515 } 516 a.SetSessionExpireInDays(session, model.SESSION_USER_ACCESS_TOKEN_EXPIRY) 517 518 session, nErr = a.Srv().Store.Session().Save(session) 519 if nErr != nil { 520 var invErr *store.ErrInvalidInput 521 switch { 522 case errors.As(nErr, &invErr): 523 return nil, model.NewAppError("CreateSession", "app.session.save.existing.app_error", nil, invErr.Error(), http.StatusBadRequest) 524 default: 525 return nil, model.NewAppError("CreateSession", "app.session.save.app_error", nil, nErr.Error(), http.StatusInternalServerError) 526 } 527 } 528 529 a.AddSessionToCache(session) 530 531 return session, nil 532 533 } 534 535 func (a *App) RevokeUserAccessToken(token *model.UserAccessToken) *model.AppError { 536 var session *model.Session 537 session, _ = a.Srv().Store.Session().Get(token.Token) 538 539 if err := a.Srv().Store.UserAccessToken().Delete(token.Id); err != nil { 540 return model.NewAppError("RevokeUserAccessToken", "app.user_access_token.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 541 } 542 543 if session == nil { 544 return nil 545 } 546 547 return a.RevokeSession(session) 548 } 549 550 func (a *App) DisableUserAccessToken(token *model.UserAccessToken) *model.AppError { 551 var session *model.Session 552 session, _ = a.Srv().Store.Session().Get(token.Token) 553 554 if err := a.Srv().Store.UserAccessToken().UpdateTokenDisable(token.Id); err != nil { 555 return model.NewAppError("DisableUserAccessToken", "app.user_access_token.update_token_disable.app_error", nil, err.Error(), http.StatusInternalServerError) 556 } 557 558 if session == nil { 559 return nil 560 } 561 562 return a.RevokeSession(session) 563 } 564 565 func (a *App) EnableUserAccessToken(token *model.UserAccessToken) *model.AppError { 566 var session *model.Session 567 session, _ = a.Srv().Store.Session().Get(token.Token) 568 569 err := a.Srv().Store.UserAccessToken().UpdateTokenEnable(token.Id) 570 if err != nil { 571 return model.NewAppError("EnableUserAccessToken", "app.user_access_token.update_token_enable.app_error", nil, err.Error(), http.StatusInternalServerError) 572 } 573 574 if session == nil { 575 return nil 576 } 577 578 return nil 579 } 580 581 func (a *App) GetUserAccessTokens(page, perPage int) ([]*model.UserAccessToken, *model.AppError) { 582 tokens, err := a.Srv().Store.UserAccessToken().GetAll(page*perPage, perPage) 583 if err != nil { 584 return nil, model.NewAppError("GetUserAccessTokens", "app.user_access_token.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 585 } 586 587 for _, token := range tokens { 588 token.Token = "" 589 } 590 591 return tokens, nil 592 } 593 594 func (a *App) GetUserAccessTokensForUser(userID string, page, perPage int) ([]*model.UserAccessToken, *model.AppError) { 595 tokens, err := a.Srv().Store.UserAccessToken().GetByUser(userID, page*perPage, perPage) 596 if err != nil { 597 return nil, model.NewAppError("GetUserAccessTokensForUser", "app.user_access_token.get_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 598 } 599 for _, token := range tokens { 600 token.Token = "" 601 } 602 603 return tokens, nil 604 605 } 606 607 func (a *App) GetUserAccessToken(tokenID string, sanitize bool) (*model.UserAccessToken, *model.AppError) { 608 token, err := a.Srv().Store.UserAccessToken().Get(tokenID) 609 if err != nil { 610 var nfErr *store.ErrNotFound 611 switch { 612 case errors.As(err, &nfErr): 613 return nil, model.NewAppError("GetUserAccessToken", "app.user_access_token.get_by_user.app_error", nil, nfErr.Error(), http.StatusNotFound) 614 default: 615 return nil, model.NewAppError("GetUserAccessToken", "app.user_access_token.get_by_user.app_error", nil, err.Error(), http.StatusInternalServerError) 616 } 617 } 618 619 if sanitize { 620 token.Token = "" 621 } 622 return token, nil 623 } 624 625 func (a *App) SearchUserAccessTokens(term string) ([]*model.UserAccessToken, *model.AppError) { 626 tokens, err := a.Srv().Store.UserAccessToken().Search(term) 627 if err != nil { 628 return nil, model.NewAppError("SearchUserAccessTokens", "app.user_access_token.search.app_error", nil, err.Error(), http.StatusInternalServerError) 629 } 630 for _, token := range tokens { 631 token.Token = "" 632 } 633 return tokens, nil 634 }