2019-05-06 23:18:10 +02:00
|
|
|
package config
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
import (
|
2019-06-03 22:58:15 +02:00
|
|
|
"context"
|
2020-01-02 00:03:07 +01:00
|
|
|
"runtime"
|
2020-01-31 15:29:06 +01:00
|
|
|
"sync"
|
2019-05-03 18:57:28 +02:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/jinzhu/gorm"
|
|
|
|
_ "github.com/jinzhu/gorm/dialects/mysql"
|
|
|
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
2019-12-02 00:30:58 +01:00
|
|
|
gc "github.com/patrickmn/go-cache"
|
|
|
|
"github.com/photoprism/photoprism/internal/event"
|
2020-01-19 12:50:44 +01:00
|
|
|
"github.com/photoprism/photoprism/internal/mutex"
|
2020-01-06 14:32:15 +01:00
|
|
|
"github.com/photoprism/photoprism/internal/thumb"
|
2019-12-02 00:30:58 +01:00
|
|
|
"github.com/sirupsen/logrus"
|
2019-05-03 18:57:28 +02:00
|
|
|
"github.com/urfave/cli"
|
|
|
|
)
|
|
|
|
|
2019-12-02 00:30:58 +01:00
|
|
|
var log = event.Log
|
2020-04-13 18:08:21 +02:00
|
|
|
var once sync.Once
|
2019-12-02 00:30:58 +01:00
|
|
|
|
2020-02-21 01:14:45 +01:00
|
|
|
// Config holds database, cache and all parameters of photoprism
|
2019-05-06 23:18:10 +02:00
|
|
|
type Config struct {
|
2020-04-13 18:08:21 +02:00
|
|
|
once sync.Once
|
|
|
|
db *gorm.DB
|
|
|
|
cache *gc.Cache
|
|
|
|
params *Params
|
|
|
|
settings *Settings
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
2020-01-06 14:32:15 +01:00
|
|
|
func init() {
|
2020-02-21 01:14:45 +01:00
|
|
|
// initialize the Thumbnails global variable
|
2020-01-06 14:32:15 +01:00
|
|
|
for name, t := range thumb.Types {
|
|
|
|
if t.Public {
|
|
|
|
thumbnail := Thumbnail{Name: name, Width: t.Width, Height: t.Height}
|
|
|
|
Thumbnails = append(Thumbnails, thumbnail)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-04 09:11:33 +02:00
|
|
|
func initLogger(debug bool) {
|
2020-01-31 15:29:06 +01:00
|
|
|
once.Do(func() {
|
|
|
|
log.SetFormatter(&logrus.TextFormatter{
|
|
|
|
DisableColors: false,
|
|
|
|
FullTimestamp: true,
|
|
|
|
})
|
|
|
|
|
|
|
|
if debug {
|
|
|
|
log.SetLevel(logrus.DebugLevel)
|
|
|
|
} else {
|
|
|
|
log.SetLevel(logrus.InfoLevel)
|
|
|
|
}
|
2019-05-03 18:57:28 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-02-21 01:14:45 +01:00
|
|
|
// NewConfig initialises a new configuration file
|
2019-05-06 23:18:10 +02:00
|
|
|
func NewConfig(ctx *cli.Context) *Config {
|
2019-05-04 05:25:00 +02:00
|
|
|
initLogger(ctx.GlobalBool("debug"))
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2019-05-14 16:04:17 +02:00
|
|
|
c := &Config{
|
2020-04-13 18:08:21 +02:00
|
|
|
params: NewParams(ctx),
|
2019-05-14 16:04:17 +02:00
|
|
|
}
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
c.initSettings()
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
// Propagate updates config values in other packages as needed.
|
|
|
|
func (c *Config) Propagate() {
|
2019-05-03 18:57:28 +02:00
|
|
|
log.SetLevel(c.LogLevel())
|
|
|
|
|
2020-05-05 17:04:13 +02:00
|
|
|
thumb.Size = c.ThumbSize()
|
|
|
|
thumb.Limit = c.ThumbLimit()
|
2020-05-05 17:17:19 +02:00
|
|
|
thumb.Filter = c.ThumbFilter()
|
2020-05-05 15:42:54 +02:00
|
|
|
thumb.JpegQuality = c.JpegQuality()
|
2020-01-06 14:32:15 +01:00
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
c.Settings().Propagate()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init initialises the database connection and dependencies.
|
|
|
|
func (c *Config) Init(ctx context.Context) error {
|
|
|
|
c.Propagate()
|
|
|
|
return c.connectToDatabase(ctx)
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Name returns the application name.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) Name() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Name
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
2019-12-11 14:10:20 +01:00
|
|
|
// Url returns the public server URL (default is "http://localhost:2342/").
|
|
|
|
func (c *Config) Url() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.Url == "" {
|
2019-12-11 14:10:20 +01:00
|
|
|
return "http://localhost:2342/"
|
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Url
|
2019-12-11 14:10:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Title returns the site title (default is application name).
|
|
|
|
func (c *Config) Title() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.Title == "" {
|
2019-12-11 14:10:20 +01:00
|
|
|
return c.Name()
|
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Title
|
2019-12-11 14:10:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Subtitle returns the site title.
|
|
|
|
func (c *Config) Subtitle() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Subtitle
|
2019-12-11 14:10:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Description returns the site title.
|
|
|
|
func (c *Config) Description() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Description
|
2019-12-11 14:10:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Author returns the site author / copyright.
|
|
|
|
func (c *Config) Author() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Author
|
2019-12-11 14:10:20 +01:00
|
|
|
}
|
|
|
|
|
2019-05-03 18:57:28 +02:00
|
|
|
// Version returns the application version.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) Version() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Version
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Copyright returns the application copyright.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) Copyright() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Copyright
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Debug returns true if Debug mode is on.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) Debug() bool {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Debug
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
2019-11-11 21:10:41 +01:00
|
|
|
// Public returns true if app requires no authentication.
|
|
|
|
func (c *Config) Public() bool {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Public
|
2019-11-11 21:10:41 +01:00
|
|
|
}
|
|
|
|
|
2019-12-30 12:38:11 +01:00
|
|
|
// Experimental returns true if experimental features should be enabled.
|
|
|
|
func (c *Config) Experimental() bool {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.Experimental
|
2019-12-30 12:38:11 +01:00
|
|
|
}
|
|
|
|
|
2019-05-04 09:11:33 +02:00
|
|
|
// ReadOnly returns true if photo directories are write protected.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) ReadOnly() bool {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.ReadOnly
|
2019-05-04 09:11:33 +02:00
|
|
|
}
|
|
|
|
|
2020-01-13 16:48:32 +01:00
|
|
|
// DetectNSFW returns true if NSFW photos should be detected and flagged.
|
|
|
|
func (c *Config) DetectNSFW() bool {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.DetectNSFW
|
2019-12-15 17:19:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// UploadNSFW returns true if NSFW photos can be uploaded.
|
|
|
|
func (c *Config) UploadNSFW() bool {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.UploadNSFW
|
2019-12-15 17:19:16 +01:00
|
|
|
}
|
|
|
|
|
2019-11-08 06:53:40 +01:00
|
|
|
// AdminPassword returns the admin password.
|
|
|
|
func (c *Config) AdminPassword() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.AdminPassword == "" {
|
2019-11-08 06:53:40 +01:00
|
|
|
return "photoprism"
|
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.AdminPassword
|
2019-11-08 06:53:40 +01:00
|
|
|
}
|
|
|
|
|
2020-02-21 04:23:16 +01:00
|
|
|
// WebDAVPassword returns the WebDAV password for remote access.
|
|
|
|
func (c *Config) WebDAVPassword() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
return c.params.WebDAVPassword
|
2020-02-21 04:23:16 +01:00
|
|
|
}
|
|
|
|
|
2019-05-03 18:57:28 +02:00
|
|
|
// LogLevel returns the logrus log level.
|
2019-12-02 00:30:58 +01:00
|
|
|
func (c *Config) LogLevel() logrus.Level {
|
2019-05-03 18:57:28 +02:00
|
|
|
if c.Debug() {
|
2020-04-13 18:08:21 +02:00
|
|
|
c.params.LogLevel = "debug"
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
if logLevel, err := logrus.ParseLevel(c.params.LogLevel); err == nil {
|
2019-05-03 18:57:28 +02:00
|
|
|
return logLevel
|
|
|
|
} else {
|
2019-12-02 00:30:58 +01:00
|
|
|
return logrus.InfoLevel
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-08 06:53:40 +01:00
|
|
|
// Cache returns the in-memory cache.
|
|
|
|
func (c *Config) Cache() *gc.Cache {
|
|
|
|
if c.cache == nil {
|
|
|
|
c.cache = gc.New(336*time.Hour, 30*time.Minute)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.cache
|
|
|
|
}
|
|
|
|
|
2020-01-19 12:50:44 +01:00
|
|
|
// Shutdown services and workers.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) Shutdown() {
|
2020-05-26 15:15:14 +02:00
|
|
|
mutex.MainWorker.Cancel()
|
|
|
|
mutex.ShareWorker.Cancel()
|
|
|
|
mutex.SyncWorker.Cancel()
|
2020-05-26 19:27:29 +02:00
|
|
|
mutex.PrismWorker.Cancel()
|
2020-01-19 12:50:44 +01:00
|
|
|
|
2019-05-04 17:34:51 +02:00
|
|
|
if err := c.CloseDb(); err != nil {
|
|
|
|
log.Errorf("could not close database connection: %s", err)
|
|
|
|
} else {
|
|
|
|
log.Info("closed database connection")
|
|
|
|
}
|
|
|
|
}
|
2019-11-12 04:34:37 +01:00
|
|
|
|
2020-01-02 00:03:07 +01:00
|
|
|
// Workers returns the number of workers e.g. for indexing files.
|
2020-01-02 04:08:33 +01:00
|
|
|
func (c *Config) Workers() int {
|
2020-03-09 00:51:10 +01:00
|
|
|
numCPU := runtime.NumCPU()
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.Workers > 0 && c.params.Workers <= numCPU {
|
|
|
|
return c.params.Workers
|
2020-01-06 23:43:19 +01:00
|
|
|
}
|
|
|
|
|
2020-03-09 00:51:10 +01:00
|
|
|
if numCPU > 1 {
|
|
|
|
return numCPU - 1
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1
|
2019-11-12 04:34:37 +01:00
|
|
|
}
|
2020-01-06 06:59:35 +01:00
|
|
|
|
2020-04-06 22:09:45 +02:00
|
|
|
// WakeupInterval returns the background worker wakeup interval.
|
|
|
|
func (c *Config) WakeupInterval() time.Duration {
|
2020-04-13 18:08:21 +02:00
|
|
|
if c.params.WakeupInterval <= 0 {
|
2020-04-06 22:09:45 +02:00
|
|
|
return 5 * time.Minute
|
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
return time.Duration(c.params.WakeupInterval) * time.Second
|
2020-04-06 22:09:45 +02:00
|
|
|
}
|
|
|
|
|
2020-01-06 06:59:35 +01:00
|
|
|
// GeoCodingApi returns the preferred geo coding api (none, osm or places).
|
|
|
|
func (c *Config) GeoCodingApi() string {
|
2020-04-13 18:08:21 +02:00
|
|
|
switch c.params.GeoCodingApi {
|
2020-01-06 06:59:35 +01:00
|
|
|
case "places":
|
|
|
|
return "places"
|
|
|
|
case "osm":
|
|
|
|
return "osm"
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
2020-05-25 19:10:44 +02:00
|
|
|
|
|
|
|
// OriginalsLimit returns the file size limit for originals.
|
|
|
|
func (c *Config) OriginalsLimit() int64 {
|
|
|
|
if c.params.OriginalsLimit <= 0 || c.params.OriginalsLimit > 100000 {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
// Megabyte.
|
|
|
|
return c.params.OriginalsLimit * 1024 * 1024
|
|
|
|
}
|