exchange

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

commit e326aba94adbc5556b8ea41549856625c2390a9a
parent b65481ad8fae5fe7fad9cb0253449fdc80bf7ff8
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon,  3 Jun 2024 17:20:38 +0200

-implement new AML/SPA handlers

Diffstat:
Msrc/exchange/taler-exchange-httpd.c | 11+++++++++--
Msrc/exchange/taler-exchange-httpd_spa.c | 344+++++++++++--------------------------------------------------------------------
Msrc/exchange/taler-exchange-httpd_spa.h | 20+++++++++++++++++---
Msrc/include/taler_mhd_lib.h | 22++++++++++++++++++++++
4 files changed, 95 insertions(+), 302 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c @@ -1820,9 +1820,16 @@ handle_mhd_request (void *cls, .nargs = 2 }, { - .url = "webui", + .url = "aml-spa", .method = MHD_HTTP_METHOD_GET, - .handler.get = &TEH_handler_spa, + .handler.get = &TEH_handler_aml_spa, + .nargs = 1, + .nargs_is_upper_bound = true + }, + { + .url = "kyc-spa", + .method = MHD_HTTP_METHOD_GET, + .handler.get = &TEH_handler_kyc_spa, .nargs = 1, .nargs_is_upper_bound = true }, diff --git a/src/exchange/taler-exchange-httpd_spa.c b/src/exchange/taler-exchange-httpd_spa.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020, 2023 Taler Systems SA + Copyright (C) 2020, 2023, 2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -27,308 +27,68 @@ /** - * Resource from the WebUi. + * Resources of the AML SPA. */ -struct WebuiFile -{ - /** - * Kept in a DLL. - */ - struct WebuiFile *next; - - /** - * Kept in a DLL. - */ - struct WebuiFile *prev; - - /** - * Path this resource matches. - */ - char *path; - - /** - * SPA resource, compressed. - */ - struct MHD_Response *zspa; - - /** - * SPA resource, vanilla. - */ - struct MHD_Response *spa; - -}; - - -/** - * Resources of the WebUI, kept in a DLL. - */ -static struct WebuiFile *webui_head; +static struct TALER_MHD_Spa *aml_spa; /** - * Resources of the WebUI, kept in a DLL. + * Resources of the KYC SPA. */ -static struct WebuiFile *webui_tail; +static struct TALER_MHD_Spa *kyc_spa; MHD_RESULT -TEH_handler_spa (struct TEH_RequestContext *rc, - const char *const args[]) +TEH_handler_aml_spa (struct TEH_RequestContext *rc, + const char *const args[]) { - struct WebuiFile *w = NULL; - const char *infix = args[0]; - - if ( (NULL == infix) || - (0 == strcmp (infix, - "")) ) - infix = "index.html"; - for (struct WebuiFile *pos = webui_head; - NULL != pos; - pos = pos->next) - if (0 == strcmp (infix, - pos->path)) - { - w = pos; - break; - } - if (NULL == w) - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_GENERIC_ENDPOINT_UNKNOWN, - rc->url); - if ( (MHD_YES == - TALER_MHD_can_compress (rc->connection)) && - (NULL != w->zspa) ) - return MHD_queue_response (rc->connection, - MHD_HTTP_OK, - w->zspa); - return MHD_queue_response (rc->connection, - MHD_HTTP_OK, - w->spa); -} - - -/** - * Function called on each file to load for the WebUI. - * - * @param cls NULL - * @param dn name of the file to load - */ -static enum GNUNET_GenericReturnValue -build_webui (void *cls, - const char *dn) -{ - static struct - { - const char *ext; - const char *mime; - } mime_map[] = { - { - .ext = "css", - .mime = "text/css" - }, - { - .ext = "html", - .mime = "text/html" - }, - { - .ext = "js", - .mime = "text/javascript" - }, - { - .ext = "jpg", - .mime = "image/jpeg" - }, - { - .ext = "jpeg", - .mime = "image/jpeg" - }, - { - .ext = "png", - .mime = "image/png" - }, - { - .ext = "svg", - .mime = "image/svg+xml" - }, - { - .ext = NULL, - .mime = NULL - }, - }; - int fd; - struct stat sb; - struct MHD_Response *zspa = NULL; - struct MHD_Response *spa; - const char *ext; - const char *mime; - - (void) cls; - /* finally open template */ - fd = open (dn, - O_RDONLY); - if (-1 == fd) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - dn); - return GNUNET_SYSERR; - } - if (0 != - fstat (fd, - &sb)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - dn); - GNUNET_break (0 == close (fd)); - return GNUNET_SYSERR; - } - - mime = NULL; - ext = strrchr (dn, '.'); - if (NULL == ext) - { - GNUNET_break (0 == close (fd)); - return GNUNET_OK; - } - ext++; - for (unsigned int i = 0; NULL != mime_map[i].ext; i++) - if (0 == strcasecmp (ext, - mime_map[i].ext)) - { - mime = mime_map[i].mime; - break; - } - + const char *path = args[0]; + struct TALER_AccountAccessTokenP tok; + + if (GNUNET_OK == + GNUNET_STRINGS_string_to_data (path, + strlen (path), + &tok, + sizeof (tok))) { - void *in; - ssize_t r; - size_t csize; - - in = GNUNET_malloc_large (sb.st_size); - if (NULL == in) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "malloc"); - GNUNET_break (0 == close (fd)); - return GNUNET_SYSERR; - } - r = read (fd, - in, - sb.st_size); - if ( (-1 == r) || - (sb.st_size != (size_t) r) ) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "read", - dn); - GNUNET_free (in); - GNUNET_break (0 == close (fd)); - return GNUNET_SYSERR; - } - csize = (size_t) r; - if (MHD_YES == - TALER_MHD_body_compress (&in, - &csize)) - { - zspa = MHD_create_response_from_buffer (csize, - in, - MHD_RESPMEM_MUST_FREE); - if (NULL != zspa) - { - if (MHD_NO == - MHD_add_response_header (zspa, - MHD_HTTP_HEADER_CONTENT_ENCODING, - "deflate")) - { - GNUNET_break (0); - MHD_destroy_response (zspa); - zspa = NULL; - } - if (NULL != mime) - GNUNET_break (MHD_YES == - MHD_add_response_header (zspa, - MHD_HTTP_HEADER_CONTENT_TYPE, - mime)); - } - } - else - { - GNUNET_free (in); - } + /* The access token is used internally by the SPA, + we simply map all access tokens to "index.html" */ + path = "index.html"; } + return TALER_MHD_spa_handler (aml_spa, + rc->connection, + path); +} - spa = MHD_create_response_from_fd (sb.st_size, - fd); - if (NULL == spa) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - dn); - GNUNET_break (0 == close (fd)); - if (NULL != zspa) - { - MHD_destroy_response (zspa); - zspa = NULL; - } - return GNUNET_SYSERR; - } - if (NULL != mime) - GNUNET_break (MHD_YES == - MHD_add_response_header (spa, - MHD_HTTP_HEADER_CONTENT_TYPE, - mime)); - { - struct WebuiFile *w; - const char *fn; +MHD_RESULT +TEH_handler_kyc_spa (struct TEH_RequestContext *rc, + const char *const args[]) +{ + const char *path = args[0]; - fn = strrchr (dn, '/'); - GNUNET_assert (NULL != fn); - w = GNUNET_new (struct WebuiFile); - w->path = GNUNET_strdup (fn + 1); - w->spa = spa; - w->zspa = zspa; - GNUNET_CONTAINER_DLL_insert (webui_head, - webui_tail, - w); - } - return GNUNET_OK; + return TALER_MHD_spa_handler (kyc_spa, + rc->connection, + path); } enum GNUNET_GenericReturnValue TEH_spa_init () { - char *dn; - + aml_spa = TALER_MHD_spa_load ("exchange/aml-spa/"); + if (NULL == aml_spa) { - char *path; - - path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); - if (NULL == path) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_asprintf (&dn, - "%sexchange/aml-spa/", - path); - GNUNET_free (path); + GNUNET_break (0); + return GNUNET_SYSERR; } - - if (-1 == - GNUNET_DISK_directory_scan (dn, - &build_webui, - NULL)) + kyc_spa = TALER_MHD_spa_load ("exchange/kyc-spa/"); + if (NULL == kyc_spa) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to load WebUI from `%s'\n", - dn); - GNUNET_free (dn); + GNUNET_break (0); + TALER_MHD_spa_free (aml_spa); + aml_spa = NULL; return GNUNET_SYSERR; } - GNUNET_free (dn); return GNUNET_OK; } @@ -339,24 +99,14 @@ TEH_spa_init () void __attribute__ ((destructor)) get_spa_fini () { - struct WebuiFile *w; - - while (NULL != (w = webui_head)) + if (NULL != kyc_spa) + { + TALER_MHD_spa_free (kyc_spa); + kyc_spa = NULL; + } + if (NULL != aml_spa) { - GNUNET_CONTAINER_DLL_remove (webui_head, - webui_tail, - w); - if (NULL != w->spa) - { - MHD_destroy_response (w->spa); - w->spa = NULL; - } - if (NULL != w->zspa) - { - MHD_destroy_response (w->zspa); - w->zspa = NULL; - } - GNUNET_free (w->path); - GNUNET_free (w); + TALER_MHD_spa_free (aml_spa); + aml_spa = NULL; } } diff --git a/src/exchange/taler-exchange-httpd_spa.h b/src/exchange/taler-exchange-httpd_spa.h @@ -26,15 +26,29 @@ /** - * Return our single-page-app user interface (see contrib/wallet-core/). + * Return our single-page-app user interface + * for AML staff (see contrib/wallet-core/). * * @param rc context of the handler * @param[in,out] args remaining arguments (ignored) * @return #MHD_YES on success (reply queued), #MHD_NO on error (close connection) */ MHD_RESULT -TEH_handler_spa (struct TEH_RequestContext *rc, - const char *const args[]); +TEH_handler_aml_spa (struct TEH_RequestContext *rc, + const char *const args[]); + + +/** + * Return our single-page-app user interface + * for the KYC process (see contrib/wallet-core/). + * + * @param rc context of the handler + * @param[in,out] args remaining arguments (ignored) + * @return #MHD_YES on success (reply queued), #MHD_NO on error (close connection) + */ +MHD_RESULT +TEH_handler_kyc_spa (struct TEH_RequestContext *rc, + const char *const args[]); /** diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h @@ -984,12 +984,34 @@ MHD_RESULT TALER_MHD_reply_cors_preflight (struct MHD_Connection *connection); +/** + * Load SPA files from @a dir + * + * @param dir directory suffix to append to our data directory with the location of the files of the SPA + * @return handle to serve static files from @a dir + */ struct TALER_MHD_Spa * TALER_MHD_spa_load (const char *dir); + +/** + * Release resources used by SPA handler. + * + * @param[in] spa data structure to release + */ void TALER_MHD_spa_free (struct TALER_MHD_Spa *spa); + +/** + * Handle HTTP request for files in a @a spa. Generates + * a 404 if no file at @a path does exists. + * + * @param spa the SPA to serve files from + * @param connection HTTP connection to return data on + * @param path request path to match against the @a spa + * @return MHD status code to give to MHD + */ MHD_RESULT TALER_MHD_spa_handler (const struct TALER_MHD_Spa *spa, struct MHD_Connection *connection,