Add common feature flags incl upload #284

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer 2020-04-13 18:08:21 +02:00
parent 829cd9a36a
commit c2fa3a7246
21 changed files with 331 additions and 135 deletions

View file

@ -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

View file

@ -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;

View file

@ -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>

View file

@ -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");
},

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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"

View file

@ -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>

View file

@ -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
}

View file

@ -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
}

View file

@ -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()

View file

@ -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)
}

View file

@ -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":

View file

@ -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.

View file

@ -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.

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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)

View file

@ -12,3 +12,9 @@ features:
download: true
edit: true
share: true
library:
reindex: false
duplicates: false
convert: false
create-thumbs: false
remove-imported: false