LCOV - code coverage report
Current view: top level - exchange - taler-exchange-httpd_kyc-proof.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 0 100 0.0 %
Date: 2022-08-25 06:15:09 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2021-2022 Taler Systems SA
       4             : 
       5             :   TALER is free software; you can redistribute it and/or modify it under the
       6             :   terms of the GNU Affero 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 Affero General Public License for more details.
      12             : 
      13             :   You should have received a copy of the GNU Affero General Public License along with
      14             :   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15             : */
      16             : /**
      17             :  * @file taler-exchange-httpd_kyc-proof.c
      18             :  * @brief Handle request for proof for KYC check.
      19             :  * @author Christian Grothoff
      20             :  */
      21             : #include "platform.h"
      22             : #include <gnunet/gnunet_util_lib.h>
      23             : #include <gnunet/gnunet_json_lib.h>
      24             : #include <jansson.h>
      25             : #include <microhttpd.h>
      26             : #include <pthread.h>
      27             : #include "taler_json_lib.h"
      28             : #include "taler_kyclogic_lib.h"
      29             : #include "taler_mhd_lib.h"
      30             : #include "taler-exchange-httpd_kyc-proof.h"
      31             : #include "taler-exchange-httpd_responses.h"
      32             : 
      33             : 
      34             : /**
      35             :  * Context for the proof.
      36             :  */
      37             : struct KycProofContext
      38             : {
      39             : 
      40             :   /**
      41             :    * Kept in a DLL while suspended.
      42             :    */
      43             :   struct KycProofContext *next;
      44             : 
      45             :   /**
      46             :    * Kept in a DLL while suspended.
      47             :    */
      48             :   struct KycProofContext *prev;
      49             : 
      50             :   /**
      51             :    * Details about the connection we are processing.
      52             :    */
      53             :   struct TEH_RequestContext *rc;
      54             : 
      55             :   /**
      56             :    * Proof logic to run.
      57             :    */
      58             :   struct TALER_KYCLOGIC_Plugin *logic;
      59             : 
      60             :   /**
      61             :    * Configuration for @a logic.
      62             :    */
      63             :   struct TALER_KYCLOGIC_ProviderDetails *pd;
      64             : 
      65             :   /**
      66             :    * Asynchronous operation with the proof system.
      67             :    */
      68             :   struct TALER_KYCLOGIC_ProofHandle *ph;
      69             : 
      70             :   /**
      71             :    * Process information about the user for the plugin from the database, can
      72             :    * be NULL.
      73             :    */
      74             :   char *provider_user_id;
      75             : 
      76             :   /**
      77             :    * Process information about the legitimization process for the plugin from the
      78             :    * database, can be NULL.
      79             :    */
      80             :   char *provider_legitimization_id;
      81             : 
      82             :   /**
      83             :    * Hash of payment target URI this is about.
      84             :    */
      85             :   struct TALER_PaytoHashP h_payto;
      86             : 
      87             :   /**
      88             :    * HTTP response to return.
      89             :    */
      90             :   struct MHD_Response *response;
      91             : 
      92             :   /**
      93             :    * Provider configuration section name of the logic we are running.
      94             :    */
      95             :   const char *provider_section;
      96             : 
      97             :   /**
      98             :    * Row in the database for this legitimization operation.
      99             :    */
     100             :   uint64_t process_row;
     101             : 
     102             :   /**
     103             :    * HTTP response code to return.
     104             :    */
     105             :   unsigned int response_code;
     106             : 
     107             :   /**
     108             :    * True if we are suspended,
     109             :    */
     110             :   bool suspended;
     111             : 
     112             : };
     113             : 
     114             : 
     115             : /**
     116             :  * Contexts are kept in a DLL while suspended.
     117             :  */
     118             : static struct KycProofContext *kpc_head;
     119             : 
     120             : /**
     121             :  * Contexts are kept in a DLL while suspended.
     122             :  */
     123             : static struct KycProofContext *kpc_tail;
     124             : 
     125             : 
     126             : /**
     127             :  * Resume processing the @a kpc request.
     128             :  *
     129             :  * @param kpc request to resume
     130             :  */
     131             : static void
     132           0 : kpc_resume (struct KycProofContext *kpc)
     133             : {
     134           0 :   GNUNET_assert (GNUNET_YES == kpc->suspended);
     135           0 :   kpc->suspended = false;
     136           0 :   GNUNET_CONTAINER_DLL_remove (kpc_head,
     137             :                                kpc_tail,
     138             :                                kpc);
     139           0 :   MHD_resume_connection (kpc->rc->connection);
     140           0 :   TALER_MHD_daemon_trigger ();
     141           0 : }
     142             : 
     143             : 
     144             : void
     145           0 : TEH_kyc_proof_cleanup (void)
     146             : {
     147             :   struct KycProofContext *kpc;
     148             : 
     149           0 :   while (NULL != (kpc = kpc_head))
     150             :   {
     151           0 :     if (NULL != kpc->ph)
     152             :     {
     153           0 :       kpc->logic->proof_cancel (kpc->ph);
     154           0 :       kpc->ph = NULL;
     155             :     }
     156           0 :     kpc_resume (kpc);
     157             :   }
     158           0 : }
     159             : 
     160             : 
     161             : /**
     162             :  * Function called with the result of a proof check operation.
     163             :  *
     164             :  * Note that the "decref" for the @a response
     165             :  * will be done by the callee and MUST NOT be done by the plugin.
     166             :  *
     167             :  * @param cls closure
     168             :  * @param status KYC status
     169             :  * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown
     170             :  * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown
     171             :  * @param expiration until when is the KYC check valid
     172             :  * @param http_status HTTP status code of @a response
     173             :  * @param[in] response to return to the HTTP client
     174             :  */
     175             : static void
     176           0 : proof_cb (
     177             :   void *cls,
     178             :   enum TALER_KYCLOGIC_KycStatus status,
     179             :   const char *provider_user_id,
     180             :   const char *provider_legitimization_id,
     181             :   struct GNUNET_TIME_Absolute expiration,
     182             :   unsigned int http_status,
     183             :   struct MHD_Response *response)
     184             : {
     185           0 :   struct KycProofContext *kpc = cls;
     186           0 :   struct TEH_RequestContext *rc = kpc->rc;
     187             :   struct GNUNET_AsyncScopeSave old_scope;
     188             : 
     189           0 :   kpc->ph = NULL;
     190           0 :   GNUNET_async_scope_enter (&rc->async_scope_id,
     191             :                             &old_scope);
     192             : 
     193           0 :   if (TALER_KYCLOGIC_STATUS_SUCCESS == status)
     194             :   {
     195             :     enum GNUNET_DB_QueryStatus qs;
     196             : 
     197           0 :     qs = TEH_plugin->update_kyc_process_by_row (TEH_plugin->cls,
     198             :                                                 kpc->process_row,
     199             :                                                 kpc->provider_section,
     200           0 :                                                 &kpc->h_payto,
     201             :                                                 provider_user_id,
     202             :                                                 provider_legitimization_id,
     203             :                                                 expiration);
     204           0 :     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
     205             :     {
     206           0 :       GNUNET_break (0);
     207           0 :       if (NULL != response)
     208           0 :         MHD_destroy_response (response);
     209           0 :       kpc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
     210           0 :       kpc->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
     211             :                                             "set_kyc_ok");
     212           0 :       GNUNET_async_scope_restore (&old_scope);
     213           0 :       return;
     214             :     }
     215             :   }
     216             :   else
     217             :   {
     218           0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     219             :                 "KYC process #%llu failed with status %d\n",
     220             :                 (unsigned long long) kpc->process_row,
     221             :                 status);
     222             :   }
     223           0 :   kpc->response_code = http_status;
     224           0 :   kpc->response = response;
     225           0 :   kpc_resume (kpc);
     226           0 :   GNUNET_async_scope_restore (&old_scope);
     227             : }
     228             : 
     229             : 
     230             : /**
     231             :  * Function called to clean up a context.
     232             :  *
     233             :  * @param rc request context
     234             :  */
     235             : static void
     236           0 : clean_kpc (struct TEH_RequestContext *rc)
     237             : {
     238           0 :   struct KycProofContext *kpc = rc->rh_ctx;
     239             : 
     240           0 :   if (NULL != kpc->ph)
     241             :   {
     242           0 :     kpc->logic->proof_cancel (kpc->ph);
     243           0 :     kpc->ph = NULL;
     244             :   }
     245           0 :   if (NULL != kpc->response)
     246             :   {
     247           0 :     MHD_destroy_response (kpc->response);
     248           0 :     kpc->response = NULL;
     249             :   }
     250           0 :   GNUNET_free (kpc->provider_user_id);
     251           0 :   GNUNET_free (kpc->provider_legitimization_id);
     252           0 :   GNUNET_free (kpc);
     253           0 : }
     254             : 
     255             : 
     256             : MHD_RESULT
     257           0 : TEH_handler_kyc_proof (
     258             :   struct TEH_RequestContext *rc,
     259             :   const char *const args[3])
     260             : {
     261           0 :   struct KycProofContext *kpc = rc->rh_ctx;
     262             : 
     263           0 :   if (NULL == kpc)
     264             :   {
     265             :     /* first time */
     266           0 :     if ( (NULL == args[0]) ||
     267           0 :          (NULL == args[1]) )
     268             :     {
     269           0 :       GNUNET_break_op (0);
     270           0 :       return TALER_MHD_reply_with_error (rc->connection,
     271             :                                          MHD_HTTP_NOT_FOUND,
     272             :                                          TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
     273             :                                          "'/kyc-proof/$H_PATYO/$LOGIC' required");
     274             :     }
     275             : 
     276           0 :     kpc = GNUNET_new (struct KycProofContext);
     277           0 :     kpc->rc = rc;
     278           0 :     rc->rh_ctx = kpc;
     279           0 :     rc->rh_cleaner = &clean_kpc;
     280           0 :     if (GNUNET_OK !=
     281           0 :         GNUNET_STRINGS_string_to_data (args[0],
     282             :                                        strlen (args[0]),
     283           0 :                                        &kpc->h_payto,
     284             :                                        sizeof (kpc->h_payto)))
     285             :     {
     286           0 :       GNUNET_break_op (0);
     287           0 :       return TALER_MHD_reply_with_error (rc->connection,
     288             :                                          MHD_HTTP_BAD_REQUEST,
     289             :                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
     290             :                                          "h_payto");
     291             :     }
     292           0 :     if (GNUNET_OK !=
     293           0 :         TALER_KYCLOGIC_lookup_logic (args[1],
     294             :                                      &kpc->logic,
     295             :                                      &kpc->pd,
     296             :                                      &kpc->provider_section))
     297             :     {
     298           0 :       GNUNET_break_op (0);
     299           0 :       return TALER_MHD_reply_with_error (rc->connection,
     300             :                                          MHD_HTTP_NOT_FOUND,
     301             :                                          TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN,
     302           0 :                                          args[1]);
     303             :     }
     304           0 :     if (0 != strcmp (args[1],
     305             :                      kpc->provider_section))
     306             :     {
     307           0 :       GNUNET_break_op (0);
     308           0 :       return TALER_MHD_reply_with_error (rc->connection,
     309             :                                          MHD_HTTP_BAD_REQUEST,
     310             :                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
     311             :                                          "PROVIDER_SECTION");
     312             :     }
     313             : 
     314           0 :     if (NULL != kpc->provider_section)
     315             :     {
     316             :       enum GNUNET_DB_QueryStatus qs;
     317             :       struct GNUNET_TIME_Absolute expiration;
     318             : 
     319           0 :       qs = TEH_plugin->lookup_kyc_process_by_account (
     320           0 :         TEH_plugin->cls,
     321             :         kpc->provider_section,
     322           0 :         &kpc->h_payto,
     323             :         &kpc->process_row,
     324             :         &expiration,
     325             :         &kpc->provider_user_id,
     326             :         &kpc->provider_legitimization_id);
     327           0 :       switch (qs)
     328             :       {
     329           0 :       case GNUNET_DB_STATUS_HARD_ERROR:
     330             :       case GNUNET_DB_STATUS_SOFT_ERROR:
     331           0 :         return TALER_MHD_reply_with_ec (rc->connection,
     332             :                                         TALER_EC_GENERIC_DB_STORE_FAILED,
     333             :                                         "lookup_kyc_requirement_by_account");
     334           0 :       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     335           0 :         return TALER_MHD_reply_with_error (rc->connection,
     336             :                                            MHD_HTTP_NOT_FOUND,
     337             :                                            TALER_EC_EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN,
     338             :                                            kpc->provider_section);
     339           0 :       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     340           0 :         break;
     341             :       }
     342           0 :       if (GNUNET_TIME_absolute_is_future (expiration))
     343             :       {
     344             :         /* KYC not required */
     345           0 :         return TALER_MHD_reply_static (
     346             :           rc->connection,
     347             :           MHD_HTTP_NO_CONTENT,
     348             :           NULL,
     349             :           NULL,
     350             :           0);
     351             :       }
     352             :     }
     353           0 :     kpc->ph = kpc->logic->proof (kpc->logic->cls,
     354           0 :                                  kpc->pd,
     355             :                                  &args[2],
     356             :                                  rc->connection,
     357           0 :                                  &kpc->h_payto,
     358             :                                  kpc->process_row,
     359           0 :                                  kpc->provider_user_id,
     360           0 :                                  kpc->provider_legitimization_id,
     361             :                                  &proof_cb,
     362             :                                  kpc);
     363           0 :     if (NULL == kpc->ph)
     364             :     {
     365           0 :       GNUNET_break (0);
     366           0 :       return TALER_MHD_reply_with_error (rc->connection,
     367             :                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
     368             :                                          TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
     369             :                                          "could not start proof with KYC logic");
     370             :     }
     371             : 
     372             : 
     373           0 :     kpc->suspended = true;
     374           0 :     GNUNET_CONTAINER_DLL_insert (kpc_head,
     375             :                                  kpc_tail,
     376             :                                  kpc);
     377           0 :     MHD_suspend_connection (rc->connection);
     378           0 :     return MHD_YES;
     379             :   }
     380             : 
     381           0 :   if (NULL == kpc->response)
     382             :   {
     383           0 :     GNUNET_break (0);
     384           0 :     return TALER_MHD_reply_with_error (rc->connection,
     385             :                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
     386             :                                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
     387             :                                        "handler resumed without response");
     388             :   }
     389             : 
     390             :   /* return response from KYC logic */
     391           0 :   return MHD_queue_response (rc->connection,
     392             :                              kpc->response_code,
     393             :                              kpc->response);
     394             : }
     395             : 
     396             : 
     397             : /* end of taler-exchange-httpd_kyc-proof.c */

Generated by: LCOV version 1.14