fix: optimization fail after restart (#1007)
Some checks failed
Bump Version / Bump Version Workflow (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
docker-build / platform-excludes (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
Run Pytest on Pull Request / test (push) Has been cancelled
docker-build / build (push) Has been cancelled
docker-build / merge (push) Has been cancelled
Close stale pull requests/issues / Find Stale issues and PRs (push) Has been cancelled

Fix documentation for the loadforecast_power_w key.

Fix documentation to explain the usage of import file/ JSON string to
primarily initialise prediction data.

Fix code scanning alert no. 6: URL redirection from remote source

Enable to automatically save the configuration to the configuration file
by default, which is a widespread user expectation.

Make the genetic parameters non optional for better pydantic compliance.

Update:
- bump pytest to 9.0.3
- bump pillow to 12.2.0
- bump platformdirs to 4.9.6
- bump typespyyaml to 6.0.12.20260408
- bump tzfpy to 1.2.0
- bump pydantic to 2.13.0
- bump types-requests to 2.33.0.20260408

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
Co-authored-by: Normann <github@koldrack.com>
This commit is contained in:
Bobby Noelte
2026-04-15 08:48:56 +02:00
committed by GitHub
parent 29cc3d7f3b
commit 6f28022ed0
19 changed files with 717 additions and 671 deletions

View File

@@ -114,6 +114,13 @@ def compact_eos_database() -> None:
get_measurement().db_vacuum()
def autosave_config() -> None:
"""Save config in automatic mode."""
config = get_config()
if config:
config.autosave()
async def server_shutdown_task() -> None:
"""One-shot task for shutting down the EOS server.
@@ -168,6 +175,11 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
interval_attr="server/eosdash_supervise_interval_sec",
fallback_interval=5.0,
)
manager.register(
name="autosave_config",
func=autosave_config,
interval_attr="general/config_save_interval_sec",
)
manager.register("cache_clear", cache_clear, interval_attr="cache/cleanup_interval")
manager.register(
"save_eos_database", save_eos_database, interval_attr="database/autosave_interval_sec"
@@ -1454,6 +1466,32 @@ async def redirect_put(request: Request, path: str) -> Response:
return redirect(request, path)
def _sanitize_redirect_path(path: str) -> Optional[str]:
"""Sanitize user-controlled redirect path to ensure it is a safe relative path.
Returns a normalized path segment without scheme/host information, or None if unsafe.
"""
if path is None:
return ""
# Normalize backslashes and strip leading separators/spaces
cleaned = path.replace("\\", "/").lstrip(" /")
# Disallow obvious attempts to inject a new scheme/host
lowered = cleaned.lower()
if lowered.startswith(("http://", "https://", "//")) or "://" in lowered:
return None
# Prevent directory traversal outside the intended root
parts = [p for p in cleaned.split("/") if p not in ("", ".")]
depth = 0
for p in parts:
if p == "..":
depth -= 1
else:
depth += 1
if depth < 0:
return None
return "/".join(parts)
def redirect(request: Request, path: str) -> Union[HTMLResponse, RedirectResponse]:
# Path is not for EOSdash
if not (path.startswith("eosdash") or path == ""):
@@ -1485,8 +1523,9 @@ Did you want to connect to <a href="{url}" class="back-button">EOSdash</a>?
# Use IP of EOS host
host = get_host_ip()
if host and get_config().server.eosdash_port:
# Redirect to EOSdash server
url = f"http://{host}:{get_config().server.eosdash_port}/{path}"
base_url = f"http://{host}:{get_config().server.eosdash_port}"
safe_path = _sanitize_redirect_path(path) or ""
url = f"{base_url}/{safe_path}"
return RedirectResponse(url=url, status_code=303)
# Redirect the root URL to the site map