summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/anastasis-core/src/index.ts71
-rw-r--r--packages/anastasis-core/src/reducer-types.ts8
-rw-r--r--packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts39
-rw-r--r--packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx1
-rw-r--r--packages/taler-wallet-core/src/operations/reserves.ts1
5 files changed, 101 insertions, 19 deletions
diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts
index 5dd560a2c..9db152648 100644
--- a/packages/anastasis-core/src/index.ts
+++ b/packages/anastasis-core/src/index.ts
@@ -94,6 +94,7 @@ import {
PolicyMetaInfo,
ChallengeInfo,
AggregatedPolicyMetaInfo,
+ AuthenticationProviderStatusMap,
} from "./reducer-types.js";
import fetchPonyfill from "fetch-ponyfill";
import {
@@ -329,15 +330,9 @@ async function backupEnterUserAttributes(
args: ActionArgsEnterUserAttributes,
): Promise<ReducerStateBackup> {
const attributes = args.identity_attributes;
- const providerUrls = Object.keys(state.authentication_providers ?? {});
- const newProviders = state.authentication_providers ?? {};
- for (const url of providerUrls) {
- newProviders[url] = await getProviderInfo(url);
- }
const newState = {
...state,
backup_state: BackupStates.AuthenticationsEditing,
- authentication_providers: newProviders,
identity_attributes: attributes,
};
return newState;
@@ -733,15 +728,23 @@ async function uploadSecret(
async function downloadPolicy(
state: ReducerStateRecovery,
): Promise<ReducerStateRecovery | ReducerStateError> {
+ logger.info("downloading policy");
let foundRecoveryInfo: RecoveryInternalData | undefined = undefined;
let recoveryDoc: RecoveryDocument | undefined = undefined;
const userAttributes = state.identity_attributes!;
if (!state.selected_version) {
throw Error("invalid state");
}
+ // FIXME: Do this concurrently/asynchronously so that one slow provider doens't block us.
for (const prov of state.selected_version.providers) {
- const pi = state.authentication_providers?.[prov.url];
+ let pi = state.authentication_providers?.[prov.url];
if (!pi || pi.status !== "ok") {
+ // FIXME: this one blocks!
+ logger.info(`fetching provider info for ${prov.url}`);
+ pi = await getProviderInfo(prov.url);
+ }
+ logger.info(`new provider status is ${pi.status}`);
+ if (pi.status !== "ok") {
continue;
}
const userId = await userIdentifierDerive(userAttributes, pi.provider_salt);
@@ -750,6 +753,9 @@ async function downloadPolicy(
reqUrl.searchParams.set("version", `${prov.version}`);
const resp = await fetch(reqUrl.href);
if (resp.status !== 200) {
+ logger.info(
+ `Could not download policy from provider ${prov.url}, status ${resp.status}`,
+ );
continue;
}
const body = await resp.arrayBuffer();
@@ -1058,16 +1064,10 @@ async function recoveryEnterUserAttributes(
args: ActionArgsEnterUserAttributes,
): Promise<ReducerStateRecovery | ReducerStateError> {
// FIXME: validate attributes
- const providerUrls = Object.keys(state.authentication_providers ?? {});
- const newProviders = state.authentication_providers ?? {};
- for (const url of providerUrls) {
- newProviders[url] = await getProviderInfo(url);
- }
const st: ReducerStateRecovery = {
...state,
recovery_state: RecoveryStates.SecretSelecting,
identity_attributes: args.identity_attributes,
- authentication_providers: newProviders,
};
return st;
}
@@ -1514,7 +1514,7 @@ async function nextFromChallengeSelecting(
};
}
-async function syncProviders(
+async function syncAllProvidersTransition(
state: ReducerStateRecovery,
args: void,
): Promise<ReducerStateRecovery | ReducerStateError> {
@@ -1722,7 +1722,7 @@ const recoveryTransitions: Record<
),
...transition("poll", codecForAny(), pollChallenges),
...transition("next", codecForAny(), nextFromChallengeSelecting),
- ...transition("sync_providers", codecForAny(), syncProviders),
+ ...transition("sync_providers", codecForAny(), syncAllProvidersTransition),
},
[RecoveryStates.ChallengeSolving]: {
...transitionRecoveryJump("back", RecoveryStates.ChallengeSelecting),
@@ -1746,6 +1746,7 @@ export async function discoverPolicies(
const providerUrls = Object.keys(state.authentication_providers || {});
// FIXME: Do we need to re-contact providers here / check if they're disabled?
+ // FIXME: Do this concurrently and take the first. Otherwise, one provider might block for a long time.
for (const providerUrl of providerUrls) {
const providerInfo = await getProviderInfo(providerUrl);
@@ -1839,3 +1840,43 @@ export async function reduceAction(
throw e;
}
}
+
+/**
+ * Update provider status of providers that we still need to contact.
+ *
+ * Returns updates as soon as new information about at least one provider
+ * is found.
+ *
+ * Returns an empty object if provider information is complete.
+ *
+ * FIXME: Also pass a cancelation token.
+ */
+export async function completeProviderStatus(
+ providerMap: AuthenticationProviderStatusMap,
+): Promise<AuthenticationProviderStatusMap> {
+ const updateTasks: Promise<[string, AuthenticationProviderStatus]>[] = [];
+ for (const [provUrl, pi] of Object.entries(providerMap)) {
+ switch (pi.status) {
+ case "ok":
+ case "error":
+ case "disabled":
+ default:
+ continue;
+ case "not-contacted":
+ updateTasks.push(
+ (async () => {
+ return [provUrl, await getProviderInfo(provUrl)];
+ })(),
+ );
+ }
+ }
+
+ if (updateTasks.length === 0) {
+ return {};
+ }
+
+ const [firstUrl, firstStatus] = await Promise.race(updateTasks);
+ return {
+ [firstUrl]: firstStatus,
+ };
+}
diff --git a/packages/anastasis-core/src/reducer-types.ts b/packages/anastasis-core/src/reducer-types.ts
index a0af2f86e..2e03a6ec4 100644
--- a/packages/anastasis-core/src/reducer-types.ts
+++ b/packages/anastasis-core/src/reducer-types.ts
@@ -186,6 +186,10 @@ export interface RecoveryInformation {
}[][];
}
+export interface AuthenticationProviderStatusMap {
+ [url: string]: AuthenticationProviderStatus;
+}
+
export interface ReducerStateRecovery {
reducer_type: "recovery";
@@ -231,7 +235,7 @@ export interface ReducerStateRecovery {
value: string;
};
- authentication_providers?: { [url: string]: AuthenticationProviderStatus };
+ authentication_providers?: AuthenticationProviderStatusMap;
}
/**
@@ -342,7 +346,7 @@ export interface ReducerStateBackupUserAttributesCollecting
selected_country: string;
currencies: string[];
required_attributes: UserAttributeSpec[];
- authentication_providers: { [url: string]: AuthenticationProviderStatus };
+ authentication_providers: AuthenticationProviderStatusMap;
}
export interface ActionArgsEnterUserAttributes {
diff --git a/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts b/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
index 434e5fb09..1b77db38f 100644
--- a/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
+++ b/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
@@ -21,6 +21,7 @@ import { TalerErrorCode } from "@gnu-taler/taler-util";
import {
AggregatedPolicyMetaInfo,
BackupStates,
+ completeProviderStatus,
discoverPolicies,
DiscoveryCursor,
getBackupStartState,
@@ -206,6 +207,44 @@ export function useAnastasisReducer(): AnastasisReducerApi {
console.log(e);
}
setAnastasisStateInternal(newState);
+
+ const tryUpdateProviders = () => {
+ const reducerState = newState.reducerState;
+ if (
+ reducerState?.reducer_type !== "backup" &&
+ reducerState?.reducer_type !== "recovery"
+ ) {
+ return;
+ }
+ const provMap = reducerState.authentication_providers;
+ if (!provMap) {
+ return;
+ }
+ const doUpdate = async () => {
+ const updates = await completeProviderStatus(provMap);
+ if (Object.keys(updates).length === 0) {
+ return;
+ }
+ console.log("got provider updates", updates);
+ const rs2 = reducerState;
+ if (rs2.reducer_type !== "backup" && rs2.reducer_type !== "recovery") {
+ return;
+ }
+ setAnastasisState({
+ ...anastasisState,
+ reducerState: {
+ ...rs2,
+ authentication_providers: {
+ ...rs2.authentication_providers,
+ ...updates,
+ },
+ },
+ });
+ };
+ doUpdate().catch((e) => console.log(e));
+ };
+
+ tryUpdateProviders();
};
async function doTransition(action: string, args: any): Promise<void> {
diff --git a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
index 2a480de48..e5dbcd8fc 100644
--- a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
@@ -37,7 +37,6 @@ export function ContinentSelectionScreen(): VNode {
if (!theCountry) return;
reducer.transition("select_country", {
country_code: countryCode,
- currencies: [theCountry.currency],
});
};
diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts
index 8d8912130..ff09d1a50 100644
--- a/packages/taler-wallet-core/src/operations/reserves.ts
+++ b/packages/taler-wallet-core/src/operations/reserves.ts
@@ -61,7 +61,6 @@ import {
getRetryDuration,
resetRetryInfo,
RetryInfo,
- updateRetryInfoTimeout,
} from "../util/retries.js";
import {
getExchangeDetails,