exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

fakebank_bank_post_accounts_token.c (6270B)


      1 /*
      2   This file is part of TALER
      3   (C) 2016-2023 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU General Public License
      7   as published by the Free Software Foundation; either version 3,
      8   or (at your option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful,
     11   but 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,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file bank-lib/fakebank_bank_post_accounts_token.c
     21  * @brief implementation of the bank API's POST /accounts/AID/token endpoint
     22  * @author Christian Grothoff <christian@grothoff.org>
     23  */
     24 #include "taler/platform.h"
     25 #include <pthread.h>
     26 #include "taler/taler_fakebank_lib.h"
     27 #include "taler/taler_bank_service.h"
     28 #include "taler/taler_mhd_lib.h"
     29 #include <gnunet/gnunet_mhd_compat.h>
     30 #include <gnunet/gnunet_mhd_lib.h>
     31 #include "fakebank.h"
     32 #include "fakebank_bank_post_accounts_token.h"
     33 #include "fakebank_common_lookup.h"
     34 
     35 
     36 /**
     37  * Execute POST /accounts/$account_name/token request.
     38  *
     39  * @param h our fakebank handle
     40  * @param connection the connection
     41  * @param account_name name of the account
     42  * @param scope_s scope of the token (as a string)
     43  * @param refreshable true if the token can be refreshed
     44  * @param duration how long should the token be valid
     45  * @return MHD result code
     46  */
     47 static MHD_RESULT
     48 do_post_account_token (
     49   struct TALER_FAKEBANK_Handle *h,
     50   struct MHD_Connection *connection,
     51   const char *account_name,
     52   const char *scope_s,
     53   bool refreshable,
     54   struct GNUNET_TIME_Relative duration)
     55 {
     56   struct Account *acc;
     57   char *tok;
     58   struct GNUNET_TIME_Absolute expiration;
     59   MHD_RESULT res;
     60 
     61   expiration = GNUNET_TIME_relative_to_absolute (duration);
     62   GNUNET_assert (0 ==
     63                  pthread_mutex_lock (&h->big_lock));
     64   acc = TALER_FAKEBANK_lookup_account_ (h,
     65                                         account_name,
     66                                         NULL);
     67   if (NULL == acc)
     68   {
     69     GNUNET_assert (0 ==
     70                    pthread_mutex_unlock (&h->big_lock));
     71     return TALER_MHD_reply_with_error (connection,
     72                                        MHD_HTTP_NOT_FOUND,
     73                                        TALER_EC_BANK_UNKNOWN_ACCOUNT,
     74                                        account_name);
     75   }
     76   GNUNET_assert (0 ==
     77                  pthread_mutex_unlock (&h->big_lock));
     78   /* We keep it simple and encode everything explicitly in the token,
     79      no real security here => no need to actually track tokens!
     80      (Note: this also means we cannot implement the token
     81      deletion/revocation or list APIs.) */
     82   GNUNET_asprintf (&tok,
     83                    "%s-%s-%s-%llu",
     84                    account_name,
     85                    scope_s,
     86                    refreshable ? "r" : "n",
     87                    (unsigned long long) expiration.abs_value_us);
     88   res = TALER_MHD_REPLY_JSON_PACK (
     89     connection,
     90     MHD_HTTP_OK,
     91     GNUNET_JSON_pack_string ("access_token",
     92                              tok),
     93     GNUNET_JSON_pack_timestamp ("expiration",
     94                                 GNUNET_TIME_absolute_to_timestamp (expiration)))
     95   ;
     96   GNUNET_free (tok);
     97   return res;
     98 }
     99 
    100 
    101 /**
    102  * Handle POST /accounts/$account_name/token request.
    103  *
    104  * @param h our fakebank handle
    105  * @param connection the connection
    106  * @param account_name name of the account
    107  * @param upload_data request data
    108  * @param upload_data_size size of @a upload_data in bytes
    109  * @param con_cls closure for request
    110  * @return MHD result code
    111  */
    112 MHD_RESULT
    113 TALER_FAKEBANK_bank_post_accounts_token_ (
    114   struct TALER_FAKEBANK_Handle *h,
    115   struct MHD_Connection *connection,
    116   const char *account_name,
    117   const void *upload_data,
    118   size_t *upload_data_size,
    119   void **con_cls)
    120 {
    121   struct ConnectionContext *cc = *con_cls;
    122   enum GNUNET_MHD_PostResult pr;
    123   json_t *json;
    124   MHD_RESULT res;
    125 
    126   if (NULL == cc)
    127   {
    128     cc = GNUNET_new (struct ConnectionContext);
    129     cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup;
    130     *con_cls = cc;
    131   }
    132   pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX,
    133                                connection,
    134                                &cc->ctx,
    135                                upload_data,
    136                                upload_data_size,
    137                                &json);
    138   switch (pr)
    139   {
    140   case GNUNET_MHD_PR_OUT_OF_MEMORY:
    141     GNUNET_break (0);
    142     return MHD_NO;
    143   case GNUNET_MHD_PR_CONTINUE:
    144     return MHD_YES;
    145   case GNUNET_MHD_PR_REQUEST_TOO_LARGE:
    146     GNUNET_break (0);
    147     return MHD_NO;
    148   case GNUNET_MHD_PR_JSON_INVALID:
    149     GNUNET_break (0);
    150     return MHD_NO;
    151   case GNUNET_MHD_PR_SUCCESS:
    152     break;
    153   }
    154 
    155   {
    156     const char *scope_s;
    157     struct GNUNET_TIME_Relative duration
    158       = GNUNET_TIME_UNIT_HOURS; /* default */
    159     bool refreshable = false;
    160     const char *description = NULL;
    161     enum GNUNET_GenericReturnValue ret;
    162     struct GNUNET_JSON_Specification spec[] = {
    163       GNUNET_JSON_spec_string ("scope",
    164                                &scope_s),
    165       GNUNET_JSON_spec_mark_optional (
    166         GNUNET_JSON_spec_relative_time ("duration",
    167                                         &duration),
    168         NULL),
    169       GNUNET_JSON_spec_mark_optional (
    170         GNUNET_JSON_spec_bool ("refreshable",
    171                                &refreshable),
    172         NULL),
    173       GNUNET_JSON_spec_mark_optional (
    174         GNUNET_JSON_spec_string ("description",
    175                                  &description),
    176         NULL),
    177       GNUNET_JSON_spec_end ()
    178     };
    179 
    180     if (GNUNET_OK !=
    181         (ret = TALER_MHD_parse_json_data (connection,
    182                                           json,
    183                                           spec)))
    184     {
    185       GNUNET_break_op (0);
    186       json_decref (json);
    187       return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
    188     }
    189 
    190     res = do_post_account_token (h,
    191                                  connection,
    192                                  account_name,
    193                                  scope_s,
    194                                  refreshable,
    195                                  duration);
    196   }
    197   json_decref (json);
    198   return res;
    199 }