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