new AML APIs (libtalerexchange)

This commit is contained in:
Christian Grothoff 2023-01-18 14:25:58 +01:00
parent cda751eaa5
commit 999209518d
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 880 additions and 1 deletions

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA Copyright (C) 2014-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the 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 terms of the GNU Affero General Public License as published by the Free Software
@ -4240,6 +4240,185 @@ TALER_EXCHANGE_management_revoke_signing_key_cancel (
struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *rh); struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *rh);
/**
* Function called with information about the change to
* an AML officer status.
*
* @param cls closure
* @param hr HTTP response data
*/
typedef void
(*TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback) (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr);
/**
* @brief Handle for a POST /management/aml-officers/$OFFICER_PUB request.
*/
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer;
/**
* Inform the exchange that the status of an AML officer has changed.
*
* @param ctx the context
* @param url HTTP base URL for the exchange
* @param officer_pub the public signing key of the officer
* @param officer_name name of the officer
* @param change_date when to affect the status change
* @param is_active true to enable the officer
* @param read_only true to only allow read-only access
* @param master_sig signature affirming the change
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
* @return the request handle; NULL upon error
*/
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *
TALER_EXCHANGE_management_update_aml_officer (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_AmlOfficerPublicKeyP *officer_pub,
const char *officer_name,
struct GNUNET_TIME_Timestamp change_date,
bool is_active,
bool read_only,
const struct TALER_MasterSignatureP *master_sig,
TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback cb,
void *cb_cls);
/**
* Cancel #TALER_EXCHANGE_management_update_aml_officer() operation.
*
* @param rh handle of the operation to cancel
*/
void
TALER_EXCHANGE_management_update_aml_officer_cancel (
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *rh);
/**
* Function called with information about storing an
* an AML decision.
*
* @param cls closure
* @param hr HTTP response data
*/
typedef void
(*TALER_EXCHANGE_AddAmlDecisionCallback) (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr);
/**
* @brief Handle for a POST /aml-decision/$OFFICER_PUB request.
*/
struct TALER_EXCHANGE_AddAmlDecision;
/**
* Inform the exchange that an AML decision has been taken.
*
* @param ctx the context
* @param url HTTP base URL for the exchange
* @param justification human-readable justification
* @param decision_time when was the decision made
* @param new_threshold at what monthly amount threshold
* should a revision be triggered
* @param h_payto payto URI hash of the account the
* decision is about
* @param new_state updated AML state
* @param officer_priv private key of the deciding AML officer
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
* @return the request handle; NULL upon error
*/
struct TALER_EXCHANGE_AddAmlDecision *
TALER_EXCHANGE_add_aml_decision (
struct GNUNET_CURL_Context *ctx,
const char *url,
const char *justification,
struct GNUNET_TIME_Timestamp decision_time,
const struct TALER_Amount *new_threshold,
const struct TALER_PaytoHashP *h_payto,
enum TALER_AmlDecisionState new_state,
const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
TALER_EXCHANGE_AddAmlDecisionCallback cb,
void *cb_cls);
/**
* Cancel #TALER_EXCHANGE_add_aml_decision() operation.
*
* @param rh handle of the operation to cancel
*/
void
TALER_EXCHANGE_add_aml_decision_cancel (
struct TALER_EXCHANGE_AddAmlDecision *rh);
/**
* Function called with information about the change to
* an AML officer status.
*
* @param cls closure
* @param hr HTTP response data
*/
typedef void
(*TALER_EXCHANGE_ManagementAddPartnerCallback) (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr);
/**
* @brief Handle for a POST /management/partners/$PARTNER_PUB request.
*/
struct TALER_EXCHANGE_ManagementAddPartner;
/**
* Inform the exchange that the status of a partnering
* exchange was defined.
*
* @param ctx the context
* @param url HTTP base URL for the exchange
* @param partner_pub the offline signing key of the partner
* @param start_date validity period start
* @param end_date validity period end
* @param wad_frequency how often will we do wad transfers to this partner
* @param wad_fee what is the wad fee to this partner
* @param partner_base_url what is the base URL of the @a partner_pub exchange
* @param master_sig the signature the signature
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
* @return the request handle; NULL upon error
*/
struct TALER_EXCHANGE_ManagementAddPartner *
TALER_EXCHANGE_management_add_partner (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_MasterPublicKeyP *partner_pub,
struct GNUNET_TIME_Timestamp start_date,
struct GNUNET_TIME_Timestamp end_date,
struct GNUNET_TIME_Relative wad_frequency,
const struct TALER_Amount *wad_fee,
const char *partner_base_url,
const struct TALER_MasterSignatureP *master_sig,
TALER_EXCHANGE_ManagementAddPartnerCallback cb,
void *cb_cls);
/**
* Cancel #TALER_EXCHANGE_management_update_aml_officer() operation.
*
* @param rh handle of the operation to cancel
*/
void
TALER_EXCHANGE_management_add_partner_cancel (
struct TALER_EXCHANGE_ManagementAddPartner *rh);
/** /**
* Function called with information about the auditor setup operation result. * Function called with information about the auditor setup operation result.
* *

View File

@ -0,0 +1,240 @@
/*
This file is part of TALER
Copyright (C) 2023 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/>
*/
/**
* @file lib/exchange_api_add_aml_decision.c
* @brief functions to add an AML decision by an AML officer
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_exchange_service.h"
#include "exchange_api_curl_defaults.h"
#include "taler_signatures.h"
#include "taler_curl_lib.h"
#include "taler_json_lib.h"
struct TALER_EXCHANGE_AddAmlDecision
{
/**
* The url for this request.
*/
char *url;
/**
* Minor context that holds body and headers.
*/
struct TALER_CURL_PostContext post_ctx;
/**
* Handle for the request.
*/
struct GNUNET_CURL_Job *job;
/**
* Function to call with the result.
*/
TALER_EXCHANGE_AddAmlDecisionCallback cb;
/**
* Closure for @a cb.
*/
void *cb_cls;
/**
* Reference to the execution context.
*/
struct GNUNET_CURL_Context *ctx;
};
/**
* Function called when we're done processing the
* HTTP POST /aml-decision/$OFFICER_PUB request.
*
* @param cls the `struct TALER_EXCHANGE_AddAmlDecision *`
* @param response_code HTTP response code, 0 on error
* @param response response body, NULL if not in JSON
*/
static void
handle_add_aml_decision_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_AddAmlDecision *wh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
};
wh->job = NULL;
switch (response_code)
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange AML decision\n",
(unsigned int) response_code,
(int) hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr);
wh->cb = NULL;
}
TALER_EXCHANGE_add_aml_decision_cancel (wh);
}
struct TALER_EXCHANGE_AddAmlDecision *
TALER_EXCHANGE_add_aml_decision (
struct GNUNET_CURL_Context *ctx,
const char *url,
const char *justification,
struct GNUNET_TIME_Timestamp decision_time,
const struct TALER_Amount *new_threshold,
const struct TALER_PaytoHashP *h_payto,
enum TALER_AmlDecisionState new_state,
const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
TALER_EXCHANGE_AddAmlDecisionCallback cb,
void *cb_cls)
{
struct TALER_AmlOfficerPrivateKeyP officer_pub;
struct TALER_AmlOfficerSignatureP officer_sig;
struct TALER_EXCHANGE_AddAmlDecision *wh;
CURL *eh;
json_t *body;
GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
&officer_pub.eddsa_pub);
TALER_officer_aml_decision_sign (justification,
decision_time,
h_payto,
new_state,
officer_priv,
&officer_sig);
wh = GNUNET_new (struct TALER_EXCHANGE_AddAmlDecision);
wh->cb = cb;
wh->cb_cls = cb_cls;
wh->ctx = ctx;
{
char *path;
char opus[sizeof (officer_pub) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
&officer_pub,
sizeof (officer_pub),
opus,
sizeof (opus));
*end = '\0';
GNUNET_asprintf (&path,
"aml-decision/%s",
opus);
wh->url = TALER_url_join (url,
path,
NULL);
GNUNET_free (path);
}
if (NULL == wh->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not construct request URL.\n");
GNUNET_free (wh);
return NULL;
}
body = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("justification",
justification),
GNUNET_JSON_pack_data_auto ("officer_sig",
&officer_sig),
GNUNET_JSON_pack_data_auto ("h_payto",
h_payto),
GNUNET_JSON_pack_data_uint64 ("state",
(uint32_t) new_state),
TALER_JSON_pack_amount ("new_threshold",
new_threshold),
GNUNET_JSON_pack_timestamp ("decision_time",
decision_time));
eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
TALER_curl_easy_post (&wh->post_ctx,
eh,
body)) )
{
GNUNET_break (0);
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (body);
GNUNET_free (wh->url);
return NULL;
}
json_decref (body);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting URL '%s'\n",
wh->url);
wh->job = GNUNET_CURL_job_add2 (ctx,
eh,
wh->post_ctx.headers,
&handle_add_aml_decision_finished,
wh);
if (NULL == wh->job)
{
TALER_EXCHANGE_add_aml_decision_cancel (wh);
return NULL;
}
return wh;
}
void
TALER_EXCHANGE_add_aml_decision_cancel (
struct TALER_EXCHANGE_AddAmlDecision *wh)
{
if (NULL != wh->job)
{
GNUNET_CURL_job_cancel (wh->job);
wh->job = NULL;
}
TALER_curl_easy_post_finished (&wh->post_ctx);
GNUNET_free (wh->url);
GNUNET_free (wh);
}

View File

@ -0,0 +1,232 @@
/*
This file is part of TALER
Copyright (C) 2023 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/>
*/
/**
* @file lib/exchange_api_management_add_partner.c
* @brief functions to add an partner by an AML officer
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_exchange_service.h"
#include "exchange_api_curl_defaults.h"
#include "taler_signatures.h"
#include "taler_curl_lib.h"
#include "taler_json_lib.h"
struct TALER_EXCHANGE_ManagementAddPartner
{
/**
* The url for this request.
*/
char *url;
/**
* Minor context that holds body and headers.
*/
struct TALER_CURL_PostContext post_ctx;
/**
* Handle for the request.
*/
struct GNUNET_CURL_Job *job;
/**
* Function to call with the result.
*/
TALER_EXCHANGE_ManagementAddPartnerCallback cb;
/**
* Closure for @a cb.
*/
void *cb_cls;
/**
* Reference to the execution context.
*/
struct GNUNET_CURL_Context *ctx;
};
/**
* Function called when we're done processing the
* HTTP POST /aml-decision/$OFFICER_PUB request.
*
* @param cls the `struct TALER_EXCHANGE_ManagementAddPartner *`
* @param response_code HTTP response code, 0 on error
* @param response response body, NULL if not in JSON
*/
static void
handle_add_partner_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_ManagementAddPartner *wh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
};
wh->job = NULL;
switch (response_code)
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for adding exchange partner\n",
(unsigned int) response_code,
(int) hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr);
wh->cb = NULL;
}
TALER_EXCHANGE_management_add_partner_cancel (wh);
}
struct TALER_EXCHANGE_ManagementAddPartner *
TALER_EXCHANGE_management_add_partner (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_MasterPublicKeyP *partner_pub,
struct GNUNET_TIME_Timestamp start_date,
struct GNUNET_TIME_Timestamp end_date,
struct GNUNET_TIME_Relative wad_frequency,
const struct TALER_Amount *wad_fee,
const char *partner_base_url,
const struct TALER_MasterSignatureP *master_sig,
TALER_EXCHANGE_ManagementAddPartnerCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_ManagementAddPartner *wh;
CURL *eh;
json_t *body;
wh = GNUNET_new (struct TALER_EXCHANGE_ManagementAddPartner);
wh->cb = cb;
wh->cb_cls = cb_cls;
wh->ctx = ctx;
{
char *path;
char opus[sizeof (*partner_pub) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
partner_pub,
sizeof (*partner_pub),
opus,
sizeof (opus));
*end = '\0';
GNUNET_asprintf (&path,
"management/partners/%s",
opus);
wh->url = TALER_url_join (url,
path,
NULL);
GNUNET_free (path);
}
if (NULL == wh->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not construct request URL.\n");
GNUNET_free (wh);
return NULL;
}
body = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("partner_base_url",
partner_base_url),
GNUNET_JSON_pack_timestamp ("start_date",
start_date),
GNUNET_JSON_pack_timestamp ("end_date",
end_date),
GNUNET_JSON_pack_time_rel ("wad_frequency",
wad_frequency),
GNUNET_JSON_pack_data_auto ("master_sig",
&master_sig),
TALER_JSON_pack_amount ("wad_fee",
wad_fee)
);
eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
TALER_curl_easy_post (&wh->post_ctx,
eh,
body)) )
{
GNUNET_break (0);
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (body);
GNUNET_free (wh->url);
return NULL;
}
json_decref (body);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting URL '%s'\n",
wh->url);
wh->job = GNUNET_CURL_job_add2 (ctx,
eh,
wh->post_ctx.headers,
&handle_add_partner_finished,
wh);
if (NULL == wh->job)
{
TALER_EXCHANGE_management_add_partner_cancel (wh);
return NULL;
}
return wh;
}
void
TALER_EXCHANGE_management_add_partner_cancel (
struct TALER_EXCHANGE_ManagementAddPartner *wh)
{
if (NULL != wh->job)
{
GNUNET_CURL_job_cancel (wh->job);
wh->job = NULL;
}
TALER_curl_easy_post_finished (&wh->post_ctx);
GNUNET_free (wh->url);
GNUNET_free (wh);
}

View File

@ -0,0 +1,228 @@
/*
This file is part of TALER
Copyright (C) 2023 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/>
*/
/**
* @file lib/exchange_api_management_update_aml_officer.c
* @brief functions to update AML officer status
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_exchange_service.h"
#include "exchange_api_curl_defaults.h"
#include "taler_signatures.h"
#include "taler_curl_lib.h"
#include "taler_json_lib.h"
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer
{
/**
* The url for this request.
*/
char *url;
/**
* Minor context that holds body and headers.
*/
struct TALER_CURL_PostContext post_ctx;
/**
* Handle for the request.
*/
struct GNUNET_CURL_Job *job;
/**
* Function to call with the result.
*/
TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback cb;
/**
* Closure for @a cb.
*/
void *cb_cls;
/**
* Reference to the execution context.
*/
struct GNUNET_CURL_Context *ctx;
};
/**
* Function called when we're done processing the
* HTTP /management/wire request.
*
* @param cls the `struct TALER_EXCHANGE_ManagementAuditorEnableHandle *`
* @param response_code HTTP response code, 0 on error
* @param response response body, NULL if not in JSON
*/
static void
handle_update_aml_officer_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *wh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
};
wh->job = NULL;
switch (response_code)
{
case 0:
/* no reply */
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange management update AML officer\n",
(unsigned int) response_code,
(int) hr.ec);
break;
}
if (NULL != wh->cb)
{
wh->cb (wh->cb_cls,
&hr);
wh->cb = NULL;
}
TALER_EXCHANGE_management_update_aml_officer_cancel (wh);
}
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *
TALER_EXCHANGE_management_update_aml_officer (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_AmlOfficerPublicKeyP *officer_pub,
const char *officer_name,
struct GNUNET_TIME_Timestamp change_date,
bool is_active,
bool read_only,
const struct TALER_MasterSignatureP *master_sig,
TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *wh;
CURL *eh;
json_t *body;
wh = GNUNET_new (struct TALER_EXCHANGE_ManagementUpdateAmlOfficer);
wh->cb = cb;
wh->cb_cls = cb_cls;
wh->ctx = ctx;
{
char *path;
char opus[sizeof (*officer_pub) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
officer_pub,
sizeof (*officer_pub),
opus,
sizeof (opus));
*end = '\0';
GNUNET_asprintf (&path,
"management/aml-officers/%s",
opus);
wh->url = TALER_url_join (url,
path,
NULL);
GNUNET_free (path);
}
if (NULL == wh->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not construct request URL.\n");
GNUNET_free (wh);
return NULL;
}
body = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("officer_name",
officer_name),
GNUNET_JSON_pack_data_auto ("master_sig",
master_sig),
GNUNET_JSON_pack_data_bool ("is_active",
is_active),
GNUNET_JSON_pack_data_bool ("read_only",
read_only),
GNUNET_JSON_pack_timestamp ("change_date",
change_date));
eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
TALER_curl_easy_post (&wh->post_ctx,
eh,
body)) )
{
GNUNET_break (0);
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (body);
GNUNET_free (wh->url);
return NULL;
}
json_decref (body);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting URL '%s'\n",
wh->url);
wh->job = GNUNET_CURL_job_add2 (ctx,
eh,
wh->post_ctx.headers,
&handle_update_aml_officer_finished,
wh);
if (NULL == wh->job)
{
TALER_EXCHANGE_management_update_aml_officer_cancel (wh);
return NULL;
}
return wh;
}
void
TALER_EXCHANGE_management_update_aml_officer_cancel (
struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *wh)
{
if (NULL != wh->job)
{
GNUNET_CURL_job_cancel (wh->job);
wh->job = NULL;
}
TALER_curl_easy_post_finished (&wh->post_ctx);
GNUNET_free (wh->url);
GNUNET_free (wh);
}