Skip to content

Commit

Permalink
Merge branch 'master' into doc/ref2
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreyNikiforov authored Aug 12, 2024
2 parents fc7366b + d50ddf0 commit e5f0237
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- fix: use a-z for sms mfa index to disambiguate with mfa code with leading zeros [#925](https://github.com/icloud-photos-downloader/icloud_photos_downloader/issues/925)

## 1.23.0 (2024-07-25)

- feature: update webui and allow to cancel and resume sync
Expand Down
3 changes: 3 additions & 0 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,6 @@ This is a list of all options available for command line interface (CLI) of the

: Script to be executed for notification on expired MFA

=======

TODO: SMTP & Notification params
59 changes: 48 additions & 11 deletions src/icloudpd/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,35 +131,72 @@ def request_2fa(icloud: PyiCloudService, logger: logging.Logger) -> None:
"""Request two-factor authentication."""
devices = icloud.get_trusted_phone_numbers()
devices_count = len(devices)
device_index_alphabet = "abcdefghijklmnopqrstuvwxyz"
if devices_count > 0:
if devices_count > 99:
if devices_count > len(device_index_alphabet):
logger.error("Too many trusted devices for authentication")
sys.exit(1)

for i, device in enumerate(devices):
print(f" {i}: {device.obfuscated_number}")
print(f" {device_index_alphabet[i]}: {device.obfuscated_number}")

index_str = f"..{devices_count - 1}" if devices_count > 1 else ""
code: int = click.prompt(
f"Please enter two-factor authentication code or device index (0{index_str}) to send SMS with a code",
type=click.IntRange(0, 999999),
)
index_str = f"..{device_index_alphabet[devices_count - 1]}" if devices_count > 1 else ""
index_or_code: str = ""
while True:
index_or_code = (
click.prompt(
f"Please enter two-factor authentication code or device index ({device_index_alphabet[0]}{index_str}) to send SMS with a code",
)
.strip()
.lower()
)

if index_or_code == "":
click.echo("Empty string. Try again")
continue

if len(index_or_code) == 1:
if index_or_code in device_index_alphabet:
if device_index_alphabet.index(index_or_code) > devices_count - 1:
click.echo(
f"Invalid index, should be {device_index_alphabet[0]}{index_str}. Try again"
)
continue
else:
break
else:
click.echo(
f"Invalid index, should be {device_index_alphabet[0]}{index_str}. Try again"
)
continue

if len(index_or_code) == 6:
if index_or_code.isdigit():
break
else:
click.echo("Invalid code, should be six digits. Try again")
continue

click.echo(
f"Should be index {device_index_alphabet[0]}{index_str} or six-digit code. Try again"
)

if code < devices_count:
if index_or_code in device_index_alphabet:
# need to send code
device = devices[code]
device_index = device_index_alphabet.index(index_or_code)
device = devices[device_index]
if not icloud.send_2fa_code_sms(device.id):
logger.error("Failed to send two-factor authentication code")
sys.exit(1)
code = click.prompt(
code: int = click.prompt(
"Please enter two-factor authentication code that you received over SMS",
type=click.IntRange(0, 999999),
)
if not icloud.validate_2fa_code_sms(device.id, code):
logger.error("Failed to verify two-factor authentication code")
sys.exit(1)
else:
if not icloud.validate_2fa_code(str(code)):
if not icloud.validate_2fa_code(index_or_code):
logger.error("Failed to verify two-factor authentication code")
sys.exit(1)
else:
Expand Down
12 changes: 8 additions & 4 deletions tests/test_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,14 @@ def test_password_prompt_2sa(self) -> None:
[
"--username",
"[email protected]",
"--password",
"password1",
"--no-progress-bar",
"--cookie-directory",
cookie_dir,
"--auth-only",
],
input="password1\n0\n654321\n",
input="0\n654321\n",
)
self.assertIn("DEBUG Authenticating...", self._caplog.text)
self.assertIn(
Expand Down Expand Up @@ -217,21 +219,23 @@ def test_password_prompt_2fa(self) -> None:
[
"--username",
"[email protected]",
"--password",
"password1",
"--no-progress-bar",
"--cookie-directory",
cookie_dir,
"--auth-only",
],
input="password1\n654321\n",
input="654321\n",
)
self.assertIn("DEBUG Authenticating...", self._caplog.text)
self.assertIn(
"INFO Two-factor authentication is required",
self._caplog.text,
)
self.assertIn(" 0: (***) ***-**81", result.output)
self.assertIn(" a: (***) ***-**81", result.output)
self.assertIn(
"Please enter two-factor authentication code or device index (0) to send SMS with a code: 654321",
"Please enter two-factor authentication code or device index (a) to send SMS with a code: 654321",
result.output,
)
self.assertIn(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_two_step_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def test_2fa_flow_valid_code(self) -> None:
self._caplog.text,
)
self.assertIn(
"Please enter two-factor authentication code or device index (0) to send SMS with a code: 654321",
"Please enter two-factor authentication code or device index (a) to send SMS with a code: 654321",
result.output,
)
self.assertIn(
Expand Down

0 comments on commit e5f0237

Please sign in to comment.