Skip to content

Commit d9ac515

Browse files
committed
Use shared TOTP validator for normalization and consistent error messages
1 parent 67c50e7 commit d9ac515

File tree

1 file changed

+54
-27
lines changed

1 file changed

+54
-27
lines changed

vertica_python/vertica/connection.py

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,31 @@ def __init__(self, options: Optional[Dict[str, Any]] = None) -> None:
313313
if self.totp is not None:
314314
if not isinstance(self.totp, str):
315315
raise TypeError('The value of connection option "totp" should be a string')
316-
# Normalize: trim surrounding whitespace
317-
self.totp = self.totp.strip()
318-
# Validate TOTP format: must be 6 numeric digits, with explicit non-numeric error
319-
if not self.totp.isdigit():
320-
self._logger.error('Authentication failed: Invalid TOTP: contains non-numeric characters')
321-
raise errors.ConnectionError('Authentication failed: Invalid TOTP: contains non-numeric characters')
322-
if len(self.totp) != 6:
323-
self._logger.error('Authentication failed: Invalid TOTP: must be 6 digits')
324-
raise errors.ConnectionError('Authentication failed: Invalid TOTP: must be 6 digits')
316+
# Use shared TOTP validator for normalization and precedence checks
317+
try:
318+
from .totp_validation import validate_totp_code, INVALID_TOTP_MSG
319+
except Exception:
320+
validate_totp_code = None
321+
INVALID_TOTP_MSG = 'Invalid TOTP: Please enter a valid 6-digit numeric code.'
322+
323+
if validate_totp_code is not None:
324+
result = validate_totp_code(self.totp, totp_is_valid=None)
325+
if not result.ok:
326+
msg = result.message or INVALID_TOTP_MSG
327+
self._logger.error(f'Authentication failed: {msg}')
328+
raise errors.ConnectionError(f'Authentication failed: {msg}')
329+
# normalized digits-only code
330+
self.totp = result.code
331+
else:
332+
# Fallback minimal validation
333+
s = self.totp.strip()
334+
if not s.isdigit():
335+
self._logger.error(INVALID_TOTP_MSG)
336+
raise errors.ConnectionError(INVALID_TOTP_MSG)
337+
if len(s) != 6:
338+
self._logger.error(INVALID_TOTP_MSG)
339+
raise errors.ConnectionError(INVALID_TOTP_MSG)
340+
self.totp = s
325341
self._logger.info('TOTP received in connection options')
326342

327343
# OAuth authentication setup
@@ -983,10 +999,14 @@ def send_startup(totp_value=None):
983999
short_msg = match.group(1).strip() if match else error_msg.strip()
9841000

9851001
if "Invalid TOTP" in short_msg:
986-
print("Authentication failed: Invalid TOTP")
987-
self._logger.error("Authentication failed: Invalid TOTP")
1002+
try:
1003+
from .totp_validation import INVALID_TOTP_MSG
1004+
except Exception:
1005+
INVALID_TOTP_MSG = "Invalid TOTP: Please enter a valid 6-digit numeric code."
1006+
print(f"Authentication failed: {INVALID_TOTP_MSG}")
1007+
self._logger.error(f"Authentication failed: {INVALID_TOTP_MSG}")
9881008
self.close_socket()
989-
raise errors.ConnectionError("Authentication failed: Invalid TOTP")
1009+
raise errors.ConnectionError(f"Authentication failed: {INVALID_TOTP_MSG}")
9901010

9911011
# Generic error fallback
9921012
print(f"Authentication failed: {short_msg}")
@@ -1009,21 +1029,28 @@ def send_startup(totp_value=None):
10091029
if ready:
10101030
totp_input = sys.stdin.readline().strip()
10111031

1012-
# ❌ Blank TOTP entered
1013-
if not totp_input:
1014-
self._logger.error("Invalid TOTP: Cannot be empty.")
1015-
raise errors.ConnectionError("Invalid TOTP: Cannot be empty.")
1016-
1017-
# ❌ Normalize: trim whitespace
1018-
totp_input = totp_input.strip()
1019-
# ❌ Validate TOTP format: explicit non-numeric error, then length check
1020-
if not totp_input.isdigit():
1021-
self._logger.error("Authentication failed: Invalid TOTP: contains non-numeric characters")
1022-
raise errors.ConnectionError("Authentication failed: Invalid TOTP: contains non-numeric characters")
1023-
if len(totp_input) != 6:
1024-
print("Invalid TOTP format. Please enter a 6-digit code.")
1025-
self._logger.error("Authentication failed: Invalid TOTP: must be 6 digits")
1026-
raise errors.ConnectionError("Authentication failed: Invalid TOTP: must be 6 digits")
1032+
# Validate using shared precedence
1033+
try:
1034+
from .totp_validation import validate_totp_code, INVALID_TOTP_MSG
1035+
except Exception:
1036+
validate_totp_code = None
1037+
INVALID_TOTP_MSG = "Invalid TOTP: Please enter a valid 6-digit numeric code."
1038+
1039+
if validate_totp_code is not None:
1040+
result = validate_totp_code(totp_input, totp_is_valid=None)
1041+
if not result.ok:
1042+
msg = result.message or INVALID_TOTP_MSG
1043+
print(msg)
1044+
self._logger.error(msg)
1045+
raise errors.ConnectionError(msg)
1046+
totp_input = result.code
1047+
else:
1048+
s = totp_input.strip()
1049+
if not s.isdigit() or len(s) != 6:
1050+
print(INVALID_TOTP_MSG)
1051+
self._logger.error(INVALID_TOTP_MSG)
1052+
raise errors.ConnectionError(INVALID_TOTP_MSG)
1053+
totp_input = s
10271054
# ✅ Valid TOTP — retry connection
10281055
totp = totp_input
10291056
self.close_socket()

0 commit comments

Comments
 (0)