testing_api_cmd_kyc_proof.c (8424B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2021-2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as 7 published by the Free Software Foundation; either version 3, or 8 (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, see 17 <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file testing/testing_api_cmd_kyc_proof.c 22 * @brief Implement the testing CMDs for the /kyc-proof/ operation. 23 * @author Christian Grothoff 24 */ 25 #include "taler/taler_json_lib.h" 26 #include <gnunet/gnunet_curl_lib.h> 27 28 /** 29 * State for a "track transaction" CMD. 30 */ 31 struct KycProofGetState; 32 33 #define TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE \ 34 struct KycProofGetState 35 #include "taler/exchange/get-kyc-proof-PROVIDER_NAME.h" 36 #include "taler/taler_testing_lib.h" 37 38 /** 39 * State for a "track transaction" CMD. 40 */ 41 struct KycProofGetState 42 { 43 44 /** 45 * Command to get the OAuth2 state from: a KYC start command 46 * offering the KYC URL, or any command offering a payment target, 47 * whose bare hash is then used as the state. 48 */ 49 const char *state_reference; 50 51 /** 52 * Code to pass. 53 */ 54 const char *code; 55 56 /** 57 * Logic section name to pass to `/kyc-proof/` handler. 58 */ 59 const char *logic; 60 61 /** 62 * Expected HTTP response code. 63 */ 64 unsigned int expected_response_code; 65 66 /** 67 * Set to the KYC REDIRECT *if* the exchange replied with 68 * success (#MHD_HTTP_OK). 69 */ 70 char *redirect_url; 71 72 /** 73 * Additional URL arguments (e.g. "&code=..."), kept alive 74 * for the lifetime of the request. 75 */ 76 char *uargs; 77 78 /** 79 * Handle to the "track transaction" pending operation. 80 */ 81 struct TALER_EXCHANGE_GetKycProofHandle *kph; 82 83 /** 84 * Interpreter state. 85 */ 86 struct TALER_TESTING_Interpreter *is; 87 }; 88 89 90 /** 91 * Handle response to the command. 92 * 93 * @param kcg our state 94 * @param kpr KYC proof response details 95 */ 96 static void 97 proof_kyc_cb ( 98 struct KycProofGetState *kcg, 99 const struct TALER_EXCHANGE_GetKycProofResponse *kpr) 100 { 101 struct TALER_TESTING_Interpreter *is = kcg->is; 102 103 kcg->kph = NULL; 104 if (kcg->expected_response_code != kpr->hr.http_status) 105 { 106 TALER_TESTING_unexpected_status (is, 107 kpr->hr.http_status, 108 kcg->expected_response_code); 109 return; 110 } 111 switch (kpr->hr.http_status) 112 { 113 case MHD_HTTP_SEE_OTHER: 114 kcg->redirect_url = GNUNET_strdup (kpr->details.see_other.redirect_url); 115 break; 116 case MHD_HTTP_FORBIDDEN: 117 break; 118 case MHD_HTTP_BAD_GATEWAY: 119 break; 120 default: 121 GNUNET_break (0); 122 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 123 "Unexpected response code %u to /kyc-proof\n", 124 kpr->hr.http_status); 125 break; 126 } 127 TALER_TESTING_interpreter_next (kcg->is); 128 } 129 130 131 /** 132 * Extract the OAuth2 state from the authorization URL 133 * the exchange returned to start a KYC process. 134 * 135 * @param kyc_url authorization URL to parse 136 * @return the state, NULL if @a kyc_url has none 137 */ 138 static char * 139 get_state (const char *kyc_url) 140 { 141 const char *q; 142 143 q = strchr (kyc_url, 144 '?'); 145 while (NULL != q) 146 { 147 q++; 148 if (0 == strncmp (q, 149 "state=", 150 strlen ("state="))) 151 { 152 q += strlen ("state="); 153 return GNUNET_strndup (q, 154 strcspn (q, 155 "&#")); 156 } 157 q = strchr (q, 158 '&'); 159 } 160 return NULL; 161 } 162 163 164 /** 165 * Run the command. 166 * 167 * @param cls closure. 168 * @param cmd the command to execute. 169 * @param is the interpreter state. 170 */ 171 static void 172 proof_kyc_run (void *cls, 173 const struct TALER_TESTING_Command *cmd, 174 struct TALER_TESTING_Interpreter *is) 175 { 176 struct KycProofGetState *kps = cls; 177 const struct TALER_TESTING_Command *res_cmd; 178 const char *kyc_url; 179 char *state; 180 const char *exchange_url; 181 182 (void) cmd; 183 kps->is = is; 184 exchange_url = TALER_TESTING_get_exchange_url (is); 185 if (NULL == exchange_url) 186 { 187 GNUNET_break (0); 188 return; 189 } 190 res_cmd = TALER_TESTING_interpreter_lookup_command ( 191 kps->is, 192 kps->state_reference); 193 if (NULL == res_cmd) 194 { 195 GNUNET_break (0); 196 TALER_TESTING_interpreter_fail (kps->is); 197 return; 198 } 199 if (GNUNET_OK == 200 TALER_TESTING_get_trait_kyc_url (res_cmd, 201 &kyc_url)) 202 { 203 /* Use the state the exchange issued, as the provider would. */ 204 state = get_state (kyc_url); 205 if (NULL == state) 206 { 207 GNUNET_break (0); 208 TALER_TESTING_interpreter_fail (kps->is); 209 return; 210 } 211 } 212 else 213 { 214 const struct TALER_NormalizedPaytoHashP *h_payto; 215 216 /* Only know the account, like anyone who did not see the 217 authorization request. */ 218 if (GNUNET_OK != 219 TALER_TESTING_get_trait_h_normalized_payto (res_cmd, 220 &h_payto)) 221 { 222 GNUNET_break (0); 223 TALER_TESTING_interpreter_fail (kps->is); 224 return; 225 } 226 state = GNUNET_STRINGS_data_to_string_alloc (h_payto, 227 sizeof (*h_payto)); 228 } 229 if (NULL != kps->code) 230 GNUNET_asprintf (&kps->uargs, 231 "&code=%s", 232 kps->code); 233 kps->kph = TALER_EXCHANGE_get_kyc_proof_create ( 234 TALER_TESTING_interpreter_get_context (is), 235 exchange_url, 236 state, 237 kps->logic); 238 GNUNET_free (state); 239 GNUNET_assert (NULL != kps->kph); 240 if (NULL != kps->uargs) 241 TALER_EXCHANGE_get_kyc_proof_set_options ( 242 kps->kph, 243 TALER_EXCHANGE_get_kyc_proof_option_args (kps->uargs)); 244 { 245 enum TALER_ErrorCode ec; 246 247 ec = TALER_EXCHANGE_get_kyc_proof_start (kps->kph, 248 &proof_kyc_cb, 249 kps); 250 if (TALER_EC_NONE != ec) 251 { 252 GNUNET_break (0); 253 kps->kph = NULL; 254 TALER_TESTING_interpreter_fail (kps->is); 255 return; 256 } 257 } 258 } 259 260 261 /** 262 * Cleanup the state from a "kyc proof" CMD, and possibly 263 * cancel a operation thereof. 264 * 265 * @param cls closure. 266 * @param cmd the command which is being cleaned up. 267 */ 268 static void 269 proof_kyc_cleanup (void *cls, 270 const struct TALER_TESTING_Command *cmd) 271 { 272 struct KycProofGetState *kps = cls; 273 274 if (NULL != kps->kph) 275 { 276 TALER_TESTING_command_incomplete (kps->is, 277 cmd->label); 278 TALER_EXCHANGE_get_kyc_proof_cancel (kps->kph); 279 kps->kph = NULL; 280 } 281 GNUNET_free (kps->redirect_url); 282 GNUNET_free (kps->uargs); 283 GNUNET_free (kps); 284 } 285 286 287 /** 288 * Offer internal data from a "proof KYC" CMD. 289 * 290 * @param cls closure. 291 * @param[out] ret result (could be anything). 292 * @param trait name of the trait. 293 * @param index index number of the object to offer. 294 * @return #GNUNET_OK on success. 295 */ 296 static enum GNUNET_GenericReturnValue 297 proof_kyc_traits (void *cls, 298 const void **ret, 299 const char *trait, 300 unsigned int index) 301 { 302 struct KycProofGetState *kps = cls; 303 struct TALER_TESTING_Trait traits[] = { 304 TALER_TESTING_make_trait_web_url (kps->redirect_url), 305 TALER_TESTING_trait_end () 306 }; 307 308 return TALER_TESTING_get_trait (traits, 309 ret, 310 trait, 311 index); 312 } 313 314 315 struct TALER_TESTING_Command 316 TALER_TESTING_cmd_proof_kyc_oauth2 ( 317 const char *label, 318 const char *state_reference, 319 const char *logic_section, 320 const char *code, 321 unsigned int expected_response_code) 322 { 323 struct KycProofGetState *kps; 324 325 kps = GNUNET_new (struct KycProofGetState); 326 kps->code = code; 327 kps->logic = logic_section; 328 kps->state_reference = state_reference; 329 kps->expected_response_code = expected_response_code; 330 { 331 struct TALER_TESTING_Command cmd = { 332 .cls = kps, 333 .label = label, 334 .run = &proof_kyc_run, 335 .cleanup = &proof_kyc_cleanup, 336 .traits = &proof_kyc_traits 337 }; 338 339 return cmd; 340 } 341 } 342 343 344 /* end of testing_api_cmd_kyc_proof.c */