mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 00:34:13 +01:00
Config: Refactor initialization of settings and database connection
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
@@ -214,7 +214,7 @@ func OIDCRedirect(router *gin.RouterGroup) {
|
||||
// Set user avatar image?
|
||||
if avatarUrl := userInfo.Picture; avatarUrl == "" || user.HasAvatar() {
|
||||
// Do nothing.
|
||||
} else if err = avatar.SetUserImageURL(user, avatarUrl, entity.SrcOIDC); err != nil {
|
||||
} else if err = avatar.SetUserImageURL(user, avatarUrl, entity.SrcOIDC, conf.ThumbCachePath()); err != nil {
|
||||
event.AuditWarn([]string{clientIp, "create session", "oidc", userName, "failed to set avatar image", err.Error()})
|
||||
}
|
||||
} else if conf.OIDCRegister() {
|
||||
@@ -287,7 +287,7 @@ func OIDCRedirect(router *gin.RouterGroup) {
|
||||
// Set user avatar image.
|
||||
if avatarUrl := userInfo.Picture; avatarUrl == "" {
|
||||
event.AuditDebug([]string{clientIp, "create session", "oidc", userName, "no avatar image provided"})
|
||||
} else if err = avatar.SetUserImageURL(user, avatarUrl, entity.SrcOIDC); err != nil {
|
||||
} else if err = avatar.SetUserImageURL(user, avatarUrl, entity.SrcOIDC, conf.ThumbCachePath()); err != nil {
|
||||
event.AuditWarn([]string{clientIp, "create session", "oidc", userName, "failed to set avatar image", err.Error()})
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -122,7 +122,7 @@ func UploadUserAvatar(router *gin.RouterGroup) {
|
||||
}
|
||||
|
||||
// Set user avatar image.
|
||||
if err = avatar.SetUserImage(m, filePath, entity.SrcManual); err != nil {
|
||||
if err = avatar.SetUserImage(m, filePath, entity.SrcManual, conf.ThumbCachePath()); err != nil {
|
||||
event.AuditErr([]string{ClientIP(c), "session %s", "upload avatar", "%s"}, s.RefID, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
// init initializes the package.
|
||||
func init() {
|
||||
// Register OpenID Connect extension.
|
||||
config.Register("oidc", UpdateConfig, ClientConfig)
|
||||
config.Register("oidc", InitConfig, ClientConfig)
|
||||
}
|
||||
|
||||
// ClientConfig returns the OIDC client config values.
|
||||
@@ -24,7 +24,7 @@ func ClientConfig(c *config.Config, t config.ClientType) config.Map {
|
||||
return result
|
||||
}
|
||||
|
||||
// UpdateConfig initializes the OIDC config options.
|
||||
func UpdateConfig(c *config.Config) error {
|
||||
// InitConfig initializes the OIDC config options.
|
||||
func InitConfig(c *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ func backupAction(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
if backupDatabase {
|
||||
|
||||
@@ -120,7 +120,6 @@ func CallWithDependencies(ctx *cli.Context, action func(conf *config.Config) err
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
// Run command.
|
||||
|
||||
@@ -48,7 +48,6 @@ func convertAction(ctx *cli.Context) error {
|
||||
return config.ErrReadOnly
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
convertPath := conf.OriginalsPath()
|
||||
|
||||
@@ -38,7 +38,6 @@ func findAction(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
frm := form.SearchPhotos{
|
||||
|
||||
@@ -64,7 +64,6 @@ func migrationsStatusAction(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
var ids []string
|
||||
@@ -153,7 +152,6 @@ func migrationsRunAction(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
if ctx.Bool("trace") {
|
||||
|
||||
@@ -49,7 +49,6 @@ func resetAction(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
if !ctx.Bool("yes") {
|
||||
|
||||
@@ -75,7 +75,6 @@ func restoreAction(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
// Restore database from backup dump?
|
||||
|
||||
@@ -42,7 +42,6 @@ func thumbsAction(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.RegisterDb()
|
||||
defer conf.Shutdown()
|
||||
|
||||
dir := strings.TrimSpace(ctx.Args().First())
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -128,7 +127,7 @@ func NewConfig(ctx *cli.Context) *Config {
|
||||
// Initialize logger.
|
||||
initLogger()
|
||||
|
||||
// Initialize options from config file and CLI context.
|
||||
// Initialize options from the "defaults.yml" file and CLI context.
|
||||
c := &Config{
|
||||
cliCtx: ctx,
|
||||
options: NewOptions(ctx),
|
||||
@@ -137,7 +136,7 @@ func NewConfig(ctx *cli.Context) *Config {
|
||||
start: start,
|
||||
}
|
||||
|
||||
// WriteFile values with options.yml from config path.
|
||||
// Override options with values from the "options.yml" file, if it exists.
|
||||
if optionsYaml := c.OptionsYaml(); fs.FileExists(optionsYaml) {
|
||||
if err := c.options.Load(optionsYaml); err != nil {
|
||||
log.Warnf("config: failed loading values from %s (%s)", clean.Log(optionsYaml), err)
|
||||
@@ -146,102 +145,9 @@ func NewConfig(ctx *cli.Context) *Config {
|
||||
}
|
||||
}
|
||||
|
||||
Ext().Init(c)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Unsafe checks if unsafe settings are allowed.
|
||||
func (c *Config) Unsafe() bool {
|
||||
return c.options.Unsafe
|
||||
}
|
||||
|
||||
// Restart checks if the application should be restarted, e.g. after an update or a config changes.
|
||||
func (c *Config) Restart() bool {
|
||||
return mutex.Restart.Load()
|
||||
}
|
||||
|
||||
// CliContext returns the cli context if set.
|
||||
func (c *Config) CliContext() *cli.Context {
|
||||
if c.cliCtx == nil {
|
||||
log.Warnf("config: cli context not set - you may have found a bug")
|
||||
}
|
||||
|
||||
return c.cliCtx
|
||||
}
|
||||
|
||||
// CliGlobalString returns a global cli string flag value if set.
|
||||
func (c *Config) CliGlobalString(name string) string {
|
||||
if c.cliCtx == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return c.cliCtx.GlobalString(name)
|
||||
}
|
||||
|
||||
// Options returns the raw config options.
|
||||
func (c *Config) Options() *Options {
|
||||
if c.options == nil {
|
||||
log.Warnf("config: options should not be nil - you may have found a bug")
|
||||
c.options = NewOptions(nil)
|
||||
}
|
||||
|
||||
return c.options
|
||||
}
|
||||
|
||||
// Propagate updates config options in other packages as needed.
|
||||
func (c *Config) Propagate() {
|
||||
FlushCache()
|
||||
log.SetLevel(c.LogLevel())
|
||||
|
||||
// Initialize the thumbnail generation package.
|
||||
thumb.Library = c.ThumbLibrary()
|
||||
thumb.Color = c.ThumbColor()
|
||||
thumb.Filter = c.ThumbFilter()
|
||||
thumb.SizeCached = c.ThumbSizePrecached()
|
||||
thumb.SizeOnDemand = c.ThumbSizeUncached()
|
||||
thumb.JpegQualityDefault = c.JpegQuality()
|
||||
thumb.CachePublic = c.HttpCachePublic()
|
||||
|
||||
// Set cache expiration defaults.
|
||||
ttl.CacheDefault = c.HttpCacheMaxAge()
|
||||
ttl.CacheVideo = c.HttpVideoMaxAge()
|
||||
|
||||
// Set geocoding parameters.
|
||||
places.UserAgent = c.UserAgent()
|
||||
entity.GeoApi = c.GeoApi()
|
||||
|
||||
// Set session cache duration.
|
||||
entity.SessionCacheDuration = c.SessionCacheDuration()
|
||||
|
||||
// Set minimum password length.
|
||||
entity.PasswordLength = c.PasswordLength()
|
||||
|
||||
// Set path for user assets.
|
||||
entity.UsersPath = c.UsersPath()
|
||||
|
||||
// Set API preview and download default tokens.
|
||||
entity.PreviewToken.Set(c.PreviewToken(), entity.TokenConfig)
|
||||
entity.DownloadToken.Set(c.DownloadToken(), entity.TokenConfig)
|
||||
entity.ValidateTokens = !c.Public()
|
||||
|
||||
// Set face recognition parameters.
|
||||
face.ScoreThreshold = c.FaceScore()
|
||||
face.OverlapThreshold = c.FaceOverlap()
|
||||
face.ClusterScoreThreshold = c.FaceClusterScore()
|
||||
face.ClusterSizeThreshold = c.FaceClusterSize()
|
||||
face.ClusterCore = c.FaceClusterCore()
|
||||
face.ClusterDist = c.FaceClusterDist()
|
||||
face.MatchDist = c.FaceMatchDist()
|
||||
|
||||
// Set default theme and locale.
|
||||
customize.DefaultTheme = c.DefaultTheme()
|
||||
customize.DefaultLocale = c.DefaultLocale()
|
||||
|
||||
c.Settings().Propagate()
|
||||
c.Hub().Propagate()
|
||||
}
|
||||
|
||||
// Init creates directories, parses additional config files, opens a database connection and initializes dependencies.
|
||||
func (c *Config) Init() error {
|
||||
start := time.Now()
|
||||
@@ -304,11 +210,18 @@ func (c *Config) Init() error {
|
||||
_ = os.Setenv("HTTPS_PROXY", httpsProxy)
|
||||
}
|
||||
|
||||
// Configure HTTP user agent.
|
||||
places.UserAgent = c.UserAgent()
|
||||
|
||||
// Load settings from the "settings.yml" config file.
|
||||
c.initSettings()
|
||||
c.initHub()
|
||||
|
||||
// Connect to database.
|
||||
if err := c.connectDb(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.RegisterDb()
|
||||
}
|
||||
|
||||
// Initialize extensions.
|
||||
Ext().Init(c)
|
||||
|
||||
// Initialize the thumbnail generation package.
|
||||
thumb.Init(memory.FreeMemory(), c.IndexWorkers(), c.ThumbLibrary())
|
||||
@@ -316,10 +229,8 @@ func (c *Config) Init() error {
|
||||
// Update package defaults.
|
||||
c.Propagate()
|
||||
|
||||
// Connect to database.
|
||||
if err := c.connectDb(); err != nil {
|
||||
return err
|
||||
} else if !c.Sponsor() {
|
||||
// Show support information.
|
||||
if !c.Sponsor() {
|
||||
log.Info(MsgSponsor)
|
||||
log.Info(MsgSignUp)
|
||||
}
|
||||
@@ -330,6 +241,97 @@ func (c *Config) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Propagate updates config options in other packages as needed.
|
||||
func (c *Config) Propagate() {
|
||||
FlushCache()
|
||||
log.SetLevel(c.LogLevel())
|
||||
|
||||
// Initialize the thumbnail generation package.
|
||||
thumb.Library = c.ThumbLibrary()
|
||||
thumb.Color = c.ThumbColor()
|
||||
thumb.Filter = c.ThumbFilter()
|
||||
thumb.SizeCached = c.ThumbSizePrecached()
|
||||
thumb.SizeOnDemand = c.ThumbSizeUncached()
|
||||
thumb.JpegQualityDefault = c.JpegQuality()
|
||||
thumb.CachePublic = c.HttpCachePublic()
|
||||
|
||||
// Set cache expiration defaults.
|
||||
ttl.CacheDefault = c.HttpCacheMaxAge()
|
||||
ttl.CacheVideo = c.HttpVideoMaxAge()
|
||||
|
||||
// Set geocoding parameters.
|
||||
places.UserAgent = c.UserAgent()
|
||||
entity.GeoApi = c.GeoApi()
|
||||
|
||||
// Set session cache duration.
|
||||
entity.SessionCacheDuration = c.SessionCacheDuration()
|
||||
|
||||
// Set minimum password length.
|
||||
entity.PasswordLength = c.PasswordLength()
|
||||
|
||||
// Set path for user assets.
|
||||
entity.UsersPath = c.UsersPath()
|
||||
|
||||
// Set API preview and download default tokens.
|
||||
entity.PreviewToken.Set(c.PreviewToken(), entity.TokenConfig)
|
||||
entity.DownloadToken.Set(c.DownloadToken(), entity.TokenConfig)
|
||||
entity.ValidateTokens = !c.Public()
|
||||
|
||||
// Set face recognition parameters.
|
||||
face.ScoreThreshold = c.FaceScore()
|
||||
face.OverlapThreshold = c.FaceOverlap()
|
||||
face.ClusterScoreThreshold = c.FaceClusterScore()
|
||||
face.ClusterSizeThreshold = c.FaceClusterSize()
|
||||
face.ClusterCore = c.FaceClusterCore()
|
||||
face.ClusterDist = c.FaceClusterDist()
|
||||
face.MatchDist = c.FaceMatchDist()
|
||||
|
||||
// Set default theme and locale.
|
||||
customize.DefaultTheme = c.DefaultTheme()
|
||||
customize.DefaultLocale = c.DefaultLocale()
|
||||
|
||||
c.Settings().Propagate()
|
||||
c.Hub().Propagate()
|
||||
}
|
||||
|
||||
// Options returns the raw config options.
|
||||
func (c *Config) Options() *Options {
|
||||
if c.options == nil {
|
||||
log.Warnf("config: options should not be nil - you may have found a bug")
|
||||
c.options = NewOptions(nil)
|
||||
}
|
||||
|
||||
return c.options
|
||||
}
|
||||
|
||||
// Unsafe checks if unsafe settings are allowed.
|
||||
func (c *Config) Unsafe() bool {
|
||||
return c.options.Unsafe
|
||||
}
|
||||
|
||||
// Restart checks if the application should be restarted, e.g. after an update or a config changes.
|
||||
func (c *Config) Restart() bool {
|
||||
return mutex.Restart.Load()
|
||||
}
|
||||
|
||||
// CliContext returns the cli context if set.
|
||||
func (c *Config) CliContext() *cli.Context {
|
||||
if c.cliCtx == nil {
|
||||
log.Warnf("config: cli context not set - you may have found a bug")
|
||||
}
|
||||
|
||||
return c.cliCtx
|
||||
}
|
||||
|
||||
// CliGlobalString returns a global cli string flag value if set.
|
||||
func (c *Config) CliGlobalString(name string) string {
|
||||
if c.cliCtx == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return c.cliCtx.GlobalString(name)
|
||||
}
|
||||
|
||||
// readSerial reads and returns the current storage serial.
|
||||
func (c *Config) readSerial() string {
|
||||
storageName := filepath.Join(c.StoragePath(), serialName)
|
||||
@@ -437,192 +439,6 @@ func (c *Config) Copyright() string {
|
||||
return c.options.Copyright
|
||||
}
|
||||
|
||||
// BaseUri returns the site base URI for a given resource.
|
||||
func (c *Config) BaseUri(res string) string {
|
||||
if c.SiteUrl() == "" {
|
||||
return res
|
||||
}
|
||||
|
||||
u, err := url.Parse(c.SiteUrl())
|
||||
|
||||
if err != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
return strings.TrimRight(u.EscapedPath(), "/") + res
|
||||
}
|
||||
|
||||
// ApiUri returns the api URI.
|
||||
func (c *Config) ApiUri() string {
|
||||
return c.BaseUri(ApiUri)
|
||||
}
|
||||
|
||||
// CdnUrl returns the optional content delivery network URI without trailing slash.
|
||||
func (c *Config) CdnUrl(res string) string {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return res
|
||||
}
|
||||
|
||||
return strings.TrimRight(c.options.CdnUrl, "/") + res
|
||||
}
|
||||
|
||||
// UseCdn checks if a Content Deliver Network (CDN) is used to serve static content.
|
||||
func (c *Config) UseCdn() bool {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// NoCdn checks if there is no Content Deliver Network (CDN) configured to serve static content.
|
||||
func (c *Config) NoCdn() bool {
|
||||
return !c.UseCdn()
|
||||
}
|
||||
|
||||
// CdnDomain returns the content delivery network domain name if specified.
|
||||
func (c *Config) CdnDomain() string {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return ""
|
||||
} else if u, err := url.Parse(c.options.CdnUrl); err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return u.Hostname()
|
||||
}
|
||||
}
|
||||
|
||||
// CdnVideo checks if videos should be streamed using the configured CDN.
|
||||
func (c *Config) CdnVideo() bool {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return false
|
||||
}
|
||||
|
||||
return c.options.CdnVideo
|
||||
}
|
||||
|
||||
// CORSOrigin returns the value for the Access-Control-Allow-Origin header, if any.
|
||||
func (c *Config) CORSOrigin() string {
|
||||
return clean.Header(c.options.CORSOrigin)
|
||||
}
|
||||
|
||||
// CORSHeaders returns the value for the Access-Control-Allow-Headers header, if any.
|
||||
func (c *Config) CORSHeaders() string {
|
||||
return clean.Header(c.options.CORSHeaders)
|
||||
}
|
||||
|
||||
// CORSMethods returns the value for the Access-Control-Allow-Methods header, if any.
|
||||
func (c *Config) CORSMethods() string {
|
||||
return clean.Header(c.options.CORSMethods)
|
||||
}
|
||||
|
||||
// ContentUri returns the content delivery URI.
|
||||
func (c *Config) ContentUri() string {
|
||||
return c.CdnUrl(c.ApiUri())
|
||||
}
|
||||
|
||||
// VideoUri returns the video streaming URI.
|
||||
func (c *Config) VideoUri() string {
|
||||
if c.CdnVideo() {
|
||||
return c.ContentUri()
|
||||
}
|
||||
|
||||
return c.ApiUri()
|
||||
}
|
||||
|
||||
// StaticUri returns the static content URI.
|
||||
func (c *Config) StaticUri() string {
|
||||
return c.CdnUrl(c.BaseUri(StaticUri))
|
||||
}
|
||||
|
||||
// StaticAssetUri returns the resource URI of the static file asset.
|
||||
func (c *Config) StaticAssetUri(res string) string {
|
||||
return c.StaticUri() + "/" + res
|
||||
}
|
||||
|
||||
// SiteUrl returns the public server URL (default is "http://localhost:2342/").
|
||||
func (c *Config) SiteUrl() string {
|
||||
if c.options.SiteUrl == "" {
|
||||
return "http://localhost:2342/"
|
||||
}
|
||||
|
||||
return strings.TrimRight(c.options.SiteUrl, "/") + "/"
|
||||
}
|
||||
|
||||
// SiteHttps checks if the site URL uses HTTPS.
|
||||
func (c *Config) SiteHttps() bool {
|
||||
if c.options.SiteUrl == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.HasPrefix(c.options.SiteUrl, "https://")
|
||||
}
|
||||
|
||||
// SiteDomain returns the public server domain.
|
||||
func (c *Config) SiteDomain() string {
|
||||
if u, err := url.Parse(c.SiteUrl()); err != nil {
|
||||
return "localhost"
|
||||
} else {
|
||||
return u.Hostname()
|
||||
}
|
||||
}
|
||||
|
||||
// SiteAuthor returns the site author / copyright.
|
||||
func (c *Config) SiteAuthor() string {
|
||||
return c.options.SiteAuthor
|
||||
}
|
||||
|
||||
// SiteTitle returns the main site title (default is application name).
|
||||
func (c *Config) SiteTitle() string {
|
||||
if c.options.SiteTitle == "" {
|
||||
return c.Name()
|
||||
}
|
||||
|
||||
return c.options.SiteTitle
|
||||
}
|
||||
|
||||
// SiteCaption returns a short site caption.
|
||||
func (c *Config) SiteCaption() string {
|
||||
return c.options.SiteCaption
|
||||
}
|
||||
|
||||
// SiteDescription returns a long site description.
|
||||
func (c *Config) SiteDescription() string {
|
||||
return c.options.SiteDescription
|
||||
}
|
||||
|
||||
// SitePreview returns the site preview image URL for sharing.
|
||||
func (c *Config) SitePreview() string {
|
||||
if c.options.SitePreview == "" {
|
||||
return fmt.Sprintf("https://i.photoprism.app/prism?cover=64&style=centered%%20dark&caption=none&title=%s", url.QueryEscape(c.AppName()))
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(c.options.SitePreview, "http") {
|
||||
return c.SiteUrl() + strings.TrimPrefix(c.options.SitePreview, "/")
|
||||
}
|
||||
|
||||
return c.options.SitePreview
|
||||
}
|
||||
|
||||
// LegalInfo returns the legal info text for the page footer.
|
||||
func (c *Config) LegalInfo() string {
|
||||
if s := c.CliGlobalString("imprint"); s != "" {
|
||||
log.Warnf("config: option 'imprint' is deprecated, please use 'legal-info'")
|
||||
return s
|
||||
}
|
||||
|
||||
return c.options.LegalInfo
|
||||
}
|
||||
|
||||
// LegalUrl returns the legal info url.
|
||||
func (c *Config) LegalUrl() string {
|
||||
if s := c.CliGlobalString("imprint-url"); s != "" {
|
||||
log.Warnf("config: option 'imprint-url' is deprecated, please use 'legal-url'")
|
||||
return s
|
||||
}
|
||||
|
||||
return c.options.LegalUrl
|
||||
}
|
||||
|
||||
// Prod checks if production mode is enabled, hides non-essential log messages.
|
||||
func (c *Config) Prod() bool {
|
||||
return c.options.Prod
|
||||
@@ -679,16 +495,6 @@ func (c *Config) ReadOnly() bool {
|
||||
return c.options.ReadOnly
|
||||
}
|
||||
|
||||
// DetectNSFW checks if NSFW photos should be detected and flagged.
|
||||
func (c *Config) DetectNSFW() bool {
|
||||
return c.options.DetectNSFW
|
||||
}
|
||||
|
||||
// UploadNSFW checks if NSFW photos can be uploaded.
|
||||
func (c *Config) UploadNSFW() bool {
|
||||
return c.options.UploadNSFW
|
||||
}
|
||||
|
||||
// LogLevel returns the Logrus log level.
|
||||
func (c *Config) LogLevel() logrus.Level {
|
||||
// Normalize string.
|
||||
|
||||
@@ -16,12 +16,22 @@ func (c *Config) TensorFlowModelPath() string {
|
||||
return filepath.Join(c.AssetsPath(), "nasnet")
|
||||
}
|
||||
|
||||
// FaceNetModelPath returns the FaceNet model path.
|
||||
func (c *Config) FaceNetModelPath() string {
|
||||
return filepath.Join(c.AssetsPath(), "facenet")
|
||||
}
|
||||
|
||||
// NSFWModelPath returns the "not safe for work" TensorFlow model path.
|
||||
func (c *Config) NSFWModelPath() string {
|
||||
return filepath.Join(c.AssetsPath(), "nsfw")
|
||||
}
|
||||
|
||||
// FaceNetModelPath returns the FaceNet model path.
|
||||
func (c *Config) FaceNetModelPath() string {
|
||||
return filepath.Join(c.AssetsPath(), "facenet")
|
||||
// DetectNSFW checks if NSFW photos should be detected and flagged.
|
||||
func (c *Config) DetectNSFW() bool {
|
||||
return c.options.DetectNSFW
|
||||
}
|
||||
|
||||
// UploadNSFW checks if NSFW photos can be uploaded.
|
||||
func (c *Config) UploadNSFW() bool {
|
||||
return c.options.UploadNSFW
|
||||
}
|
||||
47
internal/config/config_ai_test.go
Normal file
47
internal/config/config_ai_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConfig_TensorFlowVersion(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
version := c.TensorFlowVersion()
|
||||
assert.IsType(t, "1.15.0", version)
|
||||
}
|
||||
|
||||
func TestConfig_TensorFlowModelPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
path := c.TensorFlowModelPath()
|
||||
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/assets/nasnet", path)
|
||||
}
|
||||
|
||||
func TestConfig_TensorFlowDisabled(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
version := c.DisableTensorFlow()
|
||||
assert.Equal(t, false, version)
|
||||
}
|
||||
|
||||
func TestConfig_NSFWModelPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Contains(t, c.NSFWModelPath(), "/assets/nsfw")
|
||||
}
|
||||
|
||||
func TestConfig_FaceNetModelPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Contains(t, c.FaceNetModelPath(), "/assets/facenet")
|
||||
}
|
||||
|
||||
func TestConfig_DetectNSFW(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
result := c.DetectNSFW()
|
||||
assert.Equal(t, true, result)
|
||||
}
|
||||
66
internal/config/config_cdn.go
Normal file
66
internal/config/config_cdn.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/clean"
|
||||
)
|
||||
|
||||
// CdnUrl returns the optional content delivery network URI without trailing slash.
|
||||
func (c *Config) CdnUrl(res string) string {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return res
|
||||
}
|
||||
|
||||
return strings.TrimRight(c.options.CdnUrl, "/") + res
|
||||
}
|
||||
|
||||
// UseCdn checks if a Content Deliver Network (CDN) is used to serve static content.
|
||||
func (c *Config) UseCdn() bool {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// NoCdn checks if there is no Content Deliver Network (CDN) configured to serve static content.
|
||||
func (c *Config) NoCdn() bool {
|
||||
return !c.UseCdn()
|
||||
}
|
||||
|
||||
// CdnDomain returns the content delivery network domain name if specified.
|
||||
func (c *Config) CdnDomain() string {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return ""
|
||||
} else if u, err := url.Parse(c.options.CdnUrl); err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return u.Hostname()
|
||||
}
|
||||
}
|
||||
|
||||
// CdnVideo checks if videos should be streamed using the configured CDN.
|
||||
func (c *Config) CdnVideo() bool {
|
||||
if c.options.CdnUrl == "" || c.options.CdnUrl == c.options.SiteUrl {
|
||||
return false
|
||||
}
|
||||
|
||||
return c.options.CdnVideo
|
||||
}
|
||||
|
||||
// CORSOrigin returns the value for the Access-Control-Allow-Origin header, if any.
|
||||
func (c *Config) CORSOrigin() string {
|
||||
return clean.Header(c.options.CORSOrigin)
|
||||
}
|
||||
|
||||
// CORSHeaders returns the value for the Access-Control-Allow-Headers header, if any.
|
||||
func (c *Config) CORSHeaders() string {
|
||||
return clean.Header(c.options.CORSHeaders)
|
||||
}
|
||||
|
||||
// CORSMethods returns the value for the Access-Control-Allow-Methods header, if any.
|
||||
func (c *Config) CORSMethods() string {
|
||||
return clean.Header(c.options.CORSMethods)
|
||||
}
|
||||
104
internal/config/config_cdn_test.go
Normal file
104
internal/config/config_cdn_test.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/header"
|
||||
)
|
||||
|
||||
func TestConfig_CdnUrl(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.options.SiteUrl)
|
||||
assert.Equal(t, "", c.CdnUrl(""))
|
||||
assert.True(t, c.NoCdn())
|
||||
assert.False(t, c.UseCdn())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "/", c.CdnUrl("/"))
|
||||
c.options.CdnUrl = "http://foo:2342/foo/"
|
||||
assert.Equal(t, "http://foo:2342/foo", c.CdnUrl(""))
|
||||
assert.Equal(t, "http://foo:2342/foo/", c.CdnUrl("/"))
|
||||
assert.False(t, c.NoCdn())
|
||||
assert.True(t, c.UseCdn())
|
||||
c.options.SiteUrl = c.options.CdnUrl
|
||||
assert.Equal(t, "/", c.CdnUrl("/"))
|
||||
assert.Equal(t, "", c.CdnUrl(""))
|
||||
assert.True(t, c.NoCdn())
|
||||
assert.False(t, c.UseCdn())
|
||||
c.options.SiteUrl = ""
|
||||
assert.False(t, c.NoCdn())
|
||||
assert.True(t, c.UseCdn())
|
||||
}
|
||||
|
||||
func TestConfig_CdnDomain(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.options.SiteUrl)
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
c.options.CdnUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "superhost", c.CdnDomain())
|
||||
c.options.CdnUrl = "https://foo.bar.com:2342/foo/"
|
||||
assert.Equal(t, "foo.bar.com", c.CdnDomain())
|
||||
c.options.SiteUrl = c.options.CdnUrl
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
c.options.SiteUrl = ""
|
||||
c.options.CdnUrl = "http:/invalid:2342/foo/"
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
c.options.CdnUrl = ""
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
}
|
||||
|
||||
func TestConfig_CdnVideo(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.CdnUrl = "http://foo:2342/foo/"
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.CdnVideo = true
|
||||
assert.True(t, c.CdnVideo())
|
||||
c.options.SiteUrl = c.options.CdnUrl
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.SiteUrl = ""
|
||||
assert.True(t, c.CdnVideo())
|
||||
c.options.CdnVideo = false
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.CdnUrl = ""
|
||||
assert.False(t, c.CdnVideo())
|
||||
}
|
||||
|
||||
func TestConfig_CORSOrigin(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
c.Options().CORSOrigin = ""
|
||||
assert.Equal(t, "", c.CORSOrigin())
|
||||
c.Options().CORSOrigin = "*"
|
||||
assert.Equal(t, "*", c.CORSOrigin())
|
||||
c.Options().CORSOrigin = "https://developer.mozilla.org"
|
||||
assert.Equal(t, "https://developer.mozilla.org", c.CORSOrigin())
|
||||
c.Options().CORSOrigin = ""
|
||||
assert.Equal(t, "", c.CORSOrigin())
|
||||
}
|
||||
|
||||
func TestConfig_CORSHeaders(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.CORSHeaders())
|
||||
c.Options().CORSHeaders = header.DefaultAccessControlAllowHeaders
|
||||
assert.Equal(t, header.DefaultAccessControlAllowHeaders, c.CORSHeaders())
|
||||
c.Options().CORSHeaders = ""
|
||||
assert.Equal(t, "", c.CORSHeaders())
|
||||
}
|
||||
|
||||
func TestConfig_CORSMethods(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.CORSMethods())
|
||||
c.Options().CORSMethods = header.DefaultAccessControlAllowMethods
|
||||
assert.Equal(t, header.DefaultAccessControlAllowMethods, c.CORSMethods())
|
||||
c.Options().CORSMethods = ""
|
||||
assert.Equal(t, "", c.CORSMethods())
|
||||
}
|
||||
135
internal/config/config_site.go
Normal file
135
internal/config/config_site.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BaseUri returns the site base URI for a given resource.
|
||||
func (c *Config) BaseUri(res string) string {
|
||||
if c.SiteUrl() == "" {
|
||||
return res
|
||||
}
|
||||
|
||||
u, err := url.Parse(c.SiteUrl())
|
||||
|
||||
if err != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
return strings.TrimRight(u.EscapedPath(), "/") + res
|
||||
}
|
||||
|
||||
// ApiUri returns the api URI.
|
||||
func (c *Config) ApiUri() string {
|
||||
return c.BaseUri(ApiUri)
|
||||
}
|
||||
|
||||
// ContentUri returns the content delivery URI based on the CdnUrl and the ApiUri.
|
||||
func (c *Config) ContentUri() string {
|
||||
return c.CdnUrl(c.ApiUri())
|
||||
}
|
||||
|
||||
// VideoUri returns the video streaming URI.
|
||||
func (c *Config) VideoUri() string {
|
||||
if c.CdnVideo() {
|
||||
return c.ContentUri()
|
||||
}
|
||||
|
||||
return c.ApiUri()
|
||||
}
|
||||
|
||||
// StaticUri returns the static content URI.
|
||||
func (c *Config) StaticUri() string {
|
||||
return c.CdnUrl(c.BaseUri(StaticUri))
|
||||
}
|
||||
|
||||
// StaticAssetUri returns the resource URI of the static file asset.
|
||||
func (c *Config) StaticAssetUri(res string) string {
|
||||
return c.StaticUri() + "/" + res
|
||||
}
|
||||
|
||||
// SiteUrl returns the public server URL (default is "http://localhost:2342/").
|
||||
func (c *Config) SiteUrl() string {
|
||||
if c.options.SiteUrl == "" {
|
||||
return "http://localhost:2342/"
|
||||
}
|
||||
|
||||
return strings.TrimRight(c.options.SiteUrl, "/") + "/"
|
||||
}
|
||||
|
||||
// SiteHttps checks if the site URL uses HTTPS.
|
||||
func (c *Config) SiteHttps() bool {
|
||||
if c.options.SiteUrl == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.HasPrefix(c.options.SiteUrl, "https://")
|
||||
}
|
||||
|
||||
// SiteDomain returns the public server domain.
|
||||
func (c *Config) SiteDomain() string {
|
||||
if u, err := url.Parse(c.SiteUrl()); err != nil {
|
||||
return "localhost"
|
||||
} else {
|
||||
return u.Hostname()
|
||||
}
|
||||
}
|
||||
|
||||
// SiteAuthor returns the site author / copyright.
|
||||
func (c *Config) SiteAuthor() string {
|
||||
return c.options.SiteAuthor
|
||||
}
|
||||
|
||||
// SiteTitle returns the main site title (default is application name).
|
||||
func (c *Config) SiteTitle() string {
|
||||
if c.options.SiteTitle == "" {
|
||||
return c.Name()
|
||||
}
|
||||
|
||||
return c.options.SiteTitle
|
||||
}
|
||||
|
||||
// SiteCaption returns a short site caption.
|
||||
func (c *Config) SiteCaption() string {
|
||||
return c.options.SiteCaption
|
||||
}
|
||||
|
||||
// SiteDescription returns a long site description.
|
||||
func (c *Config) SiteDescription() string {
|
||||
return c.options.SiteDescription
|
||||
}
|
||||
|
||||
// SitePreview returns the site preview image URL for sharing.
|
||||
func (c *Config) SitePreview() string {
|
||||
if c.options.SitePreview == "" {
|
||||
return fmt.Sprintf("https://i.photoprism.app/prism?cover=64&style=centered%%20dark&caption=none&title=%s", url.QueryEscape(c.AppName()))
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(c.options.SitePreview, "http") {
|
||||
return c.SiteUrl() + strings.TrimPrefix(c.options.SitePreview, "/")
|
||||
}
|
||||
|
||||
return c.options.SitePreview
|
||||
}
|
||||
|
||||
// LegalInfo returns the legal info text for the page footer.
|
||||
func (c *Config) LegalInfo() string {
|
||||
if s := c.CliGlobalString("imprint"); s != "" {
|
||||
log.Warnf("config: option 'imprint' is deprecated, please use 'legal-info'")
|
||||
return s
|
||||
}
|
||||
|
||||
return c.options.LegalInfo
|
||||
}
|
||||
|
||||
// LegalUrl returns the legal info url.
|
||||
func (c *Config) LegalUrl() string {
|
||||
if s := c.CliGlobalString("imprint-url"); s != "" {
|
||||
log.Warnf("config: option 'imprint-url' is deprecated, please use 'legal-url'")
|
||||
return s
|
||||
}
|
||||
|
||||
return c.options.LegalUrl
|
||||
}
|
||||
143
internal/config/config_site_test.go
Normal file
143
internal/config/config_site_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConfig_BaseUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.BaseUri(""))
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "", c.BaseUri(""))
|
||||
c.options.SiteUrl = "http://foo:2342/foo bar/"
|
||||
assert.Equal(t, "/foo%20bar", c.BaseUri(""))
|
||||
assert.Equal(t, "/foo%20bar/baz", c.BaseUri("/baz"))
|
||||
}
|
||||
|
||||
func TestConfig_StaticUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "/static", c.StaticUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "/static", c.StaticUri())
|
||||
c.options.SiteUrl = "http://foo:2342/foo/"
|
||||
assert.Equal(t, "/foo/static", c.StaticUri())
|
||||
c.options.CdnUrl = "http://foo:2342/bar"
|
||||
assert.Equal(t, "http://foo:2342/bar/foo"+StaticUri, c.StaticUri())
|
||||
}
|
||||
|
||||
func TestConfig_ApiUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, ApiUri, c.ApiUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, ApiUri, c.ApiUri())
|
||||
c.options.SiteUrl = "http://foo:2342/foo/"
|
||||
assert.Equal(t, "/foo"+ApiUri, c.ApiUri())
|
||||
}
|
||||
|
||||
func TestConfig_ContentUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, ApiUri, c.ContentUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, ApiUri, c.ContentUri())
|
||||
c.options.CdnUrl = "http://foo:2342//"
|
||||
assert.Equal(t, "http://foo:2342"+ApiUri, c.ContentUri())
|
||||
}
|
||||
|
||||
func TestConfig_VideoUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, ApiUri, c.VideoUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, ApiUri, c.VideoUri())
|
||||
c.options.CdnUrl = "http://foo:2342//"
|
||||
c.options.CdnVideo = true
|
||||
assert.Equal(t, "http://foo:2342"+ApiUri, c.VideoUri())
|
||||
c.options.CdnVideo = false
|
||||
assert.Equal(t, ApiUri, c.VideoUri())
|
||||
}
|
||||
|
||||
func TestConfig_SiteUrl(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "http://localhost:2342/", c.SiteUrl())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "http://superhost:2342/", c.SiteUrl())
|
||||
c.options.SiteUrl = "http://superhost"
|
||||
assert.Equal(t, "http://superhost/", c.SiteUrl())
|
||||
}
|
||||
|
||||
func TestConfig_SiteHttps(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
assert.False(t, c.SiteHttps())
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfig_SiteDomain(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "localhost", c.SiteDomain())
|
||||
c.options.SiteUrl = "https://foo.bar.com:2342/"
|
||||
assert.Equal(t, "foo.bar.com", c.SiteDomain())
|
||||
c.options.SiteUrl = ""
|
||||
assert.Equal(t, "localhost", c.SiteDomain())
|
||||
}
|
||||
|
||||
func TestConfig_SitePreview(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
assert.Equal(t, "https://i.photoprism.app/prism?cover=64&style=centered%20dark&caption=none&title=PhotoPrism", c.SitePreview())
|
||||
c.options.SitePreview = "http://preview.jpg"
|
||||
assert.Equal(t, "http://preview.jpg", c.SitePreview())
|
||||
c.options.SitePreview = "preview123.jpg"
|
||||
assert.Equal(t, "http://localhost:2342/preview123.jpg", c.SitePreview())
|
||||
c.options.SitePreview = "foo/preview123.jpg"
|
||||
assert.Equal(t, "http://localhost:2342/foo/preview123.jpg", c.SitePreview())
|
||||
c.options.SitePreview = "/foo/preview123.jpg"
|
||||
assert.Equal(t, "http://localhost:2342/foo/preview123.jpg", c.SitePreview())
|
||||
}
|
||||
|
||||
func TestConfig_SiteAuthor(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.SiteAuthor())
|
||||
c.options.SiteAuthor = "@Jens.Mander"
|
||||
assert.Equal(t, "@Jens.Mander", c.SiteAuthor())
|
||||
c.options.SiteAuthor = ""
|
||||
assert.Equal(t, "", c.SiteAuthor())
|
||||
}
|
||||
|
||||
func TestConfig_SiteTitle(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "PhotoPrism", c.SiteTitle())
|
||||
c.options.SiteTitle = "Cats"
|
||||
assert.Equal(t, "Cats", c.SiteTitle())
|
||||
c.options.SiteTitle = "PhotoPrism"
|
||||
assert.Equal(t, "PhotoPrism", c.SiteTitle())
|
||||
}
|
||||
|
||||
func TestConfig_SiteCaption(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.SiteCaption())
|
||||
c.options.SiteCaption = "PhotoPrism App"
|
||||
assert.Equal(t, "PhotoPrism App", c.SiteCaption())
|
||||
c.options.SiteCaption = ""
|
||||
assert.Equal(t, "", c.SiteCaption())
|
||||
}
|
||||
|
||||
func TestConfig_SiteDescription(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.SiteDescription())
|
||||
c.options.SiteDescription = "My Description!"
|
||||
assert.Equal(t, "My Description!", c.SiteDescription())
|
||||
c.options.SiteDescription = ""
|
||||
assert.Equal(t, "", c.SiteDescription())
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/header"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@@ -97,20 +96,6 @@ func TestConfig_VersionChecksum(t *testing.T) {
|
||||
assert.Equal(t, uint32(0x2e5b4b86), c.VersionChecksum())
|
||||
}
|
||||
|
||||
func TestConfig_TensorFlowVersion(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
version := c.TensorFlowVersion()
|
||||
assert.IsType(t, "1.15.0", version)
|
||||
}
|
||||
|
||||
func TestConfig_TensorFlowDisabled(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
version := c.DisableTensorFlow()
|
||||
assert.Equal(t, false, version)
|
||||
}
|
||||
|
||||
func TestConfig_Copyright(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
@@ -207,13 +192,6 @@ func TestConfig_CustomAssetsPath(t *testing.T) {
|
||||
assert.Equal(t, "", c.CustomAssetsPath())
|
||||
}
|
||||
|
||||
func TestConfig_DetectNSFW(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
result := c.DetectNSFW()
|
||||
assert.Equal(t, true, result)
|
||||
}
|
||||
|
||||
func TestConfig_AdminUser(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
@@ -230,18 +208,6 @@ func TestConfig_AdminPassword(t *testing.T) {
|
||||
assert.Equal(t, "photoprism", result)
|
||||
}
|
||||
|
||||
func TestConfig_NSFWModelPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Contains(t, c.NSFWModelPath(), "/assets/nsfw")
|
||||
}
|
||||
|
||||
func TestConfig_FaceNetModelPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Contains(t, c.FaceNetModelPath(), "/assets/facenet")
|
||||
}
|
||||
|
||||
func TestConfig_ExamplesPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
@@ -249,13 +215,6 @@ func TestConfig_ExamplesPath(t *testing.T) {
|
||||
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/assets/examples", path)
|
||||
}
|
||||
|
||||
func TestConfig_TensorFlowModelPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
path := c.TensorFlowModelPath()
|
||||
assert.Equal(t, "/go/src/github.com/photoprism/photoprism/assets/nasnet", path)
|
||||
}
|
||||
|
||||
func TestConfig_TemplatesPath(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
@@ -383,198 +342,6 @@ func TestConfig_ResolutionLimit(t *testing.T) {
|
||||
assert.Equal(t, -1, c.ResolutionLimit())
|
||||
}
|
||||
|
||||
func TestConfig_BaseUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.BaseUri(""))
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "", c.BaseUri(""))
|
||||
c.options.SiteUrl = "http://foo:2342/foo bar/"
|
||||
assert.Equal(t, "/foo%20bar", c.BaseUri(""))
|
||||
assert.Equal(t, "/foo%20bar/baz", c.BaseUri("/baz"))
|
||||
}
|
||||
|
||||
func TestConfig_StaticUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "/static", c.StaticUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "/static", c.StaticUri())
|
||||
c.options.SiteUrl = "http://foo:2342/foo/"
|
||||
assert.Equal(t, "/foo/static", c.StaticUri())
|
||||
c.options.CdnUrl = "http://foo:2342/bar"
|
||||
assert.Equal(t, "http://foo:2342/bar/foo"+StaticUri, c.StaticUri())
|
||||
}
|
||||
|
||||
func TestConfig_ApiUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, ApiUri, c.ApiUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, ApiUri, c.ApiUri())
|
||||
c.options.SiteUrl = "http://foo:2342/foo/"
|
||||
assert.Equal(t, "/foo"+ApiUri, c.ApiUri())
|
||||
}
|
||||
|
||||
func TestConfig_CdnUrl(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.options.SiteUrl)
|
||||
assert.Equal(t, "", c.CdnUrl(""))
|
||||
assert.True(t, c.NoCdn())
|
||||
assert.False(t, c.UseCdn())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "/", c.CdnUrl("/"))
|
||||
c.options.CdnUrl = "http://foo:2342/foo/"
|
||||
assert.Equal(t, "http://foo:2342/foo", c.CdnUrl(""))
|
||||
assert.Equal(t, "http://foo:2342/foo/", c.CdnUrl("/"))
|
||||
assert.False(t, c.NoCdn())
|
||||
assert.True(t, c.UseCdn())
|
||||
c.options.SiteUrl = c.options.CdnUrl
|
||||
assert.Equal(t, "/", c.CdnUrl("/"))
|
||||
assert.Equal(t, "", c.CdnUrl(""))
|
||||
assert.True(t, c.NoCdn())
|
||||
assert.False(t, c.UseCdn())
|
||||
c.options.SiteUrl = ""
|
||||
assert.False(t, c.NoCdn())
|
||||
assert.True(t, c.UseCdn())
|
||||
}
|
||||
|
||||
func TestConfig_CdnDomain(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.options.SiteUrl)
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
c.options.CdnUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "superhost", c.CdnDomain())
|
||||
c.options.CdnUrl = "https://foo.bar.com:2342/foo/"
|
||||
assert.Equal(t, "foo.bar.com", c.CdnDomain())
|
||||
c.options.SiteUrl = c.options.CdnUrl
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
c.options.SiteUrl = ""
|
||||
c.options.CdnUrl = "http:/invalid:2342/foo/"
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
c.options.CdnUrl = ""
|
||||
assert.Equal(t, "", c.CdnDomain())
|
||||
}
|
||||
|
||||
func TestConfig_CdnVideo(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.CdnUrl = "http://foo:2342/foo/"
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.CdnVideo = true
|
||||
assert.True(t, c.CdnVideo())
|
||||
c.options.SiteUrl = c.options.CdnUrl
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.SiteUrl = ""
|
||||
assert.True(t, c.CdnVideo())
|
||||
c.options.CdnVideo = false
|
||||
assert.False(t, c.CdnVideo())
|
||||
c.options.CdnUrl = ""
|
||||
assert.False(t, c.CdnVideo())
|
||||
}
|
||||
|
||||
func TestConfig_CORSOrigin(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
c.Options().CORSOrigin = ""
|
||||
assert.Equal(t, "", c.CORSOrigin())
|
||||
c.Options().CORSOrigin = "*"
|
||||
assert.Equal(t, "*", c.CORSOrigin())
|
||||
c.Options().CORSOrigin = "https://developer.mozilla.org"
|
||||
assert.Equal(t, "https://developer.mozilla.org", c.CORSOrigin())
|
||||
c.Options().CORSOrigin = ""
|
||||
assert.Equal(t, "", c.CORSOrigin())
|
||||
}
|
||||
|
||||
func TestConfig_CORSHeaders(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.CORSHeaders())
|
||||
c.Options().CORSHeaders = header.DefaultAccessControlAllowHeaders
|
||||
assert.Equal(t, header.DefaultAccessControlAllowHeaders, c.CORSHeaders())
|
||||
c.Options().CORSHeaders = ""
|
||||
assert.Equal(t, "", c.CORSHeaders())
|
||||
}
|
||||
|
||||
func TestConfig_CORSMethods(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "", c.CORSMethods())
|
||||
c.Options().CORSMethods = header.DefaultAccessControlAllowMethods
|
||||
assert.Equal(t, header.DefaultAccessControlAllowMethods, c.CORSMethods())
|
||||
c.Options().CORSMethods = ""
|
||||
assert.Equal(t, "", c.CORSMethods())
|
||||
}
|
||||
|
||||
func TestConfig_ContentUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, ApiUri, c.ContentUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, ApiUri, c.ContentUri())
|
||||
c.options.CdnUrl = "http://foo:2342//"
|
||||
assert.Equal(t, "http://foo:2342"+ApiUri, c.ContentUri())
|
||||
}
|
||||
|
||||
func TestConfig_VideoUri(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, ApiUri, c.VideoUri())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, ApiUri, c.VideoUri())
|
||||
c.options.CdnUrl = "http://foo:2342//"
|
||||
c.options.CdnVideo = true
|
||||
assert.Equal(t, "http://foo:2342"+ApiUri, c.VideoUri())
|
||||
c.options.CdnVideo = false
|
||||
assert.Equal(t, ApiUri, c.VideoUri())
|
||||
}
|
||||
|
||||
func TestConfig_SiteUrl(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "http://localhost:2342/", c.SiteUrl())
|
||||
c.options.SiteUrl = "http://superhost:2342/"
|
||||
assert.Equal(t, "http://superhost:2342/", c.SiteUrl())
|
||||
c.options.SiteUrl = "http://superhost"
|
||||
assert.Equal(t, "http://superhost/", c.SiteUrl())
|
||||
}
|
||||
|
||||
func TestConfig_SiteDomain(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "localhost", c.SiteDomain())
|
||||
c.options.SiteUrl = "https://foo.bar.com:2342/"
|
||||
assert.Equal(t, "foo.bar.com", c.SiteDomain())
|
||||
c.options.SiteUrl = ""
|
||||
assert.Equal(t, "localhost", c.SiteDomain())
|
||||
}
|
||||
|
||||
func TestConfig_SitePreview(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
assert.Equal(t, "https://i.photoprism.app/prism?cover=64&style=centered%20dark&caption=none&title=PhotoPrism", c.SitePreview())
|
||||
c.options.SitePreview = "http://preview.jpg"
|
||||
assert.Equal(t, "http://preview.jpg", c.SitePreview())
|
||||
c.options.SitePreview = "preview123.jpg"
|
||||
assert.Equal(t, "http://localhost:2342/preview123.jpg", c.SitePreview())
|
||||
c.options.SitePreview = "foo/preview123.jpg"
|
||||
assert.Equal(t, "http://localhost:2342/foo/preview123.jpg", c.SitePreview())
|
||||
c.options.SitePreview = "/foo/preview123.jpg"
|
||||
assert.Equal(t, "http://localhost:2342/foo/preview123.jpg", c.SitePreview())
|
||||
}
|
||||
|
||||
func TestConfig_SiteTitle(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
assert.Equal(t, "PhotoPrism", c.SiteTitle())
|
||||
c.options.SiteTitle = "Cats"
|
||||
assert.Equal(t, "Cats", c.SiteTitle())
|
||||
}
|
||||
|
||||
func TestConfig_Serial(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ func NewOptions(ctx *cli.Context) *Options {
|
||||
c.BackupDatabase = true
|
||||
c.BackupAlbums = true
|
||||
|
||||
// Load defaults from YAML file?
|
||||
// Initialize options with the values from the "defaults.yml" file, if it exists.
|
||||
if defaultsYaml := ctx.GlobalString("defaults-yaml"); defaultsYaml == "" {
|
||||
log.Tracef("config: defaults file was not specified")
|
||||
} else if c.DefaultsYaml = fs.Abs(defaultsYaml); !fs.FileExists(c.DefaultsYaml) {
|
||||
@@ -243,6 +243,7 @@ func NewOptions(ctx *cli.Context) *Options {
|
||||
log.Warnf("config: failed loading defaults from %s (%s)", clean.Log(c.DefaultsYaml), err)
|
||||
}
|
||||
|
||||
// Apply options specified with environment variables and command-line flags.
|
||||
if err := c.ApplyCliContext(ctx); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/photoprism/photoprism/pkg/i18n"
|
||||
)
|
||||
|
||||
// initSettings initializes user settings from a config file.
|
||||
// initSettings initializes the customization settings from the "settings.yml" file.
|
||||
func (c *Config) initSettings() {
|
||||
if c.settings != nil {
|
||||
return
|
||||
@@ -43,6 +43,7 @@ func (c *Config) initSettings() {
|
||||
|
||||
// Settings returns the global app settings.
|
||||
func (c *Config) Settings() *customize.Settings {
|
||||
// Load settings from the "settings.yml" config file.
|
||||
c.initSettings()
|
||||
|
||||
if c.DisablePlaces() {
|
||||
|
||||
@@ -202,6 +202,35 @@ var UserFixtures = UserMap{
|
||||
BirthYear: 2001,
|
||||
},
|
||||
},
|
||||
"guest": {
|
||||
ID: 10000025,
|
||||
UserUID: "usg73p55zwgr1gbq",
|
||||
UserName: "guest",
|
||||
DisplayName: "Guest User",
|
||||
UserEmail: "guest@example.com",
|
||||
UserRole: acl.RoleGuest.String(),
|
||||
AuthProvider: authn.ProviderOIDC.String(),
|
||||
AuthMethod: authn.MethodDefault.String(),
|
||||
SuperAdmin: false,
|
||||
CanLogin: true,
|
||||
WebDAV: false,
|
||||
CanInvite: false,
|
||||
InviteToken: "",
|
||||
UserSettings: &UserSettings{
|
||||
UITheme: "default",
|
||||
MapsStyle: "default",
|
||||
MapsAnimate: 6250,
|
||||
UILanguage: "en",
|
||||
UITimeZone: "UTC",
|
||||
},
|
||||
UserDetails: &UserDetails{
|
||||
NickName: "Gustav",
|
||||
UserGender: GenderMale,
|
||||
BirthDay: 23,
|
||||
BirthMonth: 1,
|
||||
BirthYear: 1999,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// CreateUserFixtures creates the user fixtures specified above
|
||||
|
||||
@@ -11,12 +11,37 @@ import (
|
||||
// RegisteredUsers finds all registered users.
|
||||
func RegisteredUsers() (result entity.Users) {
|
||||
if err := Db().Where("id > 0").Find(&result).Error; err != nil {
|
||||
log.Errorf("users: %s", err)
|
||||
log.Errorf("users: %s (find)", err)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// CountUsers returns the number of users based on the specified filter options.
|
||||
func CountUsers(registered, active bool, roles, excludeRoles []string) (count int) {
|
||||
stmt := Db().Model(entity.Users{})
|
||||
|
||||
if registered {
|
||||
stmt = stmt.Where("id > 0")
|
||||
}
|
||||
|
||||
if active {
|
||||
stmt = stmt.Where("(can_login > 0 OR webdav > 0) AND user_name <> ''")
|
||||
}
|
||||
|
||||
if len(roles) > 0 {
|
||||
stmt = stmt.Where("user_role IN (?)", roles)
|
||||
} else if len(excludeRoles) > 0 {
|
||||
stmt = stmt.Where("user_role NOT IN (?)", excludeRoles)
|
||||
}
|
||||
|
||||
if err := stmt.Count(&count).Error; err != nil {
|
||||
log.Errorf("users: %s (count)", err)
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
// Users finds users and returns them.
|
||||
func Users(limit, offset int, sortOrder, search string) (result entity.Users, err error) {
|
||||
result = entity.Users{}
|
||||
|
||||
@@ -19,6 +19,30 @@ func TestRegisteredUsers(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestCountUsers(t *testing.T) {
|
||||
t.Run("All", func(t *testing.T) {
|
||||
assert.LessOrEqual(t, CountUsers(false, false, nil, nil), 10)
|
||||
})
|
||||
t.Run("Registered", func(t *testing.T) {
|
||||
assert.LessOrEqual(t, CountUsers(true, false, nil, nil), 8)
|
||||
})
|
||||
t.Run("Active", func(t *testing.T) {
|
||||
assert.LessOrEqual(t, CountUsers(false, true, nil, nil), 8)
|
||||
})
|
||||
t.Run("RegisteredActive", func(t *testing.T) {
|
||||
assert.LessOrEqual(t, CountUsers(true, true, nil, nil), 8)
|
||||
})
|
||||
t.Run("Admins", func(t *testing.T) {
|
||||
assert.LessOrEqual(t, CountUsers(true, true, []string{"admin"}, nil), 6)
|
||||
})
|
||||
t.Run("NoAdmins", func(t *testing.T) {
|
||||
assert.LessOrEqual(t, CountUsers(true, true, []string{}, []string{"admin"}), 2)
|
||||
})
|
||||
t.Run("Guests", func(t *testing.T) {
|
||||
assert.LessOrEqual(t, CountUsers(true, true, []string{"guest"}, nil), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUsers(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
if results, err := Users(0, 0, "", ""); err != nil {
|
||||
|
||||
@@ -13,8 +13,10 @@ import (
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
// FeedbackURL is the service endpoint for submitting user feedback.
|
||||
var FeedbackURL = ServiceURL + "/%s/feedback"
|
||||
|
||||
// Feedback represents user feedback submitted through the user interface.
|
||||
type Feedback struct {
|
||||
Category string `json:"Category"`
|
||||
Subject string `json:"Subject"`
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// ServiceURL specifies the service endpoint URL.
|
||||
var ServiceURL = "https://my.photoprism.app/v1/hello"
|
||||
|
||||
// Request represents basic environment specs for debugging.
|
||||
@@ -15,10 +16,16 @@ type Request struct {
|
||||
ClientArch string `json:"ClientArch"`
|
||||
ClientCPU int `json:"ClientCPU"`
|
||||
ClientEnv string `json:"ClientEnv"`
|
||||
ClientOpt string `json:"ClientOpt"`
|
||||
PartnerID string `json:"PartnerID"`
|
||||
ApiToken string `json:"ApiToken"`
|
||||
}
|
||||
|
||||
// ClientOpt returns a custom request option.
|
||||
var ClientOpt = func() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewRequest creates a new backend key request instance.
|
||||
func NewRequest(version, serial, env, partnerId, token string) *Request {
|
||||
return &Request{
|
||||
@@ -28,6 +35,7 @@ func NewRequest(version, serial, env, partnerId, token string) *Request {
|
||||
ClientArch: runtime.GOARCH,
|
||||
ClientCPU: runtime.NumCPU(),
|
||||
ClientEnv: env,
|
||||
ClientOpt: ClientOpt(),
|
||||
PartnerID: partnerId,
|
||||
ApiToken: token,
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// SetUserImageURL sets a new user avatar URL.
|
||||
func SetUserImageURL(m *entity.User, imageUrl, imageSrc string) error {
|
||||
func SetUserImageURL(m *entity.User, imageUrl, imageSrc, thumbPath string) error {
|
||||
if imageUrl == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -52,7 +52,7 @@ func SetUserImageURL(m *entity.User, imageUrl, imageSrc string) error {
|
||||
return fmt.Errorf("failed to rename avatar image (%w)", err)
|
||||
}
|
||||
|
||||
if err = SetUserImage(m, imageName, imageSrc); err != nil {
|
||||
if err = SetUserImage(m, imageName, imageSrc, thumbPath); err != nil {
|
||||
return fmt.Errorf("failed to set avatar image (%w)", err)
|
||||
}
|
||||
|
||||
@@ -64,14 +64,16 @@ func SetUserImageURL(m *entity.User, imageUrl, imageSrc string) error {
|
||||
}
|
||||
|
||||
// SetUserImage sets a new user avatar image.
|
||||
func SetUserImage(m *entity.User, imageName, imageSrc string) error {
|
||||
func SetUserImage(m *entity.User, imageName, imageSrc, thumbPath string) error {
|
||||
var conf *config.Config
|
||||
|
||||
if conf = get.Config(); conf == nil {
|
||||
return fmt.Errorf("config required")
|
||||
}
|
||||
|
||||
thumbPath := conf.ThumbCachePath()
|
||||
if thumbPath == "" {
|
||||
thumbPath = conf.ThumbCachePath()
|
||||
}
|
||||
|
||||
if mediaFile, mediaErr := photoprism.NewMediaFile(imageName); mediaErr != nil {
|
||||
return mediaErr
|
||||
|
||||
@@ -10,31 +10,35 @@ import (
|
||||
)
|
||||
|
||||
func TestSetUserAvatarURL(t *testing.T) {
|
||||
thumbPath := fs.Abs("testdata/cache")
|
||||
|
||||
t.Run("PNG", func(t *testing.T) {
|
||||
admin := entity.UserFixtures.Get("alice")
|
||||
imageUrl := "https://dl.photoprism.app/icons/logo/256.png"
|
||||
err := SetUserImageURL(&admin, imageUrl, entity.SrcAuto)
|
||||
err := SetUserImageURL(&admin, imageUrl, entity.SrcAuto, thumbPath)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("JPEG", func(t *testing.T) {
|
||||
admin := entity.UserFixtures.Get("bob")
|
||||
imageUrl := "https://dl.photoprism.app/img/team/avatar.jpg"
|
||||
err := SetUserImageURL(&admin, imageUrl, entity.SrcOIDC)
|
||||
err := SetUserImageURL(&admin, imageUrl, entity.SrcOIDC, thumbPath)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("NotFound", func(t *testing.T) {
|
||||
admin := entity.UserFixtures.Get("alice")
|
||||
imageUrl := "https://dl.photoprism.app/img/team/avatar-invalid.jpg"
|
||||
err := SetUserImageURL(&admin, imageUrl, entity.SrcAuto)
|
||||
err := SetUserImageURL(&admin, imageUrl, entity.SrcAuto, thumbPath)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetUserAvatarImage(t *testing.T) {
|
||||
thumbPath := fs.Abs("testdata/cache")
|
||||
|
||||
t.Run("Admin", func(t *testing.T) {
|
||||
admin := entity.UserFixtures.Get("friend")
|
||||
fileName := fs.Abs("testdata/avatar.png")
|
||||
err := SetUserImage(&admin, fileName, entity.SrcAuto)
|
||||
err := SetUserImage(&admin, fileName, entity.SrcAuto, thumbPath)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user