mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
PLT-7633 (E20) Add session idle timeout config setting (#7524)
* Add session idle timeout config setting * Modify config setting name to SessionIdleTimeoutInMinutes * Small re-org of if statement * Merge with latest master
This commit is contained in:
committed by
George Goldberg
parent
8d662105d3
commit
15b361094a
@@ -157,6 +157,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
c.Err = model.NewAppError("ServeHTTP", "api.context.token_provided.app_error", nil, "token="+token, http.StatusUnauthorized)
|
||||
} else {
|
||||
c.Session = *session
|
||||
c.App.UpdateLastActivityAtIfNeeded(*session)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,18 @@ func (a *App) GetSession(token string) (*model.Session, *model.AppError) {
|
||||
return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token}, "", http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
if *utils.Cfg.ServiceSettings.SessionIdleTimeoutInMinutes > 0 &&
|
||||
utils.IsLicensed() && *utils.License().Features.Compliance &&
|
||||
session != nil && !session.IsOAuth && !session.IsMobileApp() &&
|
||||
session.Props[model.SESSION_PROP_TYPE] != model.SESSION_TYPE_USER_ACCESS_TOKEN {
|
||||
|
||||
timeout := int64(*utils.Cfg.ServiceSettings.SessionIdleTimeoutInMinutes) * 1000 * 60
|
||||
if model.GetMillis()-session.LastActivityAt > timeout {
|
||||
a.RevokeSessionById(session.Id)
|
||||
return nil, model.NewAppError("GetSession", "api.context.invalid_token.error", map[string]interface{}{"Token": token}, "idle timeout", http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/mattermost/mattermost-server/utils"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
@@ -32,3 +36,118 @@ func TestCache(t *testing.T) {
|
||||
t.Fatal("should have one less")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSessionIdleTimeoutInMinutes(t *testing.T) {
|
||||
th := Setup().InitBasic()
|
||||
|
||||
session := &model.Session{
|
||||
UserId: model.NewId(),
|
||||
}
|
||||
|
||||
session, _ = th.App.CreateSession(session)
|
||||
|
||||
isLicensed := utils.IsLicensed()
|
||||
license := utils.License()
|
||||
timeout := *utils.Cfg.ServiceSettings.SessionIdleTimeoutInMinutes
|
||||
defer func() {
|
||||
utils.SetIsLicensed(isLicensed)
|
||||
utils.SetLicense(license)
|
||||
*utils.Cfg.ServiceSettings.SessionIdleTimeoutInMinutes = timeout
|
||||
}()
|
||||
utils.SetIsLicensed(true)
|
||||
utils.SetLicense(&model.License{Features: &model.Features{}})
|
||||
utils.License().Features.SetDefaults()
|
||||
*utils.License().Features.Compliance = true
|
||||
*utils.Cfg.ServiceSettings.SessionIdleTimeoutInMinutes = 5
|
||||
|
||||
rsession, err := th.App.GetSession(session.Token)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, rsession.Id, session.Id)
|
||||
|
||||
rsession, err = th.App.GetSession(session.Token)
|
||||
|
||||
// Test regular session, should timeout
|
||||
time := session.LastActivityAt - (1000 * 60 * 6)
|
||||
<-th.App.Srv.Store.Session().UpdateLastActivityAt(session.Id, time)
|
||||
th.App.ClearSessionCacheForUserSkipClusterSend(session.UserId)
|
||||
|
||||
rsession, err = th.App.GetSession(session.Token)
|
||||
require.NotNil(t, err)
|
||||
assert.Equal(t, "api.context.invalid_token.error", err.Id)
|
||||
assert.Equal(t, "idle timeout", err.DetailedError)
|
||||
assert.Nil(t, rsession)
|
||||
|
||||
// Test mobile session, should not timeout
|
||||
session = &model.Session{
|
||||
UserId: model.NewId(),
|
||||
DeviceId: "android:" + model.NewId(),
|
||||
}
|
||||
|
||||
session, _ = th.App.CreateSession(session)
|
||||
time = session.LastActivityAt - (1000 * 60 * 6)
|
||||
<-th.App.Srv.Store.Session().UpdateLastActivityAt(session.Id, time)
|
||||
th.App.ClearSessionCacheForUserSkipClusterSend(session.UserId)
|
||||
|
||||
_, err = th.App.GetSession(session.Token)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Test oauth session, should not timeout
|
||||
session = &model.Session{
|
||||
UserId: model.NewId(),
|
||||
IsOAuth: true,
|
||||
}
|
||||
|
||||
session, _ = th.App.CreateSession(session)
|
||||
time = session.LastActivityAt - (1000 * 60 * 6)
|
||||
<-th.App.Srv.Store.Session().UpdateLastActivityAt(session.Id, time)
|
||||
th.App.ClearSessionCacheForUserSkipClusterSend(session.UserId)
|
||||
|
||||
_, err = th.App.GetSession(session.Token)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Test personal access token session, should not timeout
|
||||
session = &model.Session{
|
||||
UserId: model.NewId(),
|
||||
}
|
||||
session.AddProp(model.SESSION_PROP_TYPE, model.SESSION_TYPE_USER_ACCESS_TOKEN)
|
||||
|
||||
session, _ = th.App.CreateSession(session)
|
||||
time = session.LastActivityAt - (1000 * 60 * 6)
|
||||
<-th.App.Srv.Store.Session().UpdateLastActivityAt(session.Id, time)
|
||||
th.App.ClearSessionCacheForUserSkipClusterSend(session.UserId)
|
||||
|
||||
_, err = th.App.GetSession(session.Token)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Test regular session with license off, should not timeout
|
||||
*utils.License().Features.Compliance = false
|
||||
|
||||
session = &model.Session{
|
||||
UserId: model.NewId(),
|
||||
}
|
||||
|
||||
session, _ = th.App.CreateSession(session)
|
||||
time = session.LastActivityAt - (1000 * 60 * 6)
|
||||
<-th.App.Srv.Store.Session().UpdateLastActivityAt(session.Id, time)
|
||||
th.App.ClearSessionCacheForUserSkipClusterSend(session.UserId)
|
||||
|
||||
_, err = th.App.GetSession(session.Token)
|
||||
assert.Nil(t, err)
|
||||
|
||||
*utils.License().Features.Compliance = true
|
||||
|
||||
// Test regular session with timeout set to 0, should not timeout
|
||||
*utils.Cfg.ServiceSettings.SessionIdleTimeoutInMinutes = 0
|
||||
|
||||
session = &model.Session{
|
||||
UserId: model.NewId(),
|
||||
}
|
||||
|
||||
session, _ = th.App.CreateSession(session)
|
||||
time = session.LastActivityAt - (1000 * 60 * 6)
|
||||
<-th.App.Srv.Store.Session().UpdateLastActivityAt(session.Id, time)
|
||||
th.App.ClearSessionCacheForUserSkipClusterSend(session.UserId)
|
||||
|
||||
_, err = th.App.GetSession(session.Token)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"SessionLengthMobileInDays": 30,
|
||||
"SessionLengthSSOInDays": 30,
|
||||
"SessionCacheInMinutes": 10,
|
||||
"SessionIdleTimeout": 0,
|
||||
"WebsocketSecurePort": 443,
|
||||
"WebsocketPort": 80,
|
||||
"WebserverMode": "gzip",
|
||||
|
||||
@@ -182,6 +182,7 @@ type ServiceSettings struct {
|
||||
SessionLengthMobileInDays *int
|
||||
SessionLengthSSOInDays *int
|
||||
SessionCacheInMinutes *int
|
||||
SessionIdleTimeoutInMinutes *int
|
||||
WebsocketSecurePort *int
|
||||
WebsocketPort *int
|
||||
WebserverMode *string
|
||||
@@ -1155,6 +1156,11 @@ func (o *Config) SetDefaults() {
|
||||
*o.ServiceSettings.SessionCacheInMinutes = 10
|
||||
}
|
||||
|
||||
if o.ServiceSettings.SessionIdleTimeoutInMinutes == nil {
|
||||
o.ServiceSettings.SessionIdleTimeoutInMinutes = new(int)
|
||||
*o.ServiceSettings.SessionIdleTimeoutInMinutes = 0
|
||||
}
|
||||
|
||||
if o.ServiceSettings.EnableCommands == nil {
|
||||
o.ServiceSettings.EnableCommands = new(bool)
|
||||
*o.ServiceSettings.EnableCommands = false
|
||||
|
||||
Reference in New Issue
Block a user