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