exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit d9a2f5aa6b1bf0f669bc25446caee5c7ae75f2f2
parent d160847fceb35fb80b3e9dc559b177003bff18f5
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 22 Apr 2025 23:18:30 +0200

persist submitter class and form_id in kyc_attributes table; fixes #9661

Diffstat:
Msrc/exchange/taler-exchange-httpd_aml-decision.c | 4++++
Msrc/exchange/taler-exchange-httpd_common_kyc.c | 6++++++
Msrc/exchangedb/.gitignore | 1+
Asrc/exchangedb/0010-kyc-attributes.sql | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/exchangedb/Makefile.am | 11++++++++++-
Asrc/exchangedb/exchange-0010.sql.in | 23+++++++++++++++++++++++
Msrc/exchangedb/exchange_do_insert_aml_decision.sql | 7++++++-
Msrc/exchangedb/exchange_do_persist_kyc_attributes.sql | 7++++++-
Msrc/exchangedb/exchangedb_aml.c | 1+
Msrc/exchangedb/pg_insert_aml_decision.c | 6+++++-
Msrc/exchangedb/pg_insert_aml_decision.h | 2++
Msrc/exchangedb/pg_persist_kyc_attributes.c | 6+++++-
Msrc/exchangedb/pg_persist_kyc_attributes.h | 2++
Msrc/include/taler_exchangedb_plugin.h | 12++++++++----
14 files changed, 139 insertions(+), 9 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c b/src/exchange/taler-exchange-httpd_aml-decision.c @@ -357,9 +357,12 @@ TEH_handler_post_aml_decision ( struct GNUNET_HashCode h_attr = { 0 }; size_t eas = 0; void *ea = NULL; + const char *form_id = NULL; if (NULL != attributes) { + form_id = json_string_value (json_object_get (attributes, + "FORM_ID")); TALER_json_hash (attributes, &h_attr); TALER_CRYPTO_kyc_attributes_encrypt (&TEH_attribute_key, @@ -400,6 +403,7 @@ TEH_handler_post_aml_decision ( &officer_sig, num_events, sevents, + form_id, eas, /* enc_attributes_size*/ ea, /* enc_attributes*/ &h_attr, /* attributes_hash */ diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c b/src/exchange/taler-exchange-httpd_common_kyc.c @@ -291,6 +291,7 @@ TEH_kyc_store_attributes ( unsigned int birthday = 0; size_t eas = 0; void *ea = NULL; + const char *form_id = NULL; if (TEH_age_restriction_enabled) { @@ -316,8 +317,11 @@ TEH_kyc_store_attributes ( } } } + if (NULL != new_attributes) { + form_id = json_string_value (json_object_get (new_attributes, + "FORM_ID")); TALER_CRYPTO_kyc_attributes_encrypt (&TEH_attribute_key, new_attributes, &ea, @@ -332,6 +336,7 @@ TEH_kyc_store_attributes ( provider_legitimization_id, birthday, expiration, + form_id, eas, ea); GNUNET_free (ea); @@ -706,6 +711,7 @@ handle_aml_fallback_result ( NULL, /* decider_sig */ apr->details.success.num_events, apr->details.success.events, + NULL, /* form_id */ 0, /* enc_attributes_size*/ NULL, /* enc_attributes*/ NULL, /* attributes_hash */ diff --git a/src/exchangedb/.gitignore b/src/exchangedb/.gitignore @@ -19,3 +19,4 @@ exchange-0006.sql exchange-0007.sql exchange-0008.sql exchange-0009.sql +exchange-0010.sql diff --git a/src/exchangedb/0010-kyc-attributes.sql b/src/exchangedb/0010-kyc-attributes.sql @@ -0,0 +1,60 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2025 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +-- + +CREATE OR REPLACE FUNCTION alter_table_kyc_attributes10( + IN partition_suffix TEXT DEFAULT NULL +) +RETURNS VOID +LANGUAGE plpgsql +AS $$ +DECLARE + table_name TEXT DEFAULT 'kyc_attributes'; +BEGIN + PERFORM create_partitioned_table( + 'ALTER TABLE %I' + ' ADD COLUMN form_name TEXT DEFAULT(NULL)' + ',ADD COLUMN by_aml_officer BOOL NOT NULL DEFAULT(FALSE)' + ';' + ,table_name + ,'' + ,partition_suffix + ); + PERFORM comment_partitioned_column( + 'Name of the form (FORM_ID) that is captured in the attributes.' + ,'form_name' + ,table_name + ,partition_suffix + ); + PERFORM comment_partitioned_column( + 'TRUE if the attributes were submitted by an AML officer.' + ,'by_aml_officer' + ,table_name + ,partition_suffix + ); +END $$; + +INSERT INTO exchange_tables + (name + ,version + ,action + ,partitioned + ,by_range) + VALUES + ('kyc_attributes10' + ,'exchange-0010' + ,'alter' + ,TRUE + ,FALSE); diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am @@ -33,6 +33,7 @@ sqlinputs = \ 0007-*.sql \ 0008-*.sql \ 0009-*.sql \ + 0010-*.sql \ exchange-0002.sql.in \ exchange-0003.sql.in \ exchange-0004.sql.in \ @@ -40,7 +41,8 @@ sqlinputs = \ exchange-0006.sql.in \ exchange-0007.sql.in \ exchange-0008.sql.in \ - exchange-0009.sql.in + exchange-0009.sql.in \ + exchange-0010.sql.in sql_DATA = \ benchmark-0001.sql \ @@ -55,6 +57,7 @@ sql_DATA = \ exchange-0007.sql \ exchange-0008.sql \ exchange-0009.sql \ + exchange-0010.sql \ drop.sql \ procedures.sql \ tops-0001.sql @@ -74,6 +77,7 @@ CLEANFILES = \ exchange-0007.sql \ exchange-0008.sql \ exchange-0009.sql \ + exchange-0010.sql \ procedures.sql procedures.sql: procedures.sql.in exchange_do_*.sql exchange_statistics_helpers.sql @@ -121,6 +125,11 @@ exchange-0009.sql: exchange-0009.sql.in 0009-*.sql gcc -E -P -undef - < exchange-0009.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@ chmod ugo-w $@ +exchange-0010.sql: exchange-0010.sql.in 0010-*.sql + chmod +w $@ 2> /dev/null || true + gcc -E -P -undef - < exchange-0010.sql.in 2>/dev/null | sed -e "s/--.*//" | awk 'NF' - >$@ + chmod ugo-w $@ + check_SCRIPTS = \ test_idempotency.sh diff --git a/src/exchangedb/exchange-0010.sql.in b/src/exchangedb/exchange-0010.sql.in @@ -0,0 +1,23 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2025 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + +BEGIN; + +SELECT _v.register_patch('exchange-0010', NULL, NULL); +SET search_path TO exchange; + +#include "0010-kyc-attributes.sql" + +COMMIT; diff --git a/src/exchangedb/exchange_do_insert_aml_decision.sql b/src/exchangedb/exchange_do_insert_aml_decision.sql @@ -34,6 +34,7 @@ CREATE FUNCTION exchange_do_insert_aml_decision( IN in_decider_sig BYTEA, -- can be NULL IN in_notify_s TEXT, IN ina_events TEXT[], + IN in_form_name TEXT, -- can be NULL OUT out_invalid_officer BOOLEAN, OUT out_account_unknown BOOLEAN, OUT out_last_date INT8, @@ -233,12 +234,16 @@ THEN (h_payto ,collection_time ,expiration_time + ,form_name + ,by_aml_officer ,encrypted_attributes ,legitimization_serial ) VALUES (in_h_normalized_payto ,in_decision_time ,in_kyc_attributes_expiration + ,in_form_name + ,TRUE ,in_kyc_attributes_enc ,my_legitimization_process_serial_id ) @@ -295,5 +300,5 @@ EXECUTE FORMAT ( END $$; -COMMENT ON FUNCTION exchange_do_insert_aml_decision(TEXT, BYTEA, BYTEA, INT8, INT8, TEXT, BYTEA, BYTEA, INT8, TEXT, BOOLEAN, TEXT, TEXT, TEXT, BYTEA, BYTEA, TEXT, TEXT[]) +COMMENT ON FUNCTION exchange_do_insert_aml_decision(TEXT, BYTEA, BYTEA, INT8, INT8, TEXT, BYTEA, BYTEA, INT8, TEXT, BOOLEAN, TEXT, TEXT, TEXT, BYTEA, BYTEA, TEXT, TEXT[], TEXT) IS 'Checks whether the AML officer is eligible to make AML decisions and if so inserts the decision into the table'; diff --git a/src/exchangedb/exchange_do_persist_kyc_attributes.sql b/src/exchangedb/exchange_do_persist_kyc_attributes.sql @@ -27,6 +27,7 @@ CREATE FUNCTION exchange_do_persist_kyc_attributes( IN in_expiration_time_ts INT8, -- rounded to timestamp IN in_enc_attributes BYTEA, IN in_kyc_completed_notify_s TEXT, + IN in_form_name TEXT, -- can be NULL OUT out_ok BOOLEAN) -- set to true if we had a legi process matching in_process_row and in_provider_name for this account LANGUAGE plpgsql AS $$ @@ -36,12 +37,16 @@ INSERT INTO kyc_attributes (h_payto ,collection_time ,expiration_time + ,form_name + ,by_aml_officer ,encrypted_attributes ,legitimization_serial ) VALUES (in_h_payto ,in_collection_time_ts ,in_expiration_time_ts + ,in_form_name + ,FALSE ,in_enc_attributes ,in_process_row); @@ -86,5 +91,5 @@ INSERT INTO kyc_alerts END $$; -COMMENT ON FUNCTION exchange_do_persist_kyc_attributes(INT8, BYTEA, INT4, TEXT, TEXT, TEXT, INT8, INT8, INT8, BYTEA, TEXT) +COMMENT ON FUNCTION exchange_do_persist_kyc_attributes(INT8, BYTEA, INT4, TEXT, TEXT, TEXT, INT8, INT8, INT8, BYTEA, TEXT, TEXT) IS 'Inserts new KYC attributes and updates the status of the legitimization process'; diff --git a/src/exchangedb/exchangedb_aml.c b/src/exchangedb/exchangedb_aml.c @@ -93,6 +93,7 @@ TALER_EXCHANGEDB_persist_aml_program_result ( NULL, /* decider_sig */ apr->details.success.num_events, apr->details.success.events, + NULL, /* form ID */ 0, /* enc_attributes_size*/ NULL, /* enc_attributes*/ NULL, /* attributes_hash */ diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c @@ -44,6 +44,7 @@ TEH_PG_insert_aml_decision ( const struct TALER_AmlOfficerSignatureP *decider_sig, size_t num_events, const char *events[static num_events], + const char *form_name, size_t enc_attributes_size, const void *enc_attributes, struct GNUNET_HashCode *attributes_hash, @@ -123,6 +124,9 @@ TEH_PG_insert_aml_decision ( GNUNET_PQ_query_param_array_ptrs_string (num_events, events, pg->conn), + (NULL == form_name) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (form_name), GNUNET_PQ_query_param_end }; char *rpayto = NULL; @@ -162,7 +166,7 @@ TEH_PG_insert_aml_decision ( ",out_legitimization_measure_serial_id" ",out_payto_uri" " FROM exchange_do_insert_aml_decision" - "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18);"); + "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "do_insert_aml_decision", params, diff --git a/src/exchangedb/pg_insert_aml_decision.h b/src/exchangedb/pg_insert_aml_decision.h @@ -49,6 +49,7 @@ * @param events array of events to trigger * @param enc_attributes_size number of bytes in @a enc_attributes * @param enc_attributes encrypted attribute data + * @param form_name name of the form from which @a enc_attributes originate, can be NULL * @param attributes_hash hash of the unencrypted attribute data * @param attributes_expiration_time when does the attribute data expire * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now @@ -77,6 +78,7 @@ TEH_PG_insert_aml_decision ( const struct TALER_AmlOfficerSignatureP *decider_sig, size_t num_events, const char *events[static num_events], + const char *form_name, size_t enc_attributes_size, const void *enc_attributes, struct GNUNET_HashCode *attributes_hash, diff --git a/src/exchangedb/pg_persist_kyc_attributes.c b/src/exchangedb/pg_persist_kyc_attributes.c @@ -36,6 +36,7 @@ TEH_PG_persist_kyc_attributes ( const char *provider_legitimization_id, uint32_t birthday, struct GNUNET_TIME_Absolute expiration_time, + const char *form_name, size_t enc_attributes_size, const void *enc_attributes) { @@ -72,6 +73,9 @@ TEH_PG_persist_kyc_attributes ( : GNUNET_PQ_query_param_fixed_size (enc_attributes, enc_attributes_size), GNUNET_PQ_query_param_string (kyc_completed_notify_s), + (NULL == form_name) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (form_name), GNUNET_PQ_query_param_end }; bool ok; @@ -91,7 +95,7 @@ TEH_PG_persist_kyc_attributes ( "SELECT " " out_ok" " FROM exchange_do_persist_kyc_attributes " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);"); + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "persist_kyc_attributes", params, diff --git a/src/exchangedb/pg_persist_kyc_attributes.h b/src/exchangedb/pg_persist_kyc_attributes.h @@ -37,6 +37,7 @@ * @param provider_legitimization_id provider legitimization ID * @param birthday birthdate of user, in days after 1990, or 0 if unknown or definitively adult * @param expiration_time when does the data expire + * @param form_name name of the form from which the @a enc_attributes originate, can be NULL * @param enc_attributes_size number of bytes in @a enc_attributes * @param enc_attributes encrypted attribute data * @return database transaction status @@ -51,6 +52,7 @@ TEH_PG_persist_kyc_attributes ( const char *provider_legitimization_id, uint32_t birthday, struct GNUNET_TIME_Absolute expiration_time, + const char *form_name, size_t enc_attributes_size, const void *enc_attributes); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h @@ -8034,10 +8034,11 @@ struct TALER_EXCHANGEDB_Plugin * @param decider_sig signature of the staff member * @param num_events length of the @a events array * @param events array of events to trigger - * @param enc_attributes_size number of bytes in @a enc_attributes - * @param enc_attributes encrypted attribute data - * @param attributes_hash hash of the unencrypted attribute data - * @param attributes_expiration_time when does the attribute data expire + * @param form_name name of the form from which @a enc_attributes originate, can be NULL + * @param enc_attributes_size number of bytes in @a enc_attributes + * @param enc_attributes encrypted attribute data + * @param attributes_hash hash of the unencrypted attribute data + * @param attributes_expiration_time when does the attribute data expire * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now * @param[out] unknown_account set to TRUE if @a h_payto does not refer to a known account and @a jmeasures was given * @param[out] last_date set to the previous decision time; @@ -8064,6 +8065,7 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_AmlOfficerSignatureP *decider_sig, size_t num_events, const char *events[static num_events], + const char *form_name, size_t enc_attributes_size, const void *enc_attributes, struct GNUNET_HashCode *attributes_hash, @@ -8086,6 +8088,7 @@ struct TALER_EXCHANGEDB_Plugin * @param provider_legitimization_id provider legitimization ID * @param birthday birthdate of user, in days after 1990, or 0 if unknown or definitively adult * @param expiration_time when does the data expire + * @param form_name name of the form from which the @a enc_attributes originate, can be NULL * @param enc_attributes_size number of bytes in @a enc_attributes * @param enc_attributes encrypted attribute data * @return database transaction status @@ -8100,6 +8103,7 @@ struct TALER_EXCHANGEDB_Plugin const char *provider_legitimization_id, uint32_t birthday, struct GNUNET_TIME_Absolute expiration_time, + const char *form_name, size_t enc_attributes_size, const void *enc_attributes);