exchange_api_post-management-aml-officers.c (7698B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2023-2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see 15 <http://www.gnu.org/licenses/> 16 */ 17 /** 18 * @file lib/exchange_api_post-management-aml-officers.c 19 * @brief functions to update AML officer status via POST /management/aml-officers 20 * @author Christian Grothoff 21 */ 22 #include "taler/taler_json_lib.h" 23 #include <gnunet/gnunet_curl_lib.h> 24 #include <microhttpd.h> 25 #include "taler/exchange/post-management-aml-officers.h" 26 #include "exchange_api_curl_defaults.h" 27 #include "taler/taler_curl_lib.h" 28 29 30 /** 31 * Handle for a POST /management/aml-officers request. 32 */ 33 struct TALER_EXCHANGE_PostManagementAmlOfficersHandle 34 { 35 36 /** 37 * The base URL for this request. 38 */ 39 char *base_url; 40 41 /** 42 * The full URL for this request, set during _start. 43 */ 44 char *url; 45 46 /** 47 * Minor context that holds body and headers. 48 */ 49 struct TALER_CURL_PostContext post_ctx; 50 51 /** 52 * Handle for the request. 53 */ 54 struct GNUNET_CURL_Job *job; 55 56 /** 57 * Function to call with the result. 58 */ 59 TALER_EXCHANGE_PostManagementAmlOfficersCallback cb; 60 61 /** 62 * Closure for @a cb. 63 */ 64 TALER_EXCHANGE_POST_MANAGEMENT_AML_OFFICERS_RESULT_CLOSURE *cb_cls; 65 66 /** 67 * Reference to the execution context. 68 */ 69 struct GNUNET_CURL_Context *ctx; 70 71 /** 72 * Public key of the officer. 73 */ 74 struct TALER_AmlOfficerPublicKeyP officer_pub; 75 76 /** 77 * Name of the officer. 78 */ 79 char *officer_name; 80 81 /** 82 * When to affect the status change. 83 */ 84 struct GNUNET_TIME_Timestamp change_date; 85 86 /** 87 * Is the officer active? 88 */ 89 bool is_active; 90 91 /** 92 * Is the officer read-only? 93 */ 94 bool read_only; 95 96 /** 97 * Master signature affirming the change. 98 */ 99 struct TALER_MasterSignatureP master_sig; 100 101 }; 102 103 104 /** 105 * Function called when we're done processing the 106 * HTTP POST /management/aml-officers request. 107 * 108 * @param cls the `struct TALER_EXCHANGE_PostManagementAmlOfficersHandle` 109 * @param response_code HTTP response code, 0 on error 110 * @param response response body, NULL if not in JSON 111 */ 112 static void 113 handle_post_aml_officer_finished (void *cls, 114 long response_code, 115 const void *response) 116 { 117 struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh = cls; 118 const json_t *json = response; 119 struct TALER_EXCHANGE_PostManagementAmlOfficersResponse res = { 120 .hr.http_status = (unsigned int) response_code, 121 .hr.reply = json 122 }; 123 124 pmaoh->job = NULL; 125 switch (response_code) 126 { 127 case 0: 128 /* no reply */ 129 res.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 130 res.hr.hint = "server offline?"; 131 break; 132 case MHD_HTTP_NO_CONTENT: 133 break; 134 case MHD_HTTP_FORBIDDEN: 135 res.hr.ec = TALER_JSON_get_error_code (json); 136 res.hr.hint = TALER_JSON_get_error_hint (json); 137 break; 138 case MHD_HTTP_CONFLICT: 139 res.hr.ec = TALER_JSON_get_error_code (json); 140 res.hr.hint = TALER_JSON_get_error_hint (json); 141 break; 142 default: 143 /* unexpected response code */ 144 GNUNET_break_op (0); 145 res.hr.ec = TALER_JSON_get_error_code (json); 146 res.hr.hint = TALER_JSON_get_error_hint (json); 147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 148 "Unexpected response code %u/%d for exchange POST management AML officer\n", 149 (unsigned int) response_code, 150 (int) res.hr.ec); 151 break; 152 } 153 if (NULL != pmaoh->cb) 154 { 155 pmaoh->cb (pmaoh->cb_cls, 156 &res); 157 pmaoh->cb = NULL; 158 } 159 TALER_EXCHANGE_post_management_aml_officers_cancel (pmaoh); 160 } 161 162 163 struct TALER_EXCHANGE_PostManagementAmlOfficersHandle * 164 TALER_EXCHANGE_post_management_aml_officers_create ( 165 struct GNUNET_CURL_Context *ctx, 166 const char *url, 167 const struct TALER_AmlOfficerPublicKeyP *officer_pub, 168 const char *officer_name, 169 struct GNUNET_TIME_Timestamp change_date, 170 bool is_active, 171 bool read_only, 172 const struct TALER_MasterSignatureP *master_sig) 173 { 174 struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh; 175 176 pmaoh = GNUNET_new (struct TALER_EXCHANGE_PostManagementAmlOfficersHandle); 177 pmaoh->ctx = ctx; 178 pmaoh->base_url = GNUNET_strdup (url); 179 pmaoh->officer_pub = *officer_pub; 180 pmaoh->officer_name = GNUNET_strdup (officer_name); 181 pmaoh->change_date = change_date; 182 pmaoh->is_active = is_active; 183 pmaoh->read_only = read_only; 184 pmaoh->master_sig = *master_sig; 185 return pmaoh; 186 } 187 188 189 enum TALER_ErrorCode 190 TALER_EXCHANGE_post_management_aml_officers_start ( 191 struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh, 192 TALER_EXCHANGE_PostManagementAmlOfficersCallback cb, 193 TALER_EXCHANGE_POST_MANAGEMENT_AML_OFFICERS_RESULT_CLOSURE *cb_cls) 194 { 195 CURL *eh; 196 json_t *body; 197 198 pmaoh->cb = cb; 199 pmaoh->cb_cls = cb_cls; 200 pmaoh->url = TALER_url_join (pmaoh->base_url, 201 "management/aml-officers", 202 NULL); 203 if (NULL == pmaoh->url) 204 { 205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 206 "Could not construct request URL.\n"); 207 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 208 } 209 body = GNUNET_JSON_PACK ( 210 GNUNET_JSON_pack_string ("officer_name", 211 pmaoh->officer_name), 212 GNUNET_JSON_pack_data_auto ("officer_pub", 213 &pmaoh->officer_pub), 214 GNUNET_JSON_pack_data_auto ("master_sig", 215 &pmaoh->master_sig), 216 GNUNET_JSON_pack_bool ("is_active", 217 pmaoh->is_active), 218 GNUNET_JSON_pack_bool ("read_only", 219 pmaoh->read_only), 220 GNUNET_JSON_pack_timestamp ("change_date", 221 pmaoh->change_date)); 222 eh = TALER_EXCHANGE_curl_easy_get_ (pmaoh->url); 223 if ( (NULL == eh) || 224 (GNUNET_OK != 225 TALER_curl_easy_post (&pmaoh->post_ctx, 226 eh, 227 body)) ) 228 { 229 GNUNET_break (0); 230 if (NULL != eh) 231 curl_easy_cleanup (eh); 232 json_decref (body); 233 GNUNET_free (pmaoh->url); 234 pmaoh->url = NULL; 235 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 236 } 237 json_decref (body); 238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 239 "Requesting URL '%s'\n", 240 pmaoh->url); 241 pmaoh->job = GNUNET_CURL_job_add2 (pmaoh->ctx, 242 eh, 243 pmaoh->post_ctx.headers, 244 &handle_post_aml_officer_finished, 245 pmaoh); 246 if (NULL == pmaoh->job) 247 { 248 TALER_curl_easy_post_finished (&pmaoh->post_ctx); 249 GNUNET_free (pmaoh->url); 250 pmaoh->url = NULL; 251 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 252 } 253 return TALER_EC_NONE; 254 } 255 256 257 void 258 TALER_EXCHANGE_post_management_aml_officers_cancel ( 259 struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh) 260 { 261 if (NULL != pmaoh->job) 262 { 263 GNUNET_CURL_job_cancel (pmaoh->job); 264 pmaoh->job = NULL; 265 } 266 TALER_curl_easy_post_finished (&pmaoh->post_ctx); 267 GNUNET_free (pmaoh->url); 268 GNUNET_free (pmaoh->officer_name); 269 GNUNET_free (pmaoh->base_url); 270 GNUNET_free (pmaoh); 271 } 272 273 274 /* end of exchange_api_post-management-aml-officers.c */