Repository navigation
fix(route): sync bot public key before requests #6726
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,18 @@ suspend fun <T, R> requestRouteAPI( | |
| ): R? { | ||
| val response = | ||
| try { | ||
| val preferences = MixinApplication.appContext.defaultSharedPreferences | ||
| if (preferences.getString(PREF_ROUTE_BOT_PK, null).isNullOrBlank()) { | ||
| val sessionResponse = requestSession(listOf(ROUTE_BOT_USER_ID)) | ||
| if (!sessionResponse.isSuccess) { | ||
| defaultErrorHandle(MixinResponse<T>(requireNotNull(sessionResponse.error))) | ||
| endBlock?.invoke() | ||
| return null | ||
| } | ||
| val publicKey = sessionResponse.data?.firstOrNull { it.userId == ROUTE_BOT_USER_ID }?.publicKey | ||
| check(!publicKey.isNullOrBlank()) { "Route bot public key is missing" } | ||
| preferences.putString(PREF_ROUTE_BOT_PK, publicKey) | ||
|
Comment on lines
+43
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This stores the newly fetched key only in preferences, unlike the existing authentication-retry path, which also updates Useful? React with 👍 / 👎. |
||
| } | ||
| invokeNetwork() | ||
| } catch (t: Throwable) { | ||
| if (exceptionBlock?.invoke(t) != true) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package one.mixin.android.ui.wallet.fiatmoney | ||
|
|
||
| import androidx.test.core.app.ApplicationProvider | ||
| import kotlinx.coroutines.runBlocking | ||
| import one.mixin.android.Constants.Account.PREF_ROUTE_BOT_PK | ||
| import one.mixin.android.Constants.RouteConfig.ROUTE_BOT_USER_ID | ||
| import one.mixin.android.MixinApplication | ||
| import one.mixin.android.api.MixinResponse | ||
| import one.mixin.android.api.ResponseError | ||
| import one.mixin.android.api.response.UserSession | ||
| import one.mixin.android.extension.defaultSharedPreferences | ||
| import org.junit.Assert.assertEquals | ||
| import org.junit.Assert.assertNull | ||
| import org.junit.Test | ||
| import org.junit.runner.RunWith | ||
| import org.robolectric.RobolectricTestRunner | ||
|
|
||
| @RunWith(RobolectricTestRunner::class) | ||
| class RouteAPITest { | ||
| @Test | ||
| fun waitsForPublicKeyAndStopsWhenSynchronizationFails() = runBlocking { | ||
| MixinApplication.appContext = ApplicationProvider.getApplicationContext() | ||
| val preferences = MixinApplication.appContext.defaultSharedPreferences | ||
| val events = mutableListOf<String>() | ||
| for (mode in listOf("missing", "cached", "failed", "empty")) { | ||
| preferences.edit().remove(PREF_ROUTE_BOT_PK).commit() | ||
| if (mode == "cached") preferences.edit().putString(PREF_ROUTE_BOT_PK, "key").commit() | ||
| events.clear() | ||
| val result = requestRouteAPI<Unit, Boolean>( | ||
| invokeNetwork = { | ||
| assertEquals("key", preferences.getString(PREF_ROUTE_BOT_PK, null)) | ||
| events.add("request") | ||
| MixinResponse<Unit>() | ||
| }, | ||
| successBlock = { true }, | ||
| failureBlock = { error("Session failure must not invoke the wallet failure handler") }, | ||
| defaultErrorHandle = { events.add("error") }, | ||
| defaultExceptionHandle = { events.add("exception") }, | ||
| endBlock = { events.add("end") }, | ||
| requestSession = { ids -> | ||
| assertEquals(listOf(ROUTE_BOT_USER_ID), ids) | ||
| events.add("sync") | ||
| when (mode) { | ||
| "cached" -> error("Cached public key must be reused") | ||
| "failed" -> MixinResponse(ResponseError(404, 404, "Not found")) | ||
| else -> MixinResponse<List<UserSession>>().apply { | ||
| data = listOf(UserSession(ROUTE_BOT_USER_ID, "session", null, if (mode == "empty") "" else "key")) | ||
| } | ||
| } | ||
| }, | ||
| ) | ||
| when (mode) { | ||
| "missing" -> assertEquals(listOf("sync", "request", "end"), events) | ||
| "cached" -> assertEquals(listOf("request", "end"), events) | ||
| "failed" -> assertEquals(listOf("sync", "error", "end"), events) | ||
| "empty" -> assertEquals(listOf("sync", "exception", "end"), events) | ||
| } | ||
| if (mode == "failed" || mode == "empty") assertNull(result) else assertEquals(true, result) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the key is absent after a fresh install or account switch and
fetchSessionsSuspendreturns an API error, this branch calls onlydefaultErrorHandleand returns without notifyingfailureBlockorexceptionBlock. For example,FetchWalletViewModel.importWalletentersIMPORTINGat line 524 and only transitions toIMPORT_ERRORin those callbacks at lines 612–623; because it supplies noendBlock, the import UI remains stuck loading after this failure. Provide a dedicated session-sync failure callback or otherwise notify callers without treating a session 404 as a wallet 404.Useful? React with 👍 / 👎.