donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

donau_api_donation_statement_get.c (7347B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it
      6   under the terms of the GNU General Public License as published
      7   by the Free Software Foundation; either version 3, or (at your
      8   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 lib/donau_api_donation_statement_get.c
     22  * @brief Implementation of the "handle" component of the donau's HTTP API
     23  * @author Lukas Matyja
     24  */
     25 #include <gnunet/gnunet_curl_lib.h>
     26 #include <taler/taler_json_lib.h>
     27 #include "donau_service.h"
     28 #include "donau_api_curl_defaults.h"
     29 #include "donau_json_lib.h"
     30 
     31 
     32 /**
     33  * Handle for a GET /donation-statement/$YEAR/$HASH_DONOR_ID request.
     34  */
     35 struct DONAU_DonationStatementGetHandle
     36 {
     37   /**
     38    * The url for the /donation-statement/$YEAR/$HASH_DONOR_ID request.
     39    */
     40   char *url;
     41 
     42   /**
     43    * Entry for this request with the `struct GNUNET_CURL_Context`.
     44    */
     45   struct GNUNET_CURL_Job *job;
     46 
     47   /**
     48    * Function to call with the result.
     49    */
     50   DONAU_GetDonationStatmentResponseCallback cb;
     51 
     52   /**
     53    * Salted and hashed donor id
     54    */
     55   struct DONAU_HashDonorTaxId h_donor_tax_id;
     56 
     57   /**
     58    * year
     59    */
     60   uint64_t year;
     61 
     62   /**
     63    * Closure to pass to @e cb.
     64    */
     65   void *cb_cls;
     66 
     67 };
     68 
     69 
     70 /**
     71  * Callback used when downloading the reply to a /donation-statement/$YEAR/$HASH_DONOR_ID request
     72  * is complete.
     73  *
     74  * @param cls the `struct KeysRequest`
     75  * @param response_code HTTP response code, 0 on error
     76  * @param resp_obj parsed JSON result, NULL on error
     77  */
     78 static void
     79 handle_donation_statement_get_finished (void *cls,
     80                                         long response_code,
     81                                         const void *resp_obj)
     82 {
     83   struct DONAU_DonationStatementGetHandle *dsgh = cls;
     84   const json_t *j = resp_obj;
     85   struct DONAU_DonationStatementResponse dsresp = {
     86     .hr.reply = j,
     87     .hr.http_status = (unsigned int) response_code
     88   };
     89 
     90   dsgh->job = NULL;
     91   switch (response_code)
     92   {
     93   case 0:
     94     dsresp.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     95     break;
     96   case MHD_HTTP_OK:
     97     {
     98       struct GNUNET_JSON_Specification spec[] = {
     99         GNUNET_JSON_spec_fixed_auto (
    100           "donation_statement_sig",
    101           &dsresp.details.ok.donation_statement_sig),
    102         TALER_JSON_spec_amount_any ("total",
    103                                     &dsresp.details.ok.total_amount),
    104         GNUNET_JSON_spec_fixed_auto ("donau_pub",
    105                                      &dsresp.details.ok.donau_pub),
    106         GNUNET_JSON_spec_end ()
    107       };
    108 
    109       if (GNUNET_OK !=
    110           GNUNET_JSON_parse (j,
    111                              spec,
    112                              NULL,
    113                              NULL))
    114       {
    115         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    116                     "Could not parse response from donation-statement GET\n");
    117         GNUNET_break_op (0);
    118         dsresp.hr.http_status = 0;
    119         dsresp.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
    120       }
    121       dsgh->cb (dsgh->cb_cls,
    122                 &dsresp);
    123       dsgh->cb = NULL;
    124       break;
    125     }
    126   case MHD_HTTP_BAD_REQUEST:
    127     /* This should never happen, either us or the donau is buggy
    128        (or API version conflict); just pass JSON reply to the application */
    129     dsresp.hr.ec = TALER_JSON_get_error_code (j);
    130     dsresp.hr.hint = TALER_JSON_get_error_hint (j);
    131     break;
    132   case MHD_HTTP_NOT_FOUND:
    133     /* Nothing really to verify, this should never
    134        happen, we should pass the JSON reply to the application */
    135     dsresp.hr.ec = TALER_JSON_get_error_code (j);
    136     dsresp.hr.hint = TALER_JSON_get_error_hint (j);
    137     break;
    138   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    139     /* Server had an internal issue; we should retry, but this API
    140        leaves this to the application */
    141     dsresp.hr.ec = TALER_JSON_get_error_code (j);
    142     dsresp.hr.hint = TALER_JSON_get_error_hint (j);
    143     break;
    144   default:
    145     /* unexpected response code */
    146     GNUNET_break_op (0);
    147     dsresp.hr.ec = TALER_JSON_get_error_code (j);
    148     dsresp.hr.hint = TALER_JSON_get_error_hint (j);
    149     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    150                 "Unexpected response code %u/%d for GET %s\n",
    151                 (unsigned int) response_code,
    152                 (int) dsresp.hr.ec,
    153                 dsgh->url);
    154     break;
    155   }
    156   if (NULL != dsgh->cb)
    157   {
    158     dsgh->cb (dsgh->cb_cls,
    159               &dsresp);
    160     dsgh->cb = NULL;
    161   }
    162   DONAU_donation_statement_get_cancel (dsgh);
    163 }
    164 
    165 
    166 /**
    167  * Prepares the request URL for the age-withdraw request
    168  *
    169  * @param awbh The handler
    170  * @param donau_url The base-URL to the donau
    171  */
    172 static
    173 enum GNUNET_GenericReturnValue
    174 prepare_url (
    175   struct DONAU_DonationStatementGetHandle *dsgh,
    176   const char *donau_url)
    177 {
    178   char arg_str[sizeof (struct DONAU_HashDonorTaxId) * 2 + 32];
    179   char donor_id_hash_str[sizeof (struct DONAU_HashDonorTaxId) * 2];
    180   char *end;
    181 
    182   end = GNUNET_STRINGS_data_to_string (
    183     &dsgh->h_donor_tax_id,
    184     sizeof (struct DONAU_HashDonorTaxId),
    185     donor_id_hash_str,
    186     sizeof (donor_id_hash_str));
    187   *end = '\0';
    188   GNUNET_snprintf (arg_str,
    189                    sizeof (arg_str),
    190                    "donation-statement/%lu/%s",
    191                    dsgh->year,
    192                    donor_id_hash_str);
    193 
    194   dsgh->url = TALER_url_join (donau_url,
    195                               arg_str,
    196                               NULL);
    197   if (NULL == dsgh->url)
    198   {
    199     GNUNET_break (0);
    200     DONAU_donation_statement_get_cancel (dsgh);
    201     return GNUNET_SYSERR;
    202   }
    203 
    204   return GNUNET_OK;
    205 }
    206 
    207 
    208 struct DONAU_DonationStatementGetHandle *
    209 DONAU_donation_statement_get (
    210   struct GNUNET_CURL_Context *ctx,
    211   const char *url,
    212   const uint64_t year,
    213   const struct DONAU_HashDonorTaxId *h_donor_tax_id,
    214   DONAU_GetDonationStatmentResponseCallback cb,
    215   void *cb_cls)
    216 {
    217   struct DONAU_DonationStatementGetHandle *dsgh;
    218   CURL *eh;
    219 
    220   TALER_LOG_DEBUG ("Connecting to the donau (%s)\n",
    221                    url);
    222 
    223   dsgh = GNUNET_new (struct DONAU_DonationStatementGetHandle);
    224   dsgh->cb = cb;
    225   dsgh->cb_cls = cb_cls;
    226   dsgh->year = year;
    227   dsgh->h_donor_tax_id = *h_donor_tax_id;
    228   if (GNUNET_OK != prepare_url (dsgh,
    229                                 url))
    230     return NULL;
    231   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    232               "Requesting a charity with URL `%s'.\n",
    233               dsgh->url);
    234   eh = DONAU_curl_easy_get_ (dsgh->url);
    235   if (NULL == eh)
    236   {
    237     GNUNET_break (0);
    238     GNUNET_free (dsgh->url);
    239     GNUNET_free (dsgh);
    240     return NULL;
    241   }
    242   dsgh->job = GNUNET_CURL_job_add_with_ct_json (ctx,
    243                                                 eh,
    244                                                 &
    245                                                 handle_donation_statement_get_finished,
    246                                                 dsgh);
    247   return dsgh;
    248 }
    249 
    250 
    251 void
    252 DONAU_donation_statement_get_cancel (
    253   struct DONAU_DonationStatementGetHandle *dsgh)
    254 {
    255   if (NULL != dsgh->job)
    256   {
    257     GNUNET_CURL_job_cancel (dsgh->job);
    258     dsgh->job = NULL;
    259   }
    260   GNUNET_free (dsgh->url);
    261   GNUNET_free (dsgh);
    262 }