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  }