diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-08-08 19:22:13 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-08-08 19:22:20 +0200 |
commit | 6ef309790ffa8d1dda5e6604cfe9bc6763831668 (patch) | |
tree | ebd6f80242ef055f337f5686750e1424a2494763 /src | |
parent | e008de3ea47db34ffd6ed029bcf12fa7bfe668e1 (diff) |
return current threshold and expiration date with kyc-wallet endpoint
Diffstat (limited to 'src')
-rw-r--r-- | src/exchange/taler-exchange-aggregator.c | 17 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_common_kyc.c | 15 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_common_kyc.h | 12 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-wallet.c | 35 | ||||
-rw-r--r-- | src/include/taler_amount_lib.h | 14 | ||||
-rw-r--r-- | src/include/taler_exchange_service.h | 18 | ||||
-rw-r--r-- | src/include/taler_kyclogic_lib.h | 7 | ||||
-rw-r--r-- | src/kyclogic/kyclogic_api.c | 28 | ||||
-rw-r--r-- | src/kyclogic/taler-exchange-kyc-tester.c | 17 | ||||
-rw-r--r-- | src/lib/exchange_api_kyc_wallet.c | 26 | ||||
-rw-r--r-- | src/testing/test_kyc_api.c | 4 | ||||
-rw-r--r-- | src/util/amount.c | 23 |
12 files changed, 193 insertions, 23 deletions
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index b4ff32cd2..5a7be23b5 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -528,12 +528,17 @@ legitimization_satisfied (struct AggregationUnit *au_active) json_decref (jrules); } } - qs = TALER_KYCLOGIC_kyc_test_required ( - TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT, - lrs, - &return_relevant_amounts, - (void *) au_active, - &requirement); + { + struct TALER_Amount next_threshold; + + qs = TALER_KYCLOGIC_kyc_test_required ( + TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT, + lrs, + &return_relevant_amounts, + (void *) au_active, + &requirement, + &next_threshold); + } if (qs < 0) { TALER_KYCLOGIC_rules_free (lrs); diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c b/src/exchange/taler-exchange-httpd_common_kyc.c index 8bcda3977..0ac1fbc25 100644 --- a/src/exchange/taler-exchange-httpd_common_kyc.c +++ b/src/exchange/taler-exchange-httpd_common_kyc.c @@ -1440,6 +1440,11 @@ legitimization_check_run ( /* AML/KYC disabled, just immediately return success! */ lch->lcr.kyc.requirement_row = 0; lch->lcr.kyc.ok = true; + lch->lcr.expiration_date + = GNUNET_TIME_UNIT_FOREVER_TS; + memset (&lch->lcr.next_threshold, + 0, + sizeof (struct TALER_Amount)); lch->lcr.http_status = 0; lch->lcr.response = NULL; lch->async_task @@ -1509,7 +1514,8 @@ legitimization_check_run ( lrs, lch->ai, lch->ai_cls, - &requirement); + &requirement, + &lch->lcr.next_threshold); if (qs < 0) { TALER_KYCLOGIC_rules_free (lrs); @@ -1521,8 +1527,13 @@ legitimization_check_run ( if (NULL == requirement) { - TALER_KYCLOGIC_rules_free (lrs); lch->lcr.kyc.ok = true; + lch->lcr.expiration_date + = TALER_KYCLOGIC_rules_get_expiration (lrs); + TALER_KYCLOGIC_rules_free (lrs); + memset (&lch->lcr.next_threshold, + 0, + sizeof (struct TALER_Amount)); /* return success! */ lch->async_task = GNUNET_SCHEDULER_add_now ( diff --git a/src/exchange/taler-exchange-httpd_common_kyc.h b/src/exchange/taler-exchange-httpd_common_kyc.h index 68fc31768..cd753746b 100644 --- a/src/exchange/taler-exchange-httpd_common_kyc.h +++ b/src/exchange/taler-exchange-httpd_common_kyc.h @@ -195,6 +195,18 @@ struct TEH_LegitimizationCheckResult struct TALER_EXCHANGEDB_KycStatus kyc; /** + * Smallest amount (over any timeframe) that may + * require additional KYC checks (if @a kyc.ok). + */ + struct TALER_Amount next_threshold; + + /** + * When do the current KYC rules possibly expire. + * Only valid if @a kyc.ok. + */ + struct GNUNET_TIME_Timestamp expiration_date; + + /** * HTTP status code for @a response, or 0 */ unsigned int http_status; diff --git a/src/exchange/taler-exchange-httpd_kyc-wallet.c b/src/exchange/taler-exchange-httpd_kyc-wallet.c index a74f6eca6..0e992f5f3 100644 --- a/src/exchange/taler-exchange-httpd_kyc-wallet.c +++ b/src/exchange/taler-exchange-httpd_kyc-wallet.c @@ -93,6 +93,18 @@ struct KycRequestContext struct TALER_EXCHANGEDB_KycStatus kyc; /** + * Smallest amount (over any timeframe) that may + * require additional KYC checks (if @a kyc.ok). + */ + struct TALER_Amount next_threshold; + + /** + * When do the current KYC rules possibly expire. + * Only valid if @a kyc.ok. + */ + struct GNUNET_TIME_Timestamp expiration_date; + + /** * HTTP status code for @a response, or 0 */ unsigned int http_status; @@ -173,10 +185,15 @@ legi_result_cb ( { struct KycRequestContext *krc = cls; + GNUNET_assert (0 == + lcr->expiration_date.abs_time.abs_value_us + % GNUNET_TIME_UNIT_SECONDS.rel_value_us); krc->lch = NULL; krc->http_status = lcr->http_status; krc->response = lcr->response; krc->kyc = lcr->kyc; + krc->next_threshold = lcr->next_threshold; + krc->expiration_date = lcr->expiration_date; GNUNET_CONTAINER_DLL_remove (krc_head, krc_tail, krc); @@ -289,13 +306,21 @@ TEH_handler_kyc_wallet ( krc->response); if (krc->kyc.ok) { + bool have_ts + = TALER_amount_is_valid (&krc->next_threshold); + + /* KYC not required or already satisfied */ - return TALER_MHD_reply_static ( + return TALER_MHD_REPLY_JSON_PACK ( rc->connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); + MHD_HTTP_OK, + GNUNET_JSON_pack_timestamp ("expiration_time", + krc->expiration_date), + GNUNET_JSON_pack_allow_null ( + TALER_JSON_pack_amount ("next_threshold", + have_ts + ? &krc->next_threshold + : NULL))); } return TEH_RESPONSE_reply_kyc_required (rc->connection, &krc->h_payto, diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h index 937238d15..71af13932 100644 --- a/src/include/taler_amount_lib.h +++ b/src/include/taler_amount_lib.h @@ -251,6 +251,20 @@ TALER_amount_cmp (const struct TALER_Amount *a1, /** + * Compute maximum of two amounts. + * + * @param[out] ma set to maximum of @a a1 and @a a2 + * @param a1 first amount + * @param a2 second amount + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_amount_max (struct TALER_Amount *ma, + const struct TALER_Amount *a1, + const struct TALER_Amount *a2); + + +/** * Compare the value/fraction of two amounts. Does not compare the currency. * Comparing amounts of different currencies will cause the program to abort(). * If unsure, check with #TALER_amount_cmp_currency() first to be sure that diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index ab8b799ac..f937d9293 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -4745,6 +4745,24 @@ struct TALER_EXCHANGE_WalletKycResponse union { + struct + { + + /** + * Above which amount does the wallet need to check + * for KYC again? + */ + struct TALER_Amount next_threshold; + + /** + * When will the current set of AML/KYC rules + * expire (and the wallet should again check + * for new KYC requirements)? + */ + struct GNUNET_TIME_Timestamp expiration_time; + + } ok; + /** * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. */ diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h index b852ba14c..d146b0c57 100644 --- a/src/include/taler_kyclogic_lib.h +++ b/src/include/taler_kyclogic_lib.h @@ -331,6 +331,10 @@ TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs); * is triggered, otherwise the rule with measures * that must be satisfied (will be the highest * applicable rule by display priority) + * @param[out] next_threshold set to the next amount + * that may trigger a KYC check (note: only really + * useful for the wallet balance right now, as we + * cannot easily state the applicable timeframe) * @return transaction status */ enum GNUNET_DB_QueryStatus @@ -339,7 +343,8 @@ TALER_KYCLOGIC_kyc_test_required ( const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, TALER_KYCLOGIC_KycAmountIterator ai, void *ai_cls, - const struct TALER_KYCLOGIC_KycRule **triggered_rule); + const struct TALER_KYCLOGIC_KycRule **triggered_rule, + struct TALER_Amount *next_threshold); /** diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c index 066fd1202..1deac34ff 100644 --- a/src/kyclogic/kyclogic_api.c +++ b/src/kyclogic/kyclogic_api.c @@ -300,6 +300,11 @@ struct GNUNET_TIME_Timestamp TALER_KYCLOGIC_rules_get_expiration ( const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) { + if (NULL == lrs) + return GNUNET_TIME_UNIT_FOREVER_TS; + GNUNET_assert (0 == + lrs->expiration_time.abs_time.abs_value_us + % GNUNET_TIME_UNIT_SECONDS.rel_value_us); return lrs->expiration_time; } @@ -530,6 +535,9 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) JSON_INDENT (2)); return NULL; } + GNUNET_assert (0 == + expiration_time.abs_time.abs_value_us + % GNUNET_TIME_UNIT_SECONDS.rel_value_us); lrs = GNUNET_new (struct TALER_KYCLOGIC_LegitimizationRuleSet); lrs->expiration_time = expiration_time; lrs->successor_measure @@ -2644,6 +2652,7 @@ struct KycTestContext * Set to the triggered rule. */ const struct TALER_KYCLOGIC_KycRule *triggered_rule; + }; @@ -2736,12 +2745,17 @@ TALER_KYCLOGIC_kyc_test_required ( const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, TALER_KYCLOGIC_KycAmountIterator ai, void *ai_cls, - const struct TALER_KYCLOGIC_KycRule **triggered_rule) + const struct TALER_KYCLOGIC_KycRule **triggered_rule, + struct TALER_Amount *next_threshold) { struct GNUNET_TIME_Relative range = GNUNET_TIME_UNIT_ZERO; enum GNUNET_DB_QueryStatus qs; + bool have_threshold = false; + memset (next_threshold, + 0, + sizeof (struct TALER_Amount)); if (NULL == lrs) lrs = &default_rules; GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -2755,6 +2769,18 @@ TALER_KYCLOGIC_kyc_test_required ( if (event != rule->trigger) continue; + if (have_threshold) + { + GNUNET_assert (GNUNET_OK == + TALER_amount_max (next_threshold, + next_threshold, + &rule->threshold)); + } + else + { + *next_threshold = rule->threshold; + have_threshold = true; + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Matched rule %u with timeframe %s\n", i, diff --git a/src/kyclogic/taler-exchange-kyc-tester.c b/src/kyclogic/taler-exchange-kyc-tester.c index 841fe939a..021b10fb8 100644 --- a/src/kyclogic/taler-exchange-kyc-tester.c +++ b/src/kyclogic/taler-exchange-kyc-tester.c @@ -1586,12 +1586,17 @@ run (void *cls, GNUNET_SCHEDULER_shutdown (); return; } - qs = TALER_KYCLOGIC_kyc_test_required ( - event, - lrs, - &amount_iterator, - &trigger_amount, - &rule); + { + struct TALER_Amount next_threshold; + + qs = TALER_KYCLOGIC_kyc_test_required ( + event, + lrs, + &amount_iterator, + &trigger_amount, + &rule, + &next_threshold); + } switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: diff --git a/src/lib/exchange_api_kyc_wallet.c b/src/lib/exchange_api_kyc_wallet.c index b12657a64..695a6cfde 100644 --- a/src/lib/exchange_api_kyc_wallet.c +++ b/src/lib/exchange_api_kyc_wallet.c @@ -91,6 +91,32 @@ handle_kyc_wallet_finished (void *cls, case 0: ks.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; + case MHD_HTTP_OK: + { + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount_any ( + "next_threshold", + &ks.details.ok.next_threshold), + NULL), + GNUNET_JSON_spec_timestamp ( + "expiration_time", + &ks.details.ok.expiration_time), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (j, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + ks.hr.http_status = 0; + ks.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + break; + } case MHD_HTTP_NO_CONTENT: break; case MHD_HTTP_BAD_REQUEST: diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c index 423198433..01fda98c5 100644 --- a/src/testing/test_kyc_api.c +++ b/src/testing/test_kyc_api.c @@ -642,7 +642,7 @@ run (void *cls, "wallet-trigger-kyc-for-aml-allowed", "wallet-trigger-kyc-for-aml", "EUR:1000", - MHD_HTTP_NO_CONTENT), + MHD_HTTP_OK), TALER_TESTING_cmd_wallet_kyc_get ( "wallet-trigger-kyc-for-aml-denied-high", "wallet-trigger-kyc-for-aml", @@ -739,7 +739,7 @@ run (void *cls, "wallet-trigger-kyc-for-form-aml-allowed", "wallet-trigger-kyc-for-form-aml", "EUR:500", - MHD_HTTP_NO_CONTENT), + MHD_HTTP_OK), TALER_TESTING_cmd_end () }; diff --git a/src/util/amount.c b/src/util/amount.c index cce84d73a..d102b4d94 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -270,6 +270,29 @@ TALER_amount_is_valid (const struct TALER_Amount *amount) } +enum GNUNET_GenericReturnValue +TALER_amount_max (struct TALER_Amount *ma, + const struct TALER_Amount *a1, + const struct TALER_Amount *a2) +{ + if (GNUNET_OK != + TALER_amount_cmp_currency (a1, + a2)) + { + memset (ma, + 0, + sizeof (*ma)); + return GNUNET_SYSERR; + } + if (1 == TALER_amount_cmp (a1, + a2)) + *ma = *a1; + else + *ma = *a2; + return GNUNET_OK; +} + + bool TALER_amount_is_zero (const struct TALER_Amount *amount) { |