Coverage for seedboxsync/front/views/settings.py: 95%
65 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-26 17:46 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-26 17:46 +0000
1#
2# Copyright (C) 2015-2026 Guillaume Kulakowski <guillaume@kulakowski.fr>
3#
4# For the full copyright and license information, please view the LICENSE
5# file that was distributed with this source code.
6#
7"""SeedboxSync Flask vierw for settings."""
9from collections.abc import Iterable
10from typing import Any
11from flask import flash, render_template, request
12from flask.wrappers import Request
13from flask_babel import gettext
14from seedboxsync.core import Config, current_app as app
15from seedboxsync.core.dao import SeedboxSync
16from seedboxsync.front.babel import ALLOWED_LANGUAGES
17from seedboxsync.front.utils import init_flash
18from seedboxsync.front.views import bp
21@bp.route("/settings", methods=("GET", "POST"))
22def settings() -> str:
23 """Manage settings: load configuration, display form, persist changes."""
24 init_flash()
25 saved = False
26 languages_list = ALLOWED_LANGUAGES
28 form = _build_form()
30 if request.method == "POST":
31 missing = [f for f in _required_form_fields() if not request.form.get(f)]
32 if missing:
33 flash(
34 gettext("Missing required fields: %(missing)s", missing=", ".join(missing)),
35 "error",
36 )
37 else:
38 try:
39 _save_form(request)
40 form = _build_form() # reload cleaned values
41 saved = True
42 except Exception as e:
43 app.logger.exception("Failed to save config", exc_info=e)
44 flash(gettext("Failed to save configuration."), "error")
46 return render_template("settings.html", form=form, saved=saved, languages_list=languages_list)
49# -------------------------
50# Helpers
51# -------------------------
52def _required_form_fields() -> Iterable[str]:
53 """
54 List of all requitred fields.
56 Returns:
57 True if the value represents an enabled/true state, otherwise False.
58 """
59 return [
60 "seedbox_host",
61 "seedbox_port",
62 "seedbox_login",
63 "seedbox_password",
64 "seedbox_protocol",
65 "seedbox_tmp_path",
66 "seedbox_watch_path",
67 "seedbox_finished_path",
68 "seedbox_part_suffix",
69 ]
72def _build_form() -> dict[str, Any]:
73 """
74 Build form fields.
76 Returns:
77 Dictionnary of fields.
78 """
79 fields = {key: ((1 if value else 0) if key.endswith("_enabled") else (0 if value is False else value)) for key, value in app.seedboxsync_config.items()}
80 fields.setdefault(
81 "seedbox_timeout_enabled",
82 "1" if fields.get("seedbox_timeout", "0") not in ["", "0", False] else "0",
83 )
84 fields.setdefault(
85 "seedbox_chmod_enabled",
86 "1" if fields.get("seedbox_chmod", "0") not in ["", "0", False] else "0",
87 )
89 return fields
92def _save_form(req: Request) -> None:
93 """Save form data to the configuration file."""
94 seedbox_timeout_enabled = req.form.get("seedbox_timeout_enabled", "0") == "1"
95 seedbox_chmod_enabled = req.form.get("seedbox_chmod_enabled", "0") == "1"
96 fields = app.seedboxsync_config
97 config_to_db: list[dict[str, str]] = []
98 config_to_update: dict[str, Any] = {}
99 db_value: str = "0"
100 value: str | bool = False
102 for key in fields:
103 if key in req.form:
104 value = str(req.form[key] or "").strip()
105 db_value = value
106 if key.endswith("_enabled"):
107 value = bool(int(value))
108 elif key not in req.form and key.endswith("_enabled"):
109 value = False
110 db_value = "0"
112 app.logger.debug(f"Updated config[{Config.CONFIG_NAMESPACE}{key.upper()}] = {value}")
113 config_to_update[f"{Config.CONFIG_NAMESPACE}{key.upper()}"] = value
114 config_to_db.append(
115 {
116 "key": f"{Config.DB_CONFIG_PREFIX}{key}",
117 "value": db_value,
118 }
119 )
121 if not seedbox_timeout_enabled:
122 app.logger.debug(f"Updated config[{Config.CONFIG_NAMESPACE}SEEDBOX_TIMEOUT] = False")
123 config_to_update[f"{Config.CONFIG_NAMESPACE}SEEDBOX_TIMEOUT"] = False
124 config_to_db.append(
125 {
126 "key": f"{Config.DB_CONFIG_PREFIX}seedbox_timeout",
127 "value": "0",
128 }
129 )
131 if not seedbox_chmod_enabled:
132 app.logger.debug(f"Updated config[{Config.CONFIG_NAMESPACE}SEEDBOX_CHMOD] = False")
133 config_to_update[f"{Config.CONFIG_NAMESPACE}SEEDBOX_CHMOD"] = False
134 config_to_db.append(
135 {
136 "key": f"{Config.DB_CONFIG_PREFIX}seedbox_chmod",
137 "value": "0",
138 }
139 )
141 # Update config in Flask app
142 app.config.from_mapping(config_to_update)
144 # Save in database
145 SeedboxSync.replace_many(config_to_db).execute() # type: ignore[no-untyped-call]