diff options
Diffstat (limited to 'packages/anastasis-core/src/reducer-types.ts')
-rw-r--r-- | packages/anastasis-core/src/reducer-types.ts | 373 |
1 files changed, 320 insertions, 53 deletions
diff --git a/packages/anastasis-core/src/reducer-types.ts b/packages/anastasis-core/src/reducer-types.ts index 1a443bf9b..ad88f40ed 100644 --- a/packages/anastasis-core/src/reducer-types.ts +++ b/packages/anastasis-core/src/reducer-types.ts @@ -1,4 +1,30 @@ -import { Duration, Timestamp } from "@gnu-taler/taler-util"; +/* + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL + + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { + AmountString, + buildCodecForObject, + codecForAny, + codecForList, + codecForNumber, + codecForString, + codecForTimestamp, + TalerProtocolTimestamp, +} from "@gnu-taler/taler-util"; +import { ChallengeFeedback } from "./challenge-feedback-types.js"; import { KeyShare } from "./crypto.js"; import { RecoveryDocument } from "./recovery-document-types.js"; @@ -15,7 +41,6 @@ export interface CountryInfo { code: string; name: string; continent: string; - currency: string; } export interface Policy { @@ -23,7 +48,7 @@ export interface Policy { authentication_method: number; provider: string; }[]; -} +} export interface PolicyProvider { provider_url: string; @@ -32,45 +57,91 @@ export interface PolicyProvider { export interface SuccessDetails { [provider_url: string]: { policy_version: number; - policy_expiration: Timestamp; + policy_expiration: TalerProtocolTimestamp; }; } export interface CoreSecret { mime: string; value: string; + /** + * Filename, only set if the secret comes from + * a file. Should be set unless the mime type is "text/plain"; + */ + filename?: string; } export interface ReducerStateBackup { - recovery_state?: undefined; + reducer_type: "backup"; + backup_state: BackupStates; - code?: undefined; - currencies?: string[]; + continents?: ContinentInfo[]; - countries?: any; + + countries?: CountryInfo[]; + identity_attributes?: { [n: string]: string }; - authentication_providers?: { [url: string]: AuthenticationProviderStatus }; + + authentication_providers?: AuthenticationProviderStatusMap; + authentication_methods?: AuthMethod[]; + required_attributes?: UserAttributeSpec[]; + selected_continent?: string; + selected_country?: string; + secret_name?: string; + policies?: Policy[]; + + recovery_data?: { + /** + * Map from truth key (`${methodIndex}/${providerUrl}`) to + * the truth metadata. + */ + truth_metadata: Record<string, TruthMetaData>; + recovery_document: RecoveryDocument; + }; + /** * Policy providers are providers that we checked to be functional * and that are actually used in policies. */ policy_providers?: PolicyProvider[]; success_details?: SuccessDetails; + + /** + * 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; }[]; core_secret?: CoreSecret; - expiration?: Duration; + expiration?: TalerProtocolTimestamp; + + 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 { @@ -81,7 +152,6 @@ export interface AuthMethod { } export interface ChallengeInfo { - cost: string; instructions: string; type: string; uuid: string; @@ -93,6 +163,10 @@ export interface UserAttributeSpec { type: string; uuid: string; widget: string; + optional?: boolean; + "validation-regex": string | undefined; + "validation-logic": string | undefined; + autocomplete?: string; } export interface RecoveryInternalData { @@ -111,27 +185,22 @@ export interface RecoveryInformation { }[][]; } -export interface ReducerStateRecovery { - recovery_state: RecoveryStates; +export interface AuthenticationProviderStatusMap { + [url: string]: AuthenticationProviderStatus; +} - /** - * Unused in the recovery states. - */ - backup_state?: undefined; +export interface ReducerStateRecovery { + reducer_type: "recovery"; - /** - * Unused in the recovery states. - */ - code?: undefined; + recovery_state: RecoveryStates; identity_attributes?: { [n: string]: string }; - continents?: any; - countries?: any; + continents?: ContinentInfo[]; + countries?: CountryInfo[]; selected_continent?: string; selected_country?: string; - currencies?: string[]; required_attributes?: UserAttributeSpec[]; @@ -148,6 +217,11 @@ export interface ReducerStateRecovery { selected_challenge_uuid?: string; + /** + * Explicitly selected version by the user. + */ + selected_version?: SelectedVersionInfo; + challenge_feedback?: { [uuid: string]: ChallengeFeedback }; /** @@ -155,26 +229,45 @@ export interface ReducerStateRecovery { */ recovered_key_shares?: { [truth_uuid: string]: KeyShare }; - core_secret?: { - mime: string; - value: string; - }; - - authentication_providers?: { [url: string]: AuthenticationProviderStatus }; + core_secret?: CoreSecret; - recovery_error?: any; + authentication_providers?: AuthenticationProviderStatusMap; } -export interface ChallengeFeedback { - state: string; +/** + * Truth data as stored in the reducer. + */ +export interface TruthMetaData { + uuid: string; + + key_share: string; + + policy_index: number; + + pol_method_index: number; + + /** + * Nonce used for encrypting the truth. + */ + nonce: string; + + /** + * Key that the truth (i.e. secret question answer, email address, mobile number, ...) + * is encrypted with when stored at the provider. + */ + truth_key: string; + + /** + * Truth-specific salt. + */ + master_salt: string; } export interface ReducerStateError { - backup_state?: undefined; - recovery_state?: undefined; + reducer_type: "error"; code: number; hint?: string; - message?: string; + detail?: string; } export enum BackupStates { @@ -202,31 +295,44 @@ export enum RecoveryStates { export interface MethodSpec { type: string; - usage_fee: string; + usage_fee: AmountString; } -// FIXME: This should be tagged! -export type AuthenticationProviderStatusEmpty = {}; +export type AuthenticationProviderStatusNotContacted = { + status: "not-contacted"; +}; export interface AuthenticationProviderStatusOk { + status: "ok"; + annual_fee: string; business_name: string; currency: string; http_status: 200; liability_limit: string; - salt: string; + provider_salt: string; storage_limit_in_megabytes: number; truth_upload_fee: string; methods: MethodSpec[]; + // FIXME: add timestamp? +} + +export interface AuthenticationProviderStatusDisabled { + status: "disabled"; } export interface AuthenticationProviderStatusError { - http_status: number; - error_code: number; + status: "error"; + + http_status?: number; + code: number; + hint?: string; + // FIXME: add timestamp? } export type AuthenticationProviderStatus = - | AuthenticationProviderStatusEmpty + | AuthenticationProviderStatusNotContacted + | AuthenticationProviderStatusDisabled | AuthenticationProviderStatusError | AuthenticationProviderStatusOk; @@ -236,14 +342,27 @@ export interface ReducerStateBackupUserAttributesCollecting selected_country: string; currencies: string[]; required_attributes: UserAttributeSpec[]; - authentication_providers: { [url: string]: AuthenticationProviderStatus }; + authentication_providers: AuthenticationProviderStatusMap; } -export interface ActionArgEnterUserAttributes { +export interface ActionArgsEnterUserAttributes { identity_attributes: Record<string, string>; } -export interface ActionArgAddAuthentication { +export const codecForActionArgsEnterUserAttributes = () => + buildCodecForObject<ActionArgsEnterUserAttributes>() + .property("identity_attributes", codecForAny()) + .build("ActionArgsEnterUserAttributes"); + +export interface ActionArgsAddProvider { + provider_url: string; +} + +export interface ActionArgsDeleteProvider { + provider_url: string; +} + +export interface ActionArgsAddAuthentication { authentication_method: { type: string; instructions: string; @@ -252,32 +371,180 @@ export interface ActionArgAddAuthentication { }; } -export interface ActionArgDeleteAuthentication { +export interface ActionArgsDeleteAuthentication { authentication_method: number; } -export interface ActionArgDeletePolicy { +export interface ActionArgsDeletePolicy { policy_index: number; } -export interface ActionArgEnterSecretName { +export interface ActionArgsEnterSecretName { name: string; } -export interface ActionArgEnterSecret { +export interface ActionArgsEnterSecret { secret: { value: string; mime?: string; + filename?: string; }; - expiration: Duration; + expiration: TalerProtocolTimestamp; +} + +export interface ActionArgsSelectContinent { + continent: string; +} + +export const codecForActionArgSelectContinent = () => + buildCodecForObject<ActionArgsSelectContinent>() + .property("continent", codecForString()) + .build("ActionArgSelectContinent"); + +export interface ActionArgsSelectCountry { + country_code: string; } export interface ActionArgsSelectChallenge { uuid: string; } -export type ActionArgsSolveChallengeRequest = SolveChallengeAnswerRequest; - +export type ActionArgsSolveChallengeRequest = + | SolveChallengeAnswerRequest + | SolveChallengePinRequest + | SolveChallengeHashRequest; + +/** + * Answer to a challenge. + * + * For "question" challenges, this is a string with the answer. + * + * For "sms" / "email" / "post" this is a numeric code with optionally + * the "A-" prefix. + */ export interface SolveChallengeAnswerRequest { answer: string; } + +/** + * Answer to a challenge that requires a numeric response. + * + * XXX: Should be deprecated in favor of just "answer". + */ +export interface SolveChallengePinRequest { + pin: number; +} + +/** + * Answer to a challenge by directly providing the hash. + * + * XXX: When / why is this even used? + */ +export interface SolveChallengeHashRequest { + /** + * Base32-crock encoded hash code. + */ + hash: string; +} + +export interface PolicyMember { + authentication_method: number; + provider: string; +} + +export interface ActionArgsAddPolicy { + policy: PolicyMember[]; +} + +export interface ActionArgsUpdateExpiration { + expiration: TalerProtocolTimestamp; +} + +export interface SelectedVersionInfo { + attribute_mask: number; + providers: { + url: string; + version: number; + }[]; +} + +export type ActionArgsChangeVersion = SelectedVersionInfo; + +export interface ActionArgsUpdatePolicy { + policy_index: number; + policy: PolicyMember[]; +} + +/** + * Cursor for a provider discovery process. + */ +export interface DiscoveryCursor { + position: { + provider_url: string; + mask: number; + max_version?: number; + }[]; +} + +export interface PolicyMetaInfo { + policy_hash: string; + provider_url: string; + version: number; + attribute_mask: number; + server_time: TalerProtocolTimestamp; + secret_name?: string; +} + +/** + * Aggregated / de-duplicated policy meta info. + */ +export interface AggregatedPolicyMetaInfo { + secret_name?: string; + policy_hash: string; + attribute_mask: number; + providers: { + url: string; + version: number; + }[]; +} + +export interface DiscoveryResult { + /** + * Found policies. + */ + policies: PolicyMetaInfo[]; + + /** + * Cursor that allows getting more results. + */ + cursor?: DiscoveryCursor; +} + +// FIXME: specify schema! +export const codecForActionArgsChangeVersion = codecForAny; + +export const codecForPolicyMember = () => + buildCodecForObject<PolicyMember>() + .property("authentication_method", codecForNumber()) + .property("provider", codecForString()) + .build("PolicyMember"); + +export const codecForActionArgsAddPolicy = () => + buildCodecForObject<ActionArgsAddPolicy>() + .property("policy", codecForList(codecForPolicyMember())) + .build("ActionArgsAddPolicy"); + +export const codecForActionArgsUpdateExpiration = () => + buildCodecForObject<ActionArgsUpdateExpiration>() + .property("expiration", codecForTimestamp) + .build("ActionArgsUpdateExpiration"); + +export const codecForActionArgsSelectChallenge = () => + buildCodecForObject<ActionArgsSelectChallenge>() + .property("uuid", codecForString()) + .build("ActionArgsSelectChallenge"); + +export const codecForActionArgSelectCountry = () => + buildCodecForObject<ActionArgsSelectCountry>() + .property("country_code", codecForString()) + .build("ActionArgSelectCountry"); |