|
10 | 10 | import NSKeyedUnArchiver |
11 | 11 |
|
12 | 12 | from findmy import FindMyAccessory, MobileMeDelegateError |
13 | | -from findmy.errors import AppleServiceUnavailableError |
| 13 | +from findmy.errors import AppleServiceUnavailableError, GrandSlamRefusedError |
14 | 14 | from findmy.accessory import FixedRollingKeyPairAccessory |
15 | 15 | from findmy.keys import KeyPairType |
16 | 16 | from findmy.reports import ( |
@@ -511,6 +511,25 @@ def assertAnisetteIsSupported(serializedAccountData: str) -> str | None: |
511 | 511 | end is wasted effort. |
512 | 512 | """ |
513 | 513 |
|
| 514 | +REASON_REFUSED_BEFORE_PASSWORD = "refused_before_password" |
| 515 | +""" |
| 516 | +Grand Slam refused the first step of the sign-in, which carries the username and the Anisette |
| 517 | +headers and no password. |
| 518 | +
|
| 519 | +**So the password is not the problem, and the screen must not suggest it is.** This arrived as |
| 520 | +an `InvalidCredentialsError` reading "Email verification failed", shown verbatim, on a device |
| 521 | +whose local Anisette was working - OpenTagViewer#248. What is left is the account itself, or the |
| 522 | +machine identity the Anisette data presents, and the second is the one thing this app can change: |
| 523 | +the screen offers the remote-server route for it, as it does for :data:`REASON_APPLE_DECLINED`. |
| 524 | +
|
| 525 | +**Which `ec` means what is not established.** Apple's text here is generic, and the code was not |
| 526 | +kept until the fork started carrying it, so nothing branches on a value. The detail keeps the |
| 527 | +code, so a report carries it. |
| 528 | +
|
| 529 | +**A wrong password is not this.** That is refused at the second step, `complete`, and stays |
| 530 | +:data:`REASON_UNKNOWN` - a different Anisette identity cannot fix a bad credential. |
| 531 | +""" |
| 532 | + |
514 | 533 | REASON_UNKNOWN = "unknown" |
515 | 534 | """Anything else. The detail is shown as-is, because a wrong guess is worse than raw text.""" |
516 | 535 |
|
@@ -557,6 +576,11 @@ def classifyLoginFailure(error: BaseException) -> str: |
557 | 576 | if isinstance(error, AppleServiceUnavailableError): |
558 | 577 | return REASON_APPLE_DECLINED |
559 | 578 |
|
| 579 | + # Only the first step. The same type reports a wrong password at the second, and that one |
| 580 | + # must not offer a different Anisette server as though it could help. |
| 581 | + if isinstance(error, GrandSlamRefusedError) and error.before_password: |
| 582 | + return REASON_REFUSED_BEFORE_PASSWORD |
| 583 | + |
560 | 584 | if isinstance(error, (asyncio.TimeoutError, asyncio.CancelledError)): |
561 | 585 | return REASON_NETWORK |
562 | 586 | if isinstance(error, _NETWORK_ERRORS): |
|
0 commit comments