mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 08:44:04 +01:00
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
@@ -211,6 +211,9 @@ func (c *Config) Propagate() {
|
|||||||
places.UserAgent = c.UserAgent()
|
places.UserAgent = c.UserAgent()
|
||||||
entity.GeoApi = c.GeoApi()
|
entity.GeoApi = c.GeoApi()
|
||||||
|
|
||||||
|
// Set session cache duration.
|
||||||
|
entity.SessionCacheDuration = c.SessionCacheDuration()
|
||||||
|
|
||||||
// Set minimum password length.
|
// Set minimum password length.
|
||||||
entity.PasswordLength = c.PasswordLength()
|
entity.PasswordLength = c.PasswordLength()
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
@@ -160,6 +161,24 @@ func (c *Config) SessionTimeout() int64 {
|
|||||||
return c.options.SessionTimeout
|
return c.options.SessionTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SessionCache returns the default session cache duration in seconds.
|
||||||
|
func (c *Config) SessionCache() int64 {
|
||||||
|
if c.options.SessionCache == 0 {
|
||||||
|
return DefaultSessionCache
|
||||||
|
} else if c.options.SessionCache < 60 {
|
||||||
|
return 60
|
||||||
|
} else if c.options.SessionCache > 3600 {
|
||||||
|
return 3600
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.options.SessionCache
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionCacheDuration returns the default session cache duration.
|
||||||
|
func (c *Config) SessionCacheDuration() time.Duration {
|
||||||
|
return time.Duration(c.SessionCache()) * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
// DownloadToken returns the DOWNLOAD api token (you can optionally use a static value for permanent caching).
|
// DownloadToken returns the DOWNLOAD api token (you can optionally use a static value for permanent caching).
|
||||||
func (c *Config) DownloadToken() string {
|
func (c *Config) DownloadToken() string {
|
||||||
if c.Public() {
|
if c.Public() {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ func TestLoginUri(t *testing.T) {
|
|||||||
assert.Equal(t, "/library/login", c.LoginUri())
|
assert.Equal(t, "/library/login", c.LoginUri())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSessMaxAge(t *testing.T) {
|
func TestSessionMaxAge(t *testing.T) {
|
||||||
c := NewConfig(CliTestContext())
|
c := NewConfig(CliTestContext())
|
||||||
assert.Equal(t, DefaultSessionMaxAge, c.SessionMaxAge())
|
assert.Equal(t, DefaultSessionMaxAge, c.SessionMaxAge())
|
||||||
c.options.SessionMaxAge = -1
|
c.options.SessionMaxAge = -1
|
||||||
@@ -90,7 +91,7 @@ func TestSessMaxAge(t *testing.T) {
|
|||||||
assert.Equal(t, DefaultSessionMaxAge, c.SessionMaxAge())
|
assert.Equal(t, DefaultSessionMaxAge, c.SessionMaxAge())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSessTimeout(t *testing.T) {
|
func TestSessionTimeout(t *testing.T) {
|
||||||
c := NewConfig(CliTestContext())
|
c := NewConfig(CliTestContext())
|
||||||
assert.Equal(t, DefaultSessionTimeout, c.SessionTimeout())
|
assert.Equal(t, DefaultSessionTimeout, c.SessionTimeout())
|
||||||
c.options.SessionTimeout = -1
|
c.options.SessionTimeout = -1
|
||||||
@@ -99,6 +100,18 @@ func TestSessTimeout(t *testing.T) {
|
|||||||
assert.Equal(t, DefaultSessionTimeout, c.SessionTimeout())
|
assert.Equal(t, DefaultSessionTimeout, c.SessionTimeout())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSessionCache(t *testing.T) {
|
||||||
|
c := NewConfig(CliTestContext())
|
||||||
|
assert.Equal(t, DefaultSessionCache, c.SessionCache())
|
||||||
|
c.options.SessionCache = -1
|
||||||
|
assert.Equal(t, int64(60), c.SessionCache())
|
||||||
|
c.options.SessionCache = 100000
|
||||||
|
assert.Equal(t, int64(3600), c.SessionCache())
|
||||||
|
c.options.SessionCache = 0
|
||||||
|
assert.Equal(t, DefaultSessionCache, c.SessionCache())
|
||||||
|
assert.Equal(t, time.Duration(DefaultSessionCache)*time.Second, c.SessionCacheDuration())
|
||||||
|
}
|
||||||
|
|
||||||
func TestUtils_CheckPassword(t *testing.T) {
|
func TestUtils_CheckPassword(t *testing.T) {
|
||||||
c := NewConfig(CliTestContext())
|
c := NewConfig(CliTestContext())
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/photoprism/photoprism/pkg/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiUri defines the standard path for handling REST requests.
|
// ApiUri defines the standard path for handling REST requests.
|
||||||
@@ -43,20 +45,14 @@ const DefaultResolutionLimit = 150 // 150 Megapixels
|
|||||||
// serialName defines the name of the unique storage serial.
|
// serialName defines the name of the unique storage serial.
|
||||||
const serialName = "serial"
|
const serialName = "serial"
|
||||||
|
|
||||||
// UnixHour defines one hour in UnixTime.
|
|
||||||
const UnixHour int64 = 3600
|
|
||||||
|
|
||||||
// UnixDay defines one day in UnixTime.
|
|
||||||
const UnixDay = UnixHour * 24
|
|
||||||
|
|
||||||
// UnixWeek defines one week in UnixTime.
|
|
||||||
const UnixWeek = UnixDay * 7
|
|
||||||
|
|
||||||
// DefaultSessionMaxAge defines the standard session expiration time in seconds.
|
// DefaultSessionMaxAge defines the standard session expiration time in seconds.
|
||||||
const DefaultSessionMaxAge = UnixWeek * 2
|
const DefaultSessionMaxAge = unix.Week * 2
|
||||||
|
|
||||||
// DefaultSessionTimeout defines the standard session idle time in seconds.
|
// DefaultSessionTimeout defines the standard session idle time in seconds.
|
||||||
const DefaultSessionTimeout = UnixWeek
|
const DefaultSessionTimeout = unix.Week
|
||||||
|
|
||||||
|
// DefaultSessionCache defines the default session cache duration in seconds.
|
||||||
|
const DefaultSessionCache = unix.Minute * 15
|
||||||
|
|
||||||
// Product feature tags used to automatically generate documentation.
|
// Product feature tags used to automatically generate documentation.
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -45,15 +45,21 @@ var Flags = CliFlags{
|
|||||||
Flag: cli.Int64Flag{
|
Flag: cli.Int64Flag{
|
||||||
Name: "session-maxage",
|
Name: "session-maxage",
|
||||||
Value: DefaultSessionMaxAge,
|
Value: DefaultSessionMaxAge,
|
||||||
Usage: "standard session expiration time in `SECONDS`, doubled for accounts with 2FA (-1 to disable)",
|
Usage: "session expiration time in `SECONDS`, doubled for accounts with 2FA (-1 to disable)",
|
||||||
EnvVar: EnvVar("SESSION_MAXAGE"),
|
EnvVar: EnvVar("SESSION_MAXAGE"),
|
||||||
}}, {
|
}}, {
|
||||||
Flag: cli.Int64Flag{
|
Flag: cli.Int64Flag{
|
||||||
Name: "session-timeout",
|
Name: "session-timeout",
|
||||||
Value: DefaultSessionTimeout,
|
Value: DefaultSessionTimeout,
|
||||||
Usage: "standard session idle time in `SECONDS`, doubled for accounts with 2FA (-1 to disable)",
|
Usage: "session idle time in `SECONDS`, doubled for accounts with 2FA (-1 to disable)",
|
||||||
EnvVar: EnvVar("SESSION_TIMEOUT"),
|
EnvVar: EnvVar("SESSION_TIMEOUT"),
|
||||||
}}, {
|
}}, {
|
||||||
|
Flag: cli.Int64Flag{
|
||||||
|
Name: "session-cache",
|
||||||
|
Value: DefaultSessionCache,
|
||||||
|
Usage: "session cache duration in `SECONDS` (60-3600)",
|
||||||
|
EnvVar: EnvVar("SESSION_CACHE"),
|
||||||
|
}}, {
|
||||||
Flag: cli.StringFlag{
|
Flag: cli.StringFlag{
|
||||||
Name: "log-level, l",
|
Name: "log-level, l",
|
||||||
Usage: "log message verbosity `LEVEL` (trace, debug, info, warning, error, fatal, panic)",
|
Usage: "log message verbosity `LEVEL` (trace, debug, info, warning, error, fatal, panic)",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Options struct {
|
|||||||
LoginUri string `yaml:"LoginUri" json:"-" flag:"login-uri"`
|
LoginUri string `yaml:"LoginUri" json:"-" flag:"login-uri"`
|
||||||
SessionMaxAge int64 `yaml:"SessionMaxAge" json:"-" flag:"session-maxage"`
|
SessionMaxAge int64 `yaml:"SessionMaxAge" json:"-" flag:"session-maxage"`
|
||||||
SessionTimeout int64 `yaml:"SessionTimeout" json:"-" flag:"session-timeout"`
|
SessionTimeout int64 `yaml:"SessionTimeout" json:"-" flag:"session-timeout"`
|
||||||
|
SessionCache int64 `yaml:"SessionCache" json:"-" flag:"session-cache"`
|
||||||
LogLevel string `yaml:"LogLevel" json:"-" flag:"log-level"`
|
LogLevel string `yaml:"LogLevel" json:"-" flag:"log-level"`
|
||||||
Prod bool `yaml:"Prod" json:"Prod" flag:"prod"`
|
Prod bool `yaml:"Prod" json:"Prod" flag:"prod"`
|
||||||
Debug bool `yaml:"Debug" json:"Debug" flag:"debug"`
|
Debug bool `yaml:"Debug" json:"Debug" flag:"debug"`
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ func (c *Config) Report() (rows [][]string, cols []string) {
|
|||||||
{"login-uri", c.LoginUri()},
|
{"login-uri", c.LoginUri()},
|
||||||
{"session-maxage", fmt.Sprintf("%d", c.SessionMaxAge())},
|
{"session-maxage", fmt.Sprintf("%d", c.SessionMaxAge())},
|
||||||
{"session-timeout", fmt.Sprintf("%d", c.SessionTimeout())},
|
{"session-timeout", fmt.Sprintf("%d", c.SessionTimeout())},
|
||||||
|
{"session-cache", fmt.Sprintf("%d", c.SessionCache())},
|
||||||
|
|
||||||
// Logging.
|
// Logging.
|
||||||
{"log-level", c.LogLevel().String()},
|
{"log-level", c.LogLevel().String()},
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ func (m *Session) CacheDuration(d time.Duration) {
|
|||||||
|
|
||||||
// Cache caches the session with the default expiration duration.
|
// Cache caches the session with the default expiration duration.
|
||||||
func (m *Session) Cache() {
|
func (m *Session) Cache() {
|
||||||
m.CacheDuration(sessionCacheExpiration)
|
m.CacheDuration(SessionCacheDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearCache deletes the session from the cache.
|
// ClearCache deletes the session from the cache.
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import (
|
|||||||
"github.com/photoprism/photoprism/pkg/rnd"
|
"github.com/photoprism/photoprism/pkg/rnd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a new session cache with an expiration time of 15 minutes.
|
// SessionCacheDuration specifies how long sessions are cached.
|
||||||
var sessionCacheExpiration = 15 * time.Minute
|
var SessionCacheDuration = 15 * time.Minute
|
||||||
var sessionCache = gc.New(sessionCacheExpiration, 5*time.Minute)
|
var sessionCache = gc.New(SessionCacheDuration, time.Minute)
|
||||||
|
|
||||||
// FindSessionByAuthToken finds a session based on the auth token string or returns nil if it does not exist.
|
// FindSessionByAuthToken finds a session based on the auth token string or returns nil if it does not exist.
|
||||||
func FindSessionByAuthToken(token string) (*Session, error) {
|
func FindSessionByAuthToken(token string) (*Session, error) {
|
||||||
@@ -46,7 +46,7 @@ func FindSession(id string) (*Session, error) {
|
|||||||
} else if !found.Expired() {
|
} else if !found.Expired() {
|
||||||
// Set session activity timestamp and update the last_active column in the sessions table.
|
// Set session activity timestamp and update the last_active column in the sessions table.
|
||||||
found.UpdateLastActive(true)
|
found.UpdateLastActive(true)
|
||||||
CacheSession(found, sessionCacheExpiration)
|
CacheSession(found, SessionCacheDuration)
|
||||||
return found, nil
|
return found, nil
|
||||||
} else if err := found.Delete(); err != nil {
|
} else if err := found.Delete(); err != nil {
|
||||||
event.AuditErr([]string{found.IP(), "session %s", "failed to delete after expiration", "%s"}, found.RefID, err)
|
event.AuditErr([]string{found.IP(), "session %s", "failed to delete after expiration", "%s"}, found.RefID, err)
|
||||||
@@ -69,7 +69,7 @@ func CacheSession(s *Session, d time.Duration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if d == 0 {
|
if d == 0 {
|
||||||
d = sessionCacheExpiration
|
d = SessionCacheDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.PreviewToken != "" {
|
if s.PreviewToken != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user