Coverage for an_website/settings/settings.py: 92.857%
42 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-16 19:56 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-16 19:56 +0000
1# This program is free software: you can redistribute it and/or modify
2# it under the terms of the GNU Affero General Public License as
3# published by the Free Software Foundation, either version 3 of the
4# License, or (at your option) any later version.
5#
6# This program is distributed in the hope that it will be useful,
7# but WITHOUT ANY WARRANTY; without even the implied warranty of
8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9# GNU Affero General Public License for more details.
10#
11# You should have received a copy of the GNU Affero General Public License
12# along with this program. If not, see <https://www.gnu.org/licenses/>.
14"""The settings page used to change settings."""
16from __future__ import annotations
18import contextlib
19import types
20from base64 import b64encode
21from collections.abc import Awaitable, Mapping
23from tornado.web import HTTPError
25from ..utils.options import Options
26from ..utils.request_handler import HTMLRequestHandler
27from ..utils.themes import THEMES
28from ..utils.utils import (
29 BUMPSCOSITY_VALUES,
30 ModuleInfo,
31 bool_to_str,
32 str_to_bool,
33)
36def get_module_info() -> ModuleInfo:
37 """Create and return the ModuleInfo for this module."""
38 return ModuleInfo(
39 handlers=((r"/einstellungen", SettingsPage),),
40 name="Einstellungen",
41 description="Stelle wichtige Sachen ein",
42 path="/einstellungen",
43 keywords=(
44 "Einstellungen",
45 "Config",
46 "Settings",
47 ),
48 aliases=("/config", "/settings"),
49 )
52class SettingsPage(HTMLRequestHandler):
53 """The request handler for the settings page."""
55 async def get(self, *, head: bool = False) -> None:
56 """Handle GET requests to the settings page."""
57 if head:
58 return
59 await self.render_settings( # nosec: B106
60 save_in_cookie=self.get_bool_argument("save_in_cookie", True),
61 show_token_input=self.get_bool_argument("auth", False),
62 token="",
63 advanced_settings=self.show_advanced_settings(),
64 )
66 async def post(self) -> None:
67 """Handle POST requests to the settings page."""
68 if not self.request.body.strip():
69 raise HTTPError(400, "No body provided")
70 advanced_settings = self.get_bool_argument("advanced_settings", False)
71 save_in_cookie: bool = self.get_bool_argument("save_in_cookie", False)
72 token = self.get_argument("access_token", "")
73 access_token: None | str = (
74 b64encode(token.encode("UTF-8")).decode("ASCII") if token else None
75 )
77 if save_in_cookie:
78 if access_token:
79 self.set_cookie("access_token", access_token)
80 self.set_cookie("advanced_settings", bool_to_str(advanced_settings))
81 for option in self.user_settings.iter_options():
82 self.set_cookie(
83 option.name,
84 option.value_to_string(
85 option.get_value(
86 self,
87 include_cookie=False,
88 include_query_argument=False,
89 )
90 ),
91 )
93 replace_url_with = self.fix_url(
94 self.request.full_url(),
95 access_token=None,
96 advanced_settings=None,
97 save_in_cookie=None,
98 **dict.fromkeys(self.user_settings.iter_option_names()),
99 )
100 else:
101 replace_url_with = self.fix_url(
102 self.request.full_url(),
103 access_token=access_token,
104 advanced_settings=advanced_settings,
105 save_in_cookie=False,
106 **self.user_settings.as_dict_with_str_values(
107 include_cookie=False, include_query_argument=False
108 ),
109 )
111 if replace_url_with != self.request.full_url():
112 return self.redirect(replace_url_with)
114 await self.render_settings(
115 advanced_settings=advanced_settings,
116 save_in_cookie=save_in_cookie,
117 show_token_input=bool(
118 token or self.get_bool_argument("auth", False)
119 ),
120 token=token,
121 kwargs={
122 option.name: option.get_value(
123 self, include_cookie=False, include_query_argument=False
124 )
125 for option in self.user_settings.iter_options()
126 },
127 )
129 def render_settings( # pylint: disable=too-many-arguments
130 self,
131 *,
132 save_in_cookie: bool,
133 show_token_input: bool,
134 token: str,
135 advanced_settings: bool,
136 kwargs: Mapping[str, object] = types.MappingProxyType({}),
137 ) -> Awaitable[None]:
138 """Render the settings page."""
139 return self.render(
140 "pages/settings.html",
141 advanced_settings=advanced_settings,
142 ask_before_leaving_default=(
143 Options.ask_before_leaving.get_default_value(self)
144 ),
145 bumpscosity_values=BUMPSCOSITY_VALUES,
146 no_3rd_party_default=Options.no_3rd_party.get_default_value(self),
147 save_in_cookie=save_in_cookie,
148 show_token_input=show_token_input,
149 themes=THEMES,
150 token=token,
151 **kwargs,
152 )
154 def show_advanced_settings(self) -> bool:
155 """Whether advanced settings should be shown."""
156 if arg := self.get_argument("advanced_settings", ""):
157 with contextlib.suppress(ValueError):
158 return str_to_bool(arg)
159 return str_to_bool(self.get_cookie("advanced_settings", ""), False)