gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 02/06: fix challenger api


From: gnunet
Subject: [taler-wallet-core] 02/06: fix challenger api
Date: Mon, 22 Apr 2024 13:55:31 +0200

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

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

commit eada01727571fe0aae632696baa97bc4ab6be521
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Sun Apr 21 14:55:26 2024 -0300

    fix challenger api
---
 packages/taler-util/src/http-client/challenger.ts | 67 +++++++++++++++--------
 packages/taler-util/src/http-client/types.ts      |  8 +--
 packages/taler-util/src/http-common.ts            | 41 ++++++++++++++
 packages/taler-util/src/operation.ts              |  5 +-
 4 files changed, 92 insertions(+), 29 deletions(-)

diff --git a/packages/taler-util/src/http-client/challenger.ts 
b/packages/taler-util/src/http-client/challenger.ts
index fa4214aa6..8d23ed273 100644
--- a/packages/taler-util/src/http-client/challenger.ts
+++ b/packages/taler-util/src/http-client/challenger.ts
@@ -4,10 +4,13 @@ import { createPlatformHttpLib } from "../http.js";
 import { LibtoolVersion } from "../libtool-version.js";
 import {
   FailCasesByMethod,
+  RedirectResult,
   ResultByMethod,
+  opFixedSuccess,
+  opKnownAlternativeFailure,
   opKnownHttpFailure,
   opSuccessFromHttp,
-  opUnknownFailure
+  opUnknownFailure,
 } from "../operation.js";
 import {
   AccessToken,
@@ -16,7 +19,8 @@ import {
   codecForChallengeStatus,
   codecForChallengerAuthResponse,
   codecForChallengerInfoResponse,
-  codecForChallengerTermsOfServiceResponse
+  codecForChallengerTermsOfServiceResponse,
+  codecForInvalidPinResponse,
 } from "./types.js";
 import { makeBearerTokenAuthHeader } from "./utils.js";
 
@@ -91,7 +95,12 @@ export class ChallengerHttpClient {
    * https://docs.taler.net/core/api-challenger.html#post--authorize-$NONCE
    *
    */
-  async login(nonce: string, clientId: string, redirectUri: string, state: 
string | undefined) {
+  async login(
+    nonce: string,
+    clientId: string,
+    redirectUri: string,
+    state: string | undefined,
+  ) {
     const url = new URL(`authorize/${nonce}`, this.baseUrl);
     url.searchParams.set("response_type", "code");
     url.searchParams.set("client_id", clientId);
@@ -127,17 +136,23 @@ export class ChallengerHttpClient {
    */
   async challenge(nonce: string, body: Record<"email", string>) {
     const url = new URL(`challenge/${nonce}`, this.baseUrl);
-    
+
     const resp = await this.httpLib.fetch(url.href, {
       method: "POST",
       body: new URLSearchParams(Object.entries(body)).toString(),
       headers: {
-        "Content-Type": "application/x-www-form-urlencoded"
-      }
+        "Content-Type": "application/x-www-form-urlencoded",
+      },
+      redirect: "manual",
     });
     switch (resp.status) {
       case HttpStatusCode.Ok:
         return opSuccessFromHttp(resp, codecForChallengeCreateResponse());
+      case HttpStatusCode.Found:
+        const redirect = resp.headers.get("Location")!;
+        return opFixedSuccess<RedirectResult>({
+          redirectURL: new URL(redirect),
+        });
       case HttpStatusCode.BadRequest:
         return opKnownHttpFailure(resp.status, resp);
       case HttpStatusCode.NotFound:
@@ -165,23 +180,25 @@ export class ChallengerHttpClient {
       method: "POST",
       body: new URLSearchParams(Object.entries(body)).toString(),
       headers: {
-        "Content-Type": "application/x-www-form-urlencoded"
+        "Content-Type": "application/x-www-form-urlencoded",
       },
       redirect: "manual",
     });
     switch (resp.status) {
       case HttpStatusCode.Found:
-        const redirect = resp.headers.get("Location")!
-        const uri = new URL(redirect)
-        const code = uri.searchParams.get("code")!
-        return {
-          type: "ok" as const,
-          body: { code }
-        }
-        // return opSuccessFromHttp(resp, codecForChallengeCreateResponse());
+        const redirect = resp.headers.get("Location")!;
+        return opFixedSuccess<RedirectResult>({
+          redirectURL: new URL(redirect),
+        });
       case HttpStatusCode.BadRequest:
         return opKnownHttpFailure(resp.status, resp);
-      case HttpStatusCode.NotFound: 
+      case HttpStatusCode.Forbidden:
+        return opKnownAlternativeFailure(
+          resp,
+          resp.status,
+          codecForInvalidPinResponse(),
+        );
+      case HttpStatusCode.NotFound:
         return opKnownHttpFailure(resp.status, resp);
       case HttpStatusCode.NotAcceptable:
         return opKnownHttpFailure(resp.status, resp);
@@ -210,15 +227,17 @@ export class ChallengerHttpClient {
     const resp = await this.httpLib.fetch(url.href, {
       method: "POST",
       headers: {
-        "Content-Type": "application/x-www-form-urlencoded"
+        "Content-Type": "application/x-www-form-urlencoded",
       },
-      body: new URLSearchParams(Object.entries({
-        client_id,
-        redirect_uri,
-        client_secret,
-        code,
-        grant_type: "authorization_code",
-      })).toString(),
+      body: new URLSearchParams(
+        Object.entries({
+          client_id,
+          redirect_uri,
+          client_secret,
+          code,
+          grant_type: "authorization_code",
+        }),
+      ).toString(),
     });
     switch (resp.status) {
       case HttpStatusCode.Ok:
diff --git a/packages/taler-util/src/http-client/types.ts 
b/packages/taler-util/src/http-client/types.ts
index e12c2ed6b..13ef9a3e6 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -1533,7 +1533,7 @@ export const codecForChallengeCreateResponse =
 export const codecForInvalidPinResponse =
   (): Codec<ChallengerApi.InvalidPinResponse> =>
     buildCodecForObject<ChallengerApi.InvalidPinResponse>()
-      .property("ec", codecForNumber())
+      .property("ec", codecOptional(codecForNumber()))
       .property("hint", codecForAny())
       .property("addresses_left", codecForNumber())
       .property("pin_transmissions_left", codecForNumber())
@@ -5319,17 +5319,17 @@ export namespace ChallengerApi {
 
     // timestamp explaining when we would re-transmit the challenge the next
     // time (at the earliest) if requested by the user
-    next_tx_time: String;
+    next_tx_time: string;
   }
 
   export interface InvalidPinResponse {
     // numeric Taler error code, should be shown to indicate the error
     // compactly for reporting to developers
-    ec: Integer;
+    ec?: number;
 
     // human-readable Taler error code, should be shown for the user to
     // understand the error
-    hint: String;
+    hint: string;
 
     // how many times is the user still allowed to change the address;
     // if 0, the user should not be shown a link to jump to the
diff --git a/packages/taler-util/src/http-common.ts 
b/packages/taler-util/src/http-common.ts
index cc75debd5..d8cd36287 100644
--- a/packages/taler-util/src/http-common.ts
+++ b/packages/taler-util/src/http-common.ts
@@ -268,6 +268,47 @@ export async function 
readSuccessResponseJsonOrErrorCode<T>(
   };
 }
 
+export async function readResponseJsonOrErrorCode<T>(
+  httpResponse: HttpResponse,
+  codec: Codec<T>,
+): Promise<{ isError: boolean; response: T }> {
+  let respJson;
+  try {
+    respJson = await httpResponse.json();
+  } catch (e: any) {
+    throw TalerError.fromDetail(
+      TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+      {
+        requestUrl: httpResponse.requestUrl,
+        requestMethod: httpResponse.requestMethod,
+        httpStatusCode: httpResponse.status,
+        validationError: e.toString(),
+      },
+      "Couldn't parse JSON format from response",
+    );
+  }
+  let parsedResponse: T;
+  try {
+    parsedResponse = codec.decode(respJson);
+  } catch (e: any) {
+    throw TalerError.fromDetail(
+      TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
+      {
+        requestUrl: httpResponse.requestUrl,
+        requestMethod: httpResponse.requestMethod,
+        httpStatusCode: httpResponse.status,
+        validationError: e.toString(),
+      },
+      "Response invalid",
+    );
+  }
+  return {
+    isError: !(httpResponse.status >= 200 && httpResponse.status < 300),
+    response: parsedResponse,
+  };
+}
+
+
 type HttpErrorDetails = {
   requestUrl: string;
   requestMethod: string;
diff --git a/packages/taler-util/src/operation.ts 
b/packages/taler-util/src/operation.ts
index 771f5860b..e2ab9d4e4 100644
--- a/packages/taler-util/src/operation.ts
+++ b/packages/taler-util/src/operation.ts
@@ -19,6 +19,7 @@
  */
 import {
   HttpResponse,
+  readResponseJsonOrErrorCode,
   readSuccessResponseJsonOrThrow,
   readTalerErrorResponse,
 } from "./http-common.js";
@@ -126,7 +127,7 @@ export async function opKnownAlternativeFailure<T extends 
HttpStatusCode, B>(
   s: T,
   codec: Codec<B>,
 ): Promise<OperationAlternative<T, B>> {
-  const body = await readSuccessResponseJsonOrThrow(resp, codec);
+  const body = (await readResponseJsonOrErrorCode(resp, codec)).response;
   return { type: "fail", case: s, body };
 }
 
@@ -193,3 +194,5 @@ export type FailCasesByMethod<TT extends object, p extends 
keyof TT> = Exclude<
   ResultByMethod<TT, p>,
   OperationOk<any>
 >;
+
+export type RedirectResult = { redirectURL: URL }

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