aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2021-11-05 07:29:26 +0100
committerFlorian Dold <florian@dold.me>2021-11-05 07:29:26 +0100
commite42c282e67d49a54aa7aab2e87f9e458e488ae8e (patch)
treeb2c6349ddeaa352dcc6bb17e2cc44e94dc44d301 /packages
parent34d2e4703d8a583c8e7c3c2ea398c1280acccd08 (diff)
downloadwallet-core-e42c282e67d49a54aa7aab2e87f9e458e488ae8e.tar.xz
anastasis-core: make truth/policy payments compatible with C reducer
Diffstat (limited to 'packages')
-rw-r--r--packages/anastasis-core/src/crypto.ts3
-rw-r--r--packages/anastasis-core/src/index.ts84
-rw-r--r--packages/anastasis-core/src/reducer-types.ts13
3 files changed, 85 insertions, 15 deletions
diff --git a/packages/anastasis-core/src/crypto.ts b/packages/anastasis-core/src/crypto.ts
index 9689e4f2d..6921cb2f1 100644
--- a/packages/anastasis-core/src/crypto.ts
+++ b/packages/anastasis-core/src/crypto.ts
@@ -11,8 +11,9 @@ import {
stringToBytes,
secretbox_open,
hash,
+ Logger,
+ j2s,
} from "@gnu-taler/taler-util";
-import { gzipSync } from "fflate";
import { argon2id } from "hash-wasm";
export type Flavor<T, FlavorT extends string> = T & {
diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts
index 0f391b733..8972b057c 100644
--- a/packages/anastasis-core/src/index.ts
+++ b/packages/anastasis-core/src/index.ts
@@ -16,6 +16,7 @@ import {
HttpStatusCode,
j2s,
Logger,
+ parsePayUri,
stringToBytes,
TalerErrorCode,
TalerSignaturePurpose,
@@ -328,7 +329,6 @@ async function getTruthValue(
* Compress the recovery document and add a size header.
*/
async function compressRecoveryDoc(rd: any): Promise<Uint8Array> {
- logger.info(`recovery document: ${j2s(rd)}`);
const docBytes = stringToBytes(JSON.stringify(rd));
const sizeHeaderBuf = new ArrayBuffer(4);
const dvbuf = new DataView(sizeHeaderBuf);
@@ -457,6 +457,8 @@ async function uploadSecret(
const rd = recoveryData.recovery_document;
const truthPayUris: string[] = [];
+ const truthPaySecrets: Record<string, string> = {};
+
const userIdCache: Record<string, UserIdentifier> = {};
const getUserIdCaching = async (providerUrl: string) => {
let userId = userIdCache[providerUrl];
@@ -483,9 +485,8 @@ async function uploadSecret(
tm.truth_key,
truthValue,
);
- logger.info(`uploading to ${meth.provider}`);
+ logger.info(`uploading truth to ${meth.provider}`);
const userId = await getUserIdCaching(meth.provider);
- // FIXME: check that the question salt is okay here, looks weird.
const encryptedKeyShare = await encryptKeyshare(
tm.key_share,
userId,
@@ -500,10 +501,21 @@ async function uploadSecret(
type: authMethod.type,
truth_mime: authMethod.mime_type,
};
- const resp = await fetch(new URL(`truth/${tm.uuid}`, meth.provider).href, {
+ const reqUrl = new URL(`truth/${tm.uuid}`, meth.provider);
+ const paySecret = (state.truth_upload_payment_secrets ?? {})[meth.provider];
+ if (paySecret) {
+ // FIXME: Get this from the params
+ reqUrl.searchParams.set("timeout_ms", "500");
+ }
+ const resp = await fetch(reqUrl.href, {
method: "POST",
headers: {
"content-type": "application/json",
+ ...(paySecret
+ ? {
+ "Anastasis-Payment-Identifier": paySecret,
+ }
+ : {}),
},
body: JSON.stringify(tur),
});
@@ -520,6 +532,14 @@ async function uploadSecret(
};
}
truthPayUris.push(talerPayUri);
+ const parsedUri = parsePayUri(talerPayUri);
+ if (!parsedUri) {
+ return {
+ code: TalerErrorCode.ANASTASIS_REDUCER_BACKEND_FAILURE,
+ hint: `payment requested, but no taler://pay URI given`,
+ };
+ }
+ truthPaySecrets[meth.provider] = parsedUri.orderId;
continue;
}
return {
@@ -532,6 +552,7 @@ async function uploadSecret(
return {
...state,
backup_state: BackupStates.TruthsPaying,
+ truth_upload_payment_secrets: truthPaySecrets,
payments: truthPayUris,
};
}
@@ -539,6 +560,8 @@ async function uploadSecret(
const successDetails: SuccessDetails = {};
const policyPayUris: string[] = [];
+ const policyPayUriMap: Record<string, string> = {};
+ //const policyPaySecrets: Record<string, string> = {};
for (const prov of state.policy_providers!) {
const userId = await getUserIdCaching(prov.provider_url);
@@ -553,17 +576,33 @@ async function uploadSecret(
.put(bodyHash)
.build();
const sig = eddsaSign(sigPS, decodeCrock(acctKeypair.priv));
- const resp = await fetch(
- new URL(`policy/${acctKeypair.pub}`, prov.provider_url).href,
- {
- method: "POST",
- headers: {
- "Anastasis-Policy-Signature": encodeCrock(sig),
- "If-None-Match": encodeCrock(bodyHash),
- },
- body: decodeCrock(encRecoveryDoc),
+ const talerPayUri = state.policy_payment_requests?.find(
+ (x) => x.provider === prov.provider_url,
+ )?.payto;
+ let paySecret: string | undefined;
+ if (talerPayUri) {
+ paySecret = parsePayUri(talerPayUri)!.orderId;
+ }
+ const reqUrl = new URL(`policy/${acctKeypair.pub}`, prov.provider_url);
+ if (paySecret) {
+ // FIXME: Get this from the params
+ reqUrl.searchParams.set("timeout_ms", "500");
+ }
+ logger.info(`uploading policy to ${prov.provider_url}`);
+ const resp = await fetch(reqUrl.href, {
+ method: "POST",
+ headers: {
+ "Anastasis-Policy-Signature": encodeCrock(sig),
+ "If-None-Match": encodeCrock(bodyHash),
+ ...(paySecret
+ ? {
+ "Anastasis-Payment-Identifier": paySecret,
+ }
+ : {}),
},
- );
+ body: decodeCrock(encRecoveryDoc),
+ });
+ logger.info(`got response for policy upload (http status ${resp.status})`);
if (resp.status === HttpStatusCode.NoContent) {
let policyVersion = 0;
let policyExpiration: Timestamp = { t_ms: 0 };
@@ -592,6 +631,14 @@ async function uploadSecret(
};
}
policyPayUris.push(talerPayUri);
+ const parsedUri = parsePayUri(talerPayUri);
+ if (!parsedUri) {
+ return {
+ code: TalerErrorCode.ANASTASIS_REDUCER_BACKEND_FAILURE,
+ hint: `payment requested, but no taler://pay URI given`,
+ };
+ }
+ policyPayUriMap[prov.provider_url] = talerPayUri;
continue;
}
return {
@@ -605,9 +652,17 @@ async function uploadSecret(
...state,
backup_state: BackupStates.PoliciesPaying,
payments: policyPayUris,
+ policy_payment_requests: Object.keys(policyPayUriMap).map((x) => {
+ return {
+ payto: policyPayUriMap[x],
+ provider: x,
+ };
+ }),
};
}
+ logger.info("backup finished");
+
return {
...state,
core_secret: undefined,
@@ -766,6 +821,7 @@ async function requestTruth(
const url = new URL(`/truth/${truth.uuid}`, truth.url);
if (solveRequest) {
+ logger.info(`handling solve request ${j2s(solveRequest)}`);
let respHash: string;
switch (truth.escrow_type) {
case ChallengeType.Question: {
diff --git a/packages/anastasis-core/src/reducer-types.ts b/packages/anastasis-core/src/reducer-types.ts
index e5b0c47a4..1a560b885 100644
--- a/packages/anastasis-core/src/reducer-types.ts
+++ b/packages/anastasis-core/src/reducer-types.ts
@@ -87,10 +87,19 @@ export interface ReducerStateBackup {
* Currently requested payments.
*
* List of taler://pay URIs.
+ *
+ * FIXME: There should be more information in this,
+ * including the provider and amount.
*/
payments?: string[];
+ /**
+ * FIXME: Why is this not a map from provider to payto?
+ */
policy_payment_requests?: {
+ /**
+ * FIXME: This is not a payto URI, right?!
+ */
payto: string;
provider: string;
}[];
@@ -100,6 +109,10 @@ export interface ReducerStateBackup {
expiration?: Timestamp;
upload_fees?: { fee: AmountString }[];
+
+ // FIXME: The payment secrets and pay URIs should
+ // probably be consolidated into a single field.
+ truth_upload_payment_secrets?: Record<string, string>;
}
export interface AuthMethod {