merchant_api_get_tokenfamily.c (6927B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2023-2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Lesser General Public License as published by the Free Software 7 Foundation; either version 2.1, 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 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public License along with 14 TALER; see the file COPYING.LGPL. If not, see 15 <http://www.gnu.org/licenses/> 16 */ 17 /** 18 * @file merchant_api_get_tokenfamily.c 19 * @brief Implementation of the GET /tokenfamily/$ID request of the merchant's HTTP API 20 * @author Christian Blättler 21 */ 22 #include "platform.h" 23 #include <curl/curl.h> 24 #include <gnunet/gnunet_common.h> 25 #include <gnunet/gnunet_json_lib.h> 26 #include <jansson.h> 27 #include <microhttpd.h> /* just for HTTP status codes */ 28 #include <gnunet/gnunet_util_lib.h> 29 #include <gnunet/gnunet_curl_lib.h> 30 #include "taler_merchant_service.h" 31 #include "merchant_api_curl_defaults.h" 32 #include <taler/taler_json_lib.h> 33 #include <taler/taler_signatures.h> 34 35 36 /** 37 * Handle for a GET /tokenfamilies/$SLUG operation. 38 */ 39 struct TALER_MERCHANT_TokenFamilyGetHandle 40 { 41 /** 42 * The url for this request. 43 */ 44 char *url; 45 46 /** 47 * Handle for the request. 48 */ 49 struct GNUNET_CURL_Job *job; 50 51 /** 52 * Function to call with the result. 53 */ 54 TALER_MERCHANT_TokenFamilyGetCallback cb; 55 56 /** 57 * Closure for @a cb. 58 */ 59 void *cb_cls; 60 61 /** 62 * Reference to the execution context. 63 */ 64 struct GNUNET_CURL_Context *ctx; 65 66 }; 67 68 69 /** 70 * Function called when we're done processing the 71 * HTTP GET /tokenfamilies/$ID request. 72 * 73 * @param cls the `struct TALER_MERCHANT_TokenFamilyGetHandle` 74 * @param response_code HTTP response code, 0 on error 75 * @param response response body, NULL if not in JSON 76 */ 77 static void 78 handle_get_token_family_finished (void *cls, 79 long response_code, 80 const void *response) 81 { 82 struct TALER_MERCHANT_TokenFamilyGetHandle *handle = cls; 83 const json_t *json = response; 84 struct TALER_MERCHANT_TokenFamilyGetResponse res = { 85 .hr.http_status = (unsigned int) response_code, 86 .hr.reply = json 87 }; 88 89 handle->job = NULL; 90 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 91 "Got /tokenfamilies/$ID response with status code %u\n", 92 (unsigned int) response_code); 93 switch (response_code) 94 { 95 case MHD_HTTP_OK: 96 { 97 // Parse token family response 98 struct GNUNET_JSON_Specification spec[] = { 99 GNUNET_JSON_spec_string ("slug", 100 &res.details.ok.slug), 101 GNUNET_JSON_spec_string ("name", 102 &res.details.ok.name), 103 GNUNET_JSON_spec_string ("description", 104 &res.details.ok.description), 105 GNUNET_JSON_spec_object_const ("description_i18n", 106 &res.details.ok.description_i18n), 107 GNUNET_JSON_spec_object_const ("extra_data", 108 &res.details.ok.extra_data), 109 GNUNET_JSON_spec_timestamp ("valid_after", 110 &res.details.ok.valid_after), 111 GNUNET_JSON_spec_timestamp ("valid_before", 112 &res.details.ok.valid_before), 113 GNUNET_JSON_spec_relative_time ("duation", 114 &res.details.ok.duration), 115 GNUNET_JSON_spec_relative_time ("validity_granularity", 116 &res.details.ok.validity_granularity), 117 GNUNET_JSON_spec_relative_time ("start_offset", 118 &res.details.ok.start_offset), 119 GNUNET_JSON_spec_string ("kind", 120 &res.details.ok.kind), 121 GNUNET_JSON_spec_uint64 ("issued", 122 &res.details.ok.issued), 123 GNUNET_JSON_spec_uint64 ("used", 124 &res.details.ok.used), 125 GNUNET_JSON_spec_end () 126 }; 127 128 if (GNUNET_OK == 129 GNUNET_JSON_parse (json, 130 spec, 131 NULL, NULL)) 132 { 133 handle->cb (handle->cb_cls, 134 &res); 135 GNUNET_JSON_parse_free (spec); 136 TALER_MERCHANT_token_family_get_cancel (handle); 137 return; 138 } 139 res.hr.http_status = 0; 140 res.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 141 break; 142 } 143 case MHD_HTTP_UNAUTHORIZED: 144 res.hr.ec = TALER_JSON_get_error_code (json); 145 res.hr.hint = TALER_JSON_get_error_hint (json); 146 /* Nothing really to verify, merchant says we need to authenticate. */ 147 break; 148 case MHD_HTTP_NOT_FOUND: 149 res.hr.ec = TALER_JSON_get_error_code (json); 150 res.hr.hint = TALER_JSON_get_error_hint (json); 151 break; 152 default: 153 /* unexpected response code */ 154 res.hr.ec = TALER_JSON_get_error_code (json); 155 res.hr.hint = TALER_JSON_get_error_hint (json); 156 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 157 "Unexpected response code %u/%d\n", 158 (unsigned int) response_code, 159 (int) res.hr.ec); 160 break; 161 } 162 } 163 164 165 struct TALER_MERCHANT_TokenFamilyGetHandle * 166 TALER_MERCHANT_token_family_get ( 167 struct GNUNET_CURL_Context *ctx, 168 const char *backend_url, 169 const char *token_family_slug, 170 TALER_MERCHANT_TokenFamilyGetCallback cb, 171 void *cb_cls) 172 { 173 struct TALER_MERCHANT_TokenFamilyGetHandle *handle; 174 CURL *eh; 175 176 handle = GNUNET_new (struct TALER_MERCHANT_TokenFamilyGetHandle); 177 handle->ctx = ctx; 178 handle->cb = cb; 179 handle->cb_cls = cb_cls; 180 { 181 char *path; 182 183 GNUNET_asprintf (&path, 184 "private/tokenfamilies/%s", 185 token_family_slug); 186 handle->url = TALER_url_join (backend_url, 187 path, 188 NULL); 189 GNUNET_free (path); 190 } 191 if (NULL == handle->url) 192 { 193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 194 "Could not construct request URL.\n"); 195 GNUNET_free (handle); 196 return NULL; 197 } 198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 199 "Requesting URL '%s'\n", 200 handle->url); 201 eh = TALER_MERCHANT_curl_easy_get_ (handle->url); 202 handle->job = GNUNET_CURL_job_add (ctx, 203 eh, 204 &handle_get_token_family_finished, 205 handle); 206 return handle; 207 } 208 209 210 void 211 TALER_MERCHANT_token_family_get_cancel ( 212 struct TALER_MERCHANT_TokenFamilyGetHandle *handle) 213 { 214 if (NULL != handle->job) 215 GNUNET_CURL_job_cancel (handle->job); 216 GNUNET_free (handle->url); 217 GNUNET_free (handle); 218 }