gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 08/08: fix #8660


From: gnunet
Subject: [taler-wallet-core] 08/08: fix #8660
Date: Tue, 26 Mar 2024 20:58:55 +0100

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

commit dd5aa2145f06a4744cf8f4f3fe14525b613acf87
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Tue Mar 26 16:54:35 2024 -0300

    fix #8660
---
 packages/bank-ui/src/Routing.tsx                   |   2 +-
 packages/bank-ui/src/context/config.ts             |  23 +-
 packages/bank-ui/src/pages/LoginForm.tsx           |   3 +-
 packages/bank-ui/src/pages/RegistrationPage.tsx    |   2 +-
 .../src/paths/admin/create/index.tsx               |   6 +-
 .../src/paths/instance/token/index.tsx             |   4 +-
 .../src/paths/login/index.tsx                      |   6 +-
 .../create_merchantAndBankAccount_pdf.sh           |  23 ++
 packages/taler-harness/pdf-template.html           |  65 ++++
 packages/taler-harness/src/index.ts                | 393 ++++++++++++++++++---
 .../taler-util/src/http-client/authentication.ts   |  12 +-
 packages/taler-util/src/http-client/bank-core.ts   |  10 +-
 packages/taler-util/src/http-client/merchant.ts    |   6 +-
 packages/taler-util/src/http-common.ts             |   1 +
 packages/taler-util/src/http-impl.node.ts          |   9 +-
 packages/taler-util/src/http-impl.qtart.ts         |   8 +-
 packages/web-util/src/context/bank-api.ts          |   1 -
 packages/web-util/src/context/merchant-api.ts      |   2 -
 18 files changed, 481 insertions(+), 95 deletions(-)

diff --git a/packages/bank-ui/src/Routing.tsx b/packages/bank-ui/src/Routing.tsx
index 489dbe30b..3ec5f0c77 100644
--- a/packages/bank-ui/src/Routing.tsx
+++ b/packages/bank-ui/src/Routing.tsx
@@ -113,7 +113,7 @@ function PublicRounting({
 
   async function doAutomaticLogin(username: string, password: string) {
     await handleError(async () => {
-      const resp = await lib.auth(username).createAccessToken(password, {
+      const resp = await lib.auth(username).createAccessTokenBasic(username, 
password, {
         scope: "readwrite",
         duration: { d_us: "forever" },
         refreshable: true,
diff --git a/packages/bank-ui/src/context/config.ts 
b/packages/bank-ui/src/context/config.ts
index 55b21d0da..86b6df5f3 100644
--- a/packages/bank-ui/src/context/config.ts
+++ b/packages/bank-ui/src/context/config.ts
@@ -218,7 +218,6 @@ function buildApiClient(url: URL) {
   const authClient = (user: string) =>
     new TalerAuthenticationHttpClient(
       bankClient.getAuthenticationAPI(user).href,
-      user,
       httpLib,
     );
 
@@ -305,15 +304,15 @@ const evictBankSwrCache: 
CacheEvictor<TalerCoreBankCacheEviction> = {
 };
 
 const evictConversionSwrCache: CacheEvictor<TalerBankConversionCacheEviction> =
-  {
-    async notifySuccess(op) {
-      switch (op) {
-        case TalerBankConversionCacheEviction.UPDATE_RATE: {
-          await revalidateConversionInfo();
-          return;
-        }
-        default:
-          assertUnreachable(op);
+{
+  async notifySuccess(op) {
+    switch (op) {
+      case TalerBankConversionCacheEviction.UPDATE_RATE: {
+        await revalidateConversionInfo();
+        return;
       }
-    },
-  };
+      default:
+        assertUnreachable(op);
+    }
+  },
+};
diff --git a/packages/bank-ui/src/pages/LoginForm.tsx 
b/packages/bank-ui/src/pages/LoginForm.tsx
index 904cd39d2..7eed0cd9e 100644
--- a/packages/bank-ui/src/pages/LoginForm.tsx
+++ b/packages/bank-ui/src/pages/LoginForm.tsx
@@ -79,8 +79,7 @@ export function LoginForm({
       ? undefined
       : withErrorHandler(
         async () =>
-          authenticator(username).createAccessToken(password, {
-            // scope: "readwrite" as "write", // FIX: different than merchant
+          authenticator(username).createAccessTokenBasic(username, password, {
             scope: "readwrite",
             duration: { d_us: "forever" },
             refreshable: true,
diff --git a/packages/bank-ui/src/pages/RegistrationPage.tsx 
b/packages/bank-ui/src/pages/RegistrationPage.tsx
index d7093d973..dc08ce0fa 100644
--- a/packages/bank-ui/src/pages/RegistrationPage.tsx
+++ b/packages/bank-ui/src/pages/RegistrationPage.tsx
@@ -114,7 +114,7 @@ function RegistrationForm({
     onComplete: () => void,
   ) {
     await handleError(async (onError) => {
-      const resp = await api.createAccount("" as AccessToken, {
+      const resp = await api.createAccount(undefined, {
         name,
         username,
         password,
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
index 3db38acc3..0e8ea1f5b 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
@@ -57,7 +57,7 @@ export default function Create({ onBack, onConfirm, forceId 
}: Props): VNode {
           try {
             await createInstance(d);
             if (d.auth.token) {
-              const result = await lib.authenticate.createAccessToken(
+              const result = await lib.authenticate.createAccessTokenBearer(
                 d.auth.token,
                 {
                   scope: "write",
@@ -68,8 +68,8 @@ export default function Create({ onBack, onConfirm, forceId 
}: Props): VNode {
                 },
               );
               if (result.type === "ok") {
-                const { access_token } = result.body;
-                logIn({ token: access_token });
+                const { token } = result.body;
+                logIn({ token });
               }
             }
             onConfirm();
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
index 889ef6f5d..13b5c45f1 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
@@ -85,11 +85,11 @@ export default function Token({
         }}
         onNewToken={async (currentToken, newToken): Promise<void> => {
           try {
-            await lib.management.updateInstanceAuthentication(currentToken, {
+            await 
lib.management.updateCurrentInstanceAuthentication(currentToken, {
               token: newToken,
               method: "token"
             })
-            const resp = await 
lib.authenticate.createAccessTokenMerchant(newToken, {
+            const resp = await 
lib.authenticate.createAccessTokenBearer(newToken, {
               scope: "write",
               duration: {
                 d_us: "forever"
diff --git a/packages/merchant-backoffice-ui/src/paths/login/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
index 14322f079..6a698186a 100644
--- a/packages/merchant-backoffice-ui/src/paths/login/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
@@ -34,7 +34,7 @@ import {
 } from "../../context/session.js";
 import { Notification } from "../../utils/types.js";
 
-interface Props {}
+interface Props { }
 
 const tokenRequest = {
   scope: "write",
@@ -55,7 +55,7 @@ export function LoginPage(_p: Props): VNode {
   async function doImpersonateImpl(instanceId: string) {
     const result = await lib
       .impersonate(instanceId)
-      .createAccessTokenMerchant(token, tokenRequest);
+      .createAccessTokenBearer(token, tokenRequest);
     if (result.type === "ok") {
       const { token } = result.body;
       logIn({ token });
@@ -80,7 +80,7 @@ export function LoginPage(_p: Props): VNode {
     }
   }
   async function doLoginImpl() {
-    const result = await lib.authenticate.createAccessTokenMerchant(
+    const result = await lib.authenticate.createAccessTokenBearer(
       token,
       tokenRequest,
     );
diff --git a/packages/taler-harness/create_merchantAndBankAccount_pdf.sh 
b/packages/taler-harness/create_merchantAndBankAccount_pdf.sh
new file mode 100644
index 000000000..4593cc9a0
--- /dev/null
+++ b/packages/taler-harness/create_merchantAndBankAccount_pdf.sh
@@ -0,0 +1,23 @@
+DATA=$(mktemp)
+set -e
+
+[ -z "$1" ] && echo First parameter must be the json file result from 
\'taler-harness deployment provision-bank-and-merchant\'. Alternative \'-\' can 
be used if the file is provided from stdin. && exit 1
+
+cat $1 > $DATA
+
+[ -z "$(jq -r '.bankUser//empty' $DATA)" ] && echo the json file is not 
complete: missing bankUser && exit 1
+[ -z "$(jq -r '.bankURL//empty' $DATA)" ] && echo the json file is not 
complete: missing bankURL && exit 1
+[ -z "$(jq -r '.merchantURL//empty' $DATA)" ] && echo the json file is not 
complete: missing merchantURL && exit 1
+[ -z "$(jq -r '.templateURI//empty' $DATA)" ] && echo the json file is not 
complete: missing templateURI && exit 1
+[ -z "$(jq -r '.password//empty' $DATA)" ] && echo the json file is not 
complete: missing password && exit 1
+
+add_qr_image(){
+  jq -r $1 $DATA | qrencode -l Q -m 2 -s 5 -o - | base64 -w 0 | jq -Rn 
'{"'$2'":inputs}' | jq -s add - $DATA | sponge $DATA
+}
+
+add_qr_image .templateURI templateQR
+add_qr_image .bankURL bankQR
+add_qr_image .merchantURL merchantQR
+
+chevron pdf-template.html -d $DATA | wkhtmltopdf - out.pdf
+
diff --git a/packages/taler-harness/pdf-template.html 
b/packages/taler-harness/pdf-template.html
new file mode 100644
index 000000000..d308d67c4
--- /dev/null
+++ b/packages/taler-harness/pdf-template.html
@@ -0,0 +1,65 @@
+<html>
+
+<body style="padding: 3em">
+  <h1 id="account-information">Account information</h1>
+
+  <p>The information in this page is confidentail, do not share with 
others.</p>
+
+  <h2 style="margin-top: 4em;" id="bank-account">Bank</h2>
+  <p>
+    In your bank account you will be able to see how much revenue
+    has been consolidated.
+  </p>
+  <div style="display: flex; justify-content: space-between;">
+
+    <div>
+      <p>URL: {{bankURL}}</p>
+      <p>accounts id: {{bankUser}}</p>
+      <p>password: {{password}}</p>
+    </div>
+
+    <div>
+      <figure style="text-align: center;">
+        <img src="data:image/png;base64,{{bankQR}}" alt="" />
+        <figcaption>bank URL</figcaption>
+      </figure>
+    </div>
+  </div>
+
+  <hr />
+
+  <h2 style="margin-top: 4em;" id="merchant-instance">Backoffice</h2>
+  <p>
+    In this site you will be able to see how much are you selling,
+    make refunds or create new QR codes.
+  </p>
+
+  <div style="display: flex; justify-content: space-between;">
+    <div>
+      <p>URL: {{merchantURL}}</p>
+      <p>password: {{password}}</p>
+    </div>
+    <div>
+      <figure style="text-align: center;">
+        <img src="data:image/png;base64,{{merchantQR}}" alt="" />
+        <figcaption>merchant URL</figcaption>
+      </figure>
+    </div>
+  </div>
+
+  <hr />
+  <div style="page-break-after: always;">
+
+  </div>
+  <h1 style="margin-top: 4em;" id="template">Payme QR code</h1>
+  <p>
+    The following QR code can be utilized in
+    public settings to request payments.
+  </p>
+  <figure style="text-align: center;">
+    <img src="data:image/png;base64,{{templateQR}}" alt="" />
+    <figcaption>{{templateURI}}</figcaption>
+  </figure>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/packages/taler-harness/src/index.ts 
b/packages/taler-harness/src/index.ts
index 3bec1698a..4b0319a3e 100644
--- a/packages/taler-harness/src/index.ts
+++ b/packages/taler-harness/src/index.ts
@@ -18,6 +18,7 @@
  * Imports.
  */
 import {
+  AccessToken,
   AmountString,
   Amounts,
   BalancesResponse,
@@ -25,14 +26,23 @@ import {
   Duration,
   HttpStatusCode,
   Logger,
-  MerchantInstanceConfig,
-  RegisterAccountRequest,
+  PaytoString,
+  TalerAuthenticationHttpClient,
+  TalerBankConversionHttpClient,
+  TalerCoreBankHttpClient,
+  TalerErrorCode,
+  TalerMerchantInstanceHttpClient,
+  TalerMerchantManagementHttpClient,
   TransactionsResponse,
   decodeCrock,
+  encodeCrock,
   generateIban,
   j2s,
+  randomBytes,
   rsaBlind,
   setGlobalLogLevelFromString,
+  setPrintHttpRequestAsCurl,
+  stringifyPayTemplateUri
 } from "@gnu-taler/taler-util";
 import { clk } from "@gnu-taler/taler-util/clk";
 import {
@@ -69,6 +79,7 @@ import {
 } from "./harness/helpers.js";
 import { getTestInfo, runTests } from "./integrationtests/testrunner.js";
 import { lintExchangeDeployment } from "./lint.js";
+import { randomUUID } from "crypto";
 
 const logger = new Logger("taler-harness:index.ts");
 
@@ -585,6 +596,291 @@ deploymentCli
     console.log(generateIban(args.genIban.countryCode, args.genIban.length));
   });
 
+deploymentCli
+  .subcommand("provisionBankMerchant", "provision-bank-and-merchant", {
+    help: "Provision a bank account, merchant instance and link them 
together.",
+  })
+  .requiredArgument("merchantApiBaseUrl", clk.STRING, {
+    help: "URL location of the merchant backend"
+  })
+  .requiredArgument("corebankApiBaseUrl", clk.STRING, {
+    help: "URL location of the libeufin bank backend"
+  })
+  .requiredOption("merchantToken", ["--merchant-management-token"], 
clk.STRING, {
+    help: "acces token of the default instance in the merchant backend"
+  })
+  .maybeOption("bankToken", ["--bank-admin-token"], clk.STRING, {
+    help: "libeufin bank admin's password if the account creation is 
restricted"
+  })
+  .requiredOption("name", ["--legal-name"], clk.STRING, {
+    help: "legal name of the merchant"
+  })
+  .maybeOption("email", ["--email"], clk.STRING, {
+    help: "email contact of the merchant"
+  })
+  .maybeOption("phone", ["--phone"], clk.STRING, {
+    help: "phone contact of the merchant"
+  })
+  .requiredOption("id", ["--id"], clk.STRING, {
+    help: "login id for the bank account and instance id of the merchant 
backend"
+  })
+  .flag("template", ["--create-template"], {
+    help: "use this flag to create a default template for the merchant with 
fixed summary"
+  })
+  .requiredOption("password", ["--password"], clk.STRING, {
+    help: "password of the accounts in libeufin bank and merchant backend"
+  })
+  .flag("randomPassword", ["--set-random-password"], {
+    help: "if everything worked ok, change the password of the accounts at the 
end"
+  })
+  .action(async (args) => {
+    const managementToken = args.provisionBankMerchant.merchantToken as 
AccessToken;
+    const bankAdminPassword = args.provisionBankMerchant.bankToken as 
AccessToken;
+    const id = args.provisionBankMerchant.id;
+    const name = args.provisionBankMerchant.name;
+    const email = args.provisionBankMerchant.email;
+    const phone = args.provisionBankMerchant.phone;
+    const password = args.provisionBankMerchant.password;
+
+
+    const httpLib = createPlatformHttpLib({});
+    const merchantManager = new 
TalerMerchantManagementHttpClient(args.provisionBankMerchant.merchantApiBaseUrl,
 httpLib);
+    const bank = new 
TalerCoreBankHttpClient(args.provisionBankMerchant.corebankApiBaseUrl, httpLib);
+    const instanceURL = merchantManager.getSubInstanceAPI(id).href
+    const merchantInstance = new TalerMerchantInstanceHttpClient(instanceURL, 
httpLib);
+    const conv = new 
TalerBankConversionHttpClient(bank.getConversionInfoAPI().href, httpLib)
+    const bankAuth = new 
TalerAuthenticationHttpClient(bank.getAuthenticationAPI(id).href, httpLib)
+
+
+    const bc = await bank.getConfig()
+    if (!bank.isCompatible(bc.body.version)) {
+      logger.error(
+        `bank server version is not compatible: ${bc.body.version}, client 
version: ${bank.PROTOCOL_VERSION}`,
+      );
+      return;
+    }
+    const mc = await merchantManager.getConfig()
+    if (!merchantManager.isCompatible(mc.body.version)) {
+      logger.error(
+        `merchant server version is not compatible: ${mc.body.version}, client 
version: ${merchantManager.PROTOCOL_VERSION}`,
+      );
+      return;
+    }
+
+    /**
+     * create bank account
+     */
+    let accountPayto: PaytoString;
+    {
+      const resp = await bank.createAccount(bankAdminPassword, {
+        name: name,
+        password: password,
+        username: id,
+        contact_data: email || phone ? {
+          email: email,
+          phone: phone,
+        } : undefined,
+      })
+
+      if (resp.type === "fail") {
+        logger.error(`unable to provision bank account, HTTP response status 
${resp.case}`);
+        process.exit(2);
+      }
+      logger.info(`account ${id} successfully provisioned`);
+      accountPayto = resp.body.internal_payto_uri
+    }
+
+    /**
+     * create merchant account
+     */
+    {
+      const resp = await merchantManager.createInstance(managementToken, {
+        address: {},
+        auth: {
+          method: "token",
+          token: `secret-token:${password}`,
+        },
+        default_pay_delay: Duration.toTalerProtocolDuration(
+          Duration.fromSpec({ hours: 1 }),
+        ),
+        default_wire_transfer_delay: Duration.toTalerProtocolDuration(
+          Duration.fromSpec({ hours: 1 }),
+        ),
+        id: id,
+        jurisdiction: {},
+        name: name,
+        use_stefan: true,
+      })
+
+      if (resp.type === "ok") {
+        logger.info(`instance ${id} created successfully`);
+      } else if (resp.case === HttpStatusCode.Conflict) {
+        logger.info(`instance ${id} already exists`);
+      } else {
+        logger.error(
+          `unable to create instance ${id}, HTTP status ${resp.case}`,
+        );
+        process.exit(2);
+      }
+    }
+
+    let wireAccount: string;
+    /**
+     * link bank account and merchant
+     */
+    {
+      const resp = await merchantInstance.addAccount(password as AccessToken, {
+        payto_uri: accountPayto,
+        credit_facade_url: bank.getRevenueAPI(id).href,
+        credit_facade_credentials: {
+          type: "basic",
+          username: id,
+          password: password,
+        }
+      })
+      if (resp.type === "fail") {
+        console.error(`unable to configure bank account for instance ${id}, 
status ${resp.case}`)
+        console.error(j2s(resp.detail));
+        process.exit(2);
+      }
+      wireAccount = resp.body.h_wire
+    }
+
+    logger.info(`successfully configured bank account for ${id}`);
+
+    let templateURI;
+    /**
+     * create template
+     */
+    if (args.provisionBankMerchant.template) {
+      let currency = bc.body.currency;
+      if (bc.body.allow_conversion) {
+        const cc = await conv.getConfig();
+        if (cc.type === "ok") {
+          currency = cc.body.fiat_currency
+        } else {
+          console.error(
+            `could not get fiat currency status ${cc.case}`,
+          );
+          console.error(j2s(cc.detail));
+        }
+      } else {
+        console.log(`conversion is disabled, using bank currency`)
+      }
+
+      {
+        const resp = await merchantInstance.addTemplate(password as 
AccessToken, {
+          template_id: "default",
+          template_description: "First template",
+          template_contract: {
+            pay_duration: Duration.toTalerProtocolDuration(
+              Duration.fromSpec({ hours: 1 }),
+            ),
+            minimum_age: 0,
+            currency,
+            summary: "Pay me!"
+          }
+        })
+        if (resp.type === "fail") {
+          console.error(`unable to create template for insntaince ${id}, 
status ${resp.case}`)
+          console.error(j2s(resp.detail));
+          process.exit(2);
+        }
+      }
+
+      logger.info(`template default successfully created`);
+      templateURI = stringifyPayTemplateUri({
+        merchantBaseUrl: instanceURL,
+        templateId: "default",
+        templateParams: {
+          amount: currency
+        }
+      })
+    }
+
+    let finalPassword = password;
+    if (args.provisionBankMerchant.randomPassword) {
+      const prevPassword = password as AccessToken
+      const randomPassword = encodeCrock(randomBytes(16));
+      logger.info("random password: ", randomPassword)
+      let token: AccessToken;
+      {
+        const resp = await bankAuth.createAccessTokenBasic(id, prevPassword, {
+          scope: "readwrite",
+          duration: Duration.toTalerProtocolDuration(Duration.fromSpec({ 
minutes: 1 })),
+          refreshable: false,
+        })
+        if (resp.type === "fail") {
+          console.error(`unable to login into bank accountfor user ${id}, 
status ${resp.case}`)
+          console.error(j2s(resp.detail));
+          process.exit(2);
+        }
+        token = resp.body.access_token;
+      }
+
+      {
+        const resp = await bank.updatePassword({ username: id, token }, {
+          old_password: prevPassword,
+          new_password: randomPassword,
+        });
+        if (resp.type === "fail") {
+          console.error(`unable to change bank pasword for user ${id}, status 
${resp.case}`)
+          if (resp.case !== HttpStatusCode.Accepted) {
+            console.error(j2s(resp.detail));
+          } else {
+            console.error("2FA required")
+          }
+          process.exit(2);
+        }
+      }
+
+      {
+        const resp = await 
merchantInstance.updateCurrentInstanceAuthentication(prevPassword, {
+          method: "token",
+          token: `secret-token:${randomPassword}` as AccessToken
+        })
+        if (resp.type === "fail") {
+          console.error(`unable to change merchant password for instance 
${id}, status ${resp.case}`)
+          console.error(j2s(resp.detail));
+          process.exit(2);
+        }
+      }
+
+      {
+        const resp = await merchantInstance.updateAccount(randomPassword as 
AccessToken, wireAccount, {
+          credit_facade_url: bank.getRevenueAPI(id).href,
+          credit_facade_credentials: {
+            type: "basic",
+            username: id,
+            password: randomPassword,
+          }
+        })
+        if (resp.type != "ok") {
+          console.error(
+            `unable to update bank account for instance ${id}, status 
${resp.case}`,
+          );
+          console.error(j2s(resp.detail));
+          process.exit(2);
+        }
+      }
+      finalPassword = randomPassword;
+    }
+    logger.info(`successfully configured bank account for ${id}`);
+
+    /**
+     * show result
+     */
+    console.log(JSON.stringify({
+      bankUser: id,
+      bankURL: args.provisionBankMerchant.corebankApiBaseUrl,
+      merchantURL: instanceURL,
+      templateURI,
+      password: finalPassword,
+    }, undefined, 2))
+
+  });
+
+
 deploymentCli
   .subcommand("provisionMerchantInstance", "provision-merchant-instance", {
     help: "Provision a merchant backend instance.",
@@ -595,17 +891,27 @@ deploymentCli
   .requiredOption("name", ["--name"], clk.STRING)
   .requiredOption("id", ["--id"], clk.STRING)
   .requiredOption("payto", ["--payto"], clk.STRING)
+  .maybeOption("bankURL", ["--bankURL"], clk.STRING)
+  .maybeOption("bankUser", ["--bankUser"], clk.STRING)
+  .maybeOption("bankPassword", ["--bankPassword"], clk.STRING)
   .action(async (args) => {
-    const httpLib = createPlatformHttpLib();
+    const httpLib = createPlatformHttpLib({});
     const baseUrl = args.provisionMerchantInstance.merchantApiBaseUrl;
-    const managementToken = args.provisionMerchantInstance.managementToken;
-    const instanceToken = args.provisionMerchantInstance.instanceToken;
+    const api = new TalerMerchantManagementHttpClient(baseUrl, httpLib)
+    const managementToken = args.provisionMerchantInstance.managementToken as 
AccessToken;
+    const instanceToken = args.provisionMerchantInstance.instanceToken as 
AccessToken;
     const instanceId = args.provisionMerchantInstance.id;
-    const body: MerchantInstanceConfig = {
+    const instancceName = args.provisionMerchantInstance.name;
+    const bankURL = args.provisionMerchantInstance.bankURL;
+    const bankUser = args.provisionMerchantInstance.bankUser;
+    const bankPassword = args.provisionMerchantInstance.bankPassword;
+    const accountPayto = args.provisionMerchantInstance.payto as PaytoString;
+
+    const createResp = await api.createInstance(managementToken, {
       address: {},
       auth: {
         method: "token",
-        token: args.provisionMerchantInstance.instanceToken,
+        token: `secret-token:${instanceToken}`,
       },
       default_pay_delay: Duration.toTalerProtocolDuration(
         Duration.fromSpec({ hours: 1 }),
@@ -613,48 +919,35 @@ deploymentCli
       default_wire_transfer_delay: { d_us: 1 },
       id: instanceId,
       jurisdiction: {},
-      name: args.provisionMerchantInstance.name,
+      name: instancceName,
       use_stefan: true,
-    };
-    const url = new URL("management/instances", baseUrl);
-    const createResp = await httpLib.fetch(url.href, {
-      method: "POST",
-      body,
-      headers: {
-        Authorization: `Bearer ${managementToken}`,
-      },
-    });
-    if (createResp.status >= 200 && createResp.status <= 299) {
+    })
+
+    if (createResp.type === "ok") {
       logger.info(`instance ${instanceId} created successfully`);
-    } else if (createResp.status === HttpStatusCode.Conflict) {
+    } else if (createResp.case === HttpStatusCode.Conflict) {
       logger.info(`instance ${instanceId} already exists`);
     } else {
       logger.error(
-        `unable to create instance ${instanceId}, HTTP status 
${createResp.status}`,
+        `unable to create instance ${instanceId}, HTTP status 
${createResp.case}`,
       );
       process.exit(2);
     }
 
-    const accountsUrl = new URL(
-      `instances/${instanceId}/private/accounts`,
-      baseUrl,
-    );
-    const accountBody = {
-      payto_uri: args.provisionMerchantInstance.payto,
-    };
-    const createAccountResp = await httpLib.fetch(accountsUrl.href, {
-      method: "POST",
-      body: accountBody,
-      headers: {
-        Authorization: `Bearer ${instanceToken}`,
-      },
-    });
-    if (createAccountResp.status != 200) {
+    const createAccountResp = await api.addAccount(instanceToken, {
+      payto_uri: accountPayto,
+      credit_facade_url: bankURL,
+      credit_facade_credentials: bankUser && bankPassword ? {
+        type: "basic",
+        username: bankUser,
+        password: bankPassword,
+      } : undefined
+    })
+    if (createAccountResp.type != "ok") {
       console.error(
-        `unable to configure bank account for instance ${instanceId}, status 
${createAccountResp.status}`,
+        `unable to configure bank account for instance ${instanceId}, status 
${createAccountResp.case}`,
       );
-      const resp = await createAccountResp.json();
-      console.error(j2s(resp));
+      console.error(j2s(createAccountResp.detail));
       process.exit(2);
     }
     logger.info(`successfully configured bank account for ${instanceId}`);
@@ -673,31 +966,25 @@ deploymentCli
   .maybeOption("internalPayto", ["--payto"], clk.STRING)
   .action(async (args) => {
     const httpLib = createPlatformHttpLib();
-    const corebankApiBaseUrl = args.provisionBankAccount.corebankApiBaseUrl;
-    const url = new URL("accounts", corebankApiBaseUrl);
+    const baseUrl = args.provisionBankAccount.corebankApiBaseUrl;
+    const api = new TalerCoreBankHttpClient(baseUrl, httpLib);
+
     const accountLogin = args.provisionBankAccount.login;
-    const body: RegisterAccountRequest = {
+    const resp = await api.createAccount(undefined, {
       name: args.provisionBankAccount.name,
       password: args.provisionBankAccount.password,
       username: accountLogin,
       is_public: !!args.provisionBankAccount.public,
       is_taler_exchange: !!args.provisionBankAccount.exchange,
-      payto_uri: args.provisionBankAccount.internalPayto,
-    };
-    const resp = await httpLib.fetch(url.href, {
-      method: "POST",
-      body,
-    });
-    if (resp.status >= 200 && resp.status <= 299) {
+      payto_uri: args.provisionBankAccount.internalPayto as PaytoString,
+    })
+
+    if (resp.type === "ok") {
       logger.info(`account ${accountLogin} successfully provisioned`);
       return;
     }
-    if (resp.status === HttpStatusCode.Conflict) {
-      logger.info(`account ${accountLogin} already provisioned`);
-      return;
-    }
     logger.error(
-      `unable to provision bank account, HTTP response status ${resp.status}`,
+      `unable to provision bank account, HTTP response status ${resp.case}`,
     );
     process.exit(2);
   });
diff --git a/packages/taler-util/src/http-client/authentication.ts 
b/packages/taler-util/src/http-client/authentication.ts
index 00ef21a06..f77df2ed0 100644
--- a/packages/taler-util/src/http-client/authentication.ts
+++ b/packages/taler-util/src/http-client/authentication.ts
@@ -45,7 +45,6 @@ export class TalerAuthenticationHttpClient {
 
   constructor(
     readonly baseUrl: string,
-    readonly username: string,
     httpClient?: HttpRequestLibrary,
   ) {
     this.httpLib = httpClient ?? createPlatformHttpLib();
@@ -61,7 +60,8 @@ export class TalerAuthenticationHttpClient {
    *
    * @returns
    */
-  async createAccessToken(
+  async createAccessTokenBasic(
+    username: string,
     password: string,
     body: TalerAuthentication.TokenRequest,
   ) {
@@ -69,7 +69,7 @@ export class TalerAuthenticationHttpClient {
     const resp = await this.httpLib.fetch(url.href, {
       method: "POST",
       headers: {
-        Authorization: makeBasicAuthHeader(this.username, password),
+        Authorization: makeBasicAuthHeader(username, password),
       },
       body,
     });
@@ -90,15 +90,15 @@ export class TalerAuthenticationHttpClient {
    *
    * @returns
    */
-  async createAccessTokenMerchant(
-    password: string,
+  async createAccessTokenBearer(
+    token: string,
     body: TalerAuthentication.TokenRequest,
   ) {
     const url = new URL(`token`, this.baseUrl);
     const resp = await this.httpLib.fetch(url.href, {
       method: "POST",
       headers: {
-        Authorization: makeBearerTokenAuthHeader(password as AccessToken),
+        Authorization: makeBearerTokenAuthHeader(token as AccessToken),
       },
       body,
     });
diff --git a/packages/taler-util/src/http-client/bank-core.ts 
b/packages/taler-util/src/http-client/bank-core.ts
index b544d56fe..7a98b6281 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -140,16 +140,18 @@ export class TalerCoreBankHttpClient {
    *
    */
   async createAccount(
-    auth: AccessToken,
+    auth: AccessToken | undefined,
     body: TalerCorebankApi.RegisterAccountRequest,
   ) {
     const url = new URL(`accounts`, this.baseUrl);
+    const headers: Record<string, string> = {}
+    if (auth) {
+      headers.Authorization = makeBearerTokenAuthHeader(auth)
+    }
     const resp = await this.httpLib.fetch(url.href, {
       method: "POST",
       body,
-      headers: {
-        Authorization: makeBearerTokenAuthHeader(auth),
-      },
+      headers: headers,
     });
     switch (resp.status) {
       case HttpStatusCode.Ok: {
diff --git a/packages/taler-util/src/http-client/merchant.ts 
b/packages/taler-util/src/http-client/merchant.ts
index 1b1a7b4a8..394625e38 100644
--- a/packages/taler-util/src/http-client/merchant.ts
+++ b/packages/taler-util/src/http-client/merchant.ts
@@ -354,10 +354,11 @@ export class TalerMerchantInstanceHttpClient {
       headers,
     });
 
-    //
     switch (resp.status) {
       case HttpStatusCode.Ok:
         return opEmptySuccess(resp);
+      case HttpStatusCode.NoContent: // FIXME: missing in docs
+        return opEmptySuccess(resp);
       case HttpStatusCode.NotFound:
         return opKnownHttpFailure(resp.status, resp);
       default:
@@ -1778,9 +1779,10 @@ export class TalerMerchantManagementHttpClient extends 
TalerMerchantInstanceHttp
    */
   async updateInstanceAuthentication(
     token: AccessToken | undefined,
+    instanceId: string,
     body: TalerMerchantApi.InstanceAuthConfigurationMessage,
   ) {
-    const url = new URL(`management/instances`, this.baseUrl);
+    const url = new URL(`management/instances/${instanceId}/auth`, 
this.baseUrl);
 
     const headers: Record<string, string> = {}
     if (token) {
diff --git a/packages/taler-util/src/http-common.ts 
b/packages/taler-util/src/http-common.ts
index 3973e66fb..cc75debd5 100644
--- a/packages/taler-util/src/http-common.ts
+++ b/packages/taler-util/src/http-common.ts
@@ -440,6 +440,7 @@ export interface HttpLibArgs {
    * Only allow HTTPS connections, not plain http.
    */
   requireTls?: boolean;
+  printAsCurl?: boolean;
 }
 
 export function encodeBody(body: any): ArrayBuffer {
diff --git a/packages/taler-util/src/http-impl.node.ts 
b/packages/taler-util/src/http-impl.node.ts
index b5c87843f..8606bc451 100644
--- a/packages/taler-util/src/http-impl.node.ts
+++ b/packages/taler-util/src/http-impl.node.ts
@@ -119,8 +119,13 @@ export class HttpLibImpl implements HttpRequestLibrary {
       timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS;
     }
 
-    const requestHeadersMap = { ...getDefaultHeaders(method), ...opt?.headers 
};
-
+    const requestHeadersMap = getDefaultHeaders(method);
+    if (opt?.headers) {
+      Object.entries(opt?.headers).forEach(([key, value]) => {
+        if (value === undefined) return;
+        requestHeadersMap[key] = value
+      })
+    }
     logger.trace(`request timeout ${timeoutMs} ms`);
 
     let reqBody: ArrayBuffer | undefined;
diff --git a/packages/taler-util/src/http-impl.qtart.ts 
b/packages/taler-util/src/http-impl.qtart.ts
index 0be9f2c23..b4e4ebbe7 100644
--- a/packages/taler-util/src/http-impl.qtart.ts
+++ b/packages/taler-util/src/http-impl.qtart.ts
@@ -98,7 +98,13 @@ export class HttpLibImpl implements HttpRequestLibrary {
     }
 
     let data: ArrayBuffer | undefined = undefined;
-    const requestHeadersMap = { ...getDefaultHeaders(method), ...opt?.headers 
};
+    const requestHeadersMap = getDefaultHeaders(method);
+    if (opt?.headers) {
+      Object.entries(opt?.headers).forEach(([key, value]) => {
+        if (value === undefined) return;
+        requestHeadersMap[key] = value
+      })
+    }
     let headersList: string[] = [];
     for (let headerName of Object.keys(requestHeadersMap)) {
       headersList.push(`${headerName}: ${requestHeadersMap[headerName]}`);
diff --git a/packages/web-util/src/context/bank-api.ts 
b/packages/web-util/src/context/bank-api.ts
index 645eda183..bd0653451 100644
--- a/packages/web-util/src/context/bank-api.ts
+++ b/packages/web-util/src/context/bank-api.ts
@@ -167,7 +167,6 @@ function buildBankApiClient(url: URL, evictors: Evictors,
   const auth = (user: string) =>
     new TalerAuthenticationHttpClient(
       bank.getAuthenticationAPI(user).href,
-      user,
       httpLib,
     );
 
diff --git a/packages/web-util/src/context/merchant-api.ts 
b/packages/web-util/src/context/merchant-api.ts
index 79c79ee9c..a531a5958 100644
--- a/packages/web-util/src/context/merchant-api.ts
+++ b/packages/web-util/src/context/merchant-api.ts
@@ -183,13 +183,11 @@ function buildMerchantApiClient(
     );
   const authenticate = new TalerAuthenticationHttpClient(
     management.getAuthenticationAPI().href,
-    "default",
     httpLib,
   );
   const impersonate = (instanceId: string) =>
     new TalerAuthenticationHttpClient(
       instance(instanceId).getAuthenticationAPI().href,
-      instanceId,
       httpLib,
     );
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]