diff --git a/config/config.go b/config/config.go index 906e190..174f647 100644 --- a/config/config.go +++ b/config/config.go @@ -221,7 +221,7 @@ func VerifyConfig() error { UIAuthFile = filepath.Clean(UIAuthFile) if !isFile(UIAuthFile) { - return fmt.Errorf("[ui] HTTP password file not found: %s", UIAuthFile) + return fmt.Errorf("[ui] HTTP password file not found or readable: %s", UIAuthFile) } b, err := os.ReadFile(UIAuthFile) @@ -243,11 +243,11 @@ func VerifyConfig() error { UITLSKey = filepath.Clean(UITLSKey) if !isFile(UITLSCert) { - return fmt.Errorf("[ui] TLS certificate not found: %s", UITLSCert) + return fmt.Errorf("[ui] TLS certificate not found or readable: %s", UITLSCert) } if !isFile(UITLSKey) { - return fmt.Errorf("[ui] TLS key not found: %s", UITLSKey) + return fmt.Errorf("[ui] TLS key not found or readable: %s", UITLSKey) } } @@ -260,11 +260,11 @@ func VerifyConfig() error { SMTPTLSKey = filepath.Clean(SMTPTLSKey) if !isFile(SMTPTLSCert) { - return fmt.Errorf("[smtp] TLS certificate not found: %s", SMTPTLSCert) + return fmt.Errorf("[smtp] TLS certificate not found or readable: %s", SMTPTLSCert) } if !isFile(SMTPTLSKey) { - return fmt.Errorf("[smtp] TLS key not found: %s", SMTPTLSKey) + return fmt.Errorf("[smtp] TLS key not found or readable: %s", SMTPTLSKey) } } else if SMTPRequireTLS { return errors.New("[smtp] TLS cannot be required without an SMTP TLS certificate and key") @@ -282,7 +282,7 @@ func VerifyConfig() error { SMTPAuthFile = filepath.Clean(SMTPAuthFile) if !isFile(SMTPAuthFile) { - return fmt.Errorf("[smtp] password file not found: %s", SMTPAuthFile) + return fmt.Errorf("[smtp] password file not found or readable: %s", SMTPAuthFile) } b, err := os.ReadFile(SMTPAuthFile) @@ -321,11 +321,11 @@ func VerifyConfig() error { POP3TLSKey = filepath.Clean(POP3TLSKey) if !isFile(POP3TLSCert) { - return fmt.Errorf("[pop3] TLS certificate not found: %s", POP3TLSCert) + return fmt.Errorf("[pop3] TLS certificate not found or readable: %s", POP3TLSCert) } if !isFile(POP3TLSKey) { - return fmt.Errorf("[pop3] TLS key not found: %s", POP3TLSKey) + return fmt.Errorf("[pop3] TLS key not found or readable: %s", POP3TLSKey) } } if POP3TLSCert != "" && POP3TLSKey == "" || POP3TLSCert == "" && POP3TLSKey != "" { @@ -341,7 +341,7 @@ func VerifyConfig() error { POP3AuthFile = filepath.Clean(POP3AuthFile) if !isFile(POP3AuthFile) { - return fmt.Errorf("[pop3] password file not found: %s", POP3AuthFile) + return fmt.Errorf("[pop3] password file not found or readable: %s", POP3AuthFile) } b, err := os.ReadFile(POP3AuthFile) @@ -459,7 +459,7 @@ func parseRelayConfig(c string) error { c = filepath.Clean(c) if !isFile(c) { - return fmt.Errorf("[smtp] relay configuration not found: %s", c) + return fmt.Errorf("[smtp] relay configuration not found or readable: %s", c) } data, err := os.ReadFile(c) @@ -536,20 +536,17 @@ func validateRelayConfig() error { return nil } -// IsFile returns if a path is a file +// IsFile returns whether a file exists and is readable func isFile(path string) bool { - info, err := os.Stat(path) - if os.IsNotExist(err) || !info.Mode().IsRegular() { - return false - } - - return true + f, err := os.Open(filepath.Clean(path)) + defer f.Close() + return err == nil } // IsDir returns whether a path is a directory func isDir(path string) bool { info, err := os.Stat(path) - if os.IsNotExist(err) || !info.IsDir() { + if err != nil || os.IsNotExist(err) || !info.IsDir() { return false } diff --git a/internal/storage/database.go b/internal/storage/database.go index 71db412..a74a2b5 100644 --- a/internal/storage/database.go +++ b/internal/storage/database.go @@ -63,6 +63,17 @@ func InitDB() error { config.Database = p + if sqlDriver == "sqlite" { + if !isFile(p) { + // try create a file to ensure permissions + f, err := os.Create(p) + if err != nil { + return fmt.Errorf("[db] %s", err.Error()) + } + _ = f.Close() + } + } + var err error db, err = sql.Open(sqlDriver, dsn) @@ -73,7 +84,7 @@ func InitDB() error { for i := 1; i < 6; i++ { if err := Ping(); err != nil { logger.Log().Errorf("[db] %s", err.Error()) - logger.Log().Infof("[db] reconnecting in 5 seconds (%d/5)", i) + logger.Log().Infof("[db] reconnecting in 5 seconds (attempt %d/5)", i) time.Sleep(5 * time.Second) } else { continue diff --git a/server/server.go b/server/server.go index 60efd8f..f659165 100644 --- a/server/server.go +++ b/server/server.go @@ -96,8 +96,6 @@ func Listen() { // Mark the application here as ready isReady.Store(true) - logger.Log().Infof("[http] starting on %s", config.HTTPListen) - server := &http.Server{ Addr: config.HTTPListen, ReadTimeout: 30 * time.Second, @@ -105,19 +103,20 @@ func Listen() { } if config.UITLSCert != "" && config.UITLSKey != "" { + logger.Log().Infof("[http] starting on %s (TLS)", config.HTTPListen) + logger.Log().Infof("[http] accessible via https://%s%s", logger.CleanHTTPIP(config.HTTPListen), config.Webroot) if err := server.ListenAndServeTLS(config.UITLSCert, config.UITLSKey); err != nil { storage.Close() logger.Log().Fatal(err) } - logger.Log().Infof("[http] accessible via https://%s%s", logger.CleanHTTPIP(config.HTTPListen), config.Webroot) } else { + logger.Log().Infof("[http] starting on %s", config.HTTPListen) + logger.Log().Infof("[http] accessible via http://%s%s", logger.CleanHTTPIP(config.HTTPListen), config.Webroot) if err := server.ListenAndServe(); err != nil { storage.Close() logger.Log().Fatal(err) } - - logger.Log().Infof("[http] accessible via http://%s%s", logger.CleanHTTPIP(config.HTTPListen), config.Webroot) } }