diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0f2dd56c..57bb5c8b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -447,7 +447,7 @@ chaquopy { // wheel for desktop platforms and a pure-Python `py3-none-any` one as well. // There is no Android wheel, so pip falls back to the pure-Python build - which // is correct but markedly slower. The messages here are small enough not to care. - install("git+https://github.com/parawanderer/FindMy.py@7969003ca785658369b650f75d9e7ca519566bf6") + install("git+https://github.com/parawanderer/FindMy.py@00fd962a0e8ec9f5601fe0b9db3f16ccea252a3c") install("NSKeyedUnArchiver==1.5") diff --git a/app/src/androidTest/java/dev/wander/android/opentagviewer/ForceRemoteAnisetteAfterDeclineTest.java b/app/src/androidTest/java/dev/wander/android/opentagviewer/ForceRemoteAnisetteAfterDeclineTest.java index ece9fe5e..40ce0558 100644 --- a/app/src/androidTest/java/dev/wander/android/opentagviewer/ForceRemoteAnisetteAfterDeclineTest.java +++ b/app/src/androidTest/java/dev/wander/android/opentagviewer/ForceRemoteAnisetteAfterDeclineTest.java @@ -11,6 +11,7 @@ import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; @@ -169,6 +170,29 @@ public void theRetryGoesThroughTheServerAndIsRecordedAsRemote() { UserSettings.ANISETTE_REMOTE, storedSettings().getAnisetteMode()); } + /** + * Issue #248: refused before the password was used, on a device whose local Anisette works. + * + *

The button appears, and the sentence says the password is not the problem while keeping + * Apple's text, which carries the {@code ec} a report needs. + */ + @Test + public void aRefusalBeforeThePasswordOffersTheRemoteServer() { + AppDependencies.replaceAuthService( + this.apple = FakeAppleAuthService.refusesBeforeThePasswordOnceThenSignsIn()); + + launch(); + signInExpectingAnotherLoginCall(); + + Eventually.check(() -> onView(withId(R.id.login_error_try_remote_anisette)) + .perform(scrollTo()).check(matches(isDisplayed()))); + + final String expected = getInstrumentation().getTargetContext().getString( + R.string.login_failed_refused_before_password, + "Email verification failed (ec=-1): This action cannot be completed at this time."); + onView(withId(R.id.login_error_message_text)).check(matches(withText(expected))); + } + /** * A wrong password does not offer it: a different Anisette identity would not fix a bad * credential, and saying otherwise sends people to change a setting that cannot help. diff --git a/app/src/androidTest/java/dev/wander/android/opentagviewer/python/FakeAppleAuthService.java b/app/src/androidTest/java/dev/wander/android/opentagviewer/python/FakeAppleAuthService.java index 1260de74..dd05e44f 100644 --- a/app/src/androidTest/java/dev/wander/android/opentagviewer/python/FakeAppleAuthService.java +++ b/app/src/androidTest/java/dev/wander/android/opentagviewer/python/FakeAppleAuthService.java @@ -121,6 +121,21 @@ public static FakeAppleAuthService declinesOnceThenSignsIn() { return fake; } + /** + * Apple refuses the first step of the sign-in, before the password is used, then serves the + * next - issue #248's shape, followed by the retry through a server getting past it. + * + *

Fails as {@code REFUSED_BEFORE_PASSWORD}, which the remote-server button is also gated on. + */ + public static FakeAppleAuthService refusesBeforeThePasswordOnceThenSignsIn() { + final FakeAppleAuthService fake = new FakeAppleAuthService(LOGIN_STATE.LOGGED_IN, null); + fake.loginFailsWith = new PythonAccountLoginException( + "Email verification failed (ec=-1): This action cannot be completed at this time.", + PythonAccountLoginException.REASON_REFUSED_BEFORE_PASSWORD); + fake.loginFailuresRemaining = 1; + return fake; + } + /** The password is wrong, or Apple is unreachable. */ public static FakeAppleAuthService rejectsTheSignIn(final String message) { final FakeAppleAuthService fake = diff --git a/app/src/main/java/dev/wander/android/opentagviewer/AppleLoginActivity.java b/app/src/main/java/dev/wander/android/opentagviewer/AppleLoginActivity.java index ab613b25..05be9d41 100644 --- a/app/src/main/java/dev/wander/android/opentagviewer/AppleLoginActivity.java +++ b/app/src/main/java/dev/wander/android/opentagviewer/AppleLoginActivity.java @@ -747,15 +747,18 @@ private void showLoginFailure(final Throwable error) { ((TextView) this.findViewById(R.id.login_error_message_text)) .setText(this.describeLoginFailure(error)); - // Offer the server route only when Apple itself refused the sign-in - a 429 or 503 - - // and not for a wrong password or a dead network, where a different Anisette identity - // changes nothing. That is the one failure where local Anisette worked and Apple still - // said no, so switching the machine identity a server presents is the thing left to try. + // Offer the server route only when Apple itself refused the sign-in - a 429 or 503, or + // a refusal before the password was used (#248) - and not for a wrong password or a dead + // network, where a different Anisette identity changes nothing. Those are the failures + // where local Anisette worked and Apple still said no, so switching the machine identity + // a server presents is the thing left to try. final String reason = error instanceof PythonAccountLoginException ? ((PythonAccountLoginException) error).getReason() : PythonAccountLoginException.REASON_UNKNOWN; + final boolean appleRefused = PythonAccountLoginException.REASON_APPLE_DECLINED.equals(reason) + || PythonAccountLoginException.REASON_REFUSED_BEFORE_PASSWORD.equals(reason); this.findViewById(R.id.login_error_try_remote_anisette).setVisibility( - PythonAccountLoginException.REASON_APPLE_DECLINED.equals(reason) ? VISIBLE : GONE); + appleRefused ? VISIBLE : GONE); } /** @@ -825,6 +828,13 @@ private String describeLoginFailure(final Throwable error) { return this.getString(R.string.login_failed_apple_declined); } + // Refused before the password was used (#248), so the sentence says that retyping it + // will not help. Apple's own text follows, because it carries the ec a report needs. + if (PythonAccountLoginException.REASON_REFUSED_BEFORE_PASSWORD.equals(reason)) { + return this.getString(R.string.login_failed_refused_before_password, + error.getLocalizedMessage()); + } + // Apple took the password and the code, then would not open iCloud for the account. Kept // apart from the terms sentence because the remedy is elsewhere entirely, and apart from // "Apple declined" because that one says to wait - see REASON_ICLOUD_REFUSED. diff --git a/app/src/main/java/dev/wander/android/opentagviewer/python/PythonAccountLoginException.java b/app/src/main/java/dev/wander/android/opentagviewer/python/PythonAccountLoginException.java index 4a4d289d..8c0179a7 100644 --- a/app/src/main/java/dev/wander/android/opentagviewer/python/PythonAccountLoginException.java +++ b/app/src/main/java/dev/wander/android/opentagviewer/python/PythonAccountLoginException.java @@ -60,6 +60,17 @@ public class PythonAccountLoginException extends RuntimeException { */ public static final String REASON_APPLE_DECLINED = "apple_declined"; + /** + * Apple refused the first step of the sign-in, before the password was used. Matches + * {@code REASON_REFUSED_BEFORE_PASSWORD}. + * + *

Issue #248: shown verbatim as "Email verification failed", which reads as a typo in the + * Apple ID or password and is neither. Like {@link #REASON_APPLE_DECLINED} it offers the + * remote-server route, because local Anisette worked and Apple still said no - so the machine + * identity is the thing left to change. Unlike it, nothing here says to wait. + */ + public static final String REASON_REFUSED_BEFORE_PASSWORD = "refused_before_password"; + /** Anything not recognised. The detail is shown as-is rather than guessed at. */ public static final String REASON_UNKNOWN = "unknown"; diff --git a/app/src/main/python/main.py b/app/src/main/python/main.py index 094b7dcb..5bab609f 100644 --- a/app/src/main/python/main.py +++ b/app/src/main/python/main.py @@ -10,7 +10,7 @@ import NSKeyedUnArchiver from findmy import FindMyAccessory, MobileMeDelegateError -from findmy.errors import AppleServiceUnavailableError +from findmy.errors import AppleServiceUnavailableError, GrandSlamRefusedError from findmy.accessory import FixedRollingKeyPairAccessory from findmy.keys import KeyPairType from findmy.reports import ( @@ -511,6 +511,25 @@ def assertAnisetteIsSupported(serializedAccountData: str) -> str | None: end is wasted effort. """ +REASON_REFUSED_BEFORE_PASSWORD = "refused_before_password" +""" +Grand Slam refused the first step of the sign-in, which carries the username and the Anisette +headers and no password. + +**So the password is not the problem, and the screen must not suggest it is.** This arrived as +an `InvalidCredentialsError` reading "Email verification failed", shown verbatim, on a device +whose local Anisette was working - OpenTagViewer#248. What is left is the account itself, or the +machine identity the Anisette data presents, and the second is the one thing this app can change: +the screen offers the remote-server route for it, as it does for :data:`REASON_APPLE_DECLINED`. + +**Which `ec` means what is not established.** Apple's text here is generic, and the code was not +kept until the fork started carrying it, so nothing branches on a value. The detail keeps the +code, so a report carries it. + +**A wrong password is not this.** That is refused at the second step, `complete`, and stays +:data:`REASON_UNKNOWN` - a different Anisette identity cannot fix a bad credential. +""" + REASON_UNKNOWN = "unknown" """Anything else. The detail is shown as-is, because a wrong guess is worse than raw text.""" @@ -557,6 +576,11 @@ def classifyLoginFailure(error: BaseException) -> str: if isinstance(error, AppleServiceUnavailableError): return REASON_APPLE_DECLINED + # Only the first step. The same type reports a wrong password at the second, and that one + # must not offer a different Anisette server as though it could help. + if isinstance(error, GrandSlamRefusedError) and error.before_password: + return REASON_REFUSED_BEFORE_PASSWORD + if isinstance(error, (asyncio.TimeoutError, asyncio.CancelledError)): return REASON_NETWORK if isinstance(error, _NETWORK_ERRORS): diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 34f9f6eb..772071e5 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -393,4 +393,5 @@ Wenn Apple die Anfrage lediglich abgelehnt hat, lohnt es sich, zu warten und es Apples Anmeldebibliothek stürzt auf diesem Handy ab, daher übernimmt ein Server diesen Schritt. Alles andere funktioniert normal. Warum das auf manchen Handys passiert, wissen wir noch nicht – ein Bericht mit deinem Modell hilft. Dieses Handy melden Apples Anmeldebibliothek stürzt auf diesem Handy ab, sobald sie geladen wird. Auf den meisten Handys funktioniert sie, und wir wissen noch nicht, was die betroffenen gemeinsam haben.\n\nOpenTagViewer nutzt für diesen Schritt jetzt einen Server, du kannst dich also anmelden und die App normal verwenden. Ein Bericht mit den Angaben unten hilft uns, die Ursache zu finden. + Apple hat die Anmeldung mit dieser Apple-ID abgelehnt, bevor dein Passwort geprüft wurde. Es erneut einzugeben hilft also nicht. Prüfe, ob du dich auf account.apple.com anmelden kannst und ob Apple dort etwas von dir verlangt. Ein Remote-Server stellt sich Apple als anderes Gerät vor, einen Versuch ist das wert. Apple meldete: %1$s \ No newline at end of file diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 37793706..2b758df6 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -393,4 +393,5 @@ If Apple simply refused the request, waiting and trying again is worth doing fir Apple\'s sign-in library crashes on this phone, so a server does this step instead. Everything else works normally. We don\'t know why it happens on some phones yet, and a report naming yours helps. Report this phone Apple\'s sign-in library crashes as soon as it loads on this phone. It works on most phones, and we do not know yet what the affected ones have in common.\n\nOpenTagViewer now uses a server for that step, so you can sign in and use the app normally. A report with the details below is what helps us find the cause. + Apple refused to start signing in to this Apple ID before your password was checked, so retyping it will not help. Check that you can sign in at account.apple.com and whether Apple asks anything of you there. Trying a remote server presents Apple with a different device, which is worth a try. Apple said: %1$s \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8bd2e872..eeafea73 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -393,4 +393,5 @@ Si Apple a simplement refusé la requête, il vaut mieux attendre et réessayer. La bibliothèque de connexion d\'Apple plante sur ce téléphone, un serveur se charge donc de cette étape. Tout le reste fonctionne normalement. Nous ne savons pas encore pourquoi cela arrive sur certains téléphones : un rapport indiquant le vôtre nous aide. Signaler ce téléphone La bibliothèque de connexion d\'Apple plante dès son chargement sur ce téléphone. Elle fonctionne sur la plupart des téléphones, et nous ne savons pas encore ce que les appareils concernés ont en commun.\n\nOpenTagViewer utilise désormais un serveur pour cette étape : vous pouvez vous connecter et utiliser l\'app normalement. Un rapport avec les informations ci-dessous nous aide à trouver la cause. + Apple a refusé de commencer la connexion à cet identifiant Apple avant même de vérifier votre mot de passe : le saisir à nouveau ne changera rien. Vérifiez que vous pouvez vous connecter sur account.apple.com et si Apple vous y demande quelque chose. Un serveur distant présente un autre appareil à Apple, cela vaut la peine d\'essayer. Apple a répondu : %1$s \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 4dad1f8b..70de482a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -393,4 +393,5 @@ Appleが要求を拒否しただけなら、少し待ってからもう一度お Apple のサインイン用ライブラリがこの端末ではクラッシュするため、この手順はサーバーが代わりに行います。その他の機能は通常どおり使えます。一部の端末で起きる原因はまだ分かっていません。お使いの機種を添えて報告していただけると助かります。 この端末を報告 この端末では、Apple のサインイン用ライブラリが読み込み直後にクラッシュします。ほとんどの端末では問題なく動作しており、影響を受ける端末の共通点はまだ分かっていません。\n\nOpenTagViewer はこの手順にサーバーを使うようになったため、サインインもアプリの利用も通常どおりできます。下の情報を添えて報告していただくと、原因の特定に役立ちます。 + Apple はパスワードを確認する前に、この Apple ID へのサインインの開始を拒否しました。パスワードを入力し直しても解決しません。account.apple.com にサインインできるか、そこで Apple から何か求められていないかを確認してください。リモートサーバーを使うと Apple には別のデバイスとして見えるので、試す価値があります。Apple の応答: %1$s \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 68457f33..250e0c83 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -393,4 +393,5 @@ Apple이 요청을 거부한 것뿐이라면 잠시 기다렸다가 다시 시 Apple의 로그인 라이브러리가 이 휴대폰에서 충돌하므로 이 단계는 서버가 대신 처리합니다. 나머지는 모두 정상적으로 작동합니다. 일부 휴대폰에서 왜 이런 일이 생기는지 아직 모릅니다. 기기 모델을 알려 주시면 도움이 됩니다. 이 휴대폰 신고하기 이 휴대폰에서는 Apple의 로그인 라이브러리가 불러오자마자 충돌합니다. 대부분의 휴대폰에서는 정상 작동하며, 영향을 받는 기기들의 공통점은 아직 모릅니다.\n\n이제 OpenTagViewer가 이 단계에 서버를 사용하므로 로그인하고 앱을 정상적으로 쓸 수 있습니다. 아래 정보와 함께 신고해 주시면 원인을 찾는 데 도움이 됩니다. + Apple이 비밀번호를 확인하기 전에 이 Apple ID의 로그인 시작을 거부했습니다. 비밀번호를 다시 입력해도 해결되지 않습니다. account.apple.com에 로그인할 수 있는지, 그리고 Apple이 그곳에서 무언가를 요구하는지 확인하세요. 원격 서버를 사용하면 Apple에 다른 기기로 보이므로 시도해 볼 만합니다. Apple 응답: %1$s \ No newline at end of file diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 17b21bb5..8ee3a063 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -393,4 +393,5 @@ Als Apple het verzoek simpelweg weigerde, is even wachten en opnieuw proberen he Apples aanmeldbibliotheek crasht op deze telefoon, dus doet een server deze stap. Al het andere werkt gewoon. We weten nog niet waarom dit op sommige telefoons gebeurt; een melding met jouw model helpt. Deze telefoon melden Apples aanmeldbibliotheek crasht op deze telefoon zodra ze geladen wordt. Op de meeste telefoons werkt ze, en we weten nog niet wat de getroffen toestellen gemeen hebben.\n\nOpenTagViewer gebruikt voor die stap nu een server, dus je kunt gewoon aanmelden en de app normaal gebruiken. Een melding met de gegevens hieronder helpt ons de oorzaak te vinden. + Apple weigerde het inloggen met deze Apple ID te starten voordat je wachtwoord werd gecontroleerd, dus opnieuw intypen helpt niet. Controleer of je kunt inloggen op account.apple.com en of Apple daar iets van je vraagt. Een externe server stelt zich bij Apple voor als een ander apparaat, dat is het proberen waard. Apple meldde: %1$s \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 43f3abf1..61010ef2 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -393,4 +393,5 @@ Библиотека входа Apple падает на этом телефоне, поэтому этот шаг выполняет сервер. Всё остальное работает как обычно. Мы пока не знаем, почему это происходит на некоторых телефонах, — отчёт с моделью вашего телефона поможет. Сообщить об этом телефоне На этом телефоне библиотека входа Apple падает сразу после загрузки. На большинстве телефонов она работает, и мы пока не знаем, что общего у затронутых устройств.\n\nТеперь OpenTagViewer использует для этого шага сервер, так что вы можете войти и пользоваться приложением как обычно. Отчёт с данными ниже поможет нам найти причину. + Apple отказалась начинать вход с этим Apple ID ещё до проверки пароля, поэтому вводить его заново бесполезно. Проверьте, можете ли вы войти на account.apple.com и не требует ли Apple там чего-либо. Удалённый сервер представляется Apple другим устройством — это стоит попробовать. Ответ Apple: %1$s \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index a062c5bb..fd8239fb 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -393,4 +393,5 @@ Apple 的登录库在这部手机上会崩溃,因此这一步改由服务器完成。其他功能一切正常。我们还不知道为什么会在部分手机上发生,附上你的机型报告会有帮助。 报告这部手机 Apple 的登录库在这部手机上一加载就会崩溃。它在大多数手机上都能正常运行,我们还不知道受影响的手机有什么共同点。\n\nOpenTagViewer 现在改用服务器完成这一步,因此你可以正常登录和使用应用。附上下方信息的报告能帮助我们找到原因。 + Apple 在检查你的密码之前就拒绝开始登录此 Apple ID,所以重新输入密码没有用。请确认你能否在 account.apple.com 登录,以及 Apple 是否在那里要求你做什么。远程服务器会以另一台设备的身份出现在 Apple 面前,值得一试。Apple 的回复:%1$s diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index ed4a00c0..964ba039 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -393,4 +393,5 @@ Apple 的登入函式庫在這支手機上會當機,因此這一步改由伺服器完成。其他功能一切正常。我們還不知道為什麼會在部分手機上發生,附上你的機型回報會有幫助。 回報這支手機 Apple 的登入函式庫在這支手機上一載入就會當機。它在大多數手機上都能正常運作,我們還不知道受影響的手機有什麼共通點。\n\nOpenTagViewer 現在改用伺服器完成這一步,因此你可以正常登入和使用 App。附上下方資訊的回報能幫助我們找到原因。 + Apple 在檢查你的密碼之前就拒絕開始登入此 Apple ID,所以重新輸入密碼沒有用。請確認你能否在 account.apple.com 登入,以及 Apple 是否在那裡要求你做什麼。遠端伺服器會以另一台裝置的身分出現在 Apple 面前,值得一試。Apple 的回覆:%1$s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f6a517b0..85017a97 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -426,4 +426,5 @@ If Apple simply refused the request, waiting and trying again is worth doing fir Apple\'s sign-in library crashes on this phone, so a server does this step instead. Everything else works normally. We don\'t know why it happens on some phones yet, and a report naming yours helps. Report this phone Apple\'s sign-in library crashes as soon as it loads on this phone. It works on most phones, and we do not know yet what the affected ones have in common.\n\nOpenTagViewer now uses a server for that step, so you can sign in and use the app normally. A report with the details below is what helps us find the cause. + Apple refused to start signing in to this Apple ID before your password was checked, so retyping it will not help. Check that you can sign in at account.apple.com and whether Apple asks anything of you there. Trying a remote server presents Apple with a different device, which is worth a try. Apple said: %1$s diff --git a/app/src/test/python/requirements.txt b/app/src/test/python/requirements.txt index b5bdd92a..2c54b08b 100644 --- a/app/src/test/python/requirements.txt +++ b/app/src/test/python/requirements.txt @@ -9,7 +9,7 @@ # `FindMy==0.9.8` here for as long as the app built the fork, so every bridge test # ran against a library the app does not ship - which is not a small difference: # the fork's Anisette providers take `serial=` and PyPI's do not. -git+https://github.com/parawanderer/FindMy.py@7969003ca785658369b650f75d9e7ca519566bf6 +git+https://github.com/parawanderer/FindMy.py@00fd962a0e8ec9f5601fe0b9db3f16ccea252a3c NSKeyedUnArchiver==1.5 PyYAML==6.0.2 diff --git a/app/src/test/python/test_main.py b/app/src/test/python/test_main.py index 94bd2624..4743e6d9 100644 --- a/app/src/test/python/test_main.py +++ b/app/src/test/python/test_main.py @@ -1230,6 +1230,29 @@ def test_an_ordinary_protocol_error_is_still_unclassified(self): UnhandledProtocolError("Error response for GSA request: 418"), ) == main.REASON_UNKNOWN + def test_a_refusal_before_the_password_is_its_own_reason(self): + """ + Issue #248. Grand Slam refused the `init` step, which sends no password, and the screen + showed "Email verification failed" verbatim - which reads as a typo and is not one. + """ + from findmy.errors import GrandSlamRefusedError + + refused = GrandSlamRefusedError("init", -1, "This action cannot be completed at this time.") + + assert main.classifyLoginFailure(refused) == main.REASON_REFUSED_BEFORE_PASSWORD + assert "ec=-1" in main.describeLoginFailure(refused) + + def test_a_wrong_password_is_not_a_refusal_before_it(self): + """ + Same type, second step. A different Anisette server cannot fix a bad credential, so + this must not become the reason that offers one. + """ + from findmy.errors import GrandSlamRefusedError + + wrong = GrandSlamRefusedError("complete", -20101, "Your Apple ID or password was incorrect.") + + assert main.classifyLoginFailure(wrong) == main.REASON_UNKNOWN + def test_a_library_error_is_recognised_by_its_module(self): class ClientConnectorError(Exception): pass diff --git a/python/pyproject.toml b/python/pyproject.toml index 008bd213..2f0bc4a4 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -69,7 +69,7 @@ constraint-dependencies = [ ] [tool.uv.sources] -FindMy = { git = "https://github.com/parawanderer/FindMy.py", rev = "7969003ca785658369b650f75d9e7ca519566bf6" } +FindMy = { git = "https://github.com/parawanderer/FindMy.py", rev = "00fd962a0e8ec9f5601fe0b9db3f16ccea252a3c" } [dependency-groups] # Only the release build installs this, with `uv sync --no-default-groups --group build`. It is diff --git a/python/uv.lock b/python/uv.lock index 63728cc2..b6194833 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -659,7 +659,7 @@ wheels = [ [[package]] name = "findmy" version = "0.10.1" -source = { git = "https://github.com/parawanderer/FindMy.py?rev=7969003ca785658369b650f75d9e7ca519566bf6#7969003ca785658369b650f75d9e7ca519566bf6" } +source = { git = "https://github.com/parawanderer/FindMy.py?rev=00fd962a0e8ec9f5601fe0b9db3f16ccea252a3c#00fd962a0e8ec9f5601fe0b9db3f16ccea252a3c" } dependencies = [ { name = "aiohttp" }, { name = "anisette" }, @@ -1032,7 +1032,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "findmy", git = "https://github.com/parawanderer/FindMy.py?rev=7969003ca785658369b650f75d9e7ca519566bf6" }, + { name = "findmy", git = "https://github.com/parawanderer/FindMy.py?rev=00fd962a0e8ec9f5601fe0b9db3f16ccea252a3c" }, { name = "pycryptodome", specifier = "==3.22.0" }, { name = "pyyaml", specifier = "==6.0.2" }, { name = "pyzipper", specifier = "==0.4.0" },