You've already forked focalboard
mirror of
https://github.com/mattermost/focalboard.git
synced 2025-07-15 23:54:29 +02:00
Improving sessions handling
This commit is contained in:
@ -2,6 +2,7 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/mattermost/mattermost-octo-tasks/server/model"
|
"github.com/mattermost/mattermost-octo-tasks/server/model"
|
||||||
@ -10,14 +11,19 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetSession Get a user active session and refresh the session if is needed
|
||||||
func (a *App) GetSession(token string) (*model.Session, error) {
|
func (a *App) GetSession(token string) (*model.Session, error) {
|
||||||
session, err := a.store.GetSession(token)
|
session, err := a.store.GetSession(token, a.config.SessionExpireTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "unable to get the session for the token")
|
return nil, errors.Wrap(err, "unable to get the session for the token")
|
||||||
}
|
}
|
||||||
|
if session.UpdateAt < (time.Now().Unix() - a.config.SessionRefreshTime) {
|
||||||
|
a.store.RefreshSession(session)
|
||||||
|
}
|
||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Login create a new user session if the authentication data is valid
|
||||||
func (a *App) Login(username string, email string, password string, mfaToken string) (string, error) {
|
func (a *App) Login(username string, email string, password string, mfaToken string) (string, error) {
|
||||||
var user *model.User
|
var user *model.User
|
||||||
if username != "" {
|
if username != "" {
|
||||||
@ -59,6 +65,7 @@ func (a *App) Login(username string, email string, password string, mfaToken str
|
|||||||
return session.Token, nil
|
return session.Token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterUser create a new user if the provided data is valid
|
||||||
func (a *App) RegisterUser(username string, email string, password string) error {
|
func (a *App) RegisterUser(username string, email string, password string) error {
|
||||||
var user *model.User
|
var user *model.User
|
||||||
if username != "" {
|
if username != "" {
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/mattermost/mattermost-octo-tasks/server/api"
|
"github.com/mattermost/mattermost-octo-tasks/server/api"
|
||||||
"github.com/mattermost/mattermost-octo-tasks/server/app"
|
"github.com/mattermost/mattermost-octo-tasks/server/app"
|
||||||
"github.com/mattermost/mattermost-octo-tasks/server/services/config"
|
"github.com/mattermost/mattermost-octo-tasks/server/services/config"
|
||||||
|
"github.com/mattermost/mattermost-octo-tasks/server/services/scheduler"
|
||||||
"github.com/mattermost/mattermost-octo-tasks/server/services/store"
|
"github.com/mattermost/mattermost-octo-tasks/server/services/store"
|
||||||
"github.com/mattermost/mattermost-octo-tasks/server/services/store/sqlstore"
|
"github.com/mattermost/mattermost-octo-tasks/server/services/store/sqlstore"
|
||||||
"github.com/mattermost/mattermost-octo-tasks/server/services/telemetry"
|
"github.com/mattermost/mattermost-octo-tasks/server/services/telemetry"
|
||||||
@ -26,13 +28,14 @@ import (
|
|||||||
const currentVersion = "0.0.1"
|
const currentVersion = "0.0.1"
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
config *config.Configuration
|
config *config.Configuration
|
||||||
wsServer *ws.Server
|
wsServer *ws.Server
|
||||||
webServer *web.Server
|
webServer *web.Server
|
||||||
store store.Store
|
store store.Store
|
||||||
filesBackend filesstore.FileBackend
|
filesBackend filesstore.FileBackend
|
||||||
telemetry *telemetry.Service
|
telemetry *telemetry.Service
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
|
cleanUpSessionsTask *scheduler.ScheduledTask
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
|
func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
|
||||||
@ -130,6 +133,11 @@ func (s *Server) Start() error {
|
|||||||
if err := s.webServer.Start(); err != nil {
|
if err := s.webServer.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
s.cleanUpSessionsTask = scheduler.CreateRecurringTask("cleanUpSessions", func() {
|
||||||
|
if err := s.store.CleanUpSessions(s.config.SessionExpireTime); err != nil {
|
||||||
|
s.logger.Error("Unable to clean up the sessions", zap.Error(err))
|
||||||
|
}
|
||||||
|
}, 10*time.Minute)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -139,6 +147,8 @@ func (s *Server) Shutdown() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.cleanUpSessionsTask.Cancel()
|
||||||
|
|
||||||
return s.store.Shutdown()
|
return s.store.Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,16 +13,18 @@ const (
|
|||||||
|
|
||||||
// Configuration is the app configuration stored in a json file.
|
// Configuration is the app configuration stored in a json file.
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
ServerRoot string `json:"serverRoot" mapstructure:"serverRoot"`
|
ServerRoot string `json:"serverRoot" mapstructure:"serverRoot"`
|
||||||
Port int `json:"port" mapstructure:"port"`
|
Port int `json:"port" mapstructure:"port"`
|
||||||
DBType string `json:"dbtype" mapstructure:"dbtype"`
|
DBType string `json:"dbtype" mapstructure:"dbtype"`
|
||||||
DBConfigString string `json:"dbconfig" mapstructure:"dbconfig"`
|
DBConfigString string `json:"dbconfig" mapstructure:"dbconfig"`
|
||||||
UseSSL bool `json:"useSSL" mapstructure:"useSSL"`
|
UseSSL bool `json:"useSSL" mapstructure:"useSSL"`
|
||||||
WebPath string `json:"webpath" mapstructure:"webpath"`
|
WebPath string `json:"webpath" mapstructure:"webpath"`
|
||||||
FilesPath string `json:"filespath" mapstructure:"filespath"`
|
FilesPath string `json:"filespath" mapstructure:"filespath"`
|
||||||
Telemetry bool `json:"telemetry" mapstructure:"telemetry"`
|
Telemetry bool `json:"telemetry" mapstructure:"telemetry"`
|
||||||
WebhookUpdate []string `json:"webhook_update" mapstructure:"webhook_update"`
|
WebhookUpdate []string `json:"webhook_update" mapstructure:"webhook_update"`
|
||||||
Secret string `json:"secret" mapstructure:"secret"`
|
Secret string `json:"secret" mapstructure:"secret"`
|
||||||
|
SessionExpireTime int64 `json:"session_expire_time" mapstructure:"session_expire_time"`
|
||||||
|
SessionRefreshTime int64 `json:"session_refresh_time" mapstructure:"session_refresh_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadConfigFile read the configuration from the filesystem.
|
// ReadConfigFile read the configuration from the filesystem.
|
||||||
@ -37,6 +39,8 @@ func ReadConfigFile() (*Configuration, error) {
|
|||||||
viper.SetDefault("WebPath", "./pack")
|
viper.SetDefault("WebPath", "./pack")
|
||||||
viper.SetDefault("FilesPath", "./files")
|
viper.SetDefault("FilesPath", "./files")
|
||||||
viper.SetDefault("WebhookUpdate", nil)
|
viper.SetDefault("WebhookUpdate", nil)
|
||||||
|
viper.SetDefault("SessionExpireTime", 60*60*24*30) // 30 days session lifetime
|
||||||
|
viper.SetDefault("SessionRefreshTime", 60*60*5) // 5 minutes session refresh
|
||||||
|
|
||||||
err := viper.ReadInConfig() // Find and read the config file
|
err := viper.ReadInConfig() // Find and read the config file
|
||||||
if err != nil { // Handle errors reading the config file
|
if err != nil { // Handle errors reading the config file
|
||||||
|
@ -8,11 +8,12 @@ import (
|
|||||||
"github.com/mattermost/mattermost-octo-tasks/server/model"
|
"github.com/mattermost/mattermost-octo-tasks/server/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SQLStore) GetSession(token string) (*model.Session, error) {
|
func (s *SQLStore) GetSession(token string, expireTime int64) (*model.Session, error) {
|
||||||
query := s.getQueryBuilder().
|
query := s.getQueryBuilder().
|
||||||
Select("id", "token", "user_id", "props").
|
Select("id", "token", "user_id", "props").
|
||||||
From("sessions").
|
From("sessions").
|
||||||
Where(sq.Eq{"token": token})
|
Where(sq.Eq{"token": token}).
|
||||||
|
Where(sq.Gt{"update_at": time.Now().Unix() - expireTime})
|
||||||
|
|
||||||
row := query.QueryRow()
|
row := query.QueryRow()
|
||||||
session := model.Session{}
|
session := model.Session{}
|
||||||
@ -80,3 +81,11 @@ func (s *SQLStore) DeleteSession(sessionId string) error {
|
|||||||
_, err := query.Exec()
|
_, err := query.Exec()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SQLStore) CleanUpSessions(expireTime int64) error {
|
||||||
|
query := s.getQueryBuilder().Delete("sessions").
|
||||||
|
Where(sq.Lt{"update_at": time.Now().Unix() - expireTime})
|
||||||
|
|
||||||
|
_, err := query.Exec()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
@ -22,9 +22,10 @@ type Store interface {
|
|||||||
GetUserByUsername(username string) (*model.User, error)
|
GetUserByUsername(username string) (*model.User, error)
|
||||||
CreateUser(user *model.User) error
|
CreateUser(user *model.User) error
|
||||||
UpdateUser(user *model.User) error
|
UpdateUser(user *model.User) error
|
||||||
GetSession(token string) (*model.Session, error)
|
GetSession(token string, expireTime int64) (*model.Session, error)
|
||||||
CreateSession(session *model.Session) error
|
CreateSession(session *model.Session) error
|
||||||
RefreshSession(session *model.Session) error
|
RefreshSession(session *model.Session) error
|
||||||
UpdateSession(session *model.Session) error
|
UpdateSession(session *model.Session) error
|
||||||
DeleteSession(sessionId string) error
|
DeleteSession(sessionId string) error
|
||||||
|
CleanUpSessions(expireTime int64) error
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user