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  }