exchange

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

commit 82c95245dbc11d42d3b82998e8f22d4f67ec189f
parent be04cca17ce24817c40ce7227231a859a31e87d7
Author: Florian Dold <dold@taler.net>
Date:   Sun, 30 Aug 2026 00:20:48 +0200

exchange AML API: report officer identity and permissions

Diffstat:
Msrc/exchange/meson.build | 1+
Msrc/exchange/taler-exchange-httpd.c | 15+++++----------
Asrc/exchange/taler-exchange-httpd_get-aml-OFFICER_PUB.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchange/taler-exchange-httpd_get-aml-OFFICER_PUB.h | 35+++++++++++++++++++++++++++++++++++
Msrc/exchange/taler-exchange-httpd_get-config.h | 2+-
Asrc/include/taler/exchange/get-aml-OFFICER_PUB.h | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/include/taler/taler_exchange_service.h | 1+
Msrc/include/taler/taler_testing_lib.h | 19+++++++++++++++++++
Asrc/lib/exchange_api_get-aml-OFFICER_PUB.c | 212+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/meson.build | 1+
Msrc/testing/meson.build | 1+
Msrc/testing/test_kyc_api.c | 18++++++++++++++++++
Asrc/testing/testing_api_cmd_get_aml_officer.c | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 670 insertions(+), 11 deletions(-)

diff --git a/src/exchange/meson.build b/src/exchange/meson.build @@ -163,6 +163,7 @@ executable( taler_exchange_httpd_SOURCES = [ 'taler-exchange-httpd.c', + 'taler-exchange-httpd_get-aml-OFFICER_PUB.c', 'taler-exchange-httpd_get-aml-OFFICER_PUB-accounts.c', 'taler-exchange-httpd_get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.c', 'taler-exchange-httpd_post-aml-OFFICER_PUB-decision.c', diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c @@ -82,6 +82,7 @@ #include "taler-exchange-httpd_get-transfers-WTID.h" #include <gnunet/gnunet_mhd_compat.h> #include "exchange-database/get_exists_aml_officer.h" +#include "taler-exchange-httpd_get-aml-OFFICER_PUB.h" #include "exchange-database/preflight.h" /** @@ -639,16 +640,6 @@ handle_get_aml (struct TEH_RequestContext *rc, TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED, args[0]); } - if (NULL == args[1]) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error ( - rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS, - "AML GET operations must specify an operation identifier"); - } - { const char *sig_hdr; struct TALER_AmlOfficerSignatureP officer_sig; @@ -710,6 +701,10 @@ handle_get_aml (struct TEH_RequestContext *rc, break; } } + if (NULL == args[1]) + return TEH_handler_aml_officer_get (rc, + &officer_pub, + &args[1]); for (unsigned int i = 0; NULL != h[i].op; i++) if (0 == strcmp (h[i].op, args[1])) diff --git a/src/exchange/taler-exchange-httpd_get-aml-OFFICER_PUB.c b/src/exchange/taler-exchange-httpd_get-aml-OFFICER_PUB.c @@ -0,0 +1,89 @@ +/* + This file is part of TALER + Copyright (C) 2026 Taler Systems SA + + TALER 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. +*/ +/** + * @file taler-exchange-httpd_get-aml-OFFICER_PUB.c + * @brief Return information about an authenticated AML officer + */ +#include <gnunet/gnunet_util_lib.h> +#include <jansson.h> +#include <microhttpd.h> +#include "exchange-database/get_aml_officer.h" +#include "taler/taler_json_lib.h" +#include "taler/taler_mhd_lib.h" +#include "taler-exchange-httpd.h" +#include "taler-exchange-httpd_get-aml-OFFICER_PUB.h" + + +enum MHD_Result +TEH_handler_aml_officer_get ( + struct TEH_RequestContext *rc, + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const char *const args[]) +{ + struct TALER_MasterSignatureP master_sig; + struct GNUNET_TIME_Absolute last_change; + enum GNUNET_DB_QueryStatus qs; + char *officer_name = NULL; + bool is_active; + bool read_only; + enum MHD_Result ret; + + if (NULL != args[0]) + return TALER_MHD_reply_with_error ( + rc->connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_GENERIC_ENDPOINT_UNKNOWN, + rc->url); + qs = TALER_EXCHANGEDB_get_aml_officer (TEH_pg, + officer_pub, + &master_sig, + &officer_name, + &is_active, + &read_only, + &last_change); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_break (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + NULL); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + return TALER_MHD_reply_with_error ( + rc->connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED, + NULL); + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + } + if (! is_active) + { + GNUNET_free (officer_name); + return TALER_MHD_reply_with_error ( + rc->connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED, + NULL); + } + ret = TALER_MHD_REPLY_JSON_PACK ( + rc->connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_string ("officer_name", + officer_name), + GNUNET_JSON_pack_bool ("read_only", + read_only)); + GNUNET_free (officer_name); + return ret; +} + + +/* end of taler-exchange-httpd_get-aml-OFFICER_PUB.c */ diff --git a/src/exchange/taler-exchange-httpd_get-aml-OFFICER_PUB.h b/src/exchange/taler-exchange-httpd_get-aml-OFFICER_PUB.h @@ -0,0 +1,35 @@ +/* + This file is part of TALER + Copyright (C) 2026 Taler Systems SA + + TALER 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. +*/ +/** + * @file taler-exchange-httpd_get-aml-OFFICER_PUB.h + * @brief Handle GET /aml/$OFFICER_PUB requests + */ +#ifndef TALER_EXCHANGE_HTTPD_GET_AML_OFFICER_PUB_H +#define TALER_EXCHANGE_HTTPD_GET_AML_OFFICER_PUB_H + +#include <microhttpd.h> +#include "taler-exchange-httpd.h" + + +/** + * Return information about the authenticated AML officer. + * + * @param rc request context + * @param officer_pub public key of the AML officer + * @param args remaining path arguments, must be empty + * @return MHD result code + */ +enum MHD_Result +TEH_handler_aml_officer_get ( + struct TEH_RequestContext *rc, + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const char *const args[]); + + +#endif diff --git a/src/exchange/taler-exchange-httpd_get-config.h b/src/exchange/taler-exchange-httpd_get-config.h @@ -41,7 +41,7 @@ * * Returned via both /config and /keys endpoints. */ -#define EXCHANGE_PROTOCOL_VERSION "39:0:5" +#define EXCHANGE_PROTOCOL_VERSION "40:0:6" /** diff --git a/src/include/taler/exchange/get-aml-OFFICER_PUB.h b/src/include/taler/exchange/get-aml-OFFICER_PUB.h @@ -0,0 +1,118 @@ +/* + This file is part of TALER + Copyright (C) 2026 Taler Systems SA + + TALER 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. +*/ +/** + * @file include/taler/exchange/get-aml-OFFICER_PUB.h + * @brief C interface for GET /aml/$OFFICER_PUB + */ +#ifndef _TALER_EXCHANGE__GET_AML_OFFICER_PUB_H +#define _TALER_EXCHANGE__GET_AML_OFFICER_PUB_H + +#include <taler/exchange/common.h> + + +/** + * Handle for a GET /aml/$OFFICER_PUB operation. + */ +struct TALER_EXCHANGE_GetAmlOfficerHandle; + + +/** + * Response from GET /aml/$OFFICER_PUB. + */ +struct TALER_EXCHANGE_GetAmlOfficerResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details for an HTTP 200 response. + */ + struct + { + /** + * Name configured for the AML officer. + */ + const char *officer_name; + + /** + * True if the officer may only read AML data. + */ + bool read_only; + } ok; + } details; +}; + + +#ifndef TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE +/** + * Type of the closure used by #TALER_EXCHANGE_GetAmlOfficerCallback. + */ +#define TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE void +#endif + +/** + * Callback for GET /aml/$OFFICER_PUB. + * + * @param cls closure + * @param response exchange response + */ +typedef void +(*TALER_EXCHANGE_GetAmlOfficerCallback)( + TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE *cls, + const struct TALER_EXCHANGE_GetAmlOfficerResponse *response); + + +/** + * Set up GET /aml/$OFFICER_PUB. The operation must be started explicitly. + * + * @param ctx CURL context + * @param url exchange base URL + * @param officer_priv private key of the officer + * @return operation handle + */ +struct TALER_EXCHANGE_GetAmlOfficerHandle * +TALER_EXCHANGE_get_aml_officer_create ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_AmlOfficerPrivateKeyP *officer_priv); + + +/** + * Start GET /aml/$OFFICER_PUB. + * + * @param[in,out] gaoh operation handle + * @param cb result callback + * @param cb_cls closure for @a cb + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_EXCHANGE_get_aml_officer_start ( + struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh, + TALER_EXCHANGE_GetAmlOfficerCallback cb, + TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE *cb_cls); + + +/** + * Cancel GET /aml/$OFFICER_PUB. + * + * @param[in] gaoh operation handle + */ +void +TALER_EXCHANGE_get_aml_officer_cancel ( + struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh); + + +#endif diff --git a/src/include/taler/taler_exchange_service.h b/src/include/taler/taler_exchange_service.h @@ -61,6 +61,7 @@ <taler/exchange/post-management-denominations-H_DENOM_PUB-revoke.h> #include <taler/exchange/post-management-signkeys-EXCHANGE_PUB-revoke.h> #include <taler/exchange/post-management-aml-officers.h> +#include <taler/exchange/get-aml-OFFICER_PUB.h> #include <taler/exchange/get-aml-OFFICER_PUB-measures.h> #include <taler/exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.h> #include <taler/exchange/post-aml-OFFICER_PUB-decision.h> diff --git a/src/include/taler/taler_testing_lib.h b/src/include/taler/taler_testing_lib.h @@ -2518,6 +2518,25 @@ TALER_TESTING_cmd_set_officer ( /** + * Check the authenticated AML officer resource. + * + * @param label command label + * @param ref_officer command that created the officer key + * @param expected_http_status expected HTTP status + * @param expected_name expected officer name for HTTP 200 + * @param expected_read_only expected permission for HTTP 200 + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_aml_officer ( + const char *label, + const char *ref_officer, + unsigned int expected_http_status, + const char *expected_name, + bool expected_read_only); + + +/** * Make AML decision. * * @param label command label diff --git a/src/lib/exchange_api_get-aml-OFFICER_PUB.c b/src/lib/exchange_api_get-aml-OFFICER_PUB.c @@ -0,0 +1,212 @@ +/* + This file is part of TALER + Copyright (C) 2026 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. +*/ +/** + * @file lib/exchange_api_get-aml-OFFICER_PUB.c + * @brief Implementation of GET /aml/$OFFICER_PUB + */ +#include <microhttpd.h> +#include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_curl_lib.h> +#include "taler/taler_json_lib.h" +#include "taler/exchange/get-aml-OFFICER_PUB.h" +#include "exchange_api_handle.h" +#include "taler/taler_signatures.h" +#include "exchange_api_curl_defaults.h" + + +/** + * Handle for GET /aml/$OFFICER_PUB. + */ +struct TALER_EXCHANGE_GetAmlOfficerHandle +{ + char *base_url; + char *url; + struct GNUNET_CURL_Job *job; + TALER_EXCHANGE_GetAmlOfficerCallback cb; + TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE *cb_cls; + struct GNUNET_CURL_Context *ctx; + struct TALER_AmlOfficerPublicKeyP officer_pub; + struct TALER_AmlOfficerPrivateKeyP officer_priv; +}; + + +/** + * Process a completed request. + * + * @param cls operation handle + * @param response_code HTTP status, 0 on transport failure + * @param response parsed JSON response + */ +static void +handle_get_aml_officer_finished (void *cls, + long response_code, + const void *response) +{ + struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh = cls; + const json_t *j = response; + struct TALER_EXCHANGE_GetAmlOfficerResponse result = { + .hr.reply = j, + .hr.http_status = (unsigned int) response_code + }; + + gaoh->job = NULL; + switch (response_code) + { + case 0: + result.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + case MHD_HTTP_OK: + { + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ( + "officer_name", + &result.details.ok.officer_name), + GNUNET_JSON_spec_bool ( + "read_only", + &result.details.ok.read_only), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (j, + spec, + NULL, + NULL)) + { + GNUNET_break_op (0); + result.hr.http_status = 0; + result.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + } + break; + } + case MHD_HTTP_BAD_REQUEST: + case MHD_HTTP_FORBIDDEN: + case MHD_HTTP_INTERNAL_SERVER_ERROR: + result.hr.ec = TALER_JSON_get_error_code (j); + result.hr.hint = TALER_JSON_get_error_hint (j); + break; + default: + GNUNET_break_op (0); + result.hr.ec = TALER_JSON_get_error_code (j); + result.hr.hint = TALER_JSON_get_error_hint (j); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u/%d for GET AML officer\n", + (unsigned int) response_code, + (int) result.hr.ec); + break; + } + gaoh->cb (gaoh->cb_cls, + &result); + gaoh->cb = NULL; + TALER_EXCHANGE_get_aml_officer_cancel (gaoh); +} + + +struct TALER_EXCHANGE_GetAmlOfficerHandle * +TALER_EXCHANGE_get_aml_officer_create ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_AmlOfficerPrivateKeyP *officer_priv) +{ + struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh; + + gaoh = GNUNET_new (struct TALER_EXCHANGE_GetAmlOfficerHandle); + gaoh->ctx = ctx; + gaoh->base_url = GNUNET_strdup (url); + gaoh->officer_priv = *officer_priv; + GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv, + &gaoh->officer_pub.eddsa_pub); + return gaoh; +} + + +enum TALER_ErrorCode +TALER_EXCHANGE_get_aml_officer_start ( + struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh, + TALER_EXCHANGE_GetAmlOfficerCallback cb, + TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE *cb_cls) +{ + CURL *eh; + struct TALER_AmlOfficerSignatureP officer_sig; + char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2 + 16]; + struct curl_slist *job_headers = NULL; + char pub_str[sizeof (gaoh->officer_pub) * 2]; + char sig_str[sizeof (officer_sig) * 2]; + char *end; + char *hdr; + + gaoh->cb = cb; + gaoh->cb_cls = cb_cls; + TALER_officer_aml_query_sign (&gaoh->officer_priv, + &officer_sig); + end = GNUNET_STRINGS_data_to_string (&gaoh->officer_pub, + sizeof (gaoh->officer_pub), + pub_str, + sizeof (pub_str)); + *end = '\0'; + GNUNET_snprintf (arg_str, + sizeof (arg_str), + "aml/%s", + pub_str); + gaoh->url = TALER_url_join (gaoh->base_url, + arg_str, + NULL); + if (NULL == gaoh->url) + return TALER_EC_GENERIC_CONFIGURATION_INVALID; + eh = TALER_EXCHANGE_curl_easy_get_ (gaoh->url); + if (NULL == eh) + { + GNUNET_free (gaoh->url); + gaoh->url = NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + end = GNUNET_STRINGS_data_to_string (&officer_sig, + sizeof (officer_sig), + sig_str, + sizeof (sig_str)); + *end = '\0'; + GNUNET_asprintf (&hdr, + "%s: %s", + TALER_AML_OFFICER_SIGNATURE_HEADER, + sig_str); + job_headers = curl_slist_append (NULL, + hdr); + GNUNET_free (hdr); + gaoh->job = GNUNET_CURL_job_add2 (gaoh->ctx, + eh, + job_headers, + &handle_get_aml_officer_finished, + gaoh); + curl_slist_free_all (job_headers); + if (NULL == gaoh->job) + { + GNUNET_free (gaoh->url); + gaoh->url = NULL; + return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + } + return TALER_EC_NONE; +} + + +void +TALER_EXCHANGE_get_aml_officer_cancel ( + struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh) +{ + if (NULL != gaoh->job) + { + GNUNET_CURL_job_cancel (gaoh->job); + gaoh->job = NULL; + } + GNUNET_free (gaoh->url); + GNUNET_free (gaoh->base_url); + GNUNET_free (gaoh); +} + + +/* end of exchange_api_get-aml-OFFICER_PUB.c */ diff --git a/src/lib/meson.build b/src/lib/meson.build @@ -4,6 +4,7 @@ libtalerexchange_la_SOURCES = [ 'exchange_api_delete-purses-PURSE_PUB.c', + 'exchange_api_get-aml-OFFICER_PUB.c', 'exchange_api_get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.c', 'exchange_api_get-aml-OFFICER_PUB-decisions.c', 'exchange_api_get-aml-OFFICER_PUB-kyc-statistics-NAMES.c', diff --git a/src/testing/meson.build b/src/testing/meson.build @@ -49,6 +49,7 @@ libtalertesting_la_SOURCES = [ 'testing_api_cmd_exec_wget.c', 'testing_api_cmd_exec_wirewatch.c', 'testing_api_cmd_get_active_legitimization_measures.c', + 'testing_api_cmd_get_aml_officer.c', 'testing_api_cmd_get_auditor.c', 'testing_api_cmd_get_exchange.c', 'testing_api_cmd_get_kyc_info.c', diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c @@ -590,6 +590,12 @@ run (void *cls, "Peter Falk", true, true), + TALER_TESTING_cmd_get_aml_officer ( + "get-read-only-aml-officer", + "create-aml-officer-1", + MHD_HTTP_OK, + "Peter Falk", + true), TALER_TESTING_cmd_check_aml_decisions ( "check-decisions-none-normal", "create-aml-officer-1", @@ -642,6 +648,12 @@ run (void *cls, "Peter Falk", true, false), + TALER_TESTING_cmd_get_aml_officer ( + "get-read-write-aml-officer", + "create-aml-officer-1", + MHD_HTTP_OK, + "Peter Falk", + false), TALER_TESTING_cmd_take_aml_decision ( "aml-decide", "create-aml-officer-1", @@ -683,6 +695,12 @@ run (void *cls, "Peter Falk", false, true), + TALER_TESTING_cmd_get_aml_officer ( + "get-disabled-aml-officer", + "create-aml-officer-1", + MHD_HTTP_FORBIDDEN, + NULL, + true), /* Test that we are NOT allowed to read AML decisions now that our AML staff account is disabled */ TALER_TESTING_cmd_check_aml_decisions ( diff --git a/src/testing/testing_api_cmd_get_aml_officer.c b/src/testing/testing_api_cmd_get_aml_officer.c @@ -0,0 +1,169 @@ +/* + This file is part of TALER + Copyright (C) 2026 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. +*/ +/** + * @file testing/testing_api_cmd_get_aml_officer.c + * @brief command for testing GET /aml/$OFFICER_PUB + */ +#include <gnunet/gnunet_curl_lib.h> + +struct AmlOfficerState; + +#define TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE struct AmlOfficerState +#include "taler/exchange/get-aml-OFFICER_PUB.h" +#include "taler/taler_testing_lib.h" + + +/** + * State for a GET AML officer command. + */ +struct AmlOfficerState +{ + struct TALER_EXCHANGE_GetAmlOfficerHandle *handle; + struct TALER_TESTING_Interpreter *is; + const char *ref_officer; + const char *expected_name; + unsigned int expected_http_status; + bool expected_read_only; +}; + + +/** + * Process the AML officer response. + * + * @param state command state + * @param response exchange response + */ +static void +get_aml_officer_cb ( + TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE *state, + const struct TALER_EXCHANGE_GetAmlOfficerResponse *response) +{ + state->handle = NULL; + if (state->expected_http_status != response->hr.http_status) + { + TALER_TESTING_unexpected_status (state->is, + response->hr.http_status, + state->expected_http_status); + return; + } + if (MHD_HTTP_OK == response->hr.http_status) + { + if ( (0 != strcmp (state->expected_name, + response->details.ok.officer_name)) || + (state->expected_read_only != response->details.ok.read_only) ) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (state->is); + return; + } + } + TALER_TESTING_interpreter_next (state->is); +} + + +/** + * Run the command. + */ +static void +get_aml_officer_run ( + void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct AmlOfficerState *state = cls; + const struct TALER_AmlOfficerPrivateKeyP *officer_priv; + const struct TALER_TESTING_Command *ref; + const struct TALER_TESTING_Command *exchange_cmd; + const char *exchange_url; + enum TALER_ErrorCode ec; + + (void) cmd; + state->is = is; + exchange_cmd = TALER_TESTING_interpreter_get_command (is, + "exchange"); + GNUNET_assert (NULL != exchange_cmd); + GNUNET_assert ( + GNUNET_OK == + TALER_TESTING_get_trait_exchange_url (exchange_cmd, + &exchange_url)); + ref = TALER_TESTING_interpreter_lookup_command (is, + state->ref_officer); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + GNUNET_assert ( + GNUNET_OK == + TALER_TESTING_get_trait_officer_priv (ref, + &officer_priv)); + state->handle = TALER_EXCHANGE_get_aml_officer_create ( + TALER_TESTING_interpreter_get_context (is), + exchange_url, + officer_priv); + GNUNET_assert (NULL != state->handle); + ec = TALER_EXCHANGE_get_aml_officer_start (state->handle, + &get_aml_officer_cb, + state); + if (TALER_EC_NONE != ec) + { + state->handle = NULL; + TALER_TESTING_interpreter_fail (is); + } +} + + +/** + * Clean up the command. + */ +static void +get_aml_officer_cleanup ( + void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct AmlOfficerState *state = cls; + + if (NULL != state->handle) + { + TALER_TESTING_command_incomplete (state->is, + cmd->label); + TALER_EXCHANGE_get_aml_officer_cancel (state->handle); + } + GNUNET_free (state); +} + + +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_aml_officer ( + const char *label, + const char *ref_officer, + unsigned int expected_http_status, + const char *expected_name, + bool expected_read_only) +{ + struct AmlOfficerState *state; + struct TALER_TESTING_Command cmd; + + state = GNUNET_new (struct AmlOfficerState); + state->ref_officer = ref_officer; + state->expected_http_status = expected_http_status; + state->expected_name = expected_name; + state->expected_read_only = expected_read_only; + cmd = (struct TALER_TESTING_Command) { + .cls = state, + .label = label, + .run = &get_aml_officer_run, + .cleanup = &get_aml_officer_cleanup + }; + return cmd; +} + + +/* end of testing_api_cmd_get_aml_officer.c */