Add common feature flags incl upload #284
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
829cd9a36a
commit
c2fa3a7246
|
@ -3,3 +3,12 @@ language: en
|
|||
maps:
|
||||
animate: 0
|
||||
style: streets
|
||||
features:
|
||||
upload: true
|
||||
import: true
|
||||
labels: true
|
||||
places: true
|
||||
archive: true
|
||||
download: true
|
||||
edit: true
|
||||
share: true
|
||||
|
|
|
@ -73,9 +73,9 @@ class Config {
|
|||
this.values.count;
|
||||
}
|
||||
|
||||
updateSettings(values, $vuetify) {
|
||||
this.setValue("settings", values);
|
||||
this.setTheme(values.theme);
|
||||
updateSettings(settings, $vuetify) {
|
||||
this.setValue("settings", settings);
|
||||
this.setTheme(settings.theme);
|
||||
$vuetify.theme = this.theme;
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,10 @@ class Config {
|
|||
|
||||
return this;
|
||||
}
|
||||
|
||||
feature(name) {
|
||||
return this.values.settings.features[name];
|
||||
}
|
||||
}
|
||||
|
||||
export default Config;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
color="download"
|
||||
@click.stop="download()"
|
||||
class="p-album-clipboard-download"
|
||||
v-if="$config.feature('download')"
|
||||
:disabled="selection.length !== 1"
|
||||
>
|
||||
<v-icon>cloud_download</v-icon>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<v-spacer></v-spacer>
|
||||
|
||||
<v-toolbar-items>
|
||||
<v-btn icon @click.stop="showUpload = true" v-if="!readonly">
|
||||
<v-btn icon @click.stop="showUpload = true" v-if="!readonly && $config.feature('upload')">
|
||||
<v-icon>cloud_upload</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar-items>
|
||||
|
@ -87,7 +87,7 @@
|
|||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
|
||||
<v-list-tile to="/archive" @click="" class="p-navigation-archive">
|
||||
<v-list-tile to="/archive" @click="" class="p-navigation-archive" v-if="$config.feature('archive')">
|
||||
<v-list-tile-content>
|
||||
<v-list-tile-title>
|
||||
<translate>Archive</translate>
|
||||
|
@ -109,7 +109,7 @@
|
|||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
|
||||
<v-list-tile v-if="mini" to="/archive" @click="" class="p-navigation-archive">
|
||||
<v-list-tile v-if="mini && $config.feature('archive')" to="/archive" @click="" class="p-navigation-archive">
|
||||
<v-list-tile-action>
|
||||
<v-icon>archive</v-icon>
|
||||
</v-list-tile-action>
|
||||
|
@ -153,7 +153,7 @@
|
|||
</v-list-tile>
|
||||
</v-list-group>
|
||||
|
||||
<v-list-tile to="/labels" @click="" class="p-navigation-labels">
|
||||
<v-list-tile to="/labels" @click="" class="p-navigation-labels" v-if="$config.feature('labels')">
|
||||
<v-list-tile-action>
|
||||
<v-icon>label</v-icon>
|
||||
</v-list-tile-action>
|
||||
|
@ -167,7 +167,7 @@
|
|||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
|
||||
<v-list-tile :to="{ name: 'places' }" @click="" class="p-navigation-places">
|
||||
<v-list-tile :to="{ name: 'places' }" @click="" class="p-navigation-places" v-if="$config.feature('places')">
|
||||
<v-list-tile-action>
|
||||
<v-icon>place</v-icon>
|
||||
</v-list-tile-action>
|
||||
|
@ -300,6 +300,9 @@
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
feature(name) {
|
||||
return this.$config.values.settings.features[name];
|
||||
},
|
||||
openDocs() {
|
||||
window.open("https://docs.photoprism.org/", "_blank");
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
color="share"
|
||||
@click.stop="dialog.share = true"
|
||||
:disabled="selection.length === 0"
|
||||
v-if="context !== 'archive'"
|
||||
v-if="context !== 'archive' && $config.feature('share')"
|
||||
class="p-photo-clipboard-share"
|
||||
>
|
||||
<v-icon>share</v-icon>
|
||||
|
@ -43,7 +43,7 @@
|
|||
color="edit"
|
||||
:disabled="selection.length === 0"
|
||||
@click.stop="dialog.edit = true"
|
||||
v-if="context !== 'archive'"
|
||||
v-if="context !== 'archive' && $config.feature('edit')"
|
||||
class="p-photo-clipboard-edit"
|
||||
>
|
||||
<v-icon>edit</v-icon>
|
||||
|
@ -55,7 +55,7 @@
|
|||
:title="labels.download"
|
||||
color="download"
|
||||
@click.stop="download()"
|
||||
v-if="context !== 'archive'"
|
||||
v-if="context !== 'archive' && $config.feature('download')"
|
||||
class="p-photo-clipboard-download"
|
||||
>
|
||||
<v-icon>cloud_download</v-icon>
|
||||
|
@ -82,7 +82,7 @@
|
|||
:title="labels.archive"
|
||||
@click.stop="dialog.archive = true"
|
||||
:disabled="selection.length === 0"
|
||||
v-if="!album && context !== 'archive'"
|
||||
v-if="!album && context !== 'archive' && $config.feature('archive')"
|
||||
class="p-photo-clipboard-archive"
|
||||
>
|
||||
<v-icon>archive</v-icon>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<v-icon>view_column</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn icon @click.stop="showUpload()" v-if="!this.$config.values.readonly" class="hidden-md-and-down">
|
||||
<v-btn icon @click.stop="showUpload()" v-if="!$config.values.readonly && $config.feature('upload')" class="hidden-md-and-down">
|
||||
<v-icon>cloud_upload</v-icon>
|
||||
</v-btn>
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<translate>Originals</translate>
|
||||
</v-tab>
|
||||
|
||||
<v-tab id="tab-import" :disabled="readonly" ripple @click="changePath('/library/import')">
|
||||
<v-tab id="tab-import" :disabled="readonly || !$config.feature('import')" ripple @click="changePath('/library/import')">
|
||||
<translate>Import</translate>
|
||||
</v-tab>
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<translate>Cancel</translate>
|
||||
</v-btn>
|
||||
|
||||
<v-btn v-if="!this.$config.values.readonly"
|
||||
<v-btn v-if="!$config.values.readonly && $config.feature('upload')"
|
||||
:disabled="busy"
|
||||
color="secondary-dark"
|
||||
class="white--text ml-0 mt-2 hidden-xs-only"
|
||||
|
|
|
@ -3,6 +3,128 @@
|
|||
<v-form lazy-validation dense
|
||||
ref="form" class="p-form-settings" accept-charset="UTF-8"
|
||||
@submit.prevent="save">
|
||||
<v-card flat tile class="mt-0 px-1 application">
|
||||
<v-card-title primary-title class="pb-0">
|
||||
<h3 class="body-2 mb-0">Features</h3>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-actions>
|
||||
<v-layout wrap align-center>
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.places"
|
||||
color="secondary-dark"
|
||||
label="Places"
|
||||
hint="Search and display photos on a map."
|
||||
prepend-icon="place"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.labels"
|
||||
color="secondary-dark"
|
||||
label="Labels"
|
||||
hint="Browse and edit image classification labels."
|
||||
prepend-icon="label"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.import"
|
||||
color="secondary-dark"
|
||||
label="Import"
|
||||
hint="Imported files will be sorted by date and given a unique name."
|
||||
prepend-icon="create_new_folder"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.archive"
|
||||
color="secondary-dark"
|
||||
label="Archive"
|
||||
hint="Hide photos that have been moved to archive."
|
||||
prepend-icon="archive"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.upload"
|
||||
color="secondary-dark"
|
||||
label="Upload"
|
||||
hint="Add files to your library via Web Upload."
|
||||
prepend-icon="cloud_upload"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.download"
|
||||
color="secondary-dark"
|
||||
label="Download"
|
||||
hint="Download single files and zip archives."
|
||||
prepend-icon="cloud_download"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.edit"
|
||||
color="secondary-dark"
|
||||
label="Edit"
|
||||
hint="Change photo titles, locations and other metadata."
|
||||
prepend-icon="edit"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
|
||||
<v-checkbox
|
||||
@change="save"
|
||||
class="ma-0 pa-0"
|
||||
v-model="settings.features.share"
|
||||
color="secondary-dark"
|
||||
label="Share"
|
||||
hint="Upload to WebDAV and other remote services."
|
||||
prepend-icon="share"
|
||||
persistent-hint
|
||||
>
|
||||
</v-checkbox>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
<v-card flat tile class="px-1 application">
|
||||
<v-card-title primary-title class="pb-2">
|
||||
<h3 class="body-2 mb-0">User Interface</h3>
|
||||
|
@ -12,6 +134,7 @@
|
|||
<v-layout wrap align-center>
|
||||
<v-flex xs12 sm6 class="px-2 pb-2">
|
||||
<v-select
|
||||
@change="save"
|
||||
:items="options.themes"
|
||||
:label="labels.theme"
|
||||
color="secondary-dark"
|
||||
|
@ -23,6 +146,7 @@
|
|||
|
||||
<v-flex xs12 sm6 class="px-2 pb-2">
|
||||
<v-select
|
||||
@change="save"
|
||||
:items="options.languages"
|
||||
:label="labels.language"
|
||||
color="secondary-dark"
|
||||
|
@ -35,7 +159,7 @@
|
|||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
<v-card flat tile class="mt-0 px-1 application">
|
||||
<v-card flat tile class="mt-0 px-1 application" v-if="settings.features.places">
|
||||
<v-card-title primary-title class="pb-2">
|
||||
<h3 class="body-2 mb-0">Places</h3>
|
||||
</v-card-title>
|
||||
|
@ -44,6 +168,7 @@
|
|||
<v-layout wrap align-center>
|
||||
<v-flex xs12 sm6 class="px-2 pb-2">
|
||||
<v-select
|
||||
@change="save"
|
||||
:items="options.mapsStyle"
|
||||
:label="labels.mapsStyle"
|
||||
color="secondary-dark"
|
||||
|
@ -55,6 +180,7 @@
|
|||
|
||||
<v-flex xs12 sm6 class="px-2 pb-2">
|
||||
<v-select
|
||||
@change="save"
|
||||
:items="options.mapsAnimate"
|
||||
:label="labels.mapsAnimate"
|
||||
color="secondary-dark"
|
||||
|
@ -67,7 +193,9 @@
|
|||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
<v-container fluid class="mt-1">
|
||||
|
||||
|
||||
<!-- v-container fluid class="mt-1">
|
||||
<v-btn color="secondary-dark"
|
||||
class="ml-1"
|
||||
depressed dark
|
||||
|
@ -75,7 +203,7 @@
|
|||
<translate>Save</translate>
|
||||
<v-icon right dark>save</v-icon>
|
||||
</v-btn>
|
||||
</v-container>
|
||||
</v-container -->
|
||||
</v-form>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
// POST /api/v1/import*
|
||||
func StartImport(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.POST("/import/*path", func(c *gin.Context) {
|
||||
if conf.ReadOnly() {
|
||||
if conf.ReadOnly() || !conf.Settings().Features.Import {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, ErrReadOnly)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
// POST /api/v1/upload/:path
|
||||
func Upload(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.POST("/upload/:path", func(c *gin.Context) {
|
||||
if conf.ReadOnly() {
|
||||
if conf.ReadOnly() || !conf.Settings().Features.Upload {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, ErrReadOnly)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ func startAction(ctx *cli.Context) error {
|
|||
if err := conf.Init(cctx); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// initialize the database
|
||||
conf.MigrateDb()
|
||||
|
||||
|
|
|
@ -11,19 +11,19 @@ func TestUtils_CheckPassword(t *testing.T) {
|
|||
c := NewConfig(ctx)
|
||||
formPassword := "photoprism"
|
||||
|
||||
c.config.AdminPassword = "$2b$10$cRhWIleqJkbaFWhBMp54VOI25RvVubxOooCWzWgdrvl5COFxaBnAy"
|
||||
c.params.AdminPassword = "$2b$10$cRhWIleqJkbaFWhBMp54VOI25RvVubxOooCWzWgdrvl5COFxaBnAy"
|
||||
check := c.CheckPassword(formPassword)
|
||||
assert.True(t, check)
|
||||
|
||||
c.config.AdminPassword = "photoprism"
|
||||
c.params.AdminPassword = "photoprism"
|
||||
check = c.CheckPassword(formPassword)
|
||||
assert.True(t, check)
|
||||
|
||||
c.config.AdminPassword = "$2b$10$yprZEQzm/Qy7AaePXtKfkem0kANBZgRwl8HbLE4JrjK6/8Pypgi1W"
|
||||
c.params.AdminPassword = "$2b$10$yprZEQzm/Qy7AaePXtKfkem0kANBZgRwl8HbLE4JrjK6/8Pypgi1W"
|
||||
check = c.CheckPassword(formPassword)
|
||||
assert.False(t, check)
|
||||
|
||||
c.config.AdminPassword = "admin"
|
||||
c.params.AdminPassword = "admin"
|
||||
check = c.CheckPassword(formPassword)
|
||||
assert.False(t, check)
|
||||
}
|
||||
|
|
|
@ -19,12 +19,15 @@ import (
|
|||
)
|
||||
|
||||
var log = event.Log
|
||||
var once sync.Once
|
||||
|
||||
// Config holds database, cache and all parameters of photoprism
|
||||
type Config struct {
|
||||
once sync.Once
|
||||
db *gorm.DB
|
||||
cache *gc.Cache
|
||||
config *Params
|
||||
params *Params
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -38,8 +41,6 @@ func init() {
|
|||
}
|
||||
|
||||
func initLogger(debug bool) {
|
||||
var once sync.Once
|
||||
|
||||
once.Do(func() {
|
||||
log.SetFormatter(&logrus.TextFormatter{
|
||||
DisableColors: false,
|
||||
|
@ -59,9 +60,16 @@ func NewConfig(ctx *cli.Context) *Config {
|
|||
initLogger(ctx.GlobalBool("debug"))
|
||||
|
||||
c := &Config{
|
||||
config: NewParams(ctx),
|
||||
params: NewParams(ctx),
|
||||
}
|
||||
|
||||
c.initSettings()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Propagate updates config values in other packages as needed.
|
||||
func (c *Config) Propagate() {
|
||||
log.SetLevel(c.LogLevel())
|
||||
|
||||
thumb.JpegQuality = c.ThumbQuality()
|
||||
|
@ -69,113 +77,119 @@ func NewConfig(ctx *cli.Context) *Config {
|
|||
thumb.MaxRenderSize = c.ThumbLimit()
|
||||
thumb.Filter = c.ThumbFilter()
|
||||
|
||||
return c
|
||||
c.Settings().Propagate()
|
||||
}
|
||||
|
||||
// Init initialises the database connection and dependencies.
|
||||
func (c *Config) Init(ctx context.Context) error {
|
||||
c.Propagate()
|
||||
return c.connectToDatabase(ctx)
|
||||
}
|
||||
|
||||
// Name returns the application name.
|
||||
func (c *Config) Name() string {
|
||||
return c.config.Name
|
||||
return c.params.Name
|
||||
}
|
||||
|
||||
// Url returns the public server URL (default is "http://localhost:2342/").
|
||||
func (c *Config) Url() string {
|
||||
if c.config.Url == "" {
|
||||
if c.params.Url == "" {
|
||||
return "http://localhost:2342/"
|
||||
}
|
||||
|
||||
return c.config.Url
|
||||
return c.params.Url
|
||||
}
|
||||
|
||||
// Title returns the site title (default is application name).
|
||||
func (c *Config) Title() string {
|
||||
if c.config.Title == "" {
|
||||
if c.params.Title == "" {
|
||||
return c.Name()
|
||||
}
|
||||
|
||||
return c.config.Title
|
||||
return c.params.Title
|
||||
}
|
||||
|
||||
// Subtitle returns the site title.
|
||||
func (c *Config) Subtitle() string {
|
||||
return c.config.Subtitle
|
||||
return c.params.Subtitle
|
||||
}
|
||||
|
||||
// Description returns the site title.
|
||||
func (c *Config) Description() string {
|
||||
return c.config.Description
|
||||
return c.params.Description
|
||||
}
|
||||
|
||||
// Author returns the site author / copyright.
|
||||
func (c *Config) Author() string {
|
||||
return c.config.Author
|
||||
return c.params.Author
|
||||
}
|
||||
|
||||
// Twitter returns the twitter handle for sharing.
|
||||
func (c *Config) Twitter() string {
|
||||
return c.config.Twitter
|
||||
return c.params.Twitter
|
||||
}
|
||||
|
||||
// Version returns the application version.
|
||||
func (c *Config) Version() string {
|
||||
return c.config.Version
|
||||
return c.params.Version
|
||||
}
|
||||
|
||||
// Copyright returns the application copyright.
|
||||
func (c *Config) Copyright() string {
|
||||
return c.config.Copyright
|
||||
return c.params.Copyright
|
||||
}
|
||||
|
||||
// Debug returns true if Debug mode is on.
|
||||
func (c *Config) Debug() bool {
|
||||
return c.config.Debug
|
||||
return c.params.Debug
|
||||
}
|
||||
|
||||
// Public returns true if app requires no authentication.
|
||||
func (c *Config) Public() bool {
|
||||
return c.config.Public
|
||||
return c.params.Public
|
||||
}
|
||||
|
||||
// Experimental returns true if experimental features should be enabled.
|
||||
func (c *Config) Experimental() bool {
|
||||
return c.config.Experimental
|
||||
return c.params.Experimental
|
||||
}
|
||||
|
||||
// ReadOnly returns true if photo directories are write protected.
|
||||
func (c *Config) ReadOnly() bool {
|
||||
return c.config.ReadOnly
|
||||
return c.params.ReadOnly
|
||||
}
|
||||
|
||||
// DetectNSFW returns true if NSFW photos should be detected and flagged.
|
||||
func (c *Config) DetectNSFW() bool {
|
||||
return c.config.DetectNSFW
|
||||
return c.params.DetectNSFW
|
||||
}
|
||||
|
||||
// UploadNSFW returns true if NSFW photos can be uploaded.
|
||||
func (c *Config) UploadNSFW() bool {
|
||||
return c.config.UploadNSFW
|
||||
return c.params.UploadNSFW
|
||||
}
|
||||
|
||||
// AdminPassword returns the admin password.
|
||||
func (c *Config) AdminPassword() string {
|
||||
if c.config.AdminPassword == "" {
|
||||
if c.params.AdminPassword == "" {
|
||||
return "photoprism"
|
||||
}
|
||||
|
||||
return c.config.AdminPassword
|
||||
return c.params.AdminPassword
|
||||
}
|
||||
|
||||
// WebDAVPassword returns the WebDAV password for remote access.
|
||||
func (c *Config) WebDAVPassword() string {
|
||||
return c.config.WebDAVPassword
|
||||
return c.params.WebDAVPassword
|
||||
}
|
||||
|
||||
// LogLevel returns the logrus log level.
|
||||
func (c *Config) LogLevel() logrus.Level {
|
||||
if c.Debug() {
|
||||
c.config.LogLevel = "debug"
|
||||
c.params.LogLevel = "debug"
|
||||
}
|
||||
|
||||
if logLevel, err := logrus.ParseLevel(c.config.LogLevel); err == nil {
|
||||
if logLevel, err := logrus.ParseLevel(c.params.LogLevel); err == nil {
|
||||
return logLevel
|
||||
} else {
|
||||
return logrus.InfoLevel
|
||||
|
@ -191,11 +205,6 @@ func (c *Config) Cache() *gc.Cache {
|
|||
return c.cache
|
||||
}
|
||||
|
||||
// Init initialises the Database.
|
||||
func (c *Config) Init(ctx context.Context) error {
|
||||
return c.connectToDatabase(ctx)
|
||||
}
|
||||
|
||||
// Shutdown services and workers.
|
||||
func (c *Config) Shutdown() {
|
||||
mutex.Worker.Cancel()
|
||||
|
@ -213,8 +222,8 @@ func (c *Config) Shutdown() {
|
|||
func (c *Config) Workers() int {
|
||||
numCPU := runtime.NumCPU()
|
||||
|
||||
if c.config.Workers > 0 && c.config.Workers <= numCPU {
|
||||
return c.config.Workers
|
||||
if c.params.Workers > 0 && c.params.Workers <= numCPU {
|
||||
return c.params.Workers
|
||||
}
|
||||
|
||||
if numCPU > 1 {
|
||||
|
@ -226,55 +235,55 @@ func (c *Config) Workers() int {
|
|||
|
||||
// WakeupInterval returns the background worker wakeup interval.
|
||||
func (c *Config) WakeupInterval() time.Duration {
|
||||
if c.config.WakeupInterval <= 0 {
|
||||
if c.params.WakeupInterval <= 0 {
|
||||
return 5 * time.Minute
|
||||
}
|
||||
|
||||
return time.Duration(c.config.WakeupInterval) * time.Second
|
||||
return time.Duration(c.params.WakeupInterval) * time.Second
|
||||
}
|
||||
|
||||
// ThumbQuality returns the thumbnail jpeg quality setting (25-100).
|
||||
func (c *Config) ThumbQuality() int {
|
||||
if c.config.ThumbQuality > 100 {
|
||||
if c.params.ThumbQuality > 100 {
|
||||
return 100
|
||||
}
|
||||
|
||||
if c.config.ThumbQuality < 25 {
|
||||
if c.params.ThumbQuality < 25 {
|
||||
return 25
|
||||
}
|
||||
|
||||
return c.config.ThumbQuality
|
||||
return c.params.ThumbQuality
|
||||
}
|
||||
|
||||
// ThumbSize returns the pre-rendered thumbnail size limit in pixels (720-3840).
|
||||
func (c *Config) ThumbSize() int {
|
||||
if c.config.ThumbSize > 3840 {
|
||||
if c.params.ThumbSize > 3840 {
|
||||
return 3840
|
||||
}
|
||||
|
||||
if c.config.ThumbSize < 720 {
|
||||
if c.params.ThumbSize < 720 {
|
||||
return 720
|
||||
}
|
||||
|
||||
return c.config.ThumbSize
|
||||
return c.params.ThumbSize
|
||||
}
|
||||
|
||||
// ThumbLimit returns the on-demand thumbnail size limit in pixels (720-3840).
|
||||
func (c *Config) ThumbLimit() int {
|
||||
if c.config.ThumbLimit > 3840 {
|
||||
if c.params.ThumbLimit > 3840 {
|
||||
return 3840
|
||||
}
|
||||
|
||||
if c.config.ThumbLimit < 720 {
|
||||
if c.params.ThumbLimit < 720 {
|
||||
return 720
|
||||
}
|
||||
|
||||
return c.config.ThumbLimit
|
||||
return c.params.ThumbLimit
|
||||
}
|
||||
|
||||
// ThumbFilter returns the thumbnail resample filter (blackman, lanczos, cubic or linear).
|
||||
func (c *Config) ThumbFilter() thumb.ResampleFilter {
|
||||
switch strings.ToLower(c.config.ThumbFilter) {
|
||||
switch strings.ToLower(c.params.ThumbFilter) {
|
||||
case "blackman":
|
||||
return thumb.ResampleBlackman
|
||||
case "lanczos":
|
||||
|
@ -290,7 +299,7 @@ func (c *Config) ThumbFilter() thumb.ResampleFilter {
|
|||
|
||||
// GeoCodingApi returns the preferred geo coding api (none, osm or places).
|
||||
func (c *Config) GeoCodingApi() string {
|
||||
switch c.config.GeoCodingApi {
|
||||
switch c.params.GeoCodingApi {
|
||||
case "places":
|
||||
return "places"
|
||||
case "osm":
|
||||
|
|
|
@ -18,20 +18,20 @@ import (
|
|||
|
||||
// DatabaseDriver returns the database driver name.
|
||||
func (c *Config) DatabaseDriver() string {
|
||||
if c.config.DatabaseDriver == "" {
|
||||
if c.params.DatabaseDriver == "" {
|
||||
return DbTiDB
|
||||
}
|
||||
|
||||
return c.config.DatabaseDriver
|
||||
return c.params.DatabaseDriver
|
||||
}
|
||||
|
||||
// DatabaseDsn returns the database data source name (DSN).
|
||||
func (c *Config) DatabaseDsn() string {
|
||||
if c.config.DatabaseDsn == "" {
|
||||
if c.params.DatabaseDsn == "" {
|
||||
return "root:photoprism@tcp(localhost:4000)/photoprism?parseTime=true"
|
||||
}
|
||||
|
||||
return c.config.DatabaseDsn
|
||||
return c.params.DatabaseDsn
|
||||
}
|
||||
|
||||
// Db returns the db connection.
|
||||
|
|
|
@ -86,7 +86,7 @@ func (c *Config) CreateDirectories() error {
|
|||
|
||||
// ConfigFile returns the config file name.
|
||||
func (c *Config) ConfigFile() string {
|
||||
return c.config.ConfigFile
|
||||
return c.params.ConfigFile
|
||||
}
|
||||
|
||||
// SettingsFile returns the user settings file name.
|
||||
|
@ -96,73 +96,73 @@ func (c *Config) SettingsFile() string {
|
|||
|
||||
// ConfigPath returns the config path.
|
||||
func (c *Config) ConfigPath() string {
|
||||
if c.config.ConfigPath == "" {
|
||||
if c.params.ConfigPath == "" {
|
||||
return c.AssetsPath() + "/config"
|
||||
}
|
||||
|
||||
return fs.Abs(c.config.ConfigPath)
|
||||
return fs.Abs(c.params.ConfigPath)
|
||||
}
|
||||
|
||||
// PIDFilename returns the filename for storing the server process id (pid).
|
||||
func (c *Config) PIDFilename() string {
|
||||
if c.config.PIDFilename == "" {
|
||||
if c.params.PIDFilename == "" {
|
||||
return c.AssetsPath() + "/photoprism.pid"
|
||||
}
|
||||
|
||||
return fs.Abs(c.config.PIDFilename)
|
||||
return fs.Abs(c.params.PIDFilename)
|
||||
}
|
||||
|
||||
// LogFilename returns the filename for storing server logs.
|
||||
func (c *Config) LogFilename() string {
|
||||
if c.config.LogFilename == "" {
|
||||
if c.params.LogFilename == "" {
|
||||
return c.AssetsPath() + "/photoprism.log"
|
||||
}
|
||||
|
||||
return fs.Abs(c.config.LogFilename)
|
||||
return fs.Abs(c.params.LogFilename)
|
||||
}
|
||||
|
||||
// OriginalsPath returns the originals.
|
||||
func (c *Config) OriginalsPath() string {
|
||||
return fs.Abs(c.config.OriginalsPath)
|
||||
return fs.Abs(c.params.OriginalsPath)
|
||||
}
|
||||
|
||||
// ImportPath returns the import directory.
|
||||
func (c *Config) ImportPath() string {
|
||||
return fs.Abs(c.config.ImportPath)
|
||||
return fs.Abs(c.params.ImportPath)
|
||||
}
|
||||
|
||||
// SipsBin returns the sips binary file name.
|
||||
func (c *Config) SipsBin() string {
|
||||
return findExecutable(c.config.SipsBin, "sips")
|
||||
return findExecutable(c.params.SipsBin, "sips")
|
||||
}
|
||||
|
||||
// DarktableBin returns the darktable-cli binary file name.
|
||||
func (c *Config) DarktableBin() string {
|
||||
return findExecutable(c.config.DarktableBin, "darktable-cli")
|
||||
return findExecutable(c.params.DarktableBin, "darktable-cli")
|
||||
}
|
||||
|
||||
// HeifConvertBin returns the heif-convert binary file name.
|
||||
func (c *Config) HeifConvertBin() string {
|
||||
return findExecutable(c.config.HeifConvertBin, "heif-convert")
|
||||
return findExecutable(c.params.HeifConvertBin, "heif-convert")
|
||||
}
|
||||
|
||||
// ExifToolBin returns the exiftool binary file name.
|
||||
func (c *Config) ExifToolBin() string {
|
||||
return findExecutable(c.config.ExifToolBin, "exiftool")
|
||||
return findExecutable(c.params.ExifToolBin, "exiftool")
|
||||
}
|
||||
|
||||
// TempPath returns a temporary directory name for uploads and downloads.
|
||||
func (c *Config) TempPath() string {
|
||||
if c.config.TempPath == "" {
|
||||
if c.params.TempPath == "" {
|
||||
return os.TempDir() + "/photoprism"
|
||||
}
|
||||
|
||||
return fs.Abs(c.config.TempPath)
|
||||
return fs.Abs(c.params.TempPath)
|
||||
}
|
||||
|
||||
// CachePath returns the path to the cache.
|
||||
func (c *Config) CachePath() string {
|
||||
return fs.Abs(c.config.CachePath)
|
||||
return fs.Abs(c.params.CachePath)
|
||||
}
|
||||
|
||||
// ThumbnailsPath returns the path to the cached thumbnails.
|
||||
|
@ -172,16 +172,16 @@ func (c *Config) ThumbnailsPath() string {
|
|||
|
||||
// AssetsPath returns the path to the assets.
|
||||
func (c *Config) AssetsPath() string {
|
||||
return fs.Abs(c.config.AssetsPath)
|
||||
return fs.Abs(c.params.AssetsPath)
|
||||
}
|
||||
|
||||
// ResourcesPath returns the path to the app resources like static files.
|
||||
func (c *Config) ResourcesPath() string {
|
||||
if c.config.ResourcesPath == "" {
|
||||
if c.params.ResourcesPath == "" {
|
||||
return c.AssetsPath() + "/resources"
|
||||
}
|
||||
|
||||
return fs.Abs(c.config.ResourcesPath)
|
||||
return fs.Abs(c.params.ResourcesPath)
|
||||
}
|
||||
|
||||
// ExamplesPath returns the example files path.
|
||||
|
|
|
@ -4,39 +4,39 @@ import "github.com/photoprism/photoprism/pkg/fs"
|
|||
|
||||
// DatabasePath returns the database storage path for TiDB.
|
||||
func (c *Config) DatabasePath() string {
|
||||
if c.config.DatabasePath == "" {
|
||||
if c.params.DatabasePath == "" {
|
||||
return c.ResourcesPath() + "/database"
|
||||
}
|
||||
|
||||
return fs.Abs(c.config.DatabasePath)
|
||||
return fs.Abs(c.params.DatabasePath)
|
||||
}
|
||||
|
||||
// DetachServer returns true if server should detach from console (daemon mode).
|
||||
func (c *Config) DetachServer() bool {
|
||||
return c.config.DetachServer
|
||||
return c.params.DetachServer
|
||||
}
|
||||
|
||||
// HttpServerHost returns the built-in HTTP server host name or IP address (empty for all interfaces).
|
||||
func (c *Config) HttpServerHost() string {
|
||||
if c.config.HttpServerHost == "" {
|
||||
if c.params.HttpServerHost == "" {
|
||||
return "0.0.0.0"
|
||||
}
|
||||
|
||||
return c.config.HttpServerHost
|
||||
return c.params.HttpServerHost
|
||||
}
|
||||
|
||||
// HttpServerPort returns the built-in HTTP server port.
|
||||
func (c *Config) HttpServerPort() int {
|
||||
if c.config.HttpServerPort == 0 {
|
||||
if c.params.HttpServerPort == 0 {
|
||||
return 2342
|
||||
}
|
||||
|
||||
return c.config.HttpServerPort
|
||||
return c.params.HttpServerPort
|
||||
}
|
||||
|
||||
// HttpServerMode returns the server mode.
|
||||
func (c *Config) HttpServerMode() string {
|
||||
if c.config.HttpServerMode == "" {
|
||||
if c.params.HttpServerMode == "" {
|
||||
if c.Debug() {
|
||||
return "debug"
|
||||
}
|
||||
|
@ -44,12 +44,12 @@ func (c *Config) HttpServerMode() string {
|
|||
return "release"
|
||||
}
|
||||
|
||||
return c.config.HttpServerMode
|
||||
return c.params.HttpServerMode
|
||||
}
|
||||
|
||||
// HttpServerPassword returns the password for the user interface (optional).
|
||||
func (c *Config) HttpServerPassword() string {
|
||||
return c.config.HttpServerPassword
|
||||
return c.params.HttpServerPassword
|
||||
}
|
||||
|
||||
// HttpTemplatesPath returns the server templates path.
|
||||
|
@ -74,23 +74,23 @@ func (c *Config) HttpStaticBuildPath() string {
|
|||
|
||||
// SqlServerHost returns the built-in SQL server host name or IP address (empty for all interfaces).
|
||||
func (c *Config) SqlServerHost() string {
|
||||
if c.config.SqlServerHost == "" {
|
||||
if c.params.SqlServerHost == "" {
|
||||
return "127.0.0.1"
|
||||
}
|
||||
|
||||
return c.config.SqlServerHost
|
||||
return c.params.SqlServerHost
|
||||
}
|
||||
|
||||
// SqlServerPort returns the built-in SQL server port.
|
||||
func (c *Config) SqlServerPort() uint {
|
||||
if c.config.SqlServerPort == 0 {
|
||||
if c.params.SqlServerPort == 0 {
|
||||
return 4000
|
||||
}
|
||||
|
||||
return c.config.SqlServerPort
|
||||
return c.params.SqlServerPort
|
||||
}
|
||||
|
||||
// SqlServerPassword returns the password for the built-in database server.
|
||||
func (c *Config) SqlServerPassword() string {
|
||||
return c.config.SqlServerPassword
|
||||
return c.params.SqlServerPassword
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
// DisableSettings returns true if the user is not allowed to change settings.
|
||||
func (c *Config) DisableSettings() bool {
|
||||
return c.config.DisableSettings
|
||||
return c.params.DisableSettings
|
||||
}
|
||||
|
||||
type MapsSettings struct {
|
||||
|
@ -19,7 +19,15 @@ type MapsSettings struct {
|
|||
Style string `json:"style" yaml:"style"`
|
||||
}
|
||||
|
||||
type FeatureFlags struct {
|
||||
type LibrarySettings struct {
|
||||
Reindex bool `json:"reindex" yaml:"reindex"`
|
||||
Duplicates bool `json:"duplicates" yaml:"duplicates"`
|
||||
Convert bool `json:"convert" yaml:"convert"`
|
||||
CreateThumbs bool `json:"create-thumbs" yaml:"create-thumbs"`
|
||||
RemoveImported bool `json:"remove-imported" yaml:"remove-imported"`
|
||||
}
|
||||
|
||||
type FeatureSettings struct {
|
||||
Upload bool `json:"upload" yaml:"upload"`
|
||||
Import bool `json:"import" yaml:"import"`
|
||||
Labels bool `json:"labels" yaml:"labels"`
|
||||
|
@ -35,7 +43,8 @@ type Settings struct {
|
|||
Theme string `json:"theme" yaml:"theme"`
|
||||
Language string `json:"language" yaml:"language"`
|
||||
Maps MapsSettings `json:"maps" yaml:"maps"`
|
||||
Features FeatureFlags `json:"features" yaml:"features"`
|
||||
Features FeatureSettings `json:"features" yaml:"features"`
|
||||
Library LibrarySettings `json:"library" yaml:"library"`
|
||||
}
|
||||
|
||||
// NewSettings returns a empty Settings
|
||||
|
@ -47,7 +56,7 @@ func NewSettings() *Settings {
|
|||
Animate: 0,
|
||||
Style: "streets",
|
||||
},
|
||||
Features: FeatureFlags{
|
||||
Features: FeatureSettings{
|
||||
Upload: true,
|
||||
Import: true,
|
||||
Labels: true,
|
||||
|
@ -60,6 +69,11 @@ func NewSettings() *Settings {
|
|||
}
|
||||
}
|
||||
|
||||
// Propagate updates settings in other packages as needed.
|
||||
func (s *Settings) Propagate() {
|
||||
|
||||
}
|
||||
|
||||
// Load uses a yaml config file to initiate the configuration entity.
|
||||
func (s *Settings) Load(fileName string) error {
|
||||
if !fs.FileExists(fileName) {
|
||||
|
@ -72,7 +86,13 @@ func (s *Settings) Load(fileName string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return yaml.Unmarshal(yamlConfig, s)
|
||||
if err := yaml.Unmarshal(yamlConfig, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Propagate()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Save uses a yaml config file to initiate the configuration entity.
|
||||
|
@ -83,17 +103,30 @@ func (s *Settings) Save(fileName string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(fileName, data, os.ModePerm)
|
||||
s.Propagate()
|
||||
|
||||
if err := ioutil.WriteFile(fileName, data, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Propagate()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// initSettings initializes user settings from a config file.
|
||||
func (c *Config) initSettings() {
|
||||
c.settings = NewSettings()
|
||||
p := c.SettingsFile()
|
||||
|
||||
if err := c.settings.Load(p); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
c.settings.Propagate()
|
||||
}
|
||||
|
||||
// Settings returns the current user settings.
|
||||
func (c *Config) Settings() *Settings {
|
||||
s := NewSettings()
|
||||
p := c.SettingsFile()
|
||||
|
||||
if err := s.Load(p); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
return s
|
||||
return c.settings
|
||||
}
|
||||
|
|
|
@ -9,5 +9,5 @@ func (c *Config) TensorFlowVersion() string {
|
|||
|
||||
// DisableTensorFlow returns true if the use of TensorFlow is disabled for image classification.
|
||||
func (c *Config) DisableTensorFlow() bool {
|
||||
return c.config.DisableTensorFlow
|
||||
return c.params.DisableTensorFlow
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ const (
|
|||
)
|
||||
|
||||
var testConfig *Config
|
||||
var once sync.Once
|
||||
var testConfigOnce sync.Once
|
||||
var testConfigMutex sync.Mutex
|
||||
|
||||
func testDataPath(assetsPath string) string {
|
||||
|
@ -75,11 +75,13 @@ func NewTestParamsError() *Params {
|
|||
return c
|
||||
}
|
||||
|
||||
func SetNewTestConfig() {
|
||||
testConfig = NewTestConfig()
|
||||
}
|
||||
|
||||
// TestConfig inits the global testConfig if it was not already initialised
|
||||
func TestConfig() *Config {
|
||||
once.Do(func() {
|
||||
testConfig = NewTestConfig()
|
||||
})
|
||||
testConfigOnce.Do(SetNewTestConfig)
|
||||
|
||||
return testConfig
|
||||
}
|
||||
|
@ -91,7 +93,7 @@ func NewTestConfig() *Config {
|
|||
|
||||
log.SetLevel(logrus.DebugLevel)
|
||||
|
||||
c := &Config{config: NewTestParams()}
|
||||
c := &Config{params: NewTestParams()}
|
||||
err := c.Init(context.Background())
|
||||
if err != nil {
|
||||
log.Fatalf("failed init config: %v", err)
|
||||
|
@ -115,7 +117,7 @@ func NewTestConfig() *Config {
|
|||
func NewTestErrorConfig() *Config {
|
||||
log.SetLevel(logrus.DebugLevel)
|
||||
|
||||
c := &Config{config: NewTestParamsError()}
|
||||
c := &Config{params: NewTestParamsError()}
|
||||
err := c.Init(context.Background())
|
||||
if err != nil {
|
||||
log.Fatalf("failed init config: %v", err)
|
||||
|
|
6
internal/config/testdata/configEmpty.yml
vendored
6
internal/config/testdata/configEmpty.yml
vendored
|
@ -12,3 +12,9 @@ features:
|
|||
download: true
|
||||
edit: true
|
||||
share: true
|
||||
library:
|
||||
reindex: false
|
||||
duplicates: false
|
||||
convert: false
|
||||
create-thumbs: false
|
||||
remove-imported: false
|
||||
|
|
Loading…
Reference in a new issue