diff options
author | Özgür Kesim <oec-taler@kesim.org> | 2023-10-06 16:33:05 +0200 |
---|---|---|
committer | Özgür Kesim <oec-taler@kesim.org> | 2023-10-06 16:33:05 +0200 |
commit | fe7b51ef2736edbf04f5bbd9d19f2a2d04baccc2 (patch) | |
tree | 66c68c8d6a666f6e74dc663c9ee4f07879f6626c /packages/demobank-ui/src/hooks/backend.ts | |
parent | 35611f0bf9cf67638b171c2a300fab1797d3d8f0 (diff) | |
parent | 97d7be7503168f4f3bbd05905d32aa76ca1636b2 (diff) |
Merge branch 'master' into age-withdraw
Diffstat (limited to 'packages/demobank-ui/src/hooks/backend.ts')
-rw-r--r-- | packages/demobank-ui/src/hooks/backend.ts | 113 |
1 files changed, 63 insertions, 50 deletions
diff --git a/packages/demobank-ui/src/hooks/backend.ts b/packages/demobank-ui/src/hooks/backend.ts index 4b60d1b6c..889618646 100644 --- a/packages/demobank-ui/src/hooks/backend.ts +++ b/packages/demobank-ui/src/hooks/backend.ts @@ -40,21 +40,24 @@ import { useCallback, useEffect, useState } from "preact/hooks"; import { useSWRConfig } from "swr"; import { useBackendContext } from "../context/backend.js"; import { bankUiSettings } from "../settings.js"; +import { AccessToken } from "./useCredentialsChecker.js"; /** * Has the information to reach and * authenticate at the bank's backend. */ -export type BackendState = LoggedIn | LoggedOut; +export type BackendState = LoggedIn | LoggedOut | Expired; -export interface BackendCredentials { +interface LoggedIn { + status: "loggedIn"; + isUserAdministrator: boolean; username: string; - password: string; + token: AccessToken; } - -interface LoggedIn extends BackendCredentials { - status: "loggedIn"; +interface Expired { + status: "expired"; isUserAdministrator: boolean; + username: string; } interface LoggedOut { status: "loggedOut"; @@ -64,10 +67,17 @@ export const codecForBackendStateLoggedIn = (): Codec<LoggedIn> => buildCodecForObject<LoggedIn>() .property("status", codecForConstString("loggedIn")) .property("username", codecForString()) - .property("password", codecForString()) + .property("token", codecForString() as Codec<AccessToken>) .property("isUserAdministrator", codecForBoolean()) .build("BackendState.LoggedIn"); +export const codecForBackendStateExpired = (): Codec<Expired> => + buildCodecForObject<Expired>() + .property("status", codecForConstString("expired")) + .property("username", codecForString()) + .property("isUserAdministrator", codecForBoolean()) + .build("BackendState.Expired"); + export const codecForBackendStateLoggedOut = (): Codec<LoggedOut> => buildCodecForObject<LoggedOut>() .property("status", codecForConstString("loggedOut")) @@ -78,6 +88,7 @@ export const codecForBackendState = (): Codec<BackendState> => .discriminateOn("status") .alternative("loggedIn", codecForBackendStateLoggedIn()) .alternative("loggedOut", codecForBackendStateLoggedOut()) + .alternative("expired", codecForBackendStateExpired()) .build("BackendState"); export function getInitialBackendBaseURL(): string { @@ -85,18 +96,27 @@ export function getInitialBackendBaseURL(): string { typeof localStorage !== "undefined" ? localStorage.getItem("bank-base-url") : undefined; + let result: string; if (!overrideUrl) { //normal path if (!bankUiSettings.backendBaseURL) { console.error( "ERROR: backendBaseURL was overridden by a setting file and missing. Setting value to 'window.origin'", ); - return canonicalizeBaseUrl(window.origin); + result = window.origin + } else { + result = bankUiSettings.backendBaseURL; } - return canonicalizeBaseUrl(bankUiSettings.backendBaseURL); + } else { + // testing/development path + result = overrideUrl + } + try { + return canonicalizeBaseUrl(result) + } catch (e) { + //fall back + return canonicalizeBaseUrl(window.origin) } - // testing/development path - return canonicalizeBaseUrl(overrideUrl); } export const defaultState: BackendState = { @@ -106,7 +126,8 @@ export const defaultState: BackendState = { export interface BackendStateHandler { state: BackendState; logOut(): void; - logIn(info: BackendCredentials): void; + expired(): void; + logIn(info: {username: string, token: AccessToken}): void; } const BACKEND_STATE_KEY = buildStorageKey( @@ -124,12 +145,22 @@ export function useBackendState(): BackendStateHandler { BACKEND_STATE_KEY, defaultState, ); + const mutateAll = useMatchMutate(); return { state, logOut() { update(defaultState); }, + expired() { + if (state.status === "loggedOut") return; + const nextState: BackendState = { + status: "expired", + username: state.username, + isUserAdministrator: state.username === "admin", + }; + update(nextState); + }, logIn(info) { //admin is defined by the username const nextState: BackendState = { @@ -138,6 +169,7 @@ export function useBackendState(): BackendStateHandler { isUserAdministrator: info.username === "admin", }; update(nextState); + mutateAll(/.*/) }, }; } @@ -150,7 +182,7 @@ interface useBackendType { fetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>; multiFetcher: <T>(endpoint: string[][]) => Promise<HttpResponseOk<T>[]>; paginatedFetcher: <T>( - args: [string, number, number], + args: [string, string | undefined, number], ) => Promise<HttpResponseOk<T>>; sandboxAccountsFetcher: <T>( args: [string, number, number, string], @@ -179,13 +211,15 @@ export function usePublicBackend(): useBackendType { [baseUrl], ); const paginatedFetcher = useCallback( - function fetcherImpl<T>([endpoint, page, size]: [ + function fetcherImpl<T>([endpoint, start, size]: [ string, - number, + string | undefined, number, ]): Promise<HttpResponseOk<T>> { + const delta = -1 * size //descending order + const params = start ? { delta, start } : { delta } return requestHandler<T>(baseUrl, endpoint, { - params: { page: page || 1, size }, + params, }); }, [baseUrl], @@ -247,35 +281,12 @@ interface InvalidationResult { error: unknown; } -export function useCredentialsChecker() { - const { request } = useApiContext(); - const baseUrl = getInitialBackendBaseURL(); - //check against account details endpoint - //while sandbox backend doesn't have a login endpoint - return async function testLogin( - username: string, - password: string, - ): Promise<CheckResult> { - try { - await request(baseUrl, `access-api/accounts/${username}/`, { - basicAuth: { username, password }, - preventCache: true, - }); - return { valid: true }; - } catch (error) { - if (error instanceof RequestError) { - return { valid: false, requestError: true, cause: error.cause }; - } - return { valid: false, requestError: false, error }; - } - }; -} - export function useAuthenticatedBackend(): useBackendType { const { state } = useBackendContext(); const { request: requestHandler } = useApiContext(); - const creds = state.status === "loggedIn" ? state : undefined; + // FIXME: libeufin returns 400 insteand of 401 if there is no auth token + const creds = state.status === "loggedIn" ? state.token : "secret-token:a"; const baseUrl = getInitialBackendBaseURL(); const request = useCallback( @@ -283,26 +294,28 @@ export function useAuthenticatedBackend(): useBackendType { path: string, options: RequestOptions = {}, ): Promise<HttpResponseOk<T>> { - return requestHandler<T>(baseUrl, path, { basicAuth: creds, ...options }); + return requestHandler<T>(baseUrl, path, { token: creds, ...options }); }, [baseUrl, creds], ); const fetcher = useCallback( function fetcherImpl<T>(endpoint: string): Promise<HttpResponseOk<T>> { - return requestHandler<T>(baseUrl, endpoint, { basicAuth: creds }); + return requestHandler<T>(baseUrl, endpoint, { token: creds }); }, [baseUrl, creds], ); const paginatedFetcher = useCallback( - function fetcherImpl<T>([endpoint, page = 1, size]: [ + function fetcherImpl<T>([endpoint, start, size]: [ string, - number, + string | undefined, number, ]): Promise<HttpResponseOk<T>> { + const delta = -1 * size //descending order + const params = start ? { delta, start } : { delta } return requestHandler<T>(baseUrl, endpoint, { - basicAuth: creds, - params: { page, size }, + token: creds, + params, }); }, [baseUrl, creds], @@ -313,7 +326,7 @@ export function useAuthenticatedBackend(): useBackendType { > { return Promise.all( endpoints.map((endpoint) => - requestHandler<T>(baseUrl, endpoint, { basicAuth: creds }), + requestHandler<T>(baseUrl, endpoint, { token: creds }), ), ); }, @@ -327,7 +340,7 @@ export function useAuthenticatedBackend(): useBackendType { string, ]): Promise<HttpResponseOk<T>> { return requestHandler<T>(baseUrl, endpoint, { - basicAuth: creds, + token: creds, params: { page: page || 1, size }, }); }, @@ -339,7 +352,7 @@ export function useAuthenticatedBackend(): useBackendType { HttpResponseOk<T> > { return requestHandler<T>(baseUrl, endpoint, { - basicAuth: creds, + token: creds, params: { account }, }); }, |