github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/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 "net/http" 8 9 "github.com/vnforks/kid/v5/mlog" 10 "github.com/vnforks/kid/v5/model" 11 ) 12 13 func (a *App) CreateSession(session *model.Session) (*model.Session, *model.AppError) { 14 session.Token = "" 15 16 session, err := a.Srv().Store.Session().Save(session) 17 if err != nil { 18 return nil, err 19 } 20 21 a.AddSessionToCache(session) 22 23 return session, nil 24 } 25 26 func (a *App) GetSession(token string) (*model.Session, *model.AppError) { 27 metrics := a.Metrics() 28 29 var session *model.Session 30 var err *model.AppError 31 if ts, ok := a.Srv().sessionCache.Get(token); ok { 32 session = ts.(*model.Session) 33 if metrics != nil { 34 metrics.IncrementMemCacheHitCounterSession() 35 } 36 } else { 37 if metrics != nil { 38 metrics.IncrementMemCacheMissCounterSession() 39 } 40 } 41 42 if session == nil { 43 if session, err = a.Srv().Store.Session().Get(token); err == nil { 44 if session != nil { 45 if session.Token != token { 46 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token, "Error": ""}, "", http.StatusUnauthorized) 47 } 48 49 if !session.IsExpired() { 50 a.AddSessionToCache(session) 51 } 52 } 53 } else if err.StatusCode == http.StatusInternalServerError { 54 return nil, err 55 } 56 } 57 58 if session == nil { 59 session, err = a.createSessionForUserAccessToken(token) 60 if err != nil { 61 detailedError := "" 62 statusCode := http.StatusUnauthorized 63 if err.Id != "app.user_access_token.invalid_or_missing" { 64 detailedError = err.Error() 65 statusCode = err.StatusCode 66 } 67 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token}, detailedError, statusCode) 68 } 69 } 70 71 if session == nil || session.IsExpired() { 72 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token}, "", http.StatusUnauthorized) 73 } 74 75 if *a.Config().ServiceSettings.SessionIdleTimeoutInMinutes > 0 && 76 !session.IsOAuth && 77 session.Props[model.SESSION_PROP_TYPE] != model.SESSION_TYPE_USER_ACCESS_TOKEN { 78 79 timeout := int64(*a.Config().ServiceSettings.SessionIdleTimeoutInMinutes) * 1000 * 60 80 if (model.GetMillis() - session.LastActivityAt) > timeout { 81 a.RevokeSessionById(session.Id) 82 return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token}, "idle timeout", http.StatusUnauthorized) 83 } 84 } 85 86 return session, nil 87 } 88 89 func (a *App) GetSessions(userId string) ([]*model.Session, *model.AppError) { 90 91 return a.Srv().Store.Session().GetSessions(userId) 92 } 93 94 func (a *App) UpdateSessionsIsGuest(userId string, isGuest bool) { 95 sessions, err := a.Srv().Store.Session().GetSessions(userId) 96 if err != nil { 97 mlog.Error("Unable to get user sessions", mlog.String("user_id", userId), mlog.Err(err)) 98 } 99 100 for _, session := range sessions { 101 if isGuest { 102 session.AddProp(model.SESSION_PROP_IS_GUEST, "true") 103 } else { 104 session.AddProp(model.SESSION_PROP_IS_GUEST, "false") 105 } 106 err := a.Srv().Store.Session().UpdateProps(session) 107 if err != nil { 108 mlog.Error("Unable to update isGuest session", mlog.Err(err)) 109 continue 110 } 111 a.AddSessionToCache(session) 112 } 113 } 114 115 func (a *App) RevokeAllSessions(userId string) *model.AppError { 116 sessions, err := a.Srv().Store.Session().GetSessions(userId) 117 if err != nil { 118 return err 119 } 120 for _, session := range sessions { 121 if session.IsOAuth { 122 a.RevokeAccessToken(session.Token) 123 } else { 124 if err := a.Srv().Store.Session().Remove(session.Id); err != nil { 125 return err 126 } 127 } 128 } 129 130 a.ClearSessionCacheForUser(userId) 131 132 return nil 133 } 134 135 // RevokeSessionsFromAllUsers will go through all the sessions active 136 // in the server and revoke them 137 func (a *App) RevokeSessionsFromAllUsers() *model.AppError { 138 // revoke tokens before sessions so they can't be used to relogin 139 tErr := a.Srv().Store.OAuth().RemoveAllAccessData() 140 if tErr != nil { 141 return tErr 142 } 143 err := a.Srv().Store.Session().RemoveAllSessions() 144 if err != nil { 145 return err 146 } 147 a.ClearSessionCacheForAllUsers() 148 149 return nil 150 } 151 152 func (a *App) ClearSessionCacheForUser(userId string) { 153 a.ClearSessionCacheForUserSkipClusterSend(userId) 154 155 if a.Cluster() != nil { 156 msg := &model.ClusterMessage{ 157 Event: model.CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER, 158 SendType: model.CLUSTER_SEND_RELIABLE, 159 Data: userId, 160 } 161 a.Cluster().SendClusterMessage(msg) 162 } 163 } 164 165 func (a *App) ClearSessionCacheForAllUsers() { 166 a.ClearSessionCacheForAllUsersSkipClusterSend() 167 168 if a.Cluster() != nil { 169 msg := &model.ClusterMessage{ 170 Event: model.CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_ALL_USERS, 171 SendType: model.CLUSTER_SEND_RELIABLE, 172 } 173 a.Cluster().SendClusterMessage(msg) 174 } 175 } 176 177 func (a *App) ClearSessionCacheForUserSkipClusterSend(userId string) { 178 keys := a.Srv().sessionCache.Keys() 179 180 for _, key := range keys { 181 if ts, ok := a.Srv().sessionCache.Get(key); ok { 182 session := ts.(*model.Session) 183 if session.UserId == userId { 184 a.Srv().sessionCache.Remove(key) 185 if a.Metrics() != nil { 186 a.Metrics().IncrementMemCacheInvalidationCounterSession() 187 } 188 } 189 } 190 } 191 192 a.InvalidateWebConnSessionCacheForUser(userId) 193 } 194 195 func (a *App) ClearSessionCacheForAllUsersSkipClusterSend() { 196 mlog.Info("Purging sessions cache") 197 a.Srv().sessionCache.Purge() 198 } 199 200 func (a *App) AddSessionToCache(session *model.Session) { 201 a.Srv().sessionCache.AddWithExpiresInSecs(session.Token, session, int64(*a.Config().ServiceSettings.SessionCacheInMinutes*60)) 202 } 203 204 func (a *App) SessionCacheLength() int { 205 return a.Srv().sessionCache.Len() 206 } 207 208 func (a *App) RevokeSessionsForDeviceId(userId string, deviceId string, currentSessionId string) *model.AppError { 209 sessions, err := a.Srv().Store.Session().GetSessions(userId) 210 if err != nil { 211 return err 212 } 213 for _, session := range sessions { 214 if session.DeviceId == deviceId && session.Id != currentSessionId { 215 mlog.Debug("Revoking sessionId for userId. Re-login with the same device Id", mlog.String("session_id", session.Id), mlog.String("user_id", userId)) 216 if err := a.RevokeSession(session); err != nil { 217 // Soft error so we still remove the other sessions 218 mlog.Error(err.Error()) 219 } 220 } 221 } 222 223 return nil 224 } 225 226 func (a *App) GetSessionById(sessionId string) (*model.Session, *model.AppError) { 227 session, err := a.Srv().Store.Session().Get(sessionId) 228 if err != nil { 229 err.StatusCode = http.StatusBadRequest 230 return nil, err 231 } 232 return session, nil 233 } 234 235 func (a *App) RevokeSessionById(sessionId string) *model.AppError { 236 session, err := a.Srv().Store.Session().Get(sessionId) 237 if err != nil { 238 err.StatusCode = http.StatusBadRequest 239 return err 240 } 241 return a.RevokeSession(session) 242 243 } 244 245 func (a *App) RevokeSession(session *model.Session) *model.AppError { 246 if session.IsOAuth { 247 if err := a.RevokeAccessToken(session.Token); err != nil { 248 return err 249 } 250 } else { 251 if err := a.Srv().Store.Session().Remove(session.Id); err != nil { 252 return err 253 } 254 } 255 256 a.ClearSessionCacheForUser(session.UserId) 257 258 return nil 259 } 260 261 func (a *App) AttachDeviceId(sessionId string, deviceId string, expiresAt int64) *model.AppError { 262 _, err := a.Srv().Store.Session().UpdateDeviceId(sessionId, deviceId, expiresAt) 263 if err != nil { 264 return err 265 } 266 267 return nil 268 } 269 270 func (a *App) UpdateLastActivityAtIfNeeded(session model.Session) { 271 now := model.GetMillis() 272 273 a.UpdateWebConnUserActivity(session, now) 274 275 if now-session.LastActivityAt < model.SESSION_ACTIVITY_TIMEOUT { 276 return 277 } 278 279 if err := a.Srv().Store.Session().UpdateLastActivityAt(session.Id, now); err != nil { 280 mlog.Error("Failed to update LastActivityAt", mlog.String("user_id", session.UserId), mlog.String("session_id", session.Id), mlog.Err(err)) 281 } 282 283 session.LastActivityAt = now 284 a.AddSessionToCache(&session) 285 } 286 287 func (a *App) CreateUserAccessToken(token *model.UserAccessToken) (*model.UserAccessToken, *model.AppError) { 288 289 user, err := a.Srv().Store.User().Get(token.UserId) 290 if err != nil { 291 return nil, err 292 } 293 294 if !*a.Config().ServiceSettings.EnableUserAccessTokens && !user.IsBot { 295 return nil, model.NewAppError("CreateUserAccessToken", "app.user_access_token.disabled", nil, "", http.StatusNotImplemented) 296 } 297 298 token.Token = model.NewId() 299 300 token, err = a.Srv().Store.UserAccessToken().Save(token) 301 if err != nil { 302 return nil, err 303 } 304 305 // Don't send emails to bot users. 306 if !user.IsBot { 307 if err := a.sendUserAccessTokenAddedEmail(user.Email, user.Locale, a.GetSiteURL()); err != nil { 308 a.Log().Error("Unable to send user access token added email", mlog.Err(err), mlog.String("user_id", user.Id)) 309 } 310 } 311 312 return token, nil 313 314 } 315 316 func (a *App) createSessionForUserAccessToken(tokenString string) (*model.Session, *model.AppError) { 317 token, err := a.Srv().Store.UserAccessToken().GetByToken(tokenString) 318 if err != nil { 319 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, err.Error(), http.StatusUnauthorized) 320 } 321 322 if !token.IsActive { 323 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, "inactive_token", http.StatusUnauthorized) 324 } 325 326 user, err := a.Srv().Store.User().Get(token.UserId) 327 if err != nil { 328 return nil, err 329 } 330 331 if !*a.Config().ServiceSettings.EnableUserAccessTokens && !user.IsBot { 332 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, "EnableUserAccessTokens=false", http.StatusUnauthorized) 333 } 334 335 if user.DeleteAt != 0 { 336 return nil, model.NewAppError("createSessionForUserAccessToken", "app.user_access_token.invalid_or_missing", nil, "inactive_user_id="+user.Id, http.StatusUnauthorized) 337 } 338 339 session := &model.Session{ 340 Token: token.Token, 341 UserId: user.Id, 342 Roles: user.GetRawRoles(), 343 IsOAuth: false, 344 } 345 346 session.AddProp(model.SESSION_PROP_USER_ACCESS_TOKEN_ID, token.Id) 347 session.AddProp(model.SESSION_PROP_TYPE, model.SESSION_TYPE_USER_ACCESS_TOKEN) 348 if user.IsBot { 349 session.AddProp(model.SESSION_PROP_IS_BOT, model.SESSION_PROP_IS_BOT_VALUE) 350 } 351 if user.IsGuest() { 352 session.AddProp(model.SESSION_PROP_IS_GUEST, "true") 353 } else { 354 session.AddProp(model.SESSION_PROP_IS_GUEST, "false") 355 } 356 session.SetExpireInDays(model.SESSION_USER_ACCESS_TOKEN_EXPIRY) 357 358 session, err = a.Srv().Store.Session().Save(session) 359 if err != nil { 360 return nil, err 361 } 362 363 a.AddSessionToCache(session) 364 365 return session, nil 366 367 } 368 369 func (a *App) RevokeUserAccessToken(token *model.UserAccessToken) *model.AppError { 370 var session *model.Session 371 session, _ = a.Srv().Store.Session().Get(token.Token) 372 373 if err := a.Srv().Store.UserAccessToken().Delete(token.Id); err != nil { 374 return err 375 } 376 377 if session == nil { 378 return nil 379 } 380 381 return a.RevokeSession(session) 382 } 383 384 func (a *App) DisableUserAccessToken(token *model.UserAccessToken) *model.AppError { 385 var session *model.Session 386 session, _ = a.Srv().Store.Session().Get(token.Token) 387 388 if err := a.Srv().Store.UserAccessToken().UpdateTokenDisable(token.Id); err != nil { 389 return err 390 } 391 392 if session == nil { 393 return nil 394 } 395 396 return a.RevokeSession(session) 397 } 398 399 func (a *App) EnableUserAccessToken(token *model.UserAccessToken) *model.AppError { 400 var session *model.Session 401 session, _ = a.Srv().Store.Session().Get(token.Token) 402 403 err := a.Srv().Store.UserAccessToken().UpdateTokenEnable(token.Id) 404 if err != nil { 405 return err 406 } 407 408 if session == nil { 409 return nil 410 } 411 412 return nil 413 } 414 415 func (a *App) GetUserAccessTokens(page, perPage int) ([]*model.UserAccessToken, *model.AppError) { 416 tokens, err := a.Srv().Store.UserAccessToken().GetAll(page*perPage, perPage) 417 if err != nil { 418 return nil, err 419 } 420 421 for _, token := range tokens { 422 token.Token = "" 423 } 424 425 return tokens, nil 426 } 427 428 func (a *App) GetUserAccessTokensForUser(userId string, page, perPage int) ([]*model.UserAccessToken, *model.AppError) { 429 tokens, err := a.Srv().Store.UserAccessToken().GetByUser(userId, page*perPage, perPage) 430 if err != nil { 431 return nil, err 432 } 433 for _, token := range tokens { 434 token.Token = "" 435 } 436 437 return tokens, nil 438 439 } 440 441 func (a *App) GetUserAccessToken(tokenId string, sanitize bool) (*model.UserAccessToken, *model.AppError) { 442 token, err := a.Srv().Store.UserAccessToken().Get(tokenId) 443 if err != nil { 444 return nil, err 445 } 446 447 if sanitize { 448 token.Token = "" 449 } 450 return token, nil 451 } 452 453 func (a *App) SearchUserAccessTokens(term string) ([]*model.UserAccessToken, *model.AppError) { 454 tokens, err := a.Srv().Store.UserAccessToken().Search(term) 455 if err != nil { 456 return nil, err 457 } 458 for _, token := range tokens { 459 token.Token = "" 460 } 461 return tokens, nil 462 }