fix: OPDS base_url placeholder bug + setup gate requires base_url
Three bugs fixed: 1. Schema seeded base_url with fake placeholder 'bookhoard.example.com'. Removed seed; startup now seeds from BASE_URL env var only if DB row is empty (admin changes persist across restarts). One-time UPDATE clears the placeholder in existing installs. 2. config.GetBaseURL() had a broken type assertion (local SystemConfigRow vs database.SystemConfig) that always failed, returning . Admin panel showed env var fallback instead of actual DB value. Fixed with a function-type getter that properly wraps the DB query. 3. OPDS handler read base_url only from DB with no fallback. When DB had the placeholder, all feed links pointed to an unreachable domain, breaking KOReader search/download. Added deriveBaseURL() helper that falls back to the request Host/scheme when DB value is empty. Setup gate improvements: - isSetupComplete now requires both admin user AND non-empty base_url - Setup middleware no longer exempts all /api/ routes; only allows /api/auth/register, /api/auth/login, /api/system/config before setup is complete. All other API routes get 503. - Cache invalidated when base_url is saved via admin settings Dev workflow: - New bruno/NewDevDBSetup/SetBaseUrl.yml for dev DB setup - NewDB.sh runs SetBaseUrl between RegisterUser and CreateEbookLibrary
This commit is contained in:
+40
-10
@@ -14,7 +14,40 @@ import (
|
||||
)
|
||||
|
||||
func isSetupComplete(cfg *Config) bool {
|
||||
return setupstatus.IsSetupComplete(context.Background(), cfg.Queries)
|
||||
getter := func(ctx context.Context) (string, error) {
|
||||
row, err := cfg.Queries.GetSystemConfig(ctx, "base_url")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return row.Value, nil
|
||||
}
|
||||
return setupstatus.IsSetupComplete(context.Background(), cfg.Queries, getter)
|
||||
}
|
||||
|
||||
// setupAllowedAPIRoutes lists API endpoints that remain accessible before
|
||||
// initial setup is complete so the server can be configured via API.
|
||||
var setupAllowedAPIRoutes = []string{
|
||||
"/api/auth/register",
|
||||
"/api/auth/login",
|
||||
"/api/system/config",
|
||||
}
|
||||
|
||||
// isAllowedDuringSetup reports whether a request path should bypass the setup
|
||||
// gate. This includes the setup page itself, static assets, health checks, and
|
||||
// the minimal set of API routes needed to perform initial configuration.
|
||||
func isAllowedDuringSetup(path string) bool {
|
||||
if path == "/setup" || path == "/setup/" {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(path, "/static/") || path == "/health" || path == "/favicon.ico" {
|
||||
return true
|
||||
}
|
||||
for _, route := range setupAllowedAPIRoutes {
|
||||
if path == route || strings.HasPrefix(path, route+"/") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func setupRedirectMiddleware(cfg *Config) echo.MiddlewareFunc {
|
||||
@@ -22,19 +55,16 @@ func setupRedirectMiddleware(cfg *Config) echo.MiddlewareFunc {
|
||||
return func(c *echo.Context) error {
|
||||
path := c.Request().URL.Path
|
||||
|
||||
if path == "/setup" || path == "/setup/" {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(path, "/api/") {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(path, "/static/") || path == "/health" || path == "/favicon.ico" {
|
||||
if isAllowedDuringSetup(path) {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
if !isSetupComplete(cfg) {
|
||||
if strings.HasPrefix(path, "/api/") {
|
||||
return c.JSON(http.StatusServiceUnavailable, map[string]string{
|
||||
"error": "Server setup is not complete. Configure an admin account and base_url via the setup wizard or API.",
|
||||
})
|
||||
}
|
||||
return c.Redirect(http.StatusFound, "/setup")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user