diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py index feeb2e5af..a34b92840 100644 --- a/web/pgadmin/browser/server_groups/servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/__init__.py @@ -1266,8 +1266,17 @@ class ServerNode(PGChildNodeView): ).format(arg) ) - connection_params = convert_connection_parameter( - data.get('connection_params', [])) + # convert_connection_parameter() is bidirectional: list->dict for + # save (frontend shape), dict->list for display (DB shape). Here + # we want the storage shape (dict). If the input is already a + # dict (e.g. from internal callers / tests that mimic stored + # form), keep it as-is; otherwise assume frontend list shape and + # convert. + raw_params = data.get('connection_params', []) + if isinstance(raw_params, dict): + connection_params = raw_params + else: + connection_params = convert_connection_parameter(raw_params) if 'hostaddr' in connection_params and \ not is_valid_ipaddress(connection_params['hostaddr']): diff --git a/web/pgadmin/misc/workspaces/__init__.py b/web/pgadmin/misc/workspaces/__init__.py index afb20b5e8..a5ae5c662 100644 --- a/web/pgadmin/misc/workspaces/__init__.py +++ b/web/pgadmin/misc/workspaces/__init__.py @@ -93,8 +93,14 @@ def adhoc_connect_server(): ).format(arg) ) - connection_params = convert_connection_parameter( - data.get('connection_params', [])) + # convert_connection_parameter() is bidirectional. For a save path we + # want the storage shape (dict). If the input is already a dict, keep + # it; otherwise assume frontend list shape and convert. + raw_params = data.get('connection_params', []) + if isinstance(raw_params, dict): + connection_params = raw_params + else: + connection_params = convert_connection_parameter(raw_params) if connection_params is not None: if 'hostaddr' in connection_params and \ diff --git a/web/pgadmin/tools/user_management/__init__.py b/web/pgadmin/tools/user_management/__init__.py index 52497d4b3..d7d3946c8 100644 --- a/web/pgadmin/tools/user_management/__init__.py +++ b/web/pgadmin/tools/user_management/__init__.py @@ -168,7 +168,7 @@ def user(uid): 'username': u.username, 'email': u.email, 'active': u.active, - 'role': u.roles[0].id, + 'role': u.roles[0].id if u.roles else None, 'auth_source': u.auth_source, 'locked': u.locked, 'canDrop': u.id != current_user.id diff --git a/web/pgadmin/utils/preferences.py b/web/pgadmin/utils/preferences.py index ace5f7c28..06ea7ab55 100644 --- a/web/pgadmin/utils/preferences.py +++ b/web/pgadmin/utils/preferences.py @@ -197,8 +197,8 @@ class _Preference(): if 'value' in opt and opt['value'] == value), False) assert (has_value or (self.control_props and - (self.control_props['tags'] or - self.control_props['creatable']))) + (self.control_props.get('tags') or + self.control_props.get('creatable')))) elif self._type == 'date': value = parser_map[self._type](value).date() else: diff --git a/web/pgadmin/utils/validation_utils.py b/web/pgadmin/utils/validation_utils.py index fec586951..fb6994fbf 100644 --- a/web/pgadmin/utils/validation_utils.py +++ b/web/pgadmin/utils/validation_utils.py @@ -13,6 +13,12 @@ from email_validator import validate_email as email_validate, \ def validate_email(email, email_config=None): + # email_validator raises TypeError (not EmailNotValidError) when the + # input is not str/bytes. Treat anything non-string as invalid so + # callers see a clean False, matching the contract that this wrapper + # never raises. + if not isinstance(email, (str, bytes)): + return False try: if email_config is None: email_config = {}