From 9dd6bbd9ef16d12268a165b809fb2e321b085ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Diot?= Date: Tue, 28 May 2024 08:51:40 +0100 Subject: [PATCH] Fix Database class to remove unused variables and simplify fallback logic as we have other ways of checking it now --- src/common/db/Database.py | 30 ++++++++---------------------- src/scheduler/main.py | 5 +---- src/ui/main.py | 8 ++++---- 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/common/db/Database.py b/src/common/db/Database.py index c8d15081d..d7ca2e609 100644 --- a/src/common/db/Database.py +++ b/src/common/db/Database.py @@ -75,7 +75,6 @@ class Database: """Initialize the database""" self.logger = logger self.readonly = False - self.last_fallback = None if pool: self.logger.warning("The pool parameter is deprecated, it will be removed in the next version") @@ -180,7 +179,6 @@ class Database: self.sql_engine.dispose(close=True) self.sql_engine = create_engine(self.database_uri_readonly, **self._engine_kwargs) self.readonly = True - self.last_fallback = datetime.now() fallback = True continue self.logger.error(f"Can't connect to database after {DATABASE_RETRY_TIMEOUT} seconds: {e}") @@ -192,7 +190,6 @@ class Database: self.sql_engine.dispose(close=True) self.sql_engine = create_engine(sqlalchemy_string, **self._engine_kwargs) self.readonly = True - self.last_fallback = datetime.now() if "Unknown table" in str(e): not_connected = False continue @@ -254,21 +251,6 @@ class Database: self.logger.error("The database engine is not initialized") _exit(1) - if self.database_uri and self.readonly and self.last_fallback and (datetime.now() - self.last_fallback).total_seconds() > 30: - # ? If the database is forced to be read-only, we try to connect as a non read-only user every time until the database is writable - try: - self.retry_connection(pool_timeout=1) - self.readonly = False - self.logger.info("The database is no longer read-only, defaulting to read-write mode") - except (OperationalError, DatabaseError): - try: - self.retry_connection(readonly=True, pool_timeout=1) - except (OperationalError, DatabaseError): - if self.database_uri_readonly: - with suppress(OperationalError, DatabaseError): - self.retry_connection(fallback=True, pool_timeout=1) - self.readonly = True - session = None try: with self.sql_engine.connect() as conn: @@ -289,13 +271,11 @@ class Database: with suppress(OperationalError, DatabaseError): self.retry_connection(fallback=True, pool_timeout=1) self.readonly = True - self.last_fallback = datetime.now() elif isinstance(e, (ConnectionRefusedError, OperationalError)) and self.database_uri_readonly: self.logger.warning("Can't connect to the database, falling back to read-only one ...") with suppress(OperationalError, DatabaseError): self.retry_connection(fallback=True, pool_timeout=1) self.readonly = True - self.last_fallback = datetime.now() raise finally: if session: @@ -513,7 +493,10 @@ class Database: return str(e) def checked_changes( - self, changes: Optional[List[str]] = None, plugins_changes: Optional[Union[Set[str], List[str], Tuple[str]]] = None, value: Optional[bool] = False + self, + changes: Optional[List[str]] = None, + plugins_changes: Optional[Union[Literal["all"], Set[str], List[str], Tuple[str]]] = None, + value: Optional[bool] = False, ) -> str: """Set changed bit for config, custom configs, instances and plugins""" changes = changes or ["config", "custom_configs", "external_plugins", "pro_plugins", "instances"] @@ -541,7 +524,10 @@ class Database: metadata.instances_changed = value if plugins_changes: - session.query(Plugins).filter(Plugins.id.in_(plugins_changes)).update({Plugins.config_changed: value}) + if plugins_changes == "all": + session.query(Plugins).update({Plugins.config_changed: value}) + else: + session.query(Plugins).filter(Plugins.id.in_(plugins_changes)).update({Plugins.config_changed: value}) session.commit() except BaseException as e: diff --git a/src/scheduler/main.py b/src/scheduler/main.py index 8f1434e3b..925d9ecb1 100644 --- a/src/scheduler/main.py +++ b/src/scheduler/main.py @@ -747,12 +747,9 @@ if __name__ == "__main__": logger.error(f"Exception while reloading after running jobs once scheduling : {format_exc()}") try: - ret = SCHEDULER.db.checked_changes(CHANGES) + ret = SCHEDULER.db.checked_changes(CHANGES, plugins_changes="all") if ret: logger.error(f"An error occurred when setting the changes to checked in the database : {ret}") - ret = SCHEDULER.db.checked_plugins_changes(changed_plugins) - if ret: - logger.error(f"An error occurred when setting the plugins changes to checked in the database : {ret}") except BaseException as e: logger.error(f"Error while setting changes to checked in the database: {e}") diff --git a/src/ui/main.py b/src/ui/main.py index 31aa4200d..51809a90d 100755 --- a/src/ui/main.py +++ b/src/ui/main.py @@ -407,8 +407,6 @@ def set_csp_header(response): + " base-uri 'self';" + (" connect-src *;" if request.path.startswith(("/check", "/setup")) else "") ) - if app.config["DB"].readonly: - flash("Database connection is in read-only mode : no modification possible.", "error") return response @@ -457,8 +455,7 @@ def before_request(): with suppress(BaseException): app.config["DB"].retry_connection(fallback=True, pool_timeout=1) app.config["DB"].readonly = True - - if not app.config["DB"].readonly and request.method == "POST" and not ("/totp" in request.path or "/login" in request.path): + elif not app.config["DB"].readonly and request.method == "POST" and not ("/totp" in request.path or "/login" in request.path): try: app.config["DB"].test_write() except BaseException: @@ -481,6 +478,9 @@ def before_request(): logout_user() session.clear() + if app.config["DB"].readonly: + flash("Database connection is in read-only mode : no modification possible.", "error") + @app.route("/", strict_slashes=False) def index():