diff --git a/internal/commands/cleanup.go b/internal/commands/cleanup.go index cfbeb7af9..d43323dff 100644 --- a/internal/commands/cleanup.go +++ b/internal/commands/cleanup.go @@ -43,7 +43,7 @@ func cleanUpAction(ctx *cli.Context) error { defer conf.Shutdown() if conf.ReadOnly() { - log.Infof("config: read-only mode enabled") + log.Infof("config: enabled read-only mode") } w := get.CleanUp() diff --git a/internal/commands/faces.go b/internal/commands/faces.go index fbb149875..b27834189 100644 --- a/internal/commands/faces.go +++ b/internal/commands/faces.go @@ -241,7 +241,7 @@ func facesIndexAction(ctx *cli.Context) error { } if conf.ReadOnly() { - log.Infof("config: read-only mode enabled") + log.Infof("config: enabled read-only mode") } var indexed fs.Done diff --git a/internal/commands/index.go b/internal/commands/index.go index 02f6d6677..f766ad7a2 100644 --- a/internal/commands/index.go +++ b/internal/commands/index.go @@ -65,7 +65,7 @@ func indexAction(ctx *cli.Context) error { } if conf.ReadOnly() { - log.Infof("config: read-only mode enabled") + log.Infof("config: enabled read-only mode") } var indexed fs.Done diff --git a/internal/commands/moments.go b/internal/commands/moments.go index f786bea9b..a967b4ea5 100644 --- a/internal/commands/moments.go +++ b/internal/commands/moments.go @@ -33,7 +33,7 @@ func momentsAction(ctx *cli.Context) error { defer conf.Shutdown() if conf.ReadOnly() { - log.Infof("config: read-only mode enabled") + log.Infof("config: enabled read-only mode") } w := get.Moments() diff --git a/internal/commands/optimize.go b/internal/commands/optimize.go index 2b3a8df32..bcd3815b8 100644 --- a/internal/commands/optimize.go +++ b/internal/commands/optimize.go @@ -40,7 +40,7 @@ func optimizeAction(ctx *cli.Context) error { defer conf.Shutdown() if conf.ReadOnly() { - log.Infof("config: read-only mode enabled") + log.Infof("config: enabled read-only mode") } force := ctx.Bool("force") diff --git a/internal/commands/purge.go b/internal/commands/purge.go index ed20f427b..fdffe03fc 100644 --- a/internal/commands/purge.go +++ b/internal/commands/purge.go @@ -60,7 +60,7 @@ func purgeAction(ctx *cli.Context) error { } if conf.ReadOnly() { - log.Infof("config: read-only mode enabled") + log.Infof("config: enabled read-only mode") } w := get.Purge() diff --git a/internal/commands/start.go b/internal/commands/start.go index b1cfb0829..0c82d765a 100644 --- a/internal/commands/start.go +++ b/internal/commands/start.go @@ -113,7 +113,7 @@ func startAction(ctx *cli.Context) error { } if conf.ReadOnly() { - log.Infof("config: read-only mode enabled") + log.Infof("config: enabled read-only mode") } // Start web server. diff --git a/internal/config/config_features.go b/internal/config/config_features.go index 4ff5cbd51..ac251e30f 100644 --- a/internal/config/config_features.go +++ b/internal/config/config_features.go @@ -4,7 +4,7 @@ var Sponsor = Env(EnvDemo, EnvSponsor, EnvTest) // DisableWebDAV checks if the built-in WebDAV server should be disabled. func (c *Config) DisableWebDAV() bool { - if c.Public() || c.ReadOnly() || c.Demo() { + if c.Public() || c.Demo() { return true } diff --git a/internal/config/config_features_test.go b/internal/config/config_features_test.go index 82642d613..c897c17f5 100644 --- a/internal/config/config_features_test.go +++ b/internal/config/config_features_test.go @@ -30,7 +30,7 @@ func TestConfig_DisableWebDAV(t *testing.T) { c.options.ReadOnly = true c.options.Demo = false - assert.True(t, c.DisableWebDAV()) + assert.False(t, c.DisableWebDAV()) c.options.Public = false c.options.ReadOnly = false diff --git a/internal/entity/entity_tables.go b/internal/entity/entity_tables.go index 11d0ee3c9..9c66ac834 100644 --- a/internal/entity/entity_tables.go +++ b/internal/entity/entity_tables.go @@ -107,6 +107,8 @@ func (list Tables) Migrate(db *gorm.DB, opt migrate.Options) { } }() + log.Infof("migrate: running database migrations") + // Run pre-migrations, if any. if err := migrate.Run(db, opt.Pre()); err != nil { log.Error(err) diff --git a/internal/migrate/migrations.go b/internal/migrate/migrations.go index dc899448d..9c994dcc9 100644 --- a/internal/migrate/migrations.go +++ b/internal/migrate/migrations.go @@ -73,9 +73,9 @@ func (m *Migrations) Start(db *gorm.DB, opt Options) { executed := Existing(db, opt.StageName()) if prev := len(executed); prev == 0 { - log.Infof("migrate: no previously executed migrations [%s]", opt.StageName()) + log.Debugf("migrate: no previously executed migrations [%s]", opt.StageName()) } else { - log.Infof("migrate: executing %s migrations", opt.StageName()) + log.Debugf("migrate: executing %s migrations", opt.StageName()) log.Debugf("migrate: found %s", english.Plural(len(executed), "previous migration", "previous migrations")) } diff --git a/internal/server/autotls.go b/internal/server/autotls.go index ace5592d9..fa0220ffd 100644 --- a/internal/server/autotls.go +++ b/internal/server/autotls.go @@ -15,11 +15,11 @@ func AutoTLS(conf *config.Config) (*autocert.Manager, error) { // Enable automatic HTTPS via Let's Encrypt? if !conf.SiteHttps() { - return nil, fmt.Errorf("tls disabled") + return nil, fmt.Errorf("disabled tls") } else if siteDomain = conf.SiteDomain(); !strings.Contains(siteDomain, ".") { - return nil, fmt.Errorf("no fully qualified site domain") + return nil, fmt.Errorf("fully qualified domain required to enable tls") } else if tlsEmail = conf.TLSEmail(); tlsEmail == "" { - return nil, fmt.Errorf("automatic tls disabled") + return nil, fmt.Errorf("disabled auto tls") } else if certDir = conf.CertificatesPath(); certDir == "" { return nil, fmt.Errorf("certificates path not found") } diff --git a/internal/server/routes_webdav.go b/internal/server/routes_webdav.go index 65a02399c..e6afc2154 100644 --- a/internal/server/routes_webdav.go +++ b/internal/server/routes_webdav.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "net/http" "os" "path/filepath" @@ -21,14 +22,21 @@ const WebDAVImport = "/import" // registerWebDAVRoutes configures the built-in WebDAV server. func registerWebDAVRoutes(router *gin.Engine, conf *config.Config) { if conf.DisableWebDAV() { - log.Info("webdav: server disabled") + log.Info("webdav: disabled") } else { + var info string + if conf.ReadOnly() { + info = " in read-only mode" + } else { + info = "" + } + WebDAV(conf.OriginalsPath(), router.Group(conf.BaseUri(WebDAVOriginals), BasicAuth()), conf) - log.Infof("webdav: %s/ enabled, waiting for requests", conf.BaseUri(WebDAVOriginals)) + log.Infof("webdav: shared %s/%s", conf.BaseUri(WebDAVOriginals), info) if conf.ImportPath() != "" { WebDAV(conf.ImportPath(), router.Group(conf.BaseUri(WebDAVImport), BasicAuth()), conf) - log.Infof("webdav: %s/ enabled, waiting for requests", conf.BaseUri(WebDAVImport)) + log.Infof("webdav: shared %s/%s", conf.BaseUri(WebDAVImport), info) } } } @@ -101,21 +109,39 @@ func WebDAV(filePath string, router *gin.RouterGroup, conf *config.Config) { WebDAVHandler(c, router, srv) } - // Handle supported HTTP request methods. - router.Handle(MethodHead, "/*path", handlerFunc) - router.Handle(MethodGet, "/*path", handlerFunc) - router.Handle(MethodPut, "/*path", handlerFunc) - router.Handle(MethodPost, "/*path", handlerFunc) - router.Handle(MethodPatch, "/*path", handlerFunc) - router.Handle(MethodDelete, "/*path", handlerFunc) - router.Handle(MethodOptions, "/*path", handlerFunc) - router.Handle(MethodMkcol, "/*path", handlerFunc) - router.Handle(MethodCopy, "/*path", handlerFunc) - router.Handle(MethodMove, "/*path", handlerFunc) - router.Handle(MethodLock, "/*path", handlerFunc) - router.Handle(MethodUnlock, "/*path", handlerFunc) - router.Handle(MethodPropfind, "/*path", handlerFunc) - router.Handle(MethodProppatch, "/*path", handlerFunc) + // handleRead registers WebDAV methods used for browsing and downloading. + handleRead := func(h func(*gin.Context)) { + router.Handle(MethodHead, "/*path", h) + router.Handle(MethodGet, "/*path", h) + router.Handle(MethodOptions, "/*path", h) + router.Handle(MethodLock, "/*path", h) + router.Handle(MethodUnlock, "/*path", h) + router.Handle(MethodPropfind, "/*path", h) + } + + // handleWrite registers WebDAV methods to may modify the file system. + handleWrite := func(h func(*gin.Context)) { + router.Handle(MethodPut, "/*path", h) + router.Handle(MethodPost, "/*path", h) + router.Handle(MethodPatch, "/*path", h) + router.Handle(MethodDelete, "/*path", h) + router.Handle(MethodMkcol, "/*path", h) + router.Handle(MethodCopy, "/*path", h) + router.Handle(MethodMove, "/*path", h) + router.Handle(MethodProppatch, "/*path", h) + } + + // Handle supported WebDAV request methods. + handleRead(handlerFunc) + + // Only supported with read-only mode disabled. + if conf.ReadOnly() { + handleWrite(func(c *gin.Context) { + _ = c.AbortWithError(http.StatusForbidden, fmt.Errorf("forbidden in read-only mode")) + }) + } else { + handleWrite(handlerFunc) + } } // MarkUploadAsFavorite sets the favorite flag for newly uploaded files. diff --git a/internal/server/start.go b/internal/server/start.go index 4a656ae9e..28363721d 100644 --- a/internal/server/start.go +++ b/internal/server/start.go @@ -49,7 +49,6 @@ func Start(ctx context.Context, conf *config.Config) { // Enable HTTP compression? switch conf.HttpCompression() { case "gzip": - log.Infof("server: enabling gzip compression") router.Use(gzip.Gzip( gzip.DefaultCompression, gzip.WithExcludedPaths([]string{ @@ -60,6 +59,7 @@ func Start(ctx context.Context, conf *config.Config) { conf.BaseUri(config.ApiUri + "/labels"), conf.BaseUri(config.ApiUri + "/videos"), }))) + log.Infof("server: enabled gzip compression") } // Find and load templates.