diff options
Diffstat (limited to 'packages/auditor-backoffice-ui/src/hooks/instance.ts')
-rw-r--r-- | packages/auditor-backoffice-ui/src/hooks/instance.ts | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/packages/auditor-backoffice-ui/src/hooks/instance.ts b/packages/auditor-backoffice-ui/src/hooks/instance.ts new file mode 100644 index 000000000..0677191db --- /dev/null +++ b/packages/auditor-backoffice-ui/src/hooks/instance.ts @@ -0,0 +1,313 @@ +/* + This file is part of GNU Taler + (C) 2021-2023 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +import { + HttpResponse, + HttpResponseOk, + RequestError, +} from "@gnu-taler/web-util/browser"; +import { useBackendContext } from "../context/backend.js"; +import { AccessToken, MerchantBackend } from "../declaration.js"; +import { + useBackendBaseRequest, + useBackendInstanceRequest, + useCredentialsChecker, + useMatchMutate, +} from "./backend.js"; + +// FIX default import https://github.com/microsoft/TypeScript/issues/49189 +import _useSWR, { SWRHook, useSWRConfig } from "swr"; +const useSWR = _useSWR as unknown as SWRHook; + +interface InstanceAPI { + updateInstance: ( + data: MerchantBackend.Instances.InstanceReconfigurationMessage, + ) => Promise<void>; + deleteInstance: () => Promise<void>; + clearAccessToken: (currentToken: AccessToken | undefined) => Promise<void>; + setNewAccessToken: (currentToken: AccessToken | undefined, token: AccessToken) => Promise<void>; +} + +export function useAdminAPI(): AdminAPI { + const { request } = useBackendBaseRequest(); + const mutateAll = useMatchMutate(); + + const createInstance = async ( + instance: MerchantBackend.Instances.InstanceConfigurationMessage, + ): Promise<void> => { + await request(`/management/instances`, { + method: "POST", + data: instance, + }); + + mutateAll(/\/management\/instances/); + }; + + const deleteInstance = async (id: string): Promise<void> => { + await request(`/management/instances/${id}`, { + method: "DELETE", + }); + + mutateAll(/\/management\/instances/); + }; + + const purgeInstance = async (id: string): Promise<void> => { + await request(`/management/instances/${id}`, { + method: "DELETE", + params: { + purge: "YES", + }, + }); + + mutateAll(/\/management\/instances/); + }; + + return { createInstance, deleteInstance, purgeInstance }; +} + +export interface AdminAPI { + createInstance: ( + data: MerchantBackend.Instances.InstanceConfigurationMessage, + ) => Promise<void>; + deleteInstance: (id: string) => Promise<void>; + purgeInstance: (id: string) => Promise<void>; +} + +export function useManagementAPI(instanceId: string): InstanceAPI { + const mutateAll = useMatchMutate(); + const { url: backendURL } = useBackendContext() + const { updateToken } = useBackendContext(); + const { request } = useBackendBaseRequest(); + const { requestNewLoginToken } = useCredentialsChecker() + + const updateInstance = async ( + instance: MerchantBackend.Instances.InstanceReconfigurationMessage, + ): Promise<void> => { + await request(`/management/instances/${instanceId}`, { + method: "PATCH", + data: instance, + }); + + mutateAll(/\/management\/instances/); + }; + + const deleteInstance = async (): Promise<void> => { + await request(`/management/instances/${instanceId}`, { + method: "DELETE", + }); + + mutateAll(/\/management\/instances/); + }; + + const clearAccessToken = async (currentToken: AccessToken | undefined): Promise<void> => { + await request(`/management/instances/${instanceId}/auth`, { + method: "POST", + token: currentToken, + data: { method: "external" }, + }); + + mutateAll(/\/management\/instances/); + }; + + const setNewAccessToken = async (currentToken: AccessToken | undefined, newToken: AccessToken): Promise<void> => { + await request(`/management/instances/${instanceId}/auth`, { + method: "POST", + token: currentToken, + data: { method: "token", token: newToken }, + }); + + const resp = await requestNewLoginToken(backendURL, newToken) + if (resp.valid) { + const { token, expiration } = resp + updateToken({ token, expiration }); + } else { + updateToken(undefined) + } + + mutateAll(/\/management\/instances/); + }; + + return { updateInstance, deleteInstance, setNewAccessToken, clearAccessToken }; +} + +export function useInstanceAPI(): InstanceAPI { + const { mutate } = useSWRConfig(); + const { url: backendURL, updateToken } = useBackendContext() + + const { + token: adminToken, + } = useBackendContext(); + const { request } = useBackendInstanceRequest(); + const { requestNewLoginToken } = useCredentialsChecker() + + const updateInstance = async ( + instance: MerchantBackend.Instances.InstanceReconfigurationMessage, + ): Promise<void> => { + await request(`/private/`, { + method: "PATCH", + data: instance, + }); + + if (adminToken) mutate(["/private/instances", adminToken, backendURL], null); + mutate([`/private/`], null); + }; + + const deleteInstance = async (): Promise<void> => { + await request(`/private/`, { + method: "DELETE", + // token: adminToken, + }); + + if (adminToken) mutate(["/private/instances", adminToken, backendURL], null); + mutate([`/private/`], null); + }; + + const clearAccessToken = async (currentToken: AccessToken | undefined): Promise<void> => { + await request(`/private/auth`, { + method: "POST", + token: currentToken, + data: { method: "external" }, + }); + + mutate([`/private/`], null); + }; + + const setNewAccessToken = async (currentToken: AccessToken | undefined, newToken: AccessToken): Promise<void> => { + await request(`/private/auth`, { + method: "POST", + token: currentToken, + data: { method: "token", token: newToken }, + }); + + const resp = await requestNewLoginToken(backendURL, newToken) + if (resp.valid) { + const { token, expiration } = resp + updateToken({ token, expiration }); + } else { + updateToken(undefined) + } + + mutate([`/private/`], null); + }; + + return { updateInstance, deleteInstance, setNewAccessToken, clearAccessToken }; +} + +export function useInstanceDetails(): HttpResponse< + MerchantBackend.Instances.QueryInstancesResponse, + MerchantBackend.ErrorDetail +> { + const { fetcher } = useBackendInstanceRequest(); + + const { data, error, isValidating } = useSWR< + HttpResponseOk<MerchantBackend.Instances.QueryInstancesResponse>, + RequestError<MerchantBackend.ErrorDetail> + >([`/private/`], fetcher, { + refreshInterval: 0, + refreshWhenHidden: false, + revalidateOnFocus: false, + revalidateOnReconnect: false, + refreshWhenOffline: false, + revalidateIfStale: false, + errorRetryCount: 0, + errorRetryInterval: 1, + shouldRetryOnError: false, + }); + + if (isValidating) return { loading: true, data: data?.data }; + if (data) return data; + if (error) return error.cause; + return { loading: true }; +} + +type KYCStatus = + | { type: "ok" } + | { type: "redirect"; status: MerchantBackend.KYC.AccountKycRedirects }; + +export function useInstanceKYCDetails(): HttpResponse< + KYCStatus, + MerchantBackend.ErrorDetail +> { + const { fetcher } = useBackendInstanceRequest(); + + const { data, error } = useSWR< + HttpResponseOk<MerchantBackend.KYC.AccountKycRedirects>, + RequestError<MerchantBackend.ErrorDetail> + >([`/private/kyc`], fetcher, { + refreshInterval: 60 * 1000, + refreshWhenHidden: false, + revalidateOnFocus: false, + revalidateIfStale: false, + revalidateOnMount: false, + revalidateOnReconnect: false, + refreshWhenOffline: false, + errorRetryCount: 0, + errorRetryInterval: 1, + shouldRetryOnError: false, + }); + + if (data) { + if (data.info?.status === 202) + return { ok: true, data: { type: "redirect", status: data.data } }; + return { ok: true, data: { type: "ok" } }; + } + if (error) return error.cause; + return { loading: true }; +} + +export function useManagedInstanceDetails( + instanceId: string, +): HttpResponse< + MerchantBackend.Instances.QueryInstancesResponse, + MerchantBackend.ErrorDetail +> { + const { request } = useBackendBaseRequest(); + + const { data, error, isValidating } = useSWR< + HttpResponseOk<MerchantBackend.Instances.QueryInstancesResponse>, + RequestError<MerchantBackend.ErrorDetail> + >([`/management/instances/${instanceId}`], request, { + refreshInterval: 0, + refreshWhenHidden: false, + revalidateOnFocus: false, + revalidateOnReconnect: false, + refreshWhenOffline: false, + errorRetryCount: 0, + errorRetryInterval: 1, + shouldRetryOnError: false, + }); + + if (isValidating) return { loading: true, data: data?.data }; + if (data) return data; + if (error) return error.cause; + return { loading: true }; +} + +export function useBackendInstances(): HttpResponse< + MerchantBackend.Instances.InstancesResponse, + MerchantBackend.ErrorDetail +> { + const { request } = useBackendBaseRequest(); + + const { data, error, isValidating } = useSWR< + HttpResponseOk<MerchantBackend.Instances.InstancesResponse>, + RequestError<MerchantBackend.ErrorDetail> + >(["/management/instances"], request); + + if (isValidating) return { loading: true, data: data?.data }; + if (data) return data; + if (error) return error.cause; + return { loading: true }; +} |