mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2026-08-19 01:15:04 -05:00
Five small defensive fixes that were exposed by running the full regression suite end-to-end: 1. utils/validation_utils.py: validate_email() now returns False instead of raising TypeError when passed a non-str/bytes value (e.g. None from a missing form field). Matches the wrapper's contract that it only ever returns bool. 2. tools/user_management/__init__.py: list endpoint guarded against users with no roles. u.roles[0].id -> u.roles[0].id if u.roles else None. Triggered by ChangePasswordTestCase fixtures. 3. utils/preferences.py: control_props['tags'] / ['creatable'] replaced with .get(...) so preferences whose control_props omit these keys do not raise KeyError on update. 4. browser/server_groups/servers/__init__.py (create endpoint): convert_connection_parameter() is bidirectional (list<->dict). The save path always wants the storage shape (dict). When input is already a dict (internal callers / tests mimicking storage form), skip conversion to avoid the dict->list round-trip that breaks the MutableDict column. Same fix applied to the workspaces save path. 5. misc/workspaces/__init__.py: same defensive handling for convert_connection_parameter() on the save path. These are all pre-existing master bugs surfaced by edge-case test data; none are introduced by the 9.15 CVE work.
60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
##########################################################################
|
|
#
|
|
# pgAdmin 4 - PostgreSQL Tools
|
|
#
|
|
# Copyright (C) 2013 - 2026, The pgAdmin Development Team
|
|
# This software is released under the PostgreSQL Licence
|
|
#
|
|
##########################################################################
|
|
|
|
import email_validator
|
|
from email_validator import validate_email as email_validate, \
|
|
EmailNotValidError
|
|
|
|
|
|
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 = {}
|
|
import config
|
|
email_config['CHECK_EMAIL_DELIVERABILITY'] = \
|
|
config.CHECK_EMAIL_DELIVERABILITY
|
|
email_config['ALLOW_SPECIAL_EMAIL_DOMAINS'] = \
|
|
config.ALLOW_SPECIAL_EMAIL_DOMAINS
|
|
email_config["GLOBALLY_DELIVERABLE"] = \
|
|
config.GLOBALLY_DELIVERABLE
|
|
|
|
# Allow special email domains
|
|
if isinstance(email_config['ALLOW_SPECIAL_EMAIL_DOMAINS'], str):
|
|
email_config['ALLOW_SPECIAL_EMAIL_DOMAINS'] = \
|
|
email_config['ALLOW_SPECIAL_EMAIL_DOMAINS'].split(',')
|
|
|
|
try:
|
|
email_validator.SPECIAL_USE_DOMAIN_NAMES = [
|
|
d for d in email_validator.SPECIAL_USE_DOMAIN_NAMES
|
|
if d not in email_config['ALLOW_SPECIAL_EMAIL_DOMAINS']
|
|
]
|
|
except Exception:
|
|
pass
|
|
|
|
email_validator.GLOBALLY_DELIVERABLE = \
|
|
email_config["GLOBALLY_DELIVERABLE"]
|
|
|
|
# Validate.
|
|
_ = email_validate(
|
|
email,
|
|
check_deliverability=email_config['CHECK_EMAIL_DELIVERABILITY'])
|
|
|
|
# Update with the normalized form.
|
|
return True
|
|
except EmailNotValidError as e:
|
|
# email is not valid, exception message is human-readable
|
|
print(str(e))
|
|
return False
|