UX: Refactor config options to be more intuitive

Make sure to update your local config files when upgrading as
the name of some config values has changed. The default
config path has changed from "settings" to "config".
This commit is contained in:
Michael Mayer 2020-12-18 09:11:42 +01:00
parent cd59b1b8ca
commit 7940786ce9
49 changed files with 597 additions and 539 deletions

View file

@ -32,7 +32,7 @@ upgrade: dep-upgrade-js dep-upgrade
clean-local: clean-local-config clean-local-share clean-local-cache
clean-install: clean-local dep build-js install-bin install-assets
acceptance-start:
go run cmd/photoprism/photoprism.go --public --database-driver sqlite --database-dsn ./storage/acceptance/index.db --import-path ./storage/acceptance/import --http-port=2343 --config-path ./storage/acceptance/config --originals-path ./storage/acceptance/originals --sidecar-json=false --sidecar-yaml=false start -d
go run cmd/photoprism/photoprism.go --public --database-driver sqlite --database-dsn ./storage/acceptance/index.db --import-path ./storage/acceptance/import --http-port=2343 --config-path ./storage/acceptance/config --originals-path ./storage/acceptance/originals --disable-exiftool --disable-backups start -d
acceptance-restart:
go run cmd/photoprism/photoprism.go stop
cp -f storage/acceptance/backup.db storage/acceptance/index.db
@ -40,7 +40,7 @@ acceptance-restart:
rm -rf storage/acceptance/originals/2010
rm -rf storage/acceptance/originals/2013
rm -rf storage/acceptance/originals/2017
go run cmd/photoprism/photoprism.go --public --database-driver sqlite --database-dsn ./storage/acceptance/index.db --import-path ./storage/acceptance/import --http-port=2343 --config-path ./storage/acceptance/config --originals-path ./storage/acceptance/originals --sidecar-json=false --sidecar-yaml=false start -d
go run cmd/photoprism/photoprism.go --public --database-driver sqlite --database-dsn ./storage/acceptance/index.db --import-path ./storage/acceptance/import --http-port=2343 --config-path ./storage/acceptance/config --originals-path ./storage/acceptance/originals --disable-exiftool --disable-backups start -d
acceptance-restore-db:
cp -f storage/acceptance/config/settingsBackup.yml storage/acceptance/config/settings.yml
cp -f storage/acceptance/backup.db storage/acceptance/index.db
@ -63,7 +63,7 @@ install-bin:
scripts/build.sh prod ~/.local/bin/$(BINARY_NAME)
install-assets:
$(info Installing assets)
mkdir -p ~/.photoprism/storage/settings
mkdir -p ~/.photoprism/storage/config
mkdir -p ~/.photoprism/storage/cache
mkdir -p ~/.photoprism/storage
mkdir -p ~/.photoprism/assets
@ -76,7 +76,7 @@ clean-local-assets:
clean-local-cache:
rm -rf ~/.photoprism/storage/cache/*
clean-local-config:
rm -f ~/.photoprism/storage/settings/*
rm -f ~/.photoprism/storage/config/*
dep-list:
go list -u -m -json all | go-mod-outdated -direct
dep-js:

View file

@ -21,8 +21,6 @@ services:
PHOTOPRISM_DEBUG: "false"
PHOTOPRISM_READONLY: "false"
PHOTOPRISM_PUBLIC: "true"
PHOTOPRISM_UPLOAD_NSFW: "false"
PHOTOPRISM_DETECT_NSFW: "false"
PHOTOPRISM_PID_FILENAME: "photoprism.pid"
PHOTOPRISM_LOG_FILENAME: "photoprism.log"
PHOTOPRISM_DETACH_SERVER: "true"
@ -40,16 +38,21 @@ services:
PHOTOPRISM_STORAGE_PATH: "/go/src/github.com/photoprism/photoprism/storage"
PHOTOPRISM_ORIGINALS_PATH: "/go/src/github.com/photoprism/photoprism/storage/originals"
PHOTOPRISM_IMPORT_PATH: "/go/src/github.com/photoprism/photoprism/storage/import"
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "true" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
# PHOTOPRISM_THUMB_SIZE: 4096 # Retina 4K, DCI 4K (requires more storage); 7680 for 8K Ultra HD
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use darktable presets (disables concurrent raw to jpeg conversion)
PHOTOPRISM_SIDECAR_JSON: "true" # Read metadata from JSON sidecar files created by exiftool
PHOTOPRISM_SIDECAR_YAML: "true" # Backup photo metadata to YAML sidecar files
PHOTOPRISM_DISABLE_BACKUPS: "false" # Don't backup photo and album metadata to YAML files
PHOTOPRISM_DISABLE_SETTINGS: "false" # Users can not view or change settings
PHOTOPRISM_DISABLE_PLACES: "false" # Disables reverse geocoding and maps
PHOTOPRISM_DISABLE_EXIFTOOL: "false" # Don't create ExifTool JSON files for improved metadata extraction
PHOTOPRISM_DISABLE_TENSORFLOW: "false" # Don't use TensorFlow for image classification
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "false" # Allow uploads that may be offensive
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use Darktable presets (disables concurrent raw image conversion)
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "true" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
# PHOTOPRISM_THUMB_SIZE: 4096 # Retina 4K, DCI 4K (requires more storage); 7680 for 8K Ultra HD
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
CODECOV_TOKEN:
CODECOV_ENV:
CODECOV_URL:

View file

@ -27,8 +27,6 @@ services:
PHOTOPRISM_READONLY: "false"
PHOTOPRISM_PUBLIC: "true"
PHOTOPRISM_EXPERIMENTAL: "true"
PHOTOPRISM_UPLOAD_NSFW: "false"
PHOTOPRISM_DETECT_NSFW: "false"
PHOTOPRISM_SERVER_MODE: "debug"
PHOTOPRISM_HTTP_HOST: "0.0.0.0"
PHOTOPRISM_HTTP_PORT: 2342
@ -44,16 +42,21 @@ services:
PHOTOPRISM_STORAGE_PATH: "/go/src/github.com/photoprism/photoprism/storage"
PHOTOPRISM_ORIGINALS_PATH: "/go/src/github.com/photoprism/photoprism/storage/originals"
PHOTOPRISM_IMPORT_PATH: "/go/src/github.com/photoprism/photoprism/storage/import"
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "true" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
# PHOTOPRISM_THUMB_SIZE: 4096 # Retina 4K, DCI 4K (requires more storage); 7680 for 8K Ultra HD
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use darktable presets (disables concurrent raw to jpeg conversion)
PHOTOPRISM_SIDECAR_JSON: "true" # Read metadata from JSON sidecar files created by exiftool
PHOTOPRISM_SIDECAR_YAML: "true" # Backup photo metadata to YAML sidecar files
PHOTOPRISM_DISABLE_BACKUPS: "false" # Don't backup photo and album metadata to YAML files
PHOTOPRISM_DISABLE_SETTINGS: "false" # Users can not view or change settings
PHOTOPRISM_DISABLE_PLACES: "false" # Disables reverse geocoding and maps
PHOTOPRISM_DISABLE_EXIFTOOL: "false" # Don't create ExifTool JSON files for improved metadata extraction
PHOTOPRISM_DISABLE_TENSORFLOW: "false" # Don't use TensorFlow for image classification
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "false" # Allow uploads that may be offensive
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use Darktable presets (disables concurrent raw image conversion)
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "true" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
# PHOTOPRISM_THUMB_SIZE: 4096 # Retina 4K, DCI 4K (requires more storage); 7680 for 8K Ultra HD
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
postgres:
image: postgres:12-alpine

View file

@ -42,8 +42,6 @@ services:
PHOTOPRISM_READONLY: "false"
PHOTOPRISM_PUBLIC: "true"
PHOTOPRISM_EXPERIMENTAL: "true"
PHOTOPRISM_UPLOAD_NSFW: "false"
PHOTOPRISM_DETECT_NSFW: "false"
PHOTOPRISM_SERVER_MODE: "debug"
PHOTOPRISM_HTTP_HOST: "0.0.0.0"
PHOTOPRISM_HTTP_PORT: 2342
@ -59,17 +57,21 @@ services:
PHOTOPRISM_STORAGE_PATH: "/go/src/github.com/photoprism/photoprism/storage"
PHOTOPRISM_ORIGINALS_PATH: "/go/src/github.com/photoprism/photoprism/storage/originals"
PHOTOPRISM_IMPORT_PATH: "/go/src/github.com/photoprism/photoprism/storage/import"
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "true" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
# PHOTOPRISM_THUMB_SIZE: 4096 # Retina 4K, DCI 4K (requires more storage); 7680 for 8K Ultra HD
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use darktable presets (disables concurrent raw to jpeg conversion)
PHOTOPRISM_SIDECAR_JSON: "true" # Read metadata from JSON sidecar files created by exiftool
PHOTOPRISM_SIDECAR_YAML: "true" # Backup photo metadata to YAML sidecar files
PHOTOPRISM_DISABLE_BACKUPS: "false" # Don't backup photo and album metadata to YAML files
PHOTOPRISM_DISABLE_SETTINGS: "false" # Users can not view or change settings
PHOTOPRISM_DISABLE_PLACES: "false" # Disables reverse geocoding and maps
PHOTOPRISM_DISABLE_EXIFTOOL: "false" # Don't create ExifTool JSON files for improved metadata extraction
PHOTOPRISM_DISABLE_TENSORFLOW: "false" # Don't use TensorFlow for image classification
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "false" # Allow uploads that may be offensive
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use Darktable presets (disables concurrent raw image conversion)
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "true" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
# PHOTOPRISM_THUMB_SIZE: 4096 # Retina 4K, DCI 4K (requires more storage); 7680 for 8K Ultra HD
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
photoprism-db:
image: mariadb:10.5
command: mysqld --port=4001 --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=50

View file

@ -17,9 +17,6 @@ ENV PHOTOPRISM_PUBLIC true
ENV PHOTOPRISM_EXPERIMENTAL true
ENV PHOTOPRISM_UPLOAD_NSFW false
ENV PHOTOPRISM_DETECT_NSFW false
ENV PHOTOPRISM_SIDECAR_JSON true
ENV PHOTOPRISM_SIDECAR_YAML false
ENV PHOTOPRISM_GEOCODING_API places
ENV PHOTOPRISM_THUMB_FILTER lanczos
ENV PHOTOPRISM_THUMB_UNCACHED true
ENV PHOTOPRISM_THUMB_SIZE 4096

View file

@ -85,17 +85,23 @@ ENV PHOTOPRISM_SITE_DESCRIPTION ""
ENV PHOTOPRISM_SITE_AUTHOR ""
ENV PHOTOPRISM_HTTP_HOST "0.0.0.0"
ENV PHOTOPRISM_HTTP_PORT 2342
ENV PHOTOPRISM_SETTINGS_HIDDEN "false"
ENV PHOTOPRISM_DATABASE_DRIVER "sqlite"
ENV PHOTOPRISM_SIDECAR_JSON "true"
ENV PHOTOPRISM_SIDECAR_YAML "true"
ENV PHOTOPRISM_DATABASE_SERVER ""
ENV PHOTOPRISM_DATABASE_NAME "photoprism"
ENV PHOTOPRISM_DATABASE_USER "photoprism"
ENV PHOTOPRISM_DATABASE_PASSWORD ""
ENV PHOTOPRISM_DISABLE_TENSORFLOW "false"
ENV PHOTOPRISM_DISABLE_EXIFTOOL "false"
ENV PHOTOPRISM_DISABLE_BACKUPS "false"
ENV PHOTOPRISM_DISABLE_SETTINGS "false"
ENV PHOTOPRISM_DISABLE_PLACES "false"
ENV PHOTOPRISM_DARKTABLE_PRESETS "false"
ENV PHOTOPRISM_THUMB_FILTER "lanczos"
ENV PHOTOPRISM_THUMB_UNCACHED "false"
ENV PHOTOPRISM_THUMB_SIZE 2048
ENV PHOTOPRISM_THUMB_SIZE_UNCACHED 7680
ENV PHOTOPRISM_JPEG_SIZE 7680
ENV PHOTOPRISM_JPEG_QUALITY 92
ENV PHOTOPRISM_DARKTABLE_PRESETS "false"
# Copy files to /photoprism
COPY --from=build /root/.local/bin/photoprism /photoprism/bin/photoprism
@ -106,7 +112,7 @@ RUN mkdir -p \
/var/lib/photoprism \
/photoprism/originals \
/photoprism/import \
/photoprism/storage/settings \
/photoprism/storage/config \
/photoprism/storage/cache && \
chown -R photoprism:photoprism /photoprism /var/lib/photoprism && \
chmod -R a+rw /photoprism /var/lib/photoprism

View file

@ -171,17 +171,23 @@ ENV PHOTOPRISM_SITE_DESCRIPTION ""
ENV PHOTOPRISM_SITE_AUTHOR ""
ENV PHOTOPRISM_HTTP_HOST "0.0.0.0"
ENV PHOTOPRISM_HTTP_PORT 2342
ENV PHOTOPRISM_SETTINGS_HIDDEN "false"
ENV PHOTOPRISM_DATABASE_DRIVER "sqlite"
ENV PHOTOPRISM_SIDECAR_JSON "true"
ENV PHOTOPRISM_SIDECAR_YAML "true"
ENV PHOTOPRISM_DATABASE_SERVER ""
ENV PHOTOPRISM_DATABASE_NAME "photoprism"
ENV PHOTOPRISM_DATABASE_USER "photoprism"
ENV PHOTOPRISM_DATABASE_PASSWORD ""
ENV PHOTOPRISM_DISABLE_TENSORFLOW "false"
ENV PHOTOPRISM_DISABLE_EXIFTOOL "false"
ENV PHOTOPRISM_DISABLE_BACKUPS "false"
ENV PHOTOPRISM_DISABLE_SETTINGS "false"
ENV PHOTOPRISM_DISABLE_PLACES "false"
ENV PHOTOPRISM_DARKTABLE_PRESETS "false"
ENV PHOTOPRISM_THUMB_FILTER "lanczos"
ENV PHOTOPRISM_THUMB_UNCACHED "false"
ENV PHOTOPRISM_THUMB_SIZE 2048
ENV PHOTOPRISM_THUMB_SIZE_UNCACHED 7680
ENV PHOTOPRISM_JPEG_SIZE 7680
ENV PHOTOPRISM_JPEG_QUALITY 92
ENV PHOTOPRISM_DARKTABLE_PRESETS "false"
# Copy files to /photoprism
COPY --from=build /root/.local/bin/photoprism /photoprism/bin/photoprism
@ -192,7 +198,7 @@ RUN mkdir -p \
/var/lib/photoprism \
/photoprism/originals \
/photoprism/import \
/photoprism/storage/settings \
/photoprism/storage/config \
/photoprism/storage/cache && \
chown -R photoprism:photoprism /photoprism /var/lib/photoprism && \
chmod -R a+rw /photoprism /var/lib/photoprism

View file

@ -30,12 +30,10 @@ services:
#
# Run "photoprism help" and "photoprism config" too see all config options and current values:
environment:
PHOTOPRISM_ADMIN_PASSWORD: "please-change" # Initial admin password: PLEASE CHANGE!
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: This is your initial admin password
PHOTOPRISM_DEBUG: "false" # Run in debug mode (shows additional log messages)
PHOTOPRISM_PUBLIC: "false" # No authentication required (disables password protection)
PHOTOPRISM_READONLY: "false" # Don't modify originals directory (reduced functionality)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive
PHOTOPRISM_EXPERIMENTAL: "false" # Enable experimental features
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Canonical / public site URL
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
@ -44,15 +42,20 @@ services:
PHOTOPRISM_SITE_AUTHOR: ""
PHOTOPRISM_HTTP_HOST: "0.0.0.0"
PHOTOPRISM_HTTP_PORT: 2342
PHOTOPRISM_SETTINGS_HIDDEN: "false" # Users can not view or change settings
PHOTOPRISM_DISABLE_BACKUPS: "false" # Don't backup photo and album metadata to YAML files
PHOTOPRISM_DISABLE_SETTINGS: "false" # Users can not view or change settings
PHOTOPRISM_DISABLE_PLACES: "false" # Disables reverse geocoding and maps
PHOTOPRISM_DISABLE_EXIFTOOL: "false" # Don't create ExifTool JSON files for improved metadata extraction
PHOTOPRISM_DISABLE_TENSORFLOW: "false" # Don't use TensorFlow for image classification
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use Darktable presets (disables concurrent raw image conversion)
PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
# PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB instead of SQLite for improved performance
# PHOTOPRISM_DATABASE_SERVER: "mariadb:3306"
# PHOTOPRISM_DATABASE_NAME: "photoprism"
# PHOTOPRISM_DATABASE_USER: "photoprism"
# PHOTOPRISM_DATABASE_PASSWORD: "insecure"
PHOTOPRISM_SIDECAR_JSON: "true" # Automatically create JSON sidecar files using Exiftool
PHOTOPRISM_SIDECAR_YAML: "true" # Automatically backup metadata to YAML sidecar files
# PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "false" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
@ -60,7 +63,6 @@ services:
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use darktable presets (disables concurrent raw to jpeg conversion)
# You may optionally set user, group and/or file permissions using environment variables:
# UID: 1000
# GID: 1000
@ -85,10 +87,10 @@ services:
# volumes:
# - "/var/lib/mysql"
# environment:
# MYSQL_ROOT_PASSWORD: please-change
# MYSQL_ROOT_PASSWORD: insecure
# MYSQL_DATABASE: photoprism
# MYSQL_USER: photoprism
# MYSQL_PASSWORD: insecure
# MYSQL_DATABASE: photoprism
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#

View file

@ -30,12 +30,10 @@ services:
#
# Run "photoprism help" and "photoprism config" too see all config options and current values:
environment: # Run "photoprism help" and "photoprism config" too see all config options and current values
PHOTOPRISM_ADMIN_PASSWORD: "please-change" # Initial admin password: PLEASE CHANGE!
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: This is your initial admin password
PHOTOPRISM_DEBUG: "false" # Run in debug mode (shows additional log messages)
PHOTOPRISM_PUBLIC: "false" # No authentication required (disables password protection)
PHOTOPRISM_READONLY: "false" # Don't modify originals directory (reduced functionality)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive
PHOTOPRISM_EXPERIMENTAL: "false" # Enable experimental features
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Canonical / public site URL
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
@ -44,15 +42,20 @@ services:
PHOTOPRISM_SITE_AUTHOR: ""
PHOTOPRISM_HTTP_HOST: "0.0.0.0"
PHOTOPRISM_HTTP_PORT: 2342
PHOTOPRISM_SETTINGS_HIDDEN: "false" # Users can not view or change settings
PHOTOPRISM_DISABLE_BACKUPS: "false" # Don't backup photo and album metadata to YAML files
PHOTOPRISM_DISABLE_SETTINGS: "false" # Users can not view or change settings
PHOTOPRISM_DISABLE_PLACES: "false" # Disables reverse geocoding and maps
PHOTOPRISM_DISABLE_EXIFTOOL: "false" # Don't create ExifTool JSON files for improved metadata extraction
PHOTOPRISM_DISABLE_TENSORFLOW: "false" # Don't use TensorFlow for image classification
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use Darktable presets (disables concurrent raw image conversion)
PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
# PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB instead of SQLite for improved performance
# PHOTOPRISM_DATABASE_SERVER: "mariadb:3306"
# PHOTOPRISM_DATABASE_NAME: "photoprism"
# PHOTOPRISM_DATABASE_USER: "photoprism"
# PHOTOPRISM_DATABASE_PASSWORD: "insecure"
PHOTOPRISM_SIDECAR_JSON: "true" # Automatically create JSON sidecar files using Exiftool
PHOTOPRISM_SIDECAR_YAML: "true" # Automatically backup metadata to YAML sidecar files
# PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "false" # Enable on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
@ -60,7 +63,6 @@ services:
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Use darktable presets (disables concurrent raw to jpeg conversion)
# You may optionally set user, group and/or file permissions using environment variables:
# UID: 1000
# GID: 1000
@ -85,10 +87,10 @@ services:
# volumes:
# - "/var/lib/mysql"
# environment:
# MYSQL_ROOT_PASSWORD: please-change
# MYSQL_ROOT_PASSWORD: insecure
# MYSQL_DATABASE: photoprism
# MYSQL_USER: photoprism
# MYSQL_PASSWORD: insecure
# MYSQL_DATABASE: photoprism
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#

View file

@ -339,7 +339,7 @@
</v-list-tile>
</v-list-group>
<template v-if="!config.disableSettings">
<template v-if="!config.disable.settings">
<v-list-tile v-if="mini" to="/settings" @click="" class="nav-settings">
<v-list-tile-action :title="$gettext('Settings')">
<v-icon>settings</v-icon>

View file

@ -327,7 +327,7 @@
</v-checkbox>
</v-flex>
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2">
<v-flex xs12 sm6 lg3 class="px-2 pb-2 pt-2" v-if="!config.disable.places">
<v-checkbox
@change="onChange"
:disabled="busy"
@ -345,7 +345,7 @@
</v-card-actions>
</v-card>
<v-card flat tile class="mt-0 px-1 application" v-if="settings.features.places">
<v-card flat tile class="mt-0 px-1 application" v-if="settings.features.places && !config.disable.places">
<v-card-title primary-title class="pb-2">
<h3 class="body-2 mb-0">
<translate key="Places">Places</translate>
@ -400,6 +400,7 @@ export default {
return {
readonly: this.$config.get("readonly"),
experimental: this.$config.get("experimental"),
config: this.$config.values,
settings: new Settings(this.$config.settings()),
options: options,
busy: false,

View file

@ -276,7 +276,7 @@ export default [
meta: {title: $gettext("Settings"), auth: true, background: "application-light"},
props: {tab: 0},
beforeEnter: (to, from, next) => {
if (c.disableSettings) {
if (c.disable.settings) {
next({name: "home"});
} else {
next();
@ -290,7 +290,7 @@ export default [
meta: {title: $gettext("Settings"), auth: true, background: "application-light"},
props: {tab: 1},
beforeEnter: (to, from, next) => {
if (c.disableSettings) {
if (c.disable.settings) {
next({name: "home"});
} else {
next();
@ -304,7 +304,7 @@ export default [
meta: {title: $gettext("Settings"), auth: true, background: "application-light"},
props: {tab: 2},
beforeEnter: (to, from, next) => {
if (c.disableSettings) {
if (c.disable.settings) {
next({name: "home"});
} else {
next();

View file

@ -31,7 +31,7 @@ func SaveAlbumAsYaml(a entity.Album) {
c := service.Config()
// Write YAML sidecar file (optional).
if !c.SidecarYaml() {
if !c.BackupYaml() {
return
}

View file

@ -23,7 +23,7 @@ func SavePhotoAsYaml(p entity.Photo) {
c := service.Config()
// Write YAML sidecar file (optional).
if !c.SidecarYaml() {
if !c.BackupYaml() {
return
}

View file

@ -39,7 +39,7 @@ func SaveSettings(router *gin.RouterGroup) {
conf := service.Config()
if conf.SettingsHidden() {
if conf.DisableSettings() {
AbortUnauthorized(c)
return
}

View file

@ -2,7 +2,9 @@ package commands
import (
"fmt"
"strings"
"time"
"unicode/utf8"
"github.com/photoprism/photoprism/internal/config"
"github.com/urfave/cli"
@ -35,8 +37,40 @@ func configAction(ctx *cli.Context) error {
fmt.Printf("%-25s %s\n", "config-file", conf.ConfigFile())
fmt.Printf("%-25s %s\n", "settings-file", conf.SettingsFile())
// Passwords.
fmt.Printf("%-25s %s\n", "admin-password", conf.AdminPassword())
// Main directories.
fmt.Printf("%-25s %s\n", "originals-path", conf.OriginalsPath())
fmt.Printf("%-25s %d\n", "originals-limit", conf.OriginalsLimit())
fmt.Printf("%-25s %s\n", "import-path", conf.ImportPath())
fmt.Printf("%-25s %s\n", "storage-path", conf.StoragePath())
fmt.Printf("%-25s %s\n", "sidecar-path", conf.SidecarPath())
fmt.Printf("%-25s %s\n", "albums-path", conf.AlbumsPath())
fmt.Printf("%-25s %s\n", "cache-path", conf.CachePath())
fmt.Printf("%-25s %s\n", "temp-path", conf.TempPath())
fmt.Printf("%-25s %s\n", "backup-path", conf.BackupPath())
fmt.Printf("%-25s %s\n", "assets-path", conf.AssetsPath())
// Asset path and file names.
fmt.Printf("%-25s %s\n", "static-path", conf.StaticPath())
fmt.Printf("%-25s %s\n", "build-path", conf.BuildPath())
fmt.Printf("%-25s %s\n", "img-path", conf.ImgPath())
fmt.Printf("%-25s %s\n", "templates-path", conf.TemplatesPath())
// Workers.
fmt.Printf("%-25s %d\n", "workers", conf.Workers())
fmt.Printf("%-25s %d\n", "wakeup-interval", conf.WakeupInterval()/time.Second)
// Disable features.
fmt.Printf("%-25s %t\n", "disable-backups", conf.DisableBackups())
fmt.Printf("%-25s %t\n", "disable-settings", conf.DisableSettings())
fmt.Printf("%-25s %t\n", "disable-places", conf.DisablePlaces())
fmt.Printf("%-25s %t\n", "disable-exiftool", conf.DisableExifTool())
// Everything related to TensorFlow.
fmt.Printf("%-25s %t\n", "disable-tensorflow", conf.DisableTensorFlow())
fmt.Printf("%-25s %s\n", "tensorflow-version", conf.TensorFlowVersion())
fmt.Printf("%-25s %s\n", "tensorflow-model-path", conf.TensorFlowModelPath())
fmt.Printf("%-25s %t\n", "detect-nsfw", conf.DetectNSFW())
fmt.Printf("%-25s %t\n", "upload-nsfw", conf.UploadNSFW())
// Site information.
fmt.Printf("%-25s %s\n", "site-url", conf.SiteUrl())
@ -46,24 +80,18 @@ func configAction(ctx *cli.Context) error {
fmt.Printf("%-25s %s\n", "site-description", conf.SiteDescription())
fmt.Printf("%-25s %s\n", "site-author", conf.SiteAuthor())
// Everything related to TensorFlow.
fmt.Printf("%-25s %t\n", "tensorflow-off", conf.TensorFlowOff())
fmt.Printf("%-25s %s\n", "tensorflow-version", conf.TensorFlowVersion())
fmt.Printf("%-25s %s\n", "tensorflow-model-path", conf.TensorFlowModelPath())
fmt.Printf("%-25s %t\n", "detect-nsfw", conf.DetectNSFW())
fmt.Printf("%-25s %t\n", "upload-nsfw", conf.UploadNSFW())
// Background workers and logging.
fmt.Printf("%-25s %d\n", "workers", conf.Workers())
fmt.Printf("%-25s %d\n", "wakeup-interval", conf.WakeupInterval()/time.Second)
// Logging.
fmt.Printf("%-25s %s\n", "log-level", conf.LogLevel())
fmt.Printf("%-25s %s\n", "log-filename", conf.LogFilename())
fmt.Printf("%-25s %s\n", "pid-filename", conf.PIDFilename())
// HTTP server configuration.
fmt.Printf("%-25s %s\n", "http-host", conf.HttpServerHost())
fmt.Printf("%-25s %d\n", "http-port", conf.HttpServerPort())
fmt.Printf("%-25s %s\n", "http-mode", conf.HttpServerMode())
fmt.Printf("%-25s %s\n", "http-host", conf.HttpHost())
fmt.Printf("%-25s %d\n", "http-port", conf.HttpPort())
fmt.Printf("%-25s %s\n", "http-mode", conf.HttpMode())
// Passwords.
fmt.Printf("%-25s %s\n", "admin-password", strings.Repeat("*", utf8.RuneCountInString(conf.AdminPassword())))
// Database configuration.
fmt.Printf("%-25s %s\n", "database-driver", dbDriver)
@ -73,28 +101,10 @@ func configAction(ctx *cli.Context) error {
fmt.Printf("%-25s %s\n", "database-port", conf.DatabasePortString())
fmt.Printf("%-25s %s\n", "database-name", conf.DatabaseName())
fmt.Printf("%-25s %s\n", "database-user", conf.DatabaseUser())
fmt.Printf("%-25s %s\n", "database-password", conf.DatabasePassword())
fmt.Printf("%-25s %s\n", "database-password", strings.Repeat("*", utf8.RuneCountInString(conf.DatabasePassword())))
fmt.Printf("%-25s %d\n", "database-conns", conf.DatabaseConns())
fmt.Printf("%-25s %d\n", "database-conns-idle", conf.DatabaseConnsIdle())
// Main directories.
fmt.Printf("%-25s %s\n", "assets-path", conf.AssetsPath())
fmt.Printf("%-25s %s\n", "storage-path", conf.StoragePath())
fmt.Printf("%-25s %s\n", "backup-path", conf.BackupPath())
fmt.Printf("%-25s %s\n", "albums-path", conf.AlbumsPath())
fmt.Printf("%-25s %s\n", "import-path", conf.ImportPath())
fmt.Printf("%-25s %s\n", "originals-path", conf.OriginalsPath())
fmt.Printf("%-25s %d\n", "originals-limit", conf.OriginalsLimit())
// Additional path and file names.
fmt.Printf("%-25s %s\n", "static-path", conf.StaticPath())
fmt.Printf("%-25s %s\n", "build-path", conf.BuildPath())
fmt.Printf("%-25s %s\n", "img-path", conf.ImgPath())
fmt.Printf("%-25s %s\n", "templates-path", conf.TemplatesPath())
fmt.Printf("%-25s %s\n", "cache-path", conf.CachePath())
fmt.Printf("%-25s %s\n", "temp-path", conf.TempPath())
fmt.Printf("%-25s %t\n", "settings-hidden", conf.SettingsHidden())
// External binaries and sidecar configuration.
fmt.Printf("%-25s %s\n", "rawtherapee-bin", conf.RawtherapeeBin())
fmt.Printf("%-25s %s\n", "darktable-bin", conf.DarktableBin())
@ -103,12 +113,6 @@ func configAction(ctx *cli.Context) error {
fmt.Printf("%-25s %s\n", "heifconvert-bin", conf.HeifConvertBin())
fmt.Printf("%-25s %s\n", "ffmpeg-bin", conf.FFmpegBin())
fmt.Printf("%-25s %s\n", "exiftool-bin", conf.ExifToolBin())
fmt.Printf("%-25s %t\n", "sidecar-json", conf.SidecarJson())
fmt.Printf("%-25s %t\n", "sidecar-yaml", conf.SidecarYaml())
fmt.Printf("%-25s %s\n", "sidecar-path", conf.SidecarPath())
// Geo data API.
fmt.Printf("%-25s %s\n", "geo-api", conf.GeoApi())
// Thumbs, resampling and download security token.
fmt.Printf("%-25s %s\n", "download-token", conf.DownloadToken())

View file

@ -51,14 +51,14 @@ func startAction(ctx *cli.Context) error {
fmt.Printf("NAME VALUE\n")
fmt.Printf("detach-server %t\n", conf.DetachServer())
fmt.Printf("http-host %s\n", conf.HttpServerHost())
fmt.Printf("http-port %d\n", conf.HttpServerPort())
fmt.Printf("http-mode %s\n", conf.HttpServerMode())
fmt.Printf("http-host %s\n", conf.HttpHost())
fmt.Printf("http-port %d\n", conf.HttpPort())
fmt.Printf("http-mode %s\n", conf.HttpMode())
return nil
}
if conf.HttpServerPort() < 1 || conf.HttpServerPort() > 65535 {
if conf.HttpPort() < 1 || conf.HttpPort() > 65535 {
log.Fatal("server port must be a number between 1 and 65535")
}

View file

@ -23,7 +23,7 @@ func statusAction(ctx *cli.Context) error {
conf := config.NewConfig(ctx)
client := &http.Client{Timeout: 10 * time.Second}
url := fmt.Sprintf("http://%s:%d/api/v1/status", conf.HttpServerHost(), conf.HttpServerPort())
url := fmt.Sprintf("http://%s:%d/api/v1/status", conf.HttpHost(), conf.HttpPort())
req, err := http.NewRequest(http.MethodGet, url, nil)
@ -34,9 +34,9 @@ func statusAction(ctx *cli.Context) error {
var status string
if resp, err := client.Do(req); err != nil {
return fmt.Errorf("can't connect to %s:%d", conf.HttpServerHost(), conf.HttpServerPort())
return fmt.Errorf("can't connect to %s:%d", conf.HttpHost(), conf.HttpPort())
} else if resp.StatusCode != 200 {
return fmt.Errorf("server running at %s:%d, bad status %d\n", conf.HttpServerHost(), conf.HttpServerPort(), resp.StatusCode)
return fmt.Errorf("server running at %s:%d, bad status %d\n", conf.HttpHost(), conf.HttpPort(), resp.StatusCode)
} else if body, err := ioutil.ReadAll(resp.Body); err != nil {
return err
} else {

View file

@ -27,7 +27,6 @@ type ClientConfig struct {
UploadNSFW bool `json:"uploadNSFW"`
Public bool `json:"public"`
Experimental bool `json:"experimental"`
DisableSettings bool `json:"disableSettings"`
AlbumCategories []string `json:"albumCategories"`
Albums []entity.Album `json:"albums"`
Cameras []entity.Camera `json:"cameras"`
@ -41,6 +40,7 @@ type ClientConfig struct {
JSHash string `json:"jsHash"`
CSSHash string `json:"cssHash"`
Settings Settings `json:"settings"`
Disable ClientDisable `json:"disable"`
Count ClientCounts `json:"count"`
Pos ClientPosition `json:"pos"`
Years []int `json:"years"`
@ -50,6 +50,14 @@ type ClientConfig struct {
Server RuntimeInfo `json:"server"`
}
// ClientDisable represents disabled client features a user can't turn back on.
type ClientDisable struct {
Backups bool `json:"backups"`
Settings bool `json:"settings"`
Places bool `json:"places"`
}
// ClientCounts represents photo, video and album counts for the client UI.
type ClientCounts struct {
Cameras int `json:"cameras"`
Lenses int `json:"lenses"`
@ -104,7 +112,7 @@ func (c *Config) Flags() (flags []string) {
flags = append(flags, "readonly")
}
if !c.SettingsHidden() {
if !c.DisableSettings() {
flags = append(flags, "settings")
}
@ -130,6 +138,11 @@ func (c *Config) PublicConfig() ClientConfig {
Features: settings.Features,
Share: settings.Share,
},
Disable: ClientDisable{
Backups: true,
Settings: true,
Places: c.DisablePlaces(),
},
Flags: strings.Join(c.Flags(), " "),
Name: c.Name(),
SiteUrl: c.SiteUrl(),
@ -142,7 +155,6 @@ func (c *Config) PublicConfig() ClientConfig {
Copyright: c.Copyright(),
Debug: c.Debug(),
ReadOnly: c.ReadOnly(),
DisableSettings: c.SettingsHidden(),
Public: c.Public(),
Experimental: c.Experimental(),
Status: "",
@ -170,6 +182,11 @@ func (c *Config) GuestConfig() ClientConfig {
Features: settings.Features,
Share: settings.Share,
},
Disable: ClientDisable{
Backups: true,
Settings: true,
Places: c.DisablePlaces(),
},
Flags: "readonly public shared",
Name: c.Name(),
SiteUrl: c.SiteUrl(),
@ -183,7 +200,6 @@ func (c *Config) GuestConfig() ClientConfig {
Debug: c.Debug(),
ReadOnly: true,
UploadNSFW: c.UploadNSFW(),
DisableSettings: true,
Public: true,
Experimental: false,
Colors: colors.All.List(),
@ -203,7 +219,12 @@ func (c *Config) GuestConfig() ClientConfig {
// UserConfig returns client configuration values for registered users.
func (c *Config) UserConfig() ClientConfig {
result := ClientConfig{
Settings: *c.Settings(),
Settings: *c.Settings(),
Disable: ClientDisable{
Backups: c.DisableBackups(),
Settings: c.DisableSettings(),
Places: c.DisablePlaces(),
},
Flags: strings.Join(c.Flags(), " "),
Name: c.Name(),
SiteUrl: c.SiteUrl(),
@ -217,7 +238,6 @@ func (c *Config) UserConfig() ClientConfig {
Debug: c.Debug(),
ReadOnly: c.ReadOnly(),
UploadNSFW: c.UploadNSFW(),
DisableSettings: c.SettingsHidden(),
Public: c.Public(),
Experimental: c.Experimental(),
Colors: colors.All.List(),

View file

@ -290,15 +290,13 @@ func (c *Config) WakeupInterval() time.Duration {
return time.Duration(c.params.WakeupInterval) * time.Second
}
// GeoApi returns the preferred geo coding api (none, osm or places).
// GeoApi returns the preferred geo coding api (none or places).
func (c *Config) GeoApi() string {
switch c.params.GeoApi {
case "places":
return "places"
case "osm":
return "osm"
if c.params.DisablePlaces {
return ""
}
return ""
return "places"
}
// OriginalsLimit returns the file size limit for originals.

View file

@ -63,7 +63,7 @@ func TestConfig_TensorFlowVersion(t *testing.T) {
func TestConfig_TensorFlowDisabled(t *testing.T) {
c := NewConfig(CliTestContext())
version := c.TensorFlowOff()
version := c.DisableTensorFlow()
assert.Equal(t, false, version)
}
@ -114,31 +114,24 @@ func TestConfig_DetachServer(t *testing.T) {
func TestConfig_HttpServerHost(t *testing.T) {
c := NewConfig(CliTestContext())
host := c.HttpServerHost()
host := c.HttpHost()
assert.Equal(t, "0.0.0.0", host)
}
func TestConfig_HttpServerPort(t *testing.T) {
c := NewConfig(CliTestContext())
port := c.HttpServerPort()
port := c.HttpPort()
assert.Equal(t, 2342, port)
}
func TestConfig_HttpServerMode(t *testing.T) {
c := NewConfig(CliTestContext())
mode := c.HttpServerMode()
mode := c.HttpMode()
assert.Equal(t, "release", mode)
}
func TestConfig_HttpServerPassword(t *testing.T) {
c := NewConfig(CliTestContext())
password := c.HttpServerPassword()
assert.Equal(t, "", password)
}
func TestConfig_OriginalsPath(t *testing.T) {
c := NewConfig(CliTestContext())
@ -273,11 +266,9 @@ func TestConfig_WakeupInterval(t *testing.T) {
func TestConfig_GeoApi(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, "", c.GeoApi())
c.params.GeoApi = "places"
assert.Equal(t, "places", c.GeoApi())
c.params.GeoApi = "osm"
assert.Equal(t, "osm", c.GeoApi())
c.params.DisablePlaces = true
assert.Equal(t, "", c.GeoApi())
}
func TestConfig_OriginalsLimit(t *testing.T) {

View file

@ -0,0 +1,34 @@
package config
// DisableBackups tests if photo and album metadata backups should be disabled.
func (c *Config) DisableBackups() bool {
if !c.SidecarWritable() {
return true
}
return c.params.DisableBackups
}
// DisableSettings tests if users should not be allowed to change settings.
func (c *Config) DisableSettings() bool {
return c.params.DisableSettings
}
// DisablePlaces tests if geocoding and maps should be disabled.
func (c *Config) DisablePlaces() bool {
return c.params.DisablePlaces
}
// DisableExifTool tests if ExifTool JSON files should not be created for improved metadata extraction.
func (c *Config) DisableExifTool() bool {
if !c.SidecarWritable() || c.ExifToolBin() == "" {
return true
}
return c.params.DisableExifTool
}
// DisableTensorFlow tests if TensorFlow should not be used for image classification (or anything else).
func (c *Config) DisableTensorFlow() bool {
return c.params.DisableTensorFlow
}

View file

@ -37,25 +37,113 @@ var GlobalFlags = []cli.Flag{
EnvVar: "PHOTOPRISM_CONFIG_FILE",
},
cli.StringFlag{
Name: "admin-password",
Usage: "initial admin password",
EnvVar: "PHOTOPRISM_ADMIN_PASSWORD",
Name: "originals-path",
Usage: "originals `PATH` for your photo and video collection",
EnvVar: "PHOTOPRISM_ORIGINALS_PATH",
},
cli.BoolFlag{
Name: "tensorflow-off",
Usage: "don't use TensorFlow for image classification (or anything else)",
EnvVar: "PHOTOPRISM_TENSORFLOW_OFF",
cli.IntFlag{
Name: "originals-limit",
Value: 1000,
Usage: "file size limit for originals in `MEGABYTE`",
EnvVar: "PHOTOPRISM_ORIGINALS_LIMIT",
},
cli.StringFlag{
Name: "import-path",
Usage: "optional `PATH` for importing files to originals",
EnvVar: "PHOTOPRISM_IMPORT_PATH",
},
cli.StringFlag{
Name: "storage-path",
Usage: "storage `PATH` for cache, database and sidecar files",
EnvVar: "PHOTOPRISM_STORAGE_PATH",
},
cli.StringFlag{
Name: "sidecar-path",
Usage: "relative or absolute storage `PATH` for sidecar files",
EnvVar: "PHOTOPRISM_SIDECAR_PATH",
},
cli.StringFlag{
Name: "cache-path",
Usage: "cache storage `PATH` for sessions and thumbnails",
EnvVar: "PHOTOPRISM_CACHE_PATH",
},
cli.StringFlag{
Name: "temp-path",
Usage: "temporary `PATH` for uploads and downloads",
EnvVar: "PHOTOPRISM_TEMP_PATH",
},
cli.StringFlag{
Name: "backup-path",
Usage: "backup storage `PATH`",
EnvVar: "PHOTOPRISM_BACKUP_PATH",
},
cli.StringFlag{
Name: "assets-path",
Usage: "assets `PATH` for static resources like models and templates",
EnvVar: "PHOTOPRISM_ASSETS_PATH",
},
cli.IntFlag{
Name: "workers, w",
Usage: "number of workers for indexing",
Usage: "`LIMIT` the number of indexing workers to reduce system load",
EnvVar: "PHOTOPRISM_WORKERS",
},
cli.IntFlag{
Name: "wakeup-interval",
Usage: "background worker wakeup interval in seconds",
Usage: "background worker wakeup interval in `SECONDS`",
EnvVar: "PHOTOPRISM_WAKEUP_INTERVAL",
},
cli.BoolFlag{
Name: "disable-backups",
Usage: "don't backup photo and album metadata to YAML files",
EnvVar: "PHOTOPRISM_DISABLE_BACKUPS",
},
cli.BoolFlag{
Name: "disable-settings",
Usage: "users can not view or change settings",
EnvVar: "PHOTOPRISM_DISABLE_SETTINGS",
},
cli.BoolFlag{
Name: "disable-places",
Usage: "disables reverse geocoding and maps",
EnvVar: "PHOTOPRISM_DISABLE_PLACES",
},
cli.BoolFlag{
Name: "disable-exiftool",
Usage: "don't create ExifTool JSON files for improved metadata extraction",
EnvVar: "PHOTOPRISM_DISABLE_EXIFTOOL",
},
cli.BoolFlag{
Name: "disable-tensorflow",
Usage: "don't use TensorFlow for image classification",
EnvVar: "PHOTOPRISM_DISABLE_TENSORFLOW",
},
cli.BoolFlag{
Name: "detect-nsfw",
Usage: "flag photos as private that may be offensive (requires TensorFlow)",
EnvVar: "PHOTOPRISM_DETECT_NSFW",
},
cli.BoolFlag{
Name: "upload-nsfw",
Usage: "allow uploads that may be offensive",
EnvVar: "PHOTOPRISM_UPLOAD_NSFW",
},
cli.StringFlag{
Name: "log-level, l",
Usage: "trace, debug, info, warning, error, fatal or panic",
Value: "info",
EnvVar: "PHOTOPRISM_LOG_LEVEL",
},
cli.StringFlag{
Name: "log-filename",
Usage: "server log `FILENAME`",
EnvVar: "PHOTOPRISM_LOG_FILENAME",
Value: "",
},
cli.StringFlag{
Name: "pid-filename",
Usage: "server process id `FILENAME`",
EnvVar: "PHOTOPRISM_PID_FILENAME",
},
cli.StringFlag{
Name: "site-url",
Usage: "public site `URL`",
@ -105,6 +193,11 @@ var GlobalFlags = []cli.Flag{
Usage: "debug, release or test",
EnvVar: "PHOTOPRISM_HTTP_MODE",
},
cli.StringFlag{
Name: "admin-password",
Usage: "initial admin `PASSWORD`",
EnvVar: "PHOTOPRISM_ADMIN_PASSWORD",
},
cli.StringFlag{
Name: "database-driver",
Usage: "database driver `NAME` (sqlite or mysql)",
@ -140,149 +233,55 @@ var GlobalFlags = []cli.Flag{
},
cli.IntFlag{
Name: "database-conns",
Usage: "max `NUMBER` of open connections to the database",
Usage: "`LIMIT` the number of open database connections",
EnvVar: "PHOTOPRISM_DATABASE_CONNS",
},
cli.IntFlag{
Name: "database-conns-idle",
Usage: "max `NUMBER` of idle connections (equal or less than open)",
Usage: "`LIMIT` the number of idle database connections",
EnvVar: "PHOTOPRISM_DATABASE_CONNS_IDLE",
},
cli.StringFlag{
Name: "assets-path",
Usage: "assets `PATH` for static files like templates and TensorFlow models",
EnvVar: "PHOTOPRISM_ASSETS_PATH",
},
cli.StringFlag{
Name: "storage-path",
Usage: "storage `PATH` for cache, database and sidecar files",
EnvVar: "PHOTOPRISM_STORAGE_PATH",
},
cli.StringFlag{
Name: "backup-path",
Usage: "backup storage `PATH`",
EnvVar: "PHOTOPRISM_BACKUP_PATH",
},
cli.StringFlag{
Name: "import-path",
Usage: "optional import `PATH` for copying files to originals",
EnvVar: "PHOTOPRISM_IMPORT_PATH",
},
cli.StringFlag{
Name: "originals-path",
Usage: "originals `PATH` for photo, video and sidecar files",
EnvVar: "PHOTOPRISM_ORIGINALS_PATH",
},
cli.IntFlag{
Name: "originals-limit",
Value: 1000,
Usage: "file size limit for originals in `MEGABYTE`",
EnvVar: "PHOTOPRISM_ORIGINALS_LIMIT",
},
cli.StringFlag{
Name: "log-level, l",
Usage: "trace, debug, info, warning, error, fatal or panic",
Value: "info",
EnvVar: "PHOTOPRISM_LOG_LEVEL",
},
cli.StringFlag{
Name: "log-filename",
Usage: "filename for storing server logs",
EnvVar: "PHOTOPRISM_LOG_FILENAME",
Value: "",
},
cli.StringFlag{
Name: "pid-filename",
Usage: "filename for the server process id (pid)",
EnvVar: "PHOTOPRISM_PID_FILENAME",
},
cli.StringFlag{
Name: "cache-path",
Usage: "cache `PATH`",
EnvVar: "PHOTOPRISM_CACHE_PATH",
},
cli.StringFlag{
Name: "temp-path",
Usage: "temporary `PATH` for uploads and downloads",
EnvVar: "PHOTOPRISM_TEMP_PATH",
},
cli.BoolFlag{
Name: "settings-hidden",
Usage: "users can not view or change settings",
EnvVar: "PHOTOPRISM_SETTINGS_HIDDEN",
},
cli.StringFlag{
Name: "rawtherapee-bin",
Usage: "rawtherapee-cli executable `FILENAME`",
Usage: "RawTherapee CLI `COMMAND` for raw image conversion",
Value: "rawtherapee-cli",
EnvVar: "PHOTOPRISM_RAWTHERAPEE_BIN",
},
cli.StringFlag{
Name: "darktable-bin",
Usage: "darktable-cli executable `FILENAME`",
Usage: "Darktable CLI `COMMAND` for raw image conversion",
Value: "darktable-cli",
EnvVar: "PHOTOPRISM_DARKTABLE_BIN",
},
cli.BoolFlag{
Name: "darktable-presets",
Usage: "use darktable presets (disables concurrent raw to jpeg conversion)",
Usage: "use Darktable presets (disables concurrent raw image conversion)",
EnvVar: "PHOTOPRISM_DARKTABLE_PRESETS",
},
cli.StringFlag{
Name: "sips-bin",
Usage: "sips executable `FILENAME`",
Usage: "Scriptable Image Processing System `COMMAND`",
Value: "sips",
EnvVar: "PHOTOPRISM_SIPS_BIN",
},
cli.StringFlag{
Name: "heifconvert-bin",
Usage: "heif-convert executable `FILENAME`",
Usage: "HEIC/HEIF image convert `COMMAND`",
Value: "heif-convert",
EnvVar: "PHOTOPRISM_HEIFCONVERT_BIN",
},
cli.StringFlag{
Name: "ffmpeg-bin",
Usage: "ffmpeg executable `FILENAME`",
Usage: "FFmpeg `COMMAND` for video transcoding and cover images",
Value: "ffmpeg",
EnvVar: "PHOTOPRISM_FFMPEG_BIN",
},
cli.StringFlag{
Name: "exiftool-bin",
Usage: "exiftool executable `FILENAME`",
Usage: "ExifTool `COMMAND` for metadata extraction",
Value: "exiftool",
EnvVar: "PHOTOPRISM_EXIFTOOL_BIN",
},
cli.BoolFlag{
Name: "sidecar-json, j",
Usage: "automatically create JSON sidecar files using Exiftool",
EnvVar: "PHOTOPRISM_SIDECAR_JSON",
},
cli.BoolFlag{
Name: "sidecar-yaml, y",
Usage: "automatically backup metadata to YAML sidecar files",
EnvVar: "PHOTOPRISM_SIDECAR_YAML",
},
cli.StringFlag{
Name: "sidecar-path",
Usage: "storage `PATH` for generated sidecar files (relative or absolute)",
EnvVar: "PHOTOPRISM_SIDECAR_PATH",
},
cli.BoolFlag{
Name: "detect-nsfw",
Usage: "flag photos as private that may be offensive",
EnvVar: "PHOTOPRISM_DETECT_NSFW",
},
cli.BoolFlag{
Name: "upload-nsfw",
Usage: "allow uploads that may be offensive",
EnvVar: "PHOTOPRISM_UPLOAD_NSFW",
},
cli.StringFlag{
Name: "geo-api, g",
Usage: "geo data api (none, osm or places)",
Value: "places",
EnvVar: "PHOTOPRISM_GEO_API",
},
cli.StringFlag{
Name: "download-token",
Usage: "`SECRET` url token for file downloads",

View file

@ -216,21 +216,13 @@ func (c *Config) ExifToolBin() string {
}
// Automatically create JSON sidecar files using Exiftool.
func (c *Config) SidecarJson() bool {
if !c.SidecarWritable() || c.ExifToolBin() == "" {
return false
}
return c.params.SidecarJson
func (c *Config) ExifToolJson() bool {
return !c.DisableExifTool()
}
// Automatically backup metadata to YAML sidecar files.
func (c *Config) SidecarYaml() bool {
if !c.SidecarWritable() {
return false
}
return c.params.SidecarYaml
func (c *Config) BackupYaml() bool {
return !c.DisableBackups()
}
// SidecarPath returns the storage path for generated sidecar files (relative or absolute).
@ -266,7 +258,7 @@ func (c *Config) TempPath() string {
return fs.Abs(c.params.TempPath)
}
// CachePath returns the path to the cache.
// CachePath returns the path for cache files.
func (c *Config) CachePath() string {
if c.params.CachePath == "" {
return filepath.Join(c.StoragePath(), "cache")
@ -326,7 +318,7 @@ func (c *Config) BackupPath() string {
return filepath.Join(c.StoragePath(), "backup")
}
// AssetsPath returns the path to static assets.
// AssetsPath returns the path to static assets for models and templates.
func (c *Config) AssetsPath() string {
if c.params.AssetsPath == "" {
// Try to find the right directory by iterating through a list.

View file

@ -13,17 +13,26 @@ func TestConfig_FindExecutable(t *testing.T) {
func TestConfig_SidecarJson(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, false, c.SidecarJson())
c.params.ReadOnly = true
assert.Equal(t, false, c.SidecarJson())
assert.Equal(t, true, c.ExifToolJson())
assert.Equal(t, c.DisableExifTool(), !c.ExifToolJson())
c.params.DisableExifTool = true
assert.Equal(t, false, c.ExifToolJson())
assert.Equal(t, c.DisableExifTool(), !c.ExifToolJson())
}
func TestConfig_SidecarYaml(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, false, c.SidecarYaml())
c.params.ReadOnly = true
assert.Equal(t, false, c.SidecarJson())
assert.Equal(t, true, c.BackupYaml())
assert.Equal(t, c.DisableBackups(), !c.BackupYaml())
c.params.DisableBackups = true
assert.Equal(t, false, c.BackupYaml())
assert.Equal(t, c.DisableBackups(), !c.BackupYaml())
}
func TestConfig_SidecarPath(t *testing.T) {

View file

@ -30,71 +30,71 @@ const (
//
// See https://github.com/photoprism/photoprism/issues/50#issuecomment-433856358
type Params struct {
Name string
Version string
Copyright string
Debug bool `yaml:"debug" flag:"debug"`
Public bool `yaml:"public" flag:"public"`
ReadOnly bool `yaml:"read-only" flag:"read-only"`
Experimental bool `yaml:"experimental" flag:"experimental"`
ConfigPath string `yaml:"config-path" flag:"config-path"`
ConfigFile string
AdminPassword string `yaml:"admin-password" flag:"admin-password"`
SiteUrl string `yaml:"site-url" flag:"site-url"`
SitePreview string `yaml:"site-preview" flag:"site-preview"`
SiteTitle string `yaml:"site-title" flag:"site-title"`
SiteCaption string `yaml:"site-caption" flag:"site-caption"`
SiteDescription string `yaml:"site-description" flag:"site-description"`
SiteAuthor string `yaml:"site-author" flag:"site-author"`
TensorFlowOff bool `yaml:"tensorflow-off" flag:"tensorflow-off"`
Workers int `yaml:"workers" flag:"workers"`
WakeupInterval int `yaml:"wakeup-interval" flag:"wakeup-interval"`
LogLevel string `yaml:"log-level" flag:"log-level"`
AssetsPath string `yaml:"assets-path" flag:"assets-path"`
StoragePath string `yaml:"storage-path" flag:"storage-path"`
BackupPath string `yaml:"backup-path" flag:"backup-path"`
ImportPath string `yaml:"import-path" flag:"import-path"`
OriginalsPath string `yaml:"originals-path" flag:"originals-path"`
OriginalsLimit int64 `yaml:"originals-limit" flag:"originals-limit"`
SettingsHidden bool `yaml:"settings-hidden" flag:"settings-hidden"`
TempPath string `yaml:"temp-path" flag:"temp-path"`
CachePath string `yaml:"cache-path" flag:"cache-path"`
DatabaseDriver string `yaml:"database-driver" flag:"database-driver"`
DatabaseDsn string `yaml:"database-dsn" flag:"database-dsn"`
DatabaseServer string `yaml:"database-server" flag:"database-server"`
DatabaseName string `yaml:"database-name" flag:"database-name"`
DatabaseUser string `yaml:"database-user" flag:"database-user"`
DatabasePassword string `yaml:"database-password" flag:"database-password"`
DatabaseConns int `yaml:"database-conns" flag:"database-conns"`
DatabaseConnsIdle int `yaml:"database-conns-idle" flag:"database-conns-idle"`
HttpServerHost string `yaml:"http-host" flag:"http-host"`
HttpServerPort int `yaml:"http-port" flag:"http-port"`
HttpServerMode string `yaml:"http-mode" flag:"http-mode"`
HttpServerPassword string `yaml:"http-password" flag:"http-password"`
SipsBin string `yaml:"sips-bin" flag:"sips-bin"`
RawtherapeeBin string `yaml:"rawtherapee-bin" flag:"rawtherapee-bin"`
DarktableBin string `yaml:"darktable-bin" flag:"darktable-bin"`
DarktablePresets bool `yaml:"darktable-presets" flag:"darktable-presets"`
HeifConvertBin string `yaml:"heifconvert-bin" flag:"heifconvert-bin"`
FFmpegBin string `yaml:"ffmpeg-bin" flag:"ffmpeg-bin"`
ExifToolBin string `yaml:"exiftool-bin" flag:"exiftool-bin"`
SidecarJson bool `yaml:"sidecar-json" flag:"sidecar-json"`
SidecarYaml bool `yaml:"sidecar-yaml" flag:"sidecar-yaml"`
SidecarPath string `yaml:"sidecar-path" flag:"sidecar-path"`
PIDFilename string `yaml:"pid-filename" flag:"pid-filename"`
LogFilename string `yaml:"log-filename" flag:"log-filename"`
DetachServer bool `yaml:"detach-server" flag:"detach-server"`
DetectNSFW bool `yaml:"detect-nsfw" flag:"detect-nsfw"`
UploadNSFW bool `yaml:"upload-nsfw" flag:"upload-nsfw"`
GeoApi string `yaml:"geo-api" flag:"geo-api"`
DownloadToken string `yaml:"download-token" flag:"download-token"`
PreviewToken string `yaml:"preview-token" flag:"preview-token"`
ThumbFilter string `yaml:"thumb-filter" flag:"thumb-filter"`
ThumbUncached bool `yaml:"thumb-uncached" flag:"thumb-uncached"`
ThumbSize int `yaml:"thumb-size" flag:"thumb-size"`
ThumbSizeUncached int `yaml:"thumb-size-uncached" flag:"thumb-size-uncached"`
JpegSize int `yaml:"jpeg-size" flag:"jpeg-size"`
JpegQuality int `yaml:"jpeg-quality" flag:"jpeg-quality"`
Name string
Version string
Copyright string
Debug bool `yaml:"Debug" flag:"debug"`
Public bool `yaml:"Public" flag:"public"`
ReadOnly bool `yaml:"ReadOnly" flag:"read-only"`
Experimental bool `yaml:"Experimental" flag:"experimental"`
ConfigPath string `yaml:"ConfigPath" flag:"config-path"`
ConfigFile string
AdminPassword string `yaml:"AdminPassword" flag:"admin-password"`
OriginalsPath string `yaml:"OriginalsPath" flag:"originals-path"`
OriginalsLimit int64 `yaml:"OriginalsLimit" flag:"originals-limit"`
ImportPath string `yaml:"ImportPath" flag:"import-path"`
StoragePath string `yaml:"StoragePath" flag:"storage-path"`
SidecarPath string `yaml:"SidecarPath" flag:"sidecar-path"`
TempPath string `yaml:"TempPath" flag:"temp-path"`
BackupPath string `yaml:"BackupPath" flag:"backup-path"`
AssetsPath string `yaml:"AssetsPath" flag:"assets-path"`
CachePath string `yaml:"CachePath" flag:"cache-path"`
Workers int `yaml:"Workers" flag:"workers"`
WakeupInterval int `yaml:"WakeupInterval" flag:"wakeup-interval"`
DisableBackups bool `yaml:"DisableBackups" flag:"disable-backups"`
DisableSettings bool `yaml:"DisableSettings" flag:"disable-settings"`
DisablePlaces bool `yaml:"DisablePlaces" flag:"disable-places"`
DisableExifTool bool `yaml:"DisableExifTool" flag:"disable-exiftool"`
DisableTensorFlow bool `yaml:"DisableTensorFlow" flag:"disable-tensorflow"`
DetectNSFW bool `yaml:"DetectNSFW" flag:"detect-nsfw"`
UploadNSFW bool `yaml:"UploadNSFW" flag:"upload-nsfw"`
LogLevel string `yaml:"LogLevel" flag:"log-level"`
LogFilename string `yaml:"LogFilename" flag:"log-filename"`
PIDFilename string `yaml:"PIDFilename" flag:"pid-filename"`
SiteUrl string `yaml:"SiteUrl" flag:"site-url"`
SitePreview string `yaml:"SitePreview" flag:"site-preview"`
SiteTitle string `yaml:"SiteTitle" flag:"site-title"`
SiteCaption string `yaml:"SiteCaption" flag:"site-caption"`
SiteDescription string `yaml:"SiteDescription" flag:"site-description"`
SiteAuthor string `yaml:"SiteAuthor" flag:"site-author"`
DatabaseDriver string `yaml:"DatabaseDriver" flag:"database-driver"`
DatabaseDsn string `yaml:"DatabaseDsn" flag:"database-dsn"`
DatabaseServer string `yaml:"DatabaseServer" flag:"database-server"`
DatabaseName string `yaml:"DatabaseName" flag:"database-name"`
DatabaseUser string `yaml:"DatabaseUser" flag:"database-user"`
DatabasePassword string `yaml:"DatabasePassword" flag:"database-password"`
DatabaseConns int `yaml:"DatabaseConns" flag:"database-conns"`
DatabaseConnsIdle int `yaml:"DatabaseConnsIdle" flag:"database-conns-idle"`
HttpHost string `yaml:"HttpHost" flag:"http-host"`
HttpPort int `yaml:"HttpPort" flag:"http-port"`
HttpMode string `yaml:"HttpMode" flag:"http-mode"`
SipsBin string `yaml:"SipsBin" flag:"sips-bin"`
RawtherapeeBin string `yaml:"RawtherapeeBin" flag:"rawtherapee-bin"`
DarktableBin string `yaml:"DarktableBin" flag:"darktable-bin"`
DarktablePresets bool `yaml:"DarktablePresets" flag:"darktable-presets"`
HeifConvertBin string `yaml:"HeifConvertBin" flag:"heifconvert-bin"`
FFmpegBin string `yaml:"FFmpegBin" flag:"ffmpeg-bin"`
ExifToolBin string `yaml:"ExifToolBin" flag:"exiftool-bin"`
BackupYaml bool `yaml:"BackupYaml" flag:"backup-yaml"`
DetachServer bool `yaml:"DetachServer" flag:"detach-server"`
DownloadToken string `yaml:"DownloadToken" flag:"download-token"`
PreviewToken string `yaml:"PreviewToken" flag:"preview-token"`
ThumbFilter string `yaml:"ThumbFilter" flag:"thumb-filter"`
ThumbUncached bool `yaml:"ThumbUncached" flag:"thumb-uncached"`
ThumbSize int `yaml:"ThumbSize" flag:"thumb-size"`
ThumbSizeUncached int `yaml:"ThumbSizeUncached" flag:"thumb-size-uncached"`
JpegSize int `yaml:"JpegSize" flag:"jpeg-size"`
JpegQuality int `yaml:"JpegQuality" flag:"jpeg-quality"`
}
// NewParams creates a new configuration entity by using two methods:

View file

@ -38,7 +38,7 @@ func TestParams_SetValuesFromFile(t *testing.T) {
assert.Equal(t, "/srv/photoprism/temp", c.TempPath)
assert.NotEmpty(t, c.DatabaseDriver)
assert.NotEmpty(t, c.DatabaseDsn)
assert.Equal(t, 81, c.HttpServerPort)
assert.Equal(t, 81, c.HttpPort)
}
func TestParams_ExpandFilenames(t *testing.T) {

View file

@ -11,27 +11,27 @@ func (c *Config) DetachServer() bool {
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.params.HttpServerHost == "" {
// HttpHost returns the built-in HTTP server host name or IP address (empty for all interfaces).
func (c *Config) HttpHost() string {
if c.params.HttpHost == "" {
return "0.0.0.0"
}
return c.params.HttpServerHost
return c.params.HttpHost
}
// HttpServerPort returns the built-in HTTP server port.
func (c *Config) HttpServerPort() int {
if c.params.HttpServerPort == 0 {
// HttpPort returns the built-in HTTP server port.
func (c *Config) HttpPort() int {
if c.params.HttpPort == 0 {
return 2342
}
return c.params.HttpServerPort
return c.params.HttpPort
}
// HttpServerMode returns the server mode.
func (c *Config) HttpServerMode() string {
if c.params.HttpServerMode == "" {
// HttpMode returns the server mode.
func (c *Config) HttpMode() string {
if c.params.HttpMode == "" {
if c.Debug() {
return "debug"
}
@ -39,12 +39,7 @@ func (c *Config) HttpServerMode() string {
return "release"
}
return c.params.HttpServerMode
}
// HttpServerPassword returns the password for the user interface (optional).
func (c *Config) HttpServerPassword() string {
return c.params.HttpServerPassword
return c.params.HttpMode
}
// TemplatesPath returns the server templates path.

View file

@ -9,27 +9,27 @@ import (
func TestConfig_HttpServerHost2(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, "0.0.0.0", c.HttpServerHost())
c.params.HttpServerHost = "test"
assert.Equal(t, "test", c.HttpServerHost())
assert.Equal(t, "0.0.0.0", c.HttpHost())
c.params.HttpHost = "test"
assert.Equal(t, "test", c.HttpHost())
}
func TestConfig_HttpServerPort2(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, int(2342), c.HttpServerPort())
c.params.HttpServerPort = int(1234)
assert.Equal(t, int(1234), c.HttpServerPort())
assert.Equal(t, int(2342), c.HttpPort())
c.params.HttpPort = int(1234)
assert.Equal(t, int(1234), c.HttpPort())
}
func TestConfig_HttpServerMode2(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, "release", c.HttpServerMode())
assert.Equal(t, "release", c.HttpMode())
c.params.Debug = true
assert.Equal(t, "debug", c.HttpServerMode())
c.params.HttpServerMode = "test"
assert.Equal(t, "test", c.HttpServerMode())
assert.Equal(t, "debug", c.HttpMode())
c.params.HttpMode = "test"
assert.Equal(t, "test", c.HttpMode())
}
func TestConfig_TemplateName(t *testing.T) {

View file

@ -13,89 +13,84 @@ import (
"gopkg.in/yaml.v2"
)
// SettingsHidden returns true if the user is not allowed to change settings.
func (c *Config) SettingsHidden() bool {
return c.params.SettingsHidden
}
// UISettings represents user interface settings.
type UISettings struct {
Scrollbar bool `json:"scrollbar" yaml:"scrollbar"`
Theme string `json:"theme" yaml:"theme"`
Language string `json:"language" yaml:"language"`
Scrollbar bool `json:"scrollbar" yaml:"Scrollbar"`
Theme string `json:"theme" yaml:"Theme"`
Language string `json:"language" yaml:"Language"`
}
// TemplateSettings represents template settings for the UI and messaging.
type TemplateSettings struct {
Default string `json:"default" yaml:"default"`
Default string `json:"default" yaml:"Default"`
}
// MapsSettings represents maps settings (for places).
type MapsSettings struct {
Animate int `json:"animate" yaml:"animate"`
Style string `json:"style" yaml:"style"`
Animate int `json:"animate" yaml:"Animate"`
Style string `json:"style" yaml:"Style"`
}
// FeatureSettings represents feature flags, mainly for the Web UI.
type FeatureSettings struct {
Upload bool `json:"upload" yaml:"upload"`
Download bool `json:"download" yaml:"download"`
Private bool `json:"private" yaml:"private"`
Review bool `json:"review" yaml:"review"`
Files bool `json:"files" yaml:"files"`
Moments bool `json:"moments" yaml:"moments"`
Labels bool `json:"labels" yaml:"labels"`
Places bool `json:"places" yaml:"places"`
Edit bool `json:"edit" yaml:"edit"`
Archive bool `json:"archive" yaml:"archive"`
Delete bool `json:"delete" yaml:"delete"`
Share bool `json:"share" yaml:"share"`
Library bool `json:"library" yaml:"library"`
Import bool `json:"import" yaml:"import"`
Logs bool `json:"logs" yaml:"logs"`
Upload bool `json:"upload" yaml:"Upload"`
Download bool `json:"download" yaml:"Download"`
Private bool `json:"private" yaml:"Private"`
Review bool `json:"review" yaml:"Review"`
Files bool `json:"files" yaml:"Files"`
Moments bool `json:"moments" yaml:"Moments"`
Labels bool `json:"labels" yaml:"Labels"`
Places bool `json:"places" yaml:"Places"`
Edit bool `json:"edit" yaml:"Edit"`
Archive bool `json:"archive" yaml:"Archive"`
Delete bool `json:"delete" yaml:"Delete"`
Share bool `json:"share" yaml:"Share"`
Library bool `json:"library" yaml:"Library"`
Import bool `json:"import" yaml:"Import"`
Logs bool `json:"logs" yaml:"Logs"`
}
// ImportSettings represents import settings.
type ImportSettings struct {
Path string `json:"path" yaml:"path"`
Move bool `json:"move" yaml:"move"`
Path string `json:"path" yaml:"Path"`
Move bool `json:"move" yaml:"Move"`
}
// IndexSettings represents indexing settings.
type IndexSettings struct {
Path string `json:"path" yaml:"path"`
Convert bool `json:"convert" yaml:"convert"`
Rescan bool `json:"rescan" yaml:"rescan"`
Path string `json:"path" yaml:"Path"`
Convert bool `json:"convert" yaml:"Convert"`
Rescan bool `json:"rescan" yaml:"Rescan"`
}
// StackSettings represents settings for files that belong to the same photo.
type StackSettings struct {
UUID bool `json:"uuid" yaml:"uuid"`
Meta bool `json:"meta" yaml:"meta"`
Name bool `json:"name" yaml:"name"`
UUID bool `json:"uuid" yaml:"UUID"`
Meta bool `json:"meta" yaml:"Meta"`
Name bool `json:"name" yaml:"Name"`
}
// ShareSettings represents content sharing settings.
type ShareSettings struct {
Title string `json:"title" yaml:"title"`
Title string `json:"title" yaml:"Title"`
}
// DownloadSettings represents content download settings.
type DownloadSettings struct {
Name entity.DownloadName `json:"name" yaml:"name"`
Name entity.DownloadName `json:"name" yaml:"Name"`
}
// Settings represents user settings for Web UI, indexing, and import.
type Settings struct {
UI UISettings `json:"ui" yaml:"ui"`
Templates TemplateSettings `json:"templates" yaml:"templates"`
Maps MapsSettings `json:"maps" yaml:"maps"`
Features FeatureSettings `json:"features" yaml:"features"`
Import ImportSettings `json:"import" yaml:"import"`
Index IndexSettings `json:"index" yaml:"index"`
Stack StackSettings `json:"stack" yaml:"stack"`
Share ShareSettings `json:"share" yaml:"share"`
Download DownloadSettings `json:"download" yaml:"download"`
UI UISettings `json:"ui" yaml:"UI"`
Templates TemplateSettings `json:"templates" yaml:"Templates"`
Maps MapsSettings `json:"maps" yaml:"Maps"`
Features FeatureSettings `json:"features" yaml:"Features"`
Import ImportSettings `json:"import" yaml:"Import"`
Index IndexSettings `json:"index" yaml:"Index"`
Stack StackSettings `json:"stack" yaml:"Stack"`
Share ShareSettings `json:"share" yaml:"Share"`
Download DownloadSettings `json:"download" yaml:"Download"`
}
// NewSettings creates a new Settings instance.
@ -234,5 +229,9 @@ func (c *Config) Settings() *Settings {
c.initSettings()
}
if c.DisablePlaces() {
c.settings.Features.Places = false
}
return c.settings
}

View file

@ -11,11 +11,6 @@ func (c *Config) TensorFlowVersion() string {
return tf.Version()
}
// TensorFlowOff returns true if TensorFlow should NOT be used for image classification (or anything else).
func (c *Config) TensorFlowOff() bool {
return c.params.TensorFlowOff
}
// TensorFlowModelPath returns the TensorFlow model path.
func (c *Config) TensorFlowModelPath() string {
return filepath.Join(c.AssetsPath(), "nasnet")

View file

@ -1,15 +1,15 @@
debug: false
darktable-cli: /usr/bin/darktable-cli
assets-path: /srv/photoprism
cache-path: /srv/photoprism/cache
originals-path: /srv/photoprism/photos/originals
import-path: /srv/photoprism/photos/import
temp-path: /srv/photoprism/temp
http-host:
http-mode: release
http-port: 81
http-password:
database-driver: sqlite
database-dsn: .photoprism.db
theme: lavendel
language: english
Debug: false
DarktableBin: /usr/bin/darktable-cli
AssetsPath: /srv/photoprism
CachePath: /srv/photoprism/cache
OriginalsPath: /srv/photoprism/photos/originals
ImportPath: /srv/photoprism/photos/import
TempPath: /srv/photoprism/temp
HttpServerHost:
HttpMode: release
HttpPort: 81
HttpPassword:
DatabaseDriver: sqlite
DatabaseDsn: .photoprism.db
Theme: lavendel
Language: english

View file

@ -1,40 +1,40 @@
ui:
scrollbar: true
theme: onyx
language: de
templates:
default: index.tmpl
maps:
animate: 0
style: streets
features:
upload: true
download: true
private: true
review: true
files: true
moments: true
labels: true
places: true
edit: true
archive: true
delete: false
share: true
library: true
import: true
logs: true
import:
path: /
move: false
index:
path: /
convert: true
rescan: false
stack:
uuid: true
meta: true
name: false
share:
title: ""
download:
name: file
UI:
Scrollbar: true
Theme: onyx
Language: de
Templates:
Default: index.tmpl
Maps:
Animate: 0
Style: streets
Features:
Upload: true
Download: true
Private: true
Review: true
Files: true
Moments: true
Labels: true
Places: true
Edit: true
Archive: true
Delete: false
Share: true
Library: true
Import: true
Logs: true
Import:
Path: /
Move: false
Index:
Path: /
Convert: true
Rescan: false
Stack:
UUID: true
Meta: true
Name: false
Share:
Title: ""
Download:
Name: file

View file

@ -13,7 +13,7 @@ type PhotoAlbum struct {
Order int `json:"Order" yaml:"Order,omitempty"`
Hidden bool `json:"Hidden" yaml:"Hidden,omitempty"`
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"UpdatedAt,omitempty"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
Photo *Photo `gorm:"PRELOAD:false" yaml:"-"`
Album *Album `gorm:"PRELOAD:true" yaml:"-"`
}

View file

@ -25,12 +25,12 @@ import (
// Config represents backend api credentials for maps & geodata.
type Config struct {
Key string `json:"key" yaml:"key"`
Secret string `json:"secret" yaml:"secret"`
Session string `json:"session" yaml:"session"`
Status string `json:"status" yaml:"status"`
Version string `json:"version" yaml:"version"`
Serial string `json:"serial" yaml:"serial"`
Key string `json:"key" yaml:"Key"`
Secret string `json:"secret" yaml:"Secret"`
Session string `json:"session" yaml:"Session"`
Status string `json:"status" yaml:"Status"`
Version string `json:"version" yaml:"Version"`
Serial string `json:"serial" yaml:"Serial"`
FileName string `json:"-" yaml:"-"`
}

View file

@ -1,5 +1,5 @@
key: b32e9ccdc90eb7c0f6f1b9fbc82b8a2b0e993304
secret: 5991ea36a9611e9e00a8360c10b91567
session: 3ef5685c6391a568731c8fc94ccad82d92dea60476c8b672990047c822248f45366fc0e8e812ad15e0b5ae1eb20e866235c56b
status: unregistered
version: 0.0.0
Key: b32e9ccdc90eb7c0f6f1b9fbc82b8a2b0e993304
Secret: 5991ea36a9611e9e00a8360c10b91567
Session: 3ef5685c6391a568731c8fc94ccad82d92dea60476c8b672990047c822248f45366fc0e8e812ad15e0b5ae1eb20e866235c56b
Status: unregistered
Version: 0.0.0

View file

@ -1,5 +1,5 @@
key: ab66cb5cfb3658dbea0a1433df048d900934ac68
secret: 6b0f8440fe307d3120b3a4366350094b
session: c0ca88fc3094b70a1947b5b10f980a420cd6b1542a20f6f26ecc6a16f340473b9fb16b80be1078e86d886b3a8d46bf8184d147
status: unregistered
version: 200925-f8e2b580-Darwin-i386-DEBUG
Key: ab66cb5cfb3658dbea0a1433df048d900934ac68
Secret: 6b0f8440fe307d3120b3a4366350094b
Session: c0ca88fc3094b70a1947b5b10f980a420cd6b1542a20f6f26ecc6a16f340473b9fb16b80be1078e86d886b3a8d46bf8184d147
Status: unregistered
Version: 200925-f8e2b580-Darwin-i386-DEBUG

View file

@ -1,5 +1,5 @@
key: 8dd8b115d052f91ac74b1c2475e305009366c487
secret: ddf4ce46afbf6c16a6bd8555ab1e4efb
session: 7607796238c26b2d95007957b05c72d63f504346576bc2aa064a6dc54344de47d2ab38422bd1d061c067a16ef517e6054d8b7f5336c120431935518277fed45e49472aaf740cac1bc33ab2e362c767007a59e953e9973709
status: unregistered
version: 0.0.0
Key: 8dd8b115d052f91ac74b1c2475e305009366c487
Secret: ddf4ce46afbf6c16a6bd8555ab1e4efb
Session: 7607796238c26b2d95007957b05c72d63f504346576bc2aa064a6dc54344de47d2ab38422bd1d061c067a16ef517e6054d8b7f5336c120431935518277fed45e49472aaf740cac1bc33ab2e362c767007a59e953e9973709
Status: unregistered
Version: 0.0.0

View file

@ -13,7 +13,7 @@ import (
func BackupAlbums(force bool) (count int, result error) {
c := Config()
if !c.SidecarYaml() && !force {
if !c.BackupYaml() && !force {
log.Debugf("backup: album yaml files disabled")
return count, nil
}
@ -43,7 +43,7 @@ func BackupAlbums(force bool) (count int, result error) {
func RestoreAlbums(force bool) (count int, result error) {
c := Config()
if !c.SidecarYaml() && !force {
if !c.BackupYaml() && !force {
log.Debugf("restore: album yaml files disabled")
return count, nil
}

View file

@ -12,7 +12,7 @@ import (
func TestNewImport(t *testing.T) {
conf := config.TestConfig()
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)
@ -27,7 +27,7 @@ func TestImport_DestinationFilename(t *testing.T) {
conf.InitializeTestData(t)
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)
@ -59,7 +59,7 @@ func TestImport_Start(t *testing.T) {
conf.InitializeTestData(t)
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)

View file

@ -105,7 +105,7 @@ func ImportWorker(jobs <-chan ImportJob) {
}
}
if imp.conf.SidecarJson() && f.IsMedia() && !f.HasJson() {
if imp.conf.ExifToolJson() && f.IsMedia() && !f.HasJson() {
if jsonFile, err := imp.convert.ToJson(f); err != nil {
log.Errorf("import: %s in %s (create json sidecar)", err.Error(), txt.Quote(f.BaseName()))
} else {
@ -167,7 +167,7 @@ func ImportWorker(jobs <-chan ImportJob) {
continue
}
if ind.conf.SidecarJson() && f.IsMedia() && !f.HasJson() {
if ind.conf.ExifToolJson() && f.IsMedia() && !f.HasJson() {
if jsonFile, err := ind.convert.ToJson(f); err != nil {
log.Errorf("import: failed creating json sidecar for %s (%s)", txt.Quote(f.BaseName()), err.Error())
} else {

View file

@ -560,7 +560,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
if file.FilePrimary {
primaryFile = file
if !Config().TensorFlowOff() {
if !Config().DisableTensorFlow() {
// Image classification via TensorFlow.
labels = ind.classifyImage(m)
@ -837,7 +837,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
return result
}
if file.FilePrimary && Config().SidecarYaml() {
if file.FilePrimary && Config().BackupYaml() {
// Write YAML sidecar file (optional).
yamlFile := photo.YamlFileName(Config().OriginalsPath(), Config().SidecarPath())

View file

@ -19,7 +19,7 @@ func TestIndex_MediaFile(t *testing.T) {
conf.InitializeTestData(t)
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)
@ -40,7 +40,7 @@ func TestIndex_MediaFile(t *testing.T) {
conf.InitializeTestData(t)
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)

View file

@ -46,7 +46,7 @@ func IndexMain(related *RelatedFiles, ind *Index, opt IndexOptions) (result Inde
}
}
if ind.conf.SidecarJson() && f.IsMedia() && !f.HasJson() {
if ind.conf.ExifToolJson() && f.IsMedia() && !f.HasJson() {
if jsonFile, err := ind.convert.ToJson(f); err != nil {
log.Errorf("index: failed creating json sidecar for %s (%s)", txt.Quote(f.BaseName()), err.Error())
} else {
@ -102,7 +102,7 @@ func IndexRelated(related RelatedFiles, ind *Index, opt IndexOptions) (result In
continue
}
if ind.conf.SidecarJson() && f.IsMedia() && !f.HasJson() {
if ind.conf.ExifToolJson() && f.IsMedia() && !f.HasJson() {
if jsonFile, err := ind.convert.ToJson(f); err != nil {
log.Errorf("index: failed creating json sidecar for %s (%s)", txt.Quote(f.BaseName()), err.Error())
} else {

View file

@ -50,7 +50,7 @@ func TestIndexRelated(t *testing.T) {
t.Fatal(err)
}
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)

View file

@ -19,7 +19,7 @@ func TestIndex_Start(t *testing.T) {
conf.InitializeTestData(t)
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)
@ -44,7 +44,7 @@ func TestIndex_File(t *testing.T) {
conf.InitializeTestData(t)
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)

View file

@ -28,7 +28,7 @@ func TestResample_Start(t *testing.T) {
conf.InitializeTestData(t)
tf := classify.New(conf.AssetsPath(), conf.TensorFlowOff())
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath())
convert := NewConvert(conf)

View file

@ -20,8 +20,8 @@ func Start(ctx context.Context, conf *config.Config) {
}
}()
if conf.HttpServerMode() != "" {
gin.SetMode(conf.HttpServerMode())
if conf.HttpMode() != "" {
gin.SetMode(conf.HttpMode())
} else if conf.Debug() == false {
gin.SetMode(gin.ReleaseMode)
}
@ -35,7 +35,7 @@ func Start(ctx context.Context, conf *config.Config) {
registerRoutes(router, conf)
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", conf.HttpServerHost(), conf.HttpServerPort()),
Addr: fmt.Sprintf("%s:%d", conf.HttpHost(), conf.HttpPort()),
Handler: router,
}

View file

@ -9,7 +9,7 @@ import (
var onceClassify sync.Once
func initClassify() {
services.Classify = classify.New(Config().AssetsPath(), Config().TensorFlowOff())
services.Classify = classify.New(Config().AssetsPath(), Config().DisableTensorFlow())
}
func Classify() *classify.TensorFlow {