model more backup provider errors

This commit is contained in:
Florian Dold 2021-05-12 14:16:01 +02:00
parent debc2254fd
commit 4fdcaab632
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
4 changed files with 81 additions and 18 deletions

View File

@ -304,6 +304,11 @@ export class BackupBackupProvider {
* Proposal IDs for payments to this provider. * Proposal IDs for payments to this provider.
*/ */
pay_proposal_ids: string[]; pay_proposal_ids: string[];
/**
* UIDs for adding this backup provider.
*/
uids: OperationUid[];
} }
/** /**

View File

@ -13,7 +13,22 @@ import {
IDBKeyPath, IDBKeyPath,
} from "@gnu-taler/idb-bridge"; } from "@gnu-taler/idb-bridge";
import { Logger } from "./util/logging"; import { Logger } from "./util/logging";
import { AmountJson, AmountString, Auditor, CoinDepositPermission, ContractTerms, Duration, ExchangeSignKeyJson, InternationalizedString, MerchantInfo, Product, RefreshReason, ReserveTransaction, TalerErrorDetails, Timestamp } from "@gnu-taler/taler-util"; import {
AmountJson,
AmountString,
Auditor,
CoinDepositPermission,
ContractTerms,
Duration,
ExchangeSignKeyJson,
InternationalizedString,
MerchantInfo,
Product,
RefreshReason,
ReserveTransaction,
TalerErrorDetails,
Timestamp,
} from "@gnu-taler/taler-util";
import { RetryInfo } from "./util/retries.js"; import { RetryInfo } from "./util/retries.js";
import { PayCoinSelection } from "./util/coinSelection.js"; import { PayCoinSelection } from "./util/coinSelection.js";
@ -170,7 +185,6 @@ export function deleteTalerDatabase(idbFactory: IDBFactory): void {
Database.deleteDatabase(idbFactory, TALER_DB_NAME); Database.deleteDatabase(idbFactory, TALER_DB_NAME);
} }
export enum ReserveRecordStatus { export enum ReserveRecordStatus {
/** /**
* Reserve must be registered with the bank. * Reserve must be registered with the bank.
@ -1269,14 +1283,12 @@ export interface WalletContractData {
maxDepositFee: AmountJson; maxDepositFee: AmountJson;
} }
export enum AbortStatus { export enum AbortStatus {
None = "none", None = "none",
AbortRefund = "abort-refund", AbortRefund = "abort-refund",
AbortFinished = "abort-finished", AbortFinished = "abort-finished",
} }
/** /**
* Record that stores status information about one purchase, starting from when * Record that stores status information about one purchase, starting from when
* the customer accepts a proposal. Includes refund status if applicable. * the customer accepts a proposal. Includes refund status if applicable.
@ -1548,6 +1560,12 @@ export enum BackupProviderStatus {
Ready = "ready", Ready = "ready",
} }
export interface BackupProviderTerms {
supportedProtocolVersion: string;
annualFee: AmountString;
storageLimitInMegabytes: number;
}
export interface BackupProviderRecord { export interface BackupProviderRecord {
baseUrl: string; baseUrl: string;
@ -1556,11 +1574,7 @@ export interface BackupProviderRecord {
* Might be unavailable in the DB in certain situations * Might be unavailable in the DB in certain situations
* (such as loading a recovery document). * (such as loading a recovery document).
*/ */
terms?: { terms?: BackupProviderTerms;
supportedProtocolVersion: string;
annualFee: AmountString;
storageLimitInMegabytes: number;
};
active: boolean; active: boolean;
@ -1601,6 +1615,11 @@ export interface BackupProviderRecord {
* Last error that occurred, if any. * Last error that occurred, if any.
*/ */
lastError: TalerErrorDetails | undefined; lastError: TalerErrorDetails | undefined;
/**
* UIDs for the operation that added the backup provider.
*/
uids: string[];
} }
/** /**

View File

@ -191,6 +191,7 @@ export async function exportBackup(
terms, terms,
base_url: canonicalizeBaseUrl(bp.baseUrl), base_url: canonicalizeBaseUrl(bp.baseUrl),
pay_proposal_ids: bp.paymentProposalIds, pay_proposal_ids: bp.paymentProposalIds,
uids: bp.uids,
}); });
}); });

View File

@ -31,8 +31,12 @@ import {
codecForAmountString, codecForAmountString,
WalletBackupContentV1, WalletBackupContentV1,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { TransactionHandle } from "../../util/query"; import {
import { BackupProviderRecord, ConfigRecord, Stores } from "../../db.js"; BackupProviderRecord,
BackupProviderTerms,
ConfigRecord,
Stores,
} from "../../db.js";
import { checkDbInvariant, checkLogicInvariant } from "../../util/invariants"; import { checkDbInvariant, checkLogicInvariant } from "../../util/invariants";
import { import {
bytesToString, bytesToString,
@ -40,13 +44,13 @@ import {
eddsaGetPublic, eddsaGetPublic,
EddsaKeyPair, EddsaKeyPair,
encodeCrock, encodeCrock,
getRandomBytes,
hash, hash,
rsaBlind, rsaBlind,
stringToBytes, stringToBytes,
} from "../../crypto/talerCrypto"; } from "../../crypto/talerCrypto";
import { canonicalizeBaseUrl, canonicalJson, j2s } from "@gnu-taler/taler-util"; import { canonicalizeBaseUrl, canonicalJson, j2s } from "@gnu-taler/taler-util";
import { import {
durationAdd,
durationFromSpec, durationFromSpec,
getTimestampNow, getTimestampNow,
Timestamp, Timestamp,
@ -495,6 +499,7 @@ export async function addBackupProvider(
baseUrl: canonUrl, baseUrl: canonUrl,
lastError: undefined, lastError: undefined,
retryInfo: initRetryInfo(false), retryInfo: initRetryInfo(false),
uids: [encodeCrock(getRandomBytes(32))],
}); });
} }
@ -513,14 +518,39 @@ export async function restoreFromRecoverySecret(): Promise<void> {}
export interface ProviderInfo { export interface ProviderInfo {
active: boolean; active: boolean;
syncProviderBaseUrl: string; syncProviderBaseUrl: string;
terms?: BackupProviderTerms;
/**
* Last communication issue with the provider.
*/
lastError?: TalerErrorDetails; lastError?: TalerErrorDetails;
lastRemoteClock?: number; lastSuccessfulBackupTimestamp?: Timestamp;
lastBackupTimestamp?: Timestamp; lastAttemptedBackupTimestamp?: Timestamp;
paymentProposalIds: string[]; paymentProposalIds: string[];
backupProblem?: BackupProblem;
paymentStatus: ProviderPaymentStatus; paymentStatus: ProviderPaymentStatus;
} }
export type BackupProblem =
| BackupUnreadableProblem
| BackupConflictingDeviceProblem;
export interface BackupUnreadableProblem {
type: "backup-unreadable";
}
export interface BackupUnreadableProblem {
type: "backup-unreadable";
}
export interface BackupConflictingDeviceProblem {
type: "backup-conflicting-device";
otherDeviceId: string;
myDeviceId: string;
backupTimestamp: Timestamp;
}
export type ProviderPaymentStatus = export type ProviderPaymentStatus =
| ProviderPaymentTermsChanged
| ProviderPaymentPaid | ProviderPaymentPaid
| ProviderPaymentInsufficientBalance | ProviderPaymentInsufficientBalance
| ProviderPaymentUnpaid | ProviderPaymentUnpaid
@ -529,7 +559,6 @@ export type ProviderPaymentStatus =
export interface BackupInfo { export interface BackupInfo {
walletRootPub: string; walletRootPub: string;
deviceId: string; deviceId: string;
lastLocalClock: number;
providers: ProviderInfo[]; providers: ProviderInfo[];
} }
@ -550,6 +579,7 @@ export enum ProviderPaymentType {
Pending = "pending", Pending = "pending",
InsufficientBalance = "insufficient-balance", InsufficientBalance = "insufficient-balance",
Paid = "paid", Paid = "paid",
TermsChanged = "terms-changed",
} }
export interface ProviderPaymentUnpaid { export interface ProviderPaymentUnpaid {
@ -569,6 +599,13 @@ export interface ProviderPaymentPaid {
paidUntil: Timestamp; paidUntil: Timestamp;
} }
export interface ProviderPaymentTermsChanged {
type: ProviderPaymentType.TermsChanged;
paidUntil: Timestamp;
oldTerms: BackupProviderTerms;
newTerms: BackupProviderTerms;
}
async function getProviderPaymentInfo( async function getProviderPaymentInfo(
ws: InternalWalletState, ws: InternalWalletState,
provider: BackupProviderRecord, provider: BackupProviderRecord,
@ -623,15 +660,15 @@ export async function getBackupInfo(
providers.push({ providers.push({
active: x.active, active: x.active,
syncProviderBaseUrl: x.baseUrl, syncProviderBaseUrl: x.baseUrl,
lastBackupTimestamp: x.lastBackupTimestamp, lastSuccessfulBackupTimestamp: x.lastBackupTimestamp,
paymentProposalIds: x.paymentProposalIds, paymentProposalIds: x.paymentProposalIds,
lastError: x.lastError, lastError: x.lastError,
paymentStatus: await getProviderPaymentInfo(ws, x), paymentStatus: await getProviderPaymentInfo(ws, x),
terms: x.terms,
}); });
} }
return { return {
deviceId: backupConfig.deviceId, deviceId: backupConfig.deviceId,
lastLocalClock: backupConfig.clocks[backupConfig.deviceId],
walletRootPub: backupConfig.walletRootPub, walletRootPub: backupConfig.walletRootPub,
providers, providers,
}; };
@ -686,6 +723,7 @@ async function backupRecoveryTheirs(
paymentProposalIds: [], paymentProposalIds: [],
retryInfo: initRetryInfo(false), retryInfo: initRetryInfo(false),
lastError: undefined, lastError: undefined,
uids: [encodeCrock(getRandomBytes(32))],
}); });
} }
} }