commit b0b3f998f13755e5f76d0d32e093826ab5f4793f
parent f9ca3b7442ba0f24b63a631bf679cb1e1e643037
Author: Florian Dold <florian@dold.me>
Date: Mon, 6 Jul 2026 16:07:40 +0200
exchange/auditor: use separately packaged SPA with fallback
Diffstat:
21 files changed, 212 insertions(+), 89 deletions(-)
diff --git a/.gitmodules b/.gitmodules
@@ -5,7 +5,3 @@
[submodule "contrib/gana"]
path = contrib/gana
url = ../gana.git
-[submodule "contrib/wallet-core"]
- path = contrib/wallet-core
- url = ../taler-typescript-core.git
- branch = prebuilt
diff --git a/contrib/aml-spa.lock b/contrib/aml-spa.lock
@@ -1 +0,0 @@
-1.5.14
-\ No newline at end of file
diff --git a/contrib/aml-spa/README.md b/contrib/aml-spa/README.md
@@ -0,0 +1,4 @@
+This directory contains a fallback for the AML SPA.
+
+The real KYC SPA is built from
+taler-typescript-core.git/packages/taler-exchange-aml-webui.
diff --git a/contrib/aml-spa/index.html b/contrib/aml-spa/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <h1>Taler Exchange AML Web UI not installed</h1>
+ <p>This is a fallback page shown when the Taler Exchange AML Web UI is not
+ available.</p>
+ <p>Please make sure the package is installed and the
+ <code>AML_SPA_DIR</code> option in the <code>[exchange]</code> section of
+ the taler-exchange configuration is set correctly.</p>
+</body>
+</html>
diff --git a/contrib/auditor-spa.lock b/contrib/auditor-spa.lock
@@ -1 +0,0 @@
-1.5.14
-\ No newline at end of file
diff --git a/contrib/auditor-spa/README.md b/contrib/auditor-spa/README.md
@@ -0,0 +1,4 @@
+This directory contains a fallback for the Auditor SPA.
+
+The real Auditor SPA is built from
+taler-typescript-core.git/packages/taler-auditor-webui.
diff --git a/contrib/auditor-spa/index.html b/contrib/auditor-spa/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <h1>Taler Auditor Web UI not installed</h1>
+ <p>This is a fallback page shown when the Taler Exchange KYC Web UI is not
+ available.</p>
+ <p>Please make sure the package is installed and the
+ <code>SPA_DIR</code> option in the <code>[exchange]</code> section of
+ the taler-auditor configuration is set correctly.</p>
+</body>
+</html>
diff --git a/contrib/check-prebuilt b/contrib/check-prebuilt
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import sys
-
-failed = False
-contrib = os.path.abspath(os.path.dirname(__file__))
-
-auditor_spa_ver_lock = open(contrib + "/" + "auditor-spa.lock").read().strip()
-auditor_spa_ver_prebuilt = open(contrib + "/" + "wallet-core/auditor-backoffice/version.txt").read().strip()
-
-aml_spa_ver_lock = open(contrib + "/" + "aml-spa.lock").read().strip()
-aml_spa_ver_prebuilt = open(contrib + "/" + "wallet-core/aml-backoffice/version.txt").read().strip()
-
-kyc_spa_ver_lock = open(contrib + "/" + "kyc-spa.lock").read().strip()
-kyc_spa_ver_prebuilt = open(contrib + "/" + "wallet-core/kyc/version.txt").read().strip()
-
-if aml_spa_ver_lock != aml_spa_ver_prebuilt:
- print("AML SPA version mismatch (contrib/aml-spa.lock)")
- print("lockfile has version", aml_spa_ver_lock)
- print("prebuilt has version", aml_spa_ver_prebuilt)
- failed = True
-
-if kyc_spa_ver_lock != kyc_spa_ver_prebuilt:
- print("KYC SPA version mismatch (contrib/kyc-spa.lock)")
- print("lockfile has version", kyc_spa_ver_lock)
- print("prebuilt has version", kyc_spa_ver_prebuilt)
- failed = True
-
-if auditor_spa_ver_lock != auditor_spa_ver_prebuilt:
- print("auditor SPA version mismatch (contrib/auditor-spa.lock)")
- print("lockfile has version", auditor_spa_ver_lock)
- print("prebuilt has version", auditor_spa_ver_prebuilt)
- failed = True
-
-if failed:
- sys.exit(1)
diff --git a/contrib/kyc-spa.lock b/contrib/kyc-spa.lock
@@ -1 +0,0 @@
-1.5.14
-\ No newline at end of file
diff --git a/contrib/kyc-spa/README.md b/contrib/kyc-spa/README.md
@@ -0,0 +1,4 @@
+This directory contains a fallback for the KYC SPA.
+
+The real KYC SPA is built from
+taler-typescript-core.git/packages/taler-exchange-kyc-webui.
diff --git a/contrib/kyc-spa/index.html b/contrib/kyc-spa/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <h1>Taler Exchange KYC Web UI not installed</h1>
+ <p>This is a fallback page shown when the Taler Exchange KYC Web UI is not
+ available.</p>
+ <p>Please make sure the package is installed and the
+ <code>KYC_SPA_DIR</code> option in the <code>[exchange]</code> section of
+ the taler-exchange configuration is set correctly.</p>
+</body>
+</html>
diff --git a/contrib/meson.build b/contrib/meson.build
@@ -73,15 +73,7 @@ endforeach
# be used by code generated by 'bootstrap'!
dist_amlspapkgdata_DATA = [
- 'wallet-core/aml-backoffice/bof',
- 'wallet-core/aml-backoffice/build-metadata.json',
- 'wallet-core/aml-backoffice/forms.json',
- 'wallet-core/aml-backoffice/index.css',
- 'wallet-core/aml-backoffice/index.css.map',
- 'wallet-core/aml-backoffice/index.html',
- 'wallet-core/aml-backoffice/index.js',
- 'wallet-core/aml-backoffice/index.js.map',
- 'wallet-core/aml-backoffice/version.txt',
+ 'aml-spa/index.html',
]
install_data(
sources: dist_amlspapkgdata_DATA,
@@ -89,15 +81,7 @@ install_data(
)
dist_kycspapkgdata_DATA = [
- 'wallet-core/kyc/bof',
- 'wallet-core/kyc/build-metadata.json',
- 'wallet-core/kyc/forms.json',
- 'wallet-core/kyc/index.css',
- 'wallet-core/kyc/index.css.map',
- 'wallet-core/kyc/index.html',
- 'wallet-core/kyc/index.js',
- 'wallet-core/kyc/index.js.map',
- 'wallet-core/kyc/version.txt',
+ 'kyc-spa/index.html',
]
install_data(
sources: dist_kycspapkgdata_DATA,
@@ -105,21 +89,7 @@ install_data(
)
dist_auditorspapkgdata_DATA = [
- 'wallet-core/auditor-backoffice/bof',
- 'wallet-core/auditor-backoffice/build-metadata.json',
- 'wallet-core/auditor-backoffice/index.css',
- 'wallet-core/auditor-backoffice/index.css.map',
- 'wallet-core/auditor-backoffice/index.html',
- 'wallet-core/auditor-backoffice/index.js',
- 'wallet-core/auditor-backoffice/index.js.map',
- 'wallet-core/auditor-backoffice/languageicon-LWKRUH5D.svg',
- 'wallet-core/auditor-backoffice/logo-2021-VSZSJ4QZ.svg',
- 'wallet-core/auditor-backoffice/materialdesignicons-webfont-4.9.95-7W2GKO6O.woff2',
- 'wallet-core/auditor-backoffice/materialdesignicons-webfont-4.9.95-GELXKCZG.ttf',
- 'wallet-core/auditor-backoffice/materialdesignicons-webfont-4.9.95-HENMUVWG.eot',
- 'wallet-core/auditor-backoffice/materialdesignicons-webfont-4.9.95-WP2MXZKI.woff',
- 'wallet-core/auditor-backoffice/version.txt',
- 'wallet-core/auditor-backoffice/XRXV3I6Li01BKofINeaE-34D53UZZ.ttf',
+ 'auditor-spa/index.html',
]
install_data(
sources: dist_auditorspapkgdata_DATA,
diff --git a/contrib/wallet-core b/contrib/wallet-core
@@ -1 +0,0 @@
-Subproject commit 45c7768f9153846198dac99b6a9015477b9d7d2a
diff --git a/src/auditor/auditor.conf b/src/auditor/auditor.conf
@@ -31,3 +31,6 @@ UNIXPATH_MODE = 660
# HTTP port the auditor listens to
PORT = 8083
+
+# Location of the (externally packaged) auditor SPA
+SPA_DIR = $PREFIX/share/taler-auditor-webui/
diff --git a/src/auditor/taler-auditor-httpd.c b/src/auditor/taler-auditor-httpd.c
@@ -128,6 +128,14 @@ static struct TALER_AuditorPublicKeyP auditor_pub;
struct TALER_MasterPublicKeyP TAH_master_public_key;
/**
+ * Exchange master public key (according to the
+ * configuration). (global)
+ */
+struct TALER_MasterPublicKeyP TAH_master_public_key;
+
+char *TAH_spa_dir;
+
+/**
* Default timeout in seconds for HTTP requests.
*/
static unsigned int connection_timeout = 30;
@@ -1296,6 +1304,21 @@ auditor_serve_process_config (void)
GNUNET_CRYPTO_eddsa_key_get_public (&eddsa_priv,
&auditor_pub.eddsa_pub);
}
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "auditor",
+ "SPA_DIR",
+ &TAH_spa_dir))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loading auditor SPA from %s\n",
+ TAH_spa_dir);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loading exchange AML SPA from default location\n");
+ }
return GNUNET_OK;
}
diff --git a/src/auditor/taler-auditor-httpd.h b/src/auditor/taler-auditor-httpd.h
@@ -45,6 +45,13 @@ extern struct TALER_EXCHANGEDB_PostgresContext *TAH_epg;
extern struct TALER_MasterPublicKeyP TAH_master_public_key;
/**
+ * Absolute directory path where the auditor SPA data is located.
+ *
+ * Can be NULL.
+ */
+extern char *TAH_spa_dir;
+
+/**
* Our currency.
*/
extern char *TAH_currency;
diff --git a/src/auditor/taler-auditor-httpd_spa.c b/src/auditor/taler-auditor-httpd_spa.c
@@ -53,11 +53,46 @@ TAH_spa_handler (
}
+/**
+ * Load the SPA data from an directory.
+ *
+ * If the directory is not found,
+ * fall back to a directory owned by the taler-exchange package.
+ *
+ * @param spa_abs_dir absolute location of the SPA,
+ * typically packaged separately from the exchange
+ * @param spa_fallback_dir fallback directory, relative
+ * to the project data.
+ * @returns loaded SPA or NULL on error
+ */
+static struct TALER_MHD_Spa *
+spa_load (const char *spa_abs_dir,
+ const char *spa_fallback_dir)
+{
+ bool have_spa = false;
+ GNUNET_assert (NULL != spa_fallback_dir);
+ if (NULL != spa_abs_dir)
+ {
+ struct stat sb;
+ have_spa = stat (spa_abs_dir, &sb) == 0 && S_ISDIR (sb.st_mode);
+ if (have_spa)
+ {
+ return TALER_MHD_spa_load_dir (spa_abs_dir);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "SPA not found at '%s', using fallback\n",
+ spa_abs_dir);
+ }
+ return TALER_MHD_spa_load (TALER_AUDITOR_project_data (),
+ spa_fallback_dir);
+}
+
+
enum GNUNET_GenericReturnValue
TAH_spa_init ()
{
- spa = TALER_MHD_spa_load (TALER_AUDITOR_project_data (),
- "spa/");
+ spa = spa_load (TAH_spa_dir,
+ "spa/");
if (NULL == spa)
{
GNUNET_break (0);
diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf
@@ -141,6 +141,12 @@ PRIVACY_ETAG = exchange-pp-v0
# Where are the Typst templates for form rendering.
TYPST_TEMPLATES = @taler-exchange
+# Location of the (externally packaged) AML SPA
+AML_SPA_DIR = $PREFIX/share/taler-exchange-aml-webui/
+
+# Location of the (externally packaged) KYC SPA
+KYC_SPA_DIR = $PREFIX/share/taler-exchange-kyc-webui/
+
[exchange-sanctionscheck]
# Name where we store the sanctions check offset.
MIN_ROW_FILENAME = ${HOME}/.cache/sanctionscheck-offset.bin
@@ -161,4 +167,4 @@ FREEZE_CONFIDENCE_LIMIT = 0.9
# good 0.9 match with a super-high 1.0 confidence would not (0.9 < 0.95).
# OTOH, a bad 0.2 match with super-low 0.1 confidence would again
# trigger (2.0 > 0.95).
-INVESTIGATION_LIMIT = 0.9
-\ No newline at end of file
+INVESTIGATION_LIMIT = 0.9
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
@@ -151,6 +151,10 @@ char *TEH_tos_etag;
char *TEH_shopping_url;
+char *TEH_aml_spa_dir;
+
+char *TEH_kyc_spa_dir;
+
/**
* Where to redirect users from "/"?
*/
@@ -2383,6 +2387,36 @@ exchange_serve_process_config (const char *cfg_fn)
"invalid URL");
return GNUNET_SYSERR;
}
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_filename (TEH_cfg,
+ "exchange",
+ "AML_SPA_DIR",
+ &TEH_aml_spa_dir))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loading exchange AML SPA from %s\n",
+ TEH_aml_spa_dir);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loading exchange AML SPA from default location\n");
+ }
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_filename (TEH_cfg,
+ "exchange",
+ "KYC_SPA_DIR",
+ &TEH_kyc_spa_dir))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loading exchange KYC SPA from %s\n",
+ TEH_kyc_spa_dir);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loading exchange KYC SPA from default location\n");
+ }
{
char *master_public_key_str;
diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h
@@ -171,6 +171,20 @@ extern char *TEH_tos_etag;
extern char *TEH_shopping_url;
/**
+ * Absolute directory path where the aml SPA data is located.
+ *
+ * Can be NULL.
+ */
+extern char *TEH_aml_spa_dir;
+
+/**
+ * Absolute directory path where the aml SPA data is located.
+ *
+ * Can be NULL.
+ */
+extern char *TEH_kyc_spa_dir;
+
+/**
* Linear STEFAN parameter.
*/
extern float TEH_stefan_lin;
diff --git a/src/exchange/taler-exchange-httpd_get-SPA.c b/src/exchange/taler-exchange-httpd_get-SPA.c
@@ -82,18 +82,53 @@ TEH_handler_kyc_spa (struct TEH_RequestContext *rc,
}
+/**
+ * Load the SPA data from an directory.
+ *
+ * If the directory is not found,
+ * fall back to a directory owned by the taler-exchange package.
+ *
+ * @param spa_abs_dir absolute location of the SPA,
+ * typically packaged separately from the exchange
+ * @param spa_fallback_dir fallback directory, relative
+ * to the project data.
+ * @returns loaded SPA or NULL on error
+ */
+static struct TALER_MHD_Spa *
+spa_load (const char *spa_abs_dir,
+ const char *spa_fallback_dir)
+{
+ bool have_spa = false;
+ GNUNET_assert (NULL != spa_fallback_dir);
+ if (NULL != spa_abs_dir)
+ {
+ struct stat sb;
+ have_spa = stat (spa_abs_dir, &sb) == 0 && S_ISDIR (sb.st_mode);
+ if (have_spa)
+ {
+ return TALER_MHD_spa_load_dir (spa_abs_dir);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "SPA not found at '%s', using fallback\n",
+ spa_abs_dir);
+ }
+ return TALER_MHD_spa_load (TALER_EXCHANGE_project_data (),
+ spa_fallback_dir);
+}
+
+
enum GNUNET_GenericReturnValue
TEH_spa_init ()
{
- aml_spa = TALER_MHD_spa_load (TALER_EXCHANGE_project_data (),
- "aml-spa/");
+ aml_spa = spa_load (TEH_aml_spa_dir,
+ "aml-spa/");
if (NULL == aml_spa)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
- kyc_spa = TALER_MHD_spa_load (TALER_EXCHANGE_project_data (),
- "kyc-spa/");
+ kyc_spa = spa_load (TEH_kyc_spa_dir,
+ "kyc-spa/");
if (NULL == kyc_spa)
{
GNUNET_break (0);