gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant-backoffice] 10/11: bank: implement withdrawal abort


From: gnunet
Subject: [taler-merchant-backoffice] 10/11: bank: implement withdrawal abort
Date: Mon, 20 Dec 2021 17:45:08 +0100

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

ms pushed a commit to branch master
in repository merchant-backoffice.

commit ee6e662d4838f5d0c48d7de589bb1f287ef99807
Author: ms <ms@taler.net>
AuthorDate: Mon Dec 20 10:35:36 2021 +0100

    bank: implement withdrawal abort
---
 packages/bank/src/pages/home/index.tsx    | 139 +++++++++++++++++++++++-------
 packages/bank/tests/__tests__/homepage.js |   4 +
 2 files changed, 110 insertions(+), 33 deletions(-)

diff --git a/packages/bank/src/pages/home/index.tsx 
b/packages/bank/src/pages/home/index.tsx
index baf9e75..fc52f58 100644
--- a/packages/bank/src/pages/home/index.tsx
+++ b/packages/bank/src/pages/home/index.tsx
@@ -55,6 +55,22 @@ interface AccountStateType {
  * Helpers. *
  ***********/
 
+/**
+ * Craft headers with Authorization and Content-Type.
+ */
+function prepareHeaders(username: string, password: string) {
+  let headers = new Headers();
+  headers.append(
+    "Authorization",
+    `Basic ${Buffer.from(username + ":" + password).toString("base64")}`
+  );
+  headers.append(
+    "Content-Type",
+    "application/json"
+  )
+  return headers;
+}
+
 const getRootPath = () => {
   return typeof window !== undefined
     ? window.location.origin + window.location.pathname
@@ -123,6 +139,71 @@ function usePageState(
  * a helper function.
  */
 
+/**
+ * Abort a withdrawal operation via the Access API's /abort.
+ */
+async function abortWithdrawalCall(
+  backendState: BackendStateTypeOpt,
+  withdrawalId: string | undefined,
+  pageStateSetter: StateUpdater<PageStateType>
+) {
+  if (typeof backendState === "undefined") {
+    console.log("No credentials found.");
+    pageStateSetter((prevState) => ({...prevState, hasError: true, error: "No 
credentials found."}))
+    return;
+  }
+  if (typeof withdrawalId === "undefined") {
+    console.log("No withdrawal ID found.");
+    pageStateSetter((prevState) => ({...prevState, hasError: true, error: "No 
withdrawal ID found."}))
+    return;
+  }
+
+  try {
+    const { username, password } = backendState;
+    let headers = prepareHeaders(username, password);
+    /**
+     * NOTE: tests show that when a same object is being
+     * POSTed, caching might prevent same requests from being
+     * made.  Hence, trying to POST twice the same amount might
+     * get silently ignored.
+     *
+     * headers.append("cache-control", "no-store");
+     * headers.append("cache-control", "no-cache");
+     * headers.append("pragma", "no-cache");
+     * */
+
+    // Backend URL must have been stored _with_ a final slash.
+    const url = new URL(
+      
`access-api/accounts/${backendState.username}/withdrawals/${withdrawalId}/abort`,
+       backendState.url
+    )
+    var res = await fetch(url.href, {method: 'POST', headers: headers})
+  } catch (error) {
+    console.log("Could not abort the withdrawal", error);
+    pageStateSetter((prevState) => ({
+      ...prevState,
+      hasError: true,
+      error: `Could not abort the withdrawal: ${error}`}))
+    return;
+  }
+  if (!res.ok) {
+    console.log(`Withdrawal abort gave response error (${res.status})`, 
res.statusText);
+    pageStateSetter((prevState) => ({
+      ...prevState,
+      hasError: true,
+      error: `Withdrawal abortion gave response error (${res.status})`}))
+      return;
+  } else {
+    console.log("Withdrawal operation aborted!");
+    pageStateSetter((prevState) => {
+      delete prevState.talerWithdrawUri;
+      const { talerWithdrawUri, ...rest } = prevState;
+      return {
+        ...rest,
+        withdrawalOutcome: "Withdrawal aborted!"
+      }})
+  }
+}
 
 /**
  * This function confirms a withdrawal operation AFTER
@@ -139,23 +220,21 @@ async function confirmWithdrawalCall(
   withdrawalId: string | undefined,
   pageStateSetter: StateUpdater<PageStateType>
 ) {
+
   if (typeof backendState === "undefined") {
-    console.log("Page has a problem: no credentials found in the state.");
-    pageStateSetter((prevState) => ({
-      ...prevState,
-      hasError: true,
-      error: "No credentials found in the state"}))
+    console.log("No credentials found.");
+    pageStateSetter((prevState) => ({...prevState, hasError: true, error: "No 
credentials found."}))
     return;
   }
   if (typeof withdrawalId === "undefined") {
-    pageStateSetter((prevState) => ({
-      ...prevState,
-      hasError: true,
-      error: "Withdrawal ID wasn't found in the state; cannot confirm it."}))
+    console.log("No withdrawal ID found.");
+    pageStateSetter((prevState) => ({...prevState, hasError: true, error: "No 
withdrawal ID found."}))
     return;
   }
+  
   try {
-    let headers = new Headers();
+    const { username, password } = backendState;
+    let headers = prepareHeaders(username, password);
     /**
      * NOTE: tests show that when a same object is being
      * POSTed, caching might prevent same requests from being
@@ -166,14 +245,7 @@ async function confirmWithdrawalCall(
      * headers.append("cache-control", "no-cache");
      * headers.append("pragma", "no-cache");
      * */
-    headers.append(
-      "Authorization",
-      `Basic ${Buffer.from(backendState.username + ":" + 
backendState.password).toString("base64")}`
-    );
-    headers.append(
-      "Content-Type",
-      "application/json"
-    )
+
     // Backend URL must have been stored _with_ a final slash.
     const url = new URL(
       
`access-api/accounts/${backendState.username}/withdrawals/${withdrawalId}/confirm`,
@@ -227,14 +299,12 @@ async function createWithdrawalCall(
 ) {
   if (typeof backendState === "undefined") {
     console.log("Page has a problem: no credentials found in the state.");
-    pageStateSetter((prevState) => ({
-      ...prevState,
-      hasError: true,
-      error: "No credentials found in the state"}))
+    pageStateSetter((prevState) => ({...prevState, hasError: true, error: "No 
credentials given."}))
     return;
   }
   try {
-    let headers = new Headers();
+    const { username, password } = backendState;
+    let headers = prepareHeaders(username, password);
     /**
      * NOTE: tests show that when a same object is being
      * POSTed, caching might prevent same requests from being
@@ -245,14 +315,7 @@ async function createWithdrawalCall(
      * headers.append("cache-control", "no-cache");
      * headers.append("pragma", "no-cache");
      * */
-    headers.append(
-      "Authorization",
-      `Basic ${Buffer.from(backendState.username + ":" + 
backendState.password).toString("base64")}`
-    );
-    headers.append(
-      "Content-Type",
-      "application/json"
-    )
+
     // Backend URL must have been stored _with_ a final slash.
     const url = new URL(
       `access-api/accounts/${backendState.username}/withdrawals`,
@@ -501,6 +564,10 @@ export function BankHome(): VNode {
          talerWithdrawUri={pageState.talerWithdrawUri}
          accountLabel={backendState.username}>
 
+         <button onClick={() => {
+            pageStateSetter({...pageState, isLoggedIn: false})
+         }}>Sign out</button>
+
           {!pageState.withdrawalInProgress && <button onClick={() => {
             createWithdrawalCall(
               "EUR:5",
@@ -515,12 +582,18 @@ export function BankHome(): VNode {
                return {...rest, withdrawalInProgress: 
false};})}}>Close</button>
          }
 
-         {pageState.talerWithdrawUri && <button onClick={() => {
+         {pageState.talerWithdrawUri && <div><button onClick={() => {
             confirmWithdrawalCall(
               backendState,
              pageState.withdrawalId,
              pageStateSetter);}}>Confirm withdrawal</button>
-         }
+            <button onClick={() => {
+              abortWithdrawalCall(
+                backendState,
+               pageState.withdrawalId,
+               pageStateSetter);}}>Abort withdrawal</button>
+         </div>}
+
        </Account>
       </SWRWithCredentials>
     );
diff --git a/packages/bank/tests/__tests__/homepage.js 
b/packages/bank/tests/__tests__/homepage.js
index 5508453..d15433e 100644
--- a/packages/bank/tests/__tests__/homepage.js
+++ b/packages/bank/tests/__tests__/homepage.js
@@ -206,6 +206,10 @@ describe("home page", () => {
       paytoUri: "payto://iban/123/ABC"
     }))
     fireEvent.click(signinButton);
+    expect(fetch).toHaveBeenCalledWith(
+      `http://localhost/demobanks/default/access-api/accounts/${username}`,
+      expect.anything()
+    )
     await screen.findByText("balance is EUR:10", {exact: false})
   })
 

-- 
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]