diff --git a/docs/en_US/release_notes_9_16.rst b/docs/en_US/release_notes_9_16.rst index 4f0740cdff0..d993120cef6 100644 --- a/docs/en_US/release_notes_9_16.rst +++ b/docs/en_US/release_notes_9_16.rst @@ -54,3 +54,4 @@ Bug fixes | `Issue #9984 `_ - Fix the Docker entrypoint mishandling a quoted PGADMIN_CONFIG_CONFIG_DATABASE_URI, which caused a SQLAlchemy parse error and silently skipped PGADMIN_DEFAULT_EMAIL/PASSWORD setup. | `Issue #9987 `_ - Fix "AttributeError: 'PgAdmin' object has no attribute 'login_manager'" crash when running setup.py user-management commands (add-user, update-user) from the CLI. | `Issue #9988 `_ - Provide an actionable error when 'openid' is in OAUTH2_SCOPE but OAUTH2_SERVER_METADATA_URL is not set, instead of a cryptic Authlib failure. + | `Issue #10027 `_ - Fix the spurious "Crypt key is missing" error and logged traceback in the Query Tool new-connection endpoints after a backend restart, by surfacing it as the standard CRYPTKEY_MISSING response so the client recovers transparently. diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py index c9e26df2f00..e5e583a6d4b 100644 --- a/web/pgadmin/tools/sqleditor/__init__.py +++ b/web/pgadmin/tools/sqleditor/__init__.py @@ -2379,6 +2379,8 @@ def _check_server_connection_status(sgid, sid=None): } ) + except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing): + raise except Exception as e: current_app.logger.exception(e) return make_json_response( @@ -2445,6 +2447,8 @@ def get_new_connection_data(sgid=None, sid=None): } ) + except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing): + raise except Exception as e: current_app.logger.exception(e) return make_json_response( @@ -2519,6 +2523,8 @@ def get_new_connection_database(sgid, sid=None): } } ) + except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing): + raise except Exception as e: current_app.logger.exception(e) return make_json_response( @@ -2585,6 +2591,8 @@ def get_new_connection_user(sgid, sid=None): } } ) + except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing): + raise except Exception as e: current_app.logger.exception(e) return make_json_response( @@ -2649,6 +2657,8 @@ def get_new_connection_role(sgid, sid=None): } } ) + except (ConnectionLost, SSHTunnelConnectionLost, CryptKeyMissing): + raise except Exception as e: current_app.logger.exception(e) return make_json_response( diff --git a/web/pgadmin/tools/sqleditor/tests/test_new_connection_dialog.py b/web/pgadmin/tools/sqleditor/tests/test_new_connection_dialog.py index 44b16fc3e49..41300990a33 100644 --- a/web/pgadmin/tools/sqleditor/tests/test_new_connection_dialog.py +++ b/web/pgadmin/tools/sqleditor/tests/test_new_connection_dialog.py @@ -6,11 +6,11 @@ # This software is released under the PostgreSQL Licence # ########################################################################## -import json +from unittest.mock import patch from pgadmin.utils.route import BaseTestGenerator from regression import parent_node_dict from regression.test_setup import config_data -from regression.python_test_utils import test_utils as utils +from pgadmin.utils.exception import CryptKeyMissing class TestNewConnectionDialog(BaseTestGenerator): @@ -19,15 +19,19 @@ class TestNewConnectionDialog(BaseTestGenerator): ('New connection dialog', dict( url="/sqleditor/new_connection_dialog/", - is_positive_test=True, - mocking_required=False, - is_connect_server=False, - test_data={}, - mock_data={}, + crypt_key_missing=False, expected_data={ "status_code": 200 } )), + ('New connection dialog when the crypt key is missing', + dict( + url="/sqleditor/new_connection_dialog/", + crypt_key_missing=True, + expected_data={ + "status_code": 503 + } + )), ] def setUp(self): @@ -43,8 +47,20 @@ def new_connection(self): return response def runTest(self): - if self.is_positive_test: + if self.crypt_key_missing: + # When the crypt key is missing (e.g. the backend was restarted), + # the endpoint must surface CryptKeyMissing as a 503 + # CRYPTKEY_MISSING response so the client can transparently + # recover, rather than swallowing it into a generic error and + # logging a traceback. See issue #10027. + with patch('pgadmin.utils.driver.psycopg3.server_manager.' + 'ServerManager.connection', + side_effect=CryptKeyMissing()): + response = self.new_connection() + self.assertEqual(response.status_code, + self.expected_data['status_code']) + self.assertIn('CRYPTKEY_MISSING', response.data.decode('utf-8')) + else: response = self.new_connection() - actual_response_code = response.status_code - expected_response_code = self.expected_data['status_code'] - self.assertEqual(actual_response_code, expected_response_code) + self.assertEqual(response.status_code, + self.expected_data['status_code'])