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