Refactor handling of environment variables
This commit is contained in:
parent
9098bf38d1
commit
107da91700
|
@ -1,7 +1,7 @@
|
|||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
cache/
|
||||
photo_cache/
|
||||
media_cache/
|
||||
/photos_path
|
||||
photoview.db
|
||||
|
||||
|
|
|
@ -2,13 +2,14 @@ package database
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/photoview/photoview/api/database/drivers"
|
||||
"github.com/photoview/photoview/api/graphql/models"
|
||||
"github.com/photoview/photoview/api/utils"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
|
@ -18,13 +19,14 @@ import (
|
|||
)
|
||||
|
||||
func getMysqlAddress() (*url.URL, error) {
|
||||
address, err := url.Parse(os.Getenv("PHOTOVIEW_MYSQL_URL"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not parse mysql url")
|
||||
addressString := utils.EnvMysqlURL.GetValue()
|
||||
if addressString == "" {
|
||||
return nil, errors.New(fmt.Sprintf("Environment variable %s missing, exiting", utils.EnvMysqlURL.GetName()))
|
||||
}
|
||||
|
||||
if address.String() == "" {
|
||||
return nil, errors.New("Environment variable PHOTOVIEW_MYSQL_URL missing, exiting")
|
||||
address, err := url.Parse(addressString)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not parse mysql url")
|
||||
}
|
||||
|
||||
queryValues := address.Query()
|
||||
|
@ -36,7 +38,7 @@ func getMysqlAddress() (*url.URL, error) {
|
|||
}
|
||||
|
||||
func getSqliteAddress() (*url.URL, error) {
|
||||
path := os.Getenv("PHOTOVIEW_SQLITE_PATH")
|
||||
path := utils.EnvSqlitePath.GetValue()
|
||||
if path == "" {
|
||||
path = "photoview.db"
|
||||
}
|
||||
|
@ -62,8 +64,12 @@ func SetupDatabase() (*gorm.DB, error) {
|
|||
|
||||
config := gorm.Config{}
|
||||
|
||||
// Enable database debug logging
|
||||
// Configure database logging
|
||||
if utils.DevelopmentMode() {
|
||||
config.Logger = logger.Default.LogMode(logger.Info)
|
||||
} else {
|
||||
config.Logger = logger.Default.LogMode(logger.Warn)
|
||||
}
|
||||
|
||||
var databaseDialect gorm.Dialector
|
||||
switch drivers.DatabaseDriver() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package drivers
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/photoview/photoview/api/utils"
|
||||
)
|
||||
|
||||
// DatabaseDriverType represents the name of a database driver
|
||||
type DatabaseDriverType string
|
||||
|
||||
const (
|
||||
|
@ -15,7 +17,7 @@ const (
|
|||
func DatabaseDriver() DatabaseDriverType {
|
||||
|
||||
var driver DatabaseDriverType
|
||||
driverString := strings.ToLower(os.Getenv("PHOTOVIEW_DATABASE_DRIVER"))
|
||||
driverString := strings.ToLower(utils.EnvDatabaseDriver.GetValue())
|
||||
|
||||
switch driverString {
|
||||
case "mysql":
|
||||
|
|
|
@ -13,6 +13,9 @@ PHOTOVIEW_LISTEN_PORT=4001
|
|||
PHOTOVIEW_API_ENDPOINT=http://localhost:4001/
|
||||
PHOTOVIEW_UI_ENDPOINT=http://localhost:1234/
|
||||
|
||||
# Path where media should be cached, defaults to ./media_cache
|
||||
# PHOTOVIEW_MEDIA_CACHE=./media_cache
|
||||
|
||||
# Set to 1 for the server to also serve the built static ui files
|
||||
PHOTOVIEW_SERVE_UI=0
|
||||
# When PHOTOVIEW_SERVE_UI is 1, PHOTOVIEW_PUBLIC_ENDPOINT is used instead of PHOTOVIEW_API_ENDPOINT and PHOTOVIEW_UI_ENDPOINT
|
||||
|
|
|
@ -20,6 +20,10 @@ func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onl
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if len(user.Albums) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
userAlbumIDs := make([]int, len(user.Albums))
|
||||
for i, album := range user.Albums {
|
||||
userAlbumIDs[i] = album.ID
|
||||
|
|
|
@ -335,7 +335,7 @@ func (r *mutationResolver) UserRemoveRootAlbum(ctx context.Context, userID int,
|
|||
if deletedAlbumIDs != nil {
|
||||
// Delete albums from cache
|
||||
for _, id := range deletedAlbumIDs {
|
||||
cacheAlbumPath := path.Join(scanner.PhotoCache(), strconv.Itoa(id))
|
||||
cacheAlbumPath := path.Join(scanner.MediaCachePath(), strconv.Itoa(id))
|
||||
|
||||
if err := os.RemoveAll(cacheAlbumPath); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -41,7 +41,7 @@ func RegisterPhotoRoutes(db *gorm.DB, router *mux.Router) {
|
|||
var cachedPath string
|
||||
|
||||
if mediaURL.Purpose == models.PhotoThumbnail || mediaURL.Purpose == models.PhotoHighRes || mediaURL.Purpose == models.VideoThumbnail {
|
||||
cachedPath = path.Join(scanner.PhotoCache(), strconv.Itoa(int(media.AlbumID)), strconv.Itoa(int(mediaURL.MediaID)), mediaURL.MediaName)
|
||||
cachedPath = path.Join(scanner.MediaCachePath(), strconv.Itoa(int(media.AlbumID)), strconv.Itoa(int(mediaURL.MediaID)), mediaURL.MediaName)
|
||||
} else if mediaURL.Purpose == models.MediaOriginal {
|
||||
cachedPath = media.Path
|
||||
} else {
|
||||
|
|
|
@ -40,7 +40,7 @@ func RegisterVideoRoutes(db *gorm.DB, router *mux.Router) {
|
|||
var cachedPath string
|
||||
|
||||
if mediaURL.Purpose == models.VideoWeb {
|
||||
cachedPath = path.Join(scanner.PhotoCache(), strconv.Itoa(int(media.AlbumID)), strconv.Itoa(int(mediaURL.MediaID)), mediaURL.MediaName)
|
||||
cachedPath = path.Join(scanner.MediaCachePath(), strconv.Itoa(int(media.AlbumID)), strconv.Itoa(int(mediaURL.MediaID)), mediaURL.MediaName)
|
||||
} else {
|
||||
log.Printf("ERROR: Can not handle media_purpose for video: %s\n", mediaURL.Purpose)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
|
|
@ -36,7 +36,7 @@ func CleanupMedia(db *gorm.DB, albumId int, albumMedia []*models.Media) []error
|
|||
for _, media := range mediaList {
|
||||
|
||||
mediaIDs = append(mediaIDs, media.ID)
|
||||
cachePath := path.Join(PhotoCache(), strconv.Itoa(int(albumId)), strconv.Itoa(int(media.ID)))
|
||||
cachePath := path.Join(MediaCachePath(), strconv.Itoa(int(albumId)), strconv.Itoa(int(media.ID)))
|
||||
err := os.RemoveAll(cachePath)
|
||||
if err != nil {
|
||||
deleteErrors = append(deleteErrors, errors.Wrapf(err, "delete unused cache folder (%s)", cachePath))
|
||||
|
@ -84,7 +84,7 @@ func deleteOldUserAlbums(db *gorm.DB, scannedAlbums []*models.Album, user *model
|
|||
deleteAlbumIDs := make([]int, len(albums))
|
||||
for i, album := range albums {
|
||||
deleteAlbumIDs[i] = album.ID
|
||||
cachePath := path.Join(PhotoCache(), strconv.Itoa(int(album.ID)))
|
||||
cachePath := path.Join(MediaCachePath(), strconv.Itoa(int(album.ID)))
|
||||
err := os.RemoveAll(cachePath)
|
||||
if err != nil {
|
||||
deleteErrors = append(deleteErrors, errors.Wrapf(err, "delete unused cache folder (%s)", cachePath))
|
||||
|
|
|
@ -202,14 +202,14 @@ func processPhoto(tx *gorm.DB, imageData *EncodeMediaData, photoCachePath *strin
|
|||
func makeMediaCacheDir(media *models.Media) (*string, error) {
|
||||
|
||||
// Make root cache dir if not exists
|
||||
if _, err := os.Stat(PhotoCache()); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(PhotoCache(), os.ModePerm); err != nil {
|
||||
if _, err := os.Stat(MediaCachePath()); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(MediaCachePath(), os.ModePerm); err != nil {
|
||||
return nil, errors.Wrap(err, "could not make root image cache directory")
|
||||
}
|
||||
}
|
||||
|
||||
// Make album cache dir if not exists
|
||||
albumCachePath := path.Join(PhotoCache(), strconv.Itoa(int(media.AlbumID)))
|
||||
albumCachePath := path.Join(MediaCachePath(), strconv.Itoa(int(media.AlbumID)))
|
||||
if _, err := os.Stat(albumCachePath); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(albumCachePath, os.ModePerm); err != nil {
|
||||
return nil, errors.Wrap(err, "could not make album image cache directory")
|
||||
|
|
|
@ -207,10 +207,11 @@ func ScannerError(format string, args ...interface{}) {
|
|||
})
|
||||
}
|
||||
|
||||
func PhotoCache() string {
|
||||
photoCache := os.Getenv("PHOTO_CACHE")
|
||||
// MediaCachePath returns the path for where the media cache is located on the file system
|
||||
func MediaCachePath() string {
|
||||
photoCache := utils.EnvMediaCachePath.GetValue()
|
||||
if photoCache == "" {
|
||||
photoCache = "./photo_cache"
|
||||
photoCache = "./media_cache"
|
||||
}
|
||||
|
||||
return photoCache
|
||||
|
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
|
@ -29,7 +28,7 @@ func main() {
|
|||
log.Println("No .env file found")
|
||||
}
|
||||
|
||||
devMode := os.Getenv("PHOTOVIEW_DEVELOPMENT_MODE") == "1"
|
||||
devMode := utils.DevelopmentMode()
|
||||
|
||||
db, err := database.SetupDatabase()
|
||||
if err != nil {
|
||||
|
@ -92,7 +91,7 @@ func main() {
|
|||
videoRouter := endpointRouter.PathPrefix("/video").Subrouter()
|
||||
routes.RegisterVideoRoutes(db, videoRouter)
|
||||
|
||||
shouldServeUI := os.Getenv("PHOTOVIEW_SERVE_UI") == "1"
|
||||
shouldServeUI := utils.ShouldServeUI()
|
||||
|
||||
if shouldServeUI {
|
||||
spa := routes.NewSpaHandler("/ui", "index.html")
|
||||
|
@ -111,7 +110,7 @@ func main() {
|
|||
log.Printf("Photoview UI public endpoint ready at %s\n", uiEndpoint.String())
|
||||
|
||||
if !shouldServeUI {
|
||||
log.Printf("Notice: UI is not served by the the api (PHOTOVIEW_SERVE_UI=0)")
|
||||
log.Printf("Notice: UI is not served by the the api (%s=0)", utils.EnvServeUI.GetName())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
)
|
||||
|
@ -12,7 +11,7 @@ import (
|
|||
func ApiListenUrl() *url.URL {
|
||||
const defaultPort = "4001"
|
||||
|
||||
shouldServeUI := os.Getenv("PHOTOVIEW_SERVE_UI") == "1"
|
||||
shouldServeUI := ShouldServeUI()
|
||||
|
||||
apiPrefix := "/"
|
||||
if shouldServeUI {
|
||||
|
@ -21,19 +20,19 @@ func ApiListenUrl() *url.URL {
|
|||
|
||||
var listenAddr string
|
||||
|
||||
listenAddr = os.Getenv("PHOTOVIEW_LISTEN_IP")
|
||||
listenAddr = EnvListenIP.GetValue()
|
||||
if listenAddr == "" {
|
||||
listenAddr = "127.0.0.1"
|
||||
}
|
||||
|
||||
listenPortStr := os.Getenv("PHOTOVIEW_LISTEN_PORT")
|
||||
listenPortStr := EnvListenPort.GetValue()
|
||||
if listenPortStr == "" {
|
||||
listenPortStr = defaultPort
|
||||
}
|
||||
|
||||
listenPort, err := strconv.Atoi(listenPortStr)
|
||||
if err != nil {
|
||||
log.Fatalf("PHOTOVIEW_LISTEN_PORT must be a number: '%s'\n%s", listenPortStr, err)
|
||||
log.Fatalf("%s must be a number: '%s'\n%s", EnvListenPort.GetName(), listenPortStr, err)
|
||||
}
|
||||
|
||||
apiUrl, err := url.Parse(fmt.Sprintf("http://%s:%d", listenAddr, listenPort))
|
||||
|
@ -46,16 +45,16 @@ func ApiListenUrl() *url.URL {
|
|||
}
|
||||
|
||||
func ApiEndpointUrl() *url.URL {
|
||||
apiEndpointStr := os.Getenv("PHOTOVIEW_API_ENDPOINT")
|
||||
apiEndpointStr := EnvAPIEndpoint.GetValue()
|
||||
|
||||
shouldServeUI := os.Getenv("PHOTOVIEW_SERVE_UI") == "1"
|
||||
shouldServeUI := ShouldServeUI()
|
||||
if shouldServeUI {
|
||||
apiEndpointStr = os.Getenv("PHOTOVIEW_PUBLIC_ENDPOINT")
|
||||
apiEndpointStr = EnvPublicEndpoint.GetValue()
|
||||
}
|
||||
|
||||
apiEndpointUrl, err := url.Parse(apiEndpointStr)
|
||||
if err != nil {
|
||||
log.Fatalf("ERROR: Environment variable PHOTOVIEW_API_ENDPOINT is not a proper url")
|
||||
log.Fatalf("ERROR: Environment variable %s is not a proper url (%s)", EnvAPIEndpoint.GetName(), EnvAPIEndpoint.GetValue())
|
||||
}
|
||||
|
||||
if shouldServeUI {
|
||||
|
@ -66,16 +65,16 @@ func ApiEndpointUrl() *url.URL {
|
|||
}
|
||||
|
||||
func UiEndpointUrl() *url.URL {
|
||||
uiEndpointStr := os.Getenv("PHOTOVIEW_UI_ENDPOINT")
|
||||
uiEndpointStr := EnvUIEndpoint.GetValue()
|
||||
|
||||
shouldServeUI := os.Getenv("PHOTOVIEW_SERVE_UI") == "1"
|
||||
shouldServeUI := ShouldServeUI()
|
||||
if shouldServeUI {
|
||||
uiEndpointStr = os.Getenv("PHOTOVIEW_PUBLIC_ENDPOINT")
|
||||
uiEndpointStr = EnvPublicEndpoint.GetValue()
|
||||
}
|
||||
|
||||
uiEndpointUrl, err := url.Parse(uiEndpointStr)
|
||||
if err != nil {
|
||||
log.Fatalf("ERROR: Environment variable PHOTOVIEW_UI_ENDPOINT is not a proper url")
|
||||
log.Fatalf("ERROR: Environment variable %s is not a proper url (%s)", EnvUIEndpoint.GetName(), EnvUIEndpoint.GetValue())
|
||||
}
|
||||
|
||||
return uiEndpointUrl
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package utils
|
||||
|
||||
import "os"
|
||||
|
||||
// EnvironmentVariable represents the name of an environment variable used to configure Photoview
|
||||
type EnvironmentVariable string
|
||||
|
||||
// General options
|
||||
const (
|
||||
EnvDevelopmentMode EnvironmentVariable = "PHOTOVIEW_DEVELOPMENT_MODE"
|
||||
EnvServeUI EnvironmentVariable = "PHOTOVIEW_SERVE_UI"
|
||||
EnvMediaCachePath EnvironmentVariable = "PHOTOVIEW_MEDIA_CACHE"
|
||||
)
|
||||
|
||||
// Network related
|
||||
const (
|
||||
EnvListenIP EnvironmentVariable = "PHOTOVIEW_LISTEN_IP"
|
||||
EnvListenPort EnvironmentVariable = "PHOTOVIEW_LISTEN_PORT"
|
||||
EnvAPIEndpoint EnvironmentVariable = "PHOTOVIEW_API_ENDPOINT"
|
||||
EnvUIEndpoint EnvironmentVariable = "PHOTOVIEW_UI_ENDPOINT"
|
||||
EnvPublicEndpoint EnvironmentVariable = "PHOTOVIEW_PUBLIC_ENDPOINT"
|
||||
)
|
||||
|
||||
// Database related
|
||||
const (
|
||||
EnvDatabaseDriver EnvironmentVariable = "PHOTOVIEW_DATABASE_DRIVER"
|
||||
EnvMysqlURL EnvironmentVariable = "PHOTOVIEW_MYSQL_URL"
|
||||
EnvSqlitePath EnvironmentVariable = "PHOTOVIEW_SQLITE_PATH"
|
||||
)
|
||||
|
||||
// GetName returns the name of the environment variable itself
|
||||
func (v EnvironmentVariable) GetName() string {
|
||||
return string(v)
|
||||
}
|
||||
|
||||
// GetValue returns the value of the environment
|
||||
func (v EnvironmentVariable) GetValue() string {
|
||||
return os.Getenv(string(v))
|
||||
}
|
||||
|
||||
// ShouldServeUI whether or not the "serve ui" option is enabled
|
||||
func ShouldServeUI() bool {
|
||||
return EnvServeUI.GetValue() == "1"
|
||||
}
|
||||
|
||||
// DevelopmentMode describes whether or not the server is running in development mode,
|
||||
// and should thus print debug informations and enable other features related to developing.
|
||||
func DevelopmentMode() bool {
|
||||
return EnvDevelopmentMode.GetValue() == "1"
|
||||
}
|
|
@ -24,7 +24,7 @@ services:
|
|||
- PHOTOVIEW_MYSQL_URL=photoview:photosecret@tcp(db)/photoview
|
||||
- PHOTOVIEW_LISTEN_IP=photoview
|
||||
- PHOTOVIEW_LISTEN_PORT=80
|
||||
- PHOTO_CACHE=/app/cache
|
||||
- PHOTOVIEW_MEDIA_CACHE=/app/cache
|
||||
|
||||
# Change This: The publicly exposed url
|
||||
# For example if the server is available from the domain example.com,
|
||||
|
|
Loading…
Reference in New Issue