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