generated from john/python-template
This commit is contained in:
@@ -711,7 +711,7 @@ def register_page(*, settings: Settings) -> None: # noqa: PLR0915
|
||||
|
||||
with ui.column().classes("w-full max-w-3xl mx-auto gap-2 mt-3"):
|
||||
ui.label("Other settings not shown here").classes("text-sm font-semibold")
|
||||
ui.label("Edit these directly in .env:").classes("text-xs ui-text-muted")
|
||||
ui.label(f"Edit these directly in {snapshot.env_file_path}:").classes("text-xs ui-text-muted")
|
||||
table_rows = [
|
||||
f"| {category.title} | {', '.join(f'`{key}`' for key in category.env_keys)} |"
|
||||
for category in HIDDEN_SETTINGS_CATEGORIES
|
||||
|
||||
@@ -84,6 +84,29 @@ HIDDEN_SETTINGS_CATEGORIES: tuple[HiddenSettingsCategory, ...] = (
|
||||
"DATABASE__USER",
|
||||
),
|
||||
),
|
||||
HiddenSettingsCategory(
|
||||
title="Deployment and backup/tunnel helpers (not Runtime Settings model fields)",
|
||||
reason=(
|
||||
"These keys are consumed by docker-compose, backup scripts, or deployment adapters and are "
|
||||
"intentionally edited outside the Runtime Settings UI."
|
||||
),
|
||||
env_keys=(
|
||||
"POSTGRES_DB",
|
||||
"POSTGRES_USER",
|
||||
"POSTGRES_PASSWORD",
|
||||
"POSTGRES_HOST",
|
||||
"POSTGRES_PORT",
|
||||
"CLOUDFLARE_TUNNEL_TOKEN",
|
||||
"RUNTIME_SETTINGS_ENV_FILE",
|
||||
"BACKUP_DIR",
|
||||
"APP_DATA_BACKUP_DIR",
|
||||
"UPLOADS_BACKUP_DIR",
|
||||
"BACKUP_RETENTION_DAYS",
|
||||
"SYNOLOGY_BACKUP_DIR",
|
||||
"ENV_FILE",
|
||||
"COMPOSE_FILE",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
RUNTIME_SETTINGS_CATALOG: tuple[RuntimeSettingDescriptor, ...] = (
|
||||
@@ -358,7 +381,15 @@ def save_runtime_settings(
|
||||
env_map[descriptor.env_key] = encoded
|
||||
|
||||
_validate_candidate_env(env_map=env_map, env_file_path=resolved_env_path)
|
||||
_write_env_lines_atomic(path=resolved_env_path, lines=mutable_lines)
|
||||
try:
|
||||
_write_env_lines_atomic(path=resolved_env_path, lines=mutable_lines)
|
||||
except OSError as exc:
|
||||
raise AppError(
|
||||
"Runtime settings file is not writable.",
|
||||
category=ErrorCategory.INFRA_PERSISTENT,
|
||||
suggestion="Verify file path and write permissions, then retry.",
|
||||
detail=f"Failed writing runtime env file {resolved_env_path}: {type(exc).__name__}: {exc}",
|
||||
) from exc
|
||||
refreshed = Settings(_env_file=resolved_env_path, _cli_parse_args=False)
|
||||
return read_runtime_settings_snapshot(settings=refreshed, env_file_path=resolved_env_path)
|
||||
|
||||
@@ -438,7 +469,15 @@ def _validate_candidate_env(*, env_map: dict[str, str], env_file_path: Path) ->
|
||||
def _read_env_lines(path: Path) -> list[str]:
|
||||
if not path.exists():
|
||||
return []
|
||||
return path.read_text(encoding="utf-8").splitlines()
|
||||
try:
|
||||
return path.read_text(encoding="utf-8").splitlines()
|
||||
except OSError as exc:
|
||||
raise AppError(
|
||||
"Runtime settings file is unreadable.",
|
||||
category=ErrorCategory.INFRA_PERSISTENT,
|
||||
suggestion="Verify file path and read permissions, then retry.",
|
||||
detail=f"Failed reading runtime env file {path}: {type(exc).__name__}: {exc}",
|
||||
) from exc
|
||||
|
||||
|
||||
def _parse_env_map(lines: list[str]) -> dict[str, str]:
|
||||
@@ -485,21 +524,29 @@ def _upsert_env_key(lines: list[str], key: str, value: str) -> None:
|
||||
|
||||
|
||||
def _write_env_lines_atomic(*, path: Path, lines: list[str]) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
content = "\n".join(lines).rstrip("\n")
|
||||
if content:
|
||||
content += "\n"
|
||||
with tempfile.NamedTemporaryFile(
|
||||
mode="w",
|
||||
delete=False,
|
||||
dir=path.parent,
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
suffix=".env.tmp",
|
||||
) as handle:
|
||||
temp_path = Path(handle.name)
|
||||
handle.write(content)
|
||||
temp_path.replace(path)
|
||||
try:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
content = "\n".join(lines).rstrip("\n")
|
||||
if content:
|
||||
content += "\n"
|
||||
with tempfile.NamedTemporaryFile(
|
||||
mode="w",
|
||||
delete=False,
|
||||
dir=path.parent,
|
||||
encoding="utf-8",
|
||||
newline="\n",
|
||||
suffix=".env.tmp",
|
||||
) as handle:
|
||||
temp_path = Path(handle.name)
|
||||
handle.write(content)
|
||||
temp_path.replace(path)
|
||||
except OSError as exc:
|
||||
raise AppError(
|
||||
"Runtime settings file is not writable.",
|
||||
category=ErrorCategory.INFRA_PERSISTENT,
|
||||
suggestion="Verify file path and write permissions, then retry.",
|
||||
detail=f"Failed writing runtime env file {path}: {type(exc).__name__}: {exc}",
|
||||
) from exc
|
||||
|
||||
|
||||
def _escape_json_string(value: str) -> str:
|
||||
|
||||
Reference in New Issue
Block a user