diff options
author | Sebastian <sebasjm@gmail.com> | 2023-11-21 10:08:19 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-11-21 10:08:19 -0300 |
commit | 77eb29cb7caf50e870ada861a4ef83712a31a1cb (patch) | |
tree | 8d5a55ea8ea7da6d670af2c1b390715418cad86b /packages/merchant-backoffice-ui | |
parent | 7c8c7692fb179e049ca80087d3573dc9b256fcdb (diff) | |
download | wallet-core-77eb29cb7caf50e870ada861a4ef83712a31a1cb.tar.xz |
set auth token on instance creation
Diffstat (limited to 'packages/merchant-backoffice-ui')
5 files changed, 80 insertions, 59 deletions
diff --git a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx index dcb3e21ea..c3c20bcc4 100644 --- a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx +++ b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx @@ -229,7 +229,7 @@ export function InstanceRoutes({ <InstanceCreatePage forceId="default" onConfirm={() => { - route(AdminPaths.list_instances); + route(InstancePaths.order_list); }} /> </Fragment> @@ -299,7 +299,7 @@ export function InstanceRoutes({ component={InstanceCreatePage} onBack={() => route(AdminPaths.list_instances)} onConfirm={() => { - route(AdminPaths.list_instances); + route(InstancePaths.order_list); }} /> )} @@ -342,6 +342,9 @@ export function InstanceRoutes({ onChange={() => { route(`/`); }} + onCancel={() => { + route(InstancePaths.order_list) + }} onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} onUnauthorized={LoginPageAccessDenied} onLoadError={ServerErrorRedirectTo(InstancePaths.error)} diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx index e5072a2b8..093c24c3d 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx @@ -31,6 +31,7 @@ import { DefaultInstanceFormFields } from "../../../components/instance/DefaultI import { MerchantBackend } from "../../../declaration.js"; import { INSTANCE_ID_REGEX } from "../../../utils/constants.js"; import { undefinedIfEmpty } from "../../../utils/table.js"; +import { SetTokenNewInstanceModal } from "../../../components/modal/index.js"; export type Entity = MerchantBackend.Instances.InstanceConfigurationMessage & { auth_token?: string; @@ -47,7 +48,7 @@ function with_defaults(id?: string): Partial<Entity> { id, // accounts: [], user_type: "business", - use_stefan: false, + use_stefan: true, default_pay_delay: { d_us: 2 * 1000 * 60 * 60 * 1000 }, // two hours default_wire_transfer_delay: { d_us: 1000 * 2 * 60 * 60 * 24 * 1000 }, // two days }; @@ -55,9 +56,9 @@ function with_defaults(id?: string): Partial<Entity> { export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { const [value, valueHandler] = useState(with_defaults(forceId)); - // const [isTokenSet, updateIsTokenSet] = useState<boolean>(false); - // const [isTokenDialogActive, updateIsTokenDialogActive] = - // useState<boolean>(false); + const [isTokenSet, updateIsTokenSet] = useState<boolean>(false); + const [isTokenDialogActive, updateIsTokenDialogActive] = + useState<boolean>(false); const { i18n } = useTranslationContext(); @@ -68,6 +69,7 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { ? i18n.str`is not valid` : undefined, name: !value.name ? i18n.str`required` : undefined, + user_type: !value.user_type ? i18n.str`required` : value.user_type !== "business" && value.user_type !== "individual" @@ -113,12 +115,11 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { const submit = (): Promise<void> => { // use conversion instead of this - // const newToken = value.auth_token; - // value.auth_token = undefined; - value.auth = { method: "external" } - // newToken === null || newToken === undefined - // ? { method: "external" } - // : { method: "token", token: `secret-token:${newToken}` }; + const newToken = value.auth_token; + value.auth_token = undefined; + value.auth = newToken === null || newToken === undefined + ? { method: "external" } + : { method: "token", token: `secret-token:${newToken}` }; if (!value.address) value.address = {}; if (!value.jurisdiction) value.jurisdiction = {}; // remove above use conversion @@ -126,16 +127,16 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { return onCreate(value as Entity); }; - // function updateToken(token: string | null) { - // valueHandler((old) => ({ - // ...old, - // auth_token: token === null ? undefined : token, - // })); - // } + function updateToken(token: string | null) { + valueHandler((old) => ({ + ...old, + auth_token: token === null ? undefined : token, + })); + } return ( <div> - {/* <div class="columns"> + <div class="columns"> <div class="column" /> <div class="column is-four-fifths"> {isTokenDialogActive && ( @@ -158,11 +159,21 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { )} </div> <div class="column" /> - </div> */} + </div> - {/* <section class="hero is-hero-bar"> - <div class="hero-body"> - <div class="level"> + <section class="section is-main-section"> + <div class="columns"> + <div class="column" /> + <div class="column is-four-fifths"> + <FormProvider<Entity> + errors={errors} + object={value} + valueHandler={valueHandler} + > + <DefaultInstanceFormFields readonlyId={!!forceId} showId={true} /> + </FormProvider> + + <div class="level"> <div class="level-item has-text-centered"> <h1 class="title"> <button @@ -211,21 +222,6 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { )} </div> </div> - </div> - </section> */} - - <section class="section is-main-section"> - <div class="columns"> - <div class="column" /> - <div class="column is-four-fifths"> - <FormProvider<Entity> - errors={errors} - object={value} - valueHandler={valueHandler} - > - <DefaultInstanceFormFields readonlyId={!!forceId} showId={true} /> - </FormProvider> - <div class="buttons is-right mt-5"> {onBack && ( <button class="button" onClick={onBack}> @@ -234,7 +230,7 @@ export function CreatePage({ onCreate, onBack, forceId }: Props): VNode { )} <AsyncButton onClick={submit} - disabled={hasErrors} + disabled={hasErrors || !isTokenSet} data-tooltip={ hasErrors ? i18n.str`Need to complete marked fields and choose authorization method` 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 a4013349a..23f41ecff 100644 --- a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx @@ -21,11 +21,12 @@ import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { NotificationCard } from "../../../components/menu/index.js"; -import { MerchantBackend } from "../../../declaration.js"; -import { useAdminAPI } from "../../../hooks/instance.js"; +import { AccessToken, MerchantBackend } from "../../../declaration.js"; +import { useAdminAPI, useInstanceAPI } from "../../../hooks/instance.js"; import { Notification } from "../../../utils/types.js"; import { CreatePage } from "./CreatePage.js"; -import { InstanceCreatedSuccessfully } from "./InstanceCreatedSuccessfully.js"; +import { useCredentialsChecker } from "../../../hooks/backend.js"; +import { useBackendContext } from "../../../context/backend.js"; interface Props { onBack?: () => void; @@ -37,14 +38,9 @@ export type Entity = MerchantBackend.Instances.InstanceConfigurationMessage; export default function Create({ onBack, onConfirm, forceId }: Props): VNode { const { createInstance } = useAdminAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); - const [createdOk, setCreatedOk] = useState<Entity | undefined>(undefined); const { i18n } = useTranslationContext(); - - if (createdOk) { - return ( - <InstanceCreatedSuccessfully entity={createdOk} onConfirm={onConfirm} /> - ); - } + const { requestNewLoginToken } = useCredentialsChecker() + const { url: backendURL, updateToken } = useBackendContext() return ( <Fragment> @@ -53,20 +49,32 @@ export default function Create({ onBack, onConfirm, forceId }: Props): VNode { <CreatePage onBack={onBack} forceId={forceId} - onCreate={( + onCreate={async ( d: MerchantBackend.Instances.InstanceConfigurationMessage, ) => { - return createInstance(d) - .then(() => { - setCreatedOk(d); - }) - .catch((error) => { + try { + await createInstance(d) + if (d.auth.token) { + const resp = await requestNewLoginToken(backendURL, d.auth.token as AccessToken) + if (resp.valid) { + const { token, expiration } = resp + updateToken({ token, expiration }); + } else { + updateToken(undefined) + } + } + onConfirm(); + } catch (ex) { + if (ex instanceof Error) { setNotif({ message: i18n.str`Failed to create instance`, type: "ERROR", - description: error.message, + description: ex.message, }); - }); + } else { + console.error(ex) + } + } }} /> </Fragment> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx index 89dba63b2..d22a9e4d4 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx @@ -27,6 +27,7 @@ import { FormProvider } from "../../../components/form/FormProvider.js"; import { Input } from "../../../components/form/Input.js"; import { useInstanceContext } from "../../../context/instance.js"; import { AccessToken } from "../../../declaration.js"; +import { NotificationCard } from "../../../components/menu/index.js"; interface Props { instanceId: string; @@ -66,7 +67,7 @@ export function DetailPage({ instanceId, hasToken, onBack, onNewToken, onClearTo const instance = useInstanceContext(); - const text = i18n.str`You are updating the access token from instance with id ${instance.id}`; + const text = i18n.str`You are updating the access token from instance with id "${instance.id}"`; async function submitForm() { if (hasErrors) return; @@ -84,7 +85,7 @@ export function DetailPage({ instanceId, hasToken, onBack, onNewToken, onClearTo <div class="level-left"> <div class="level-item"> <span class="is-size-4"> - Instance id: <b>{instanceId}</b> + {text} </span> </div> </div> @@ -92,6 +93,16 @@ export function DetailPage({ instanceId, hasToken, onBack, onNewToken, onClearTo </div> </section> <hr /> + + {!hasToken && + <NotificationCard + notification={{ + message: i18n.str`This instance doesn't have authentication token.`, + description: i18n.str`You can leave it empty if there is another layer of security.`, + type: "WARN", + }} + /> + } <div class="columns"> <div class="column" /> 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 bc2bd9fa3..22365c9e1 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx @@ -31,6 +31,7 @@ interface Props { onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode; onChange: () => void; onNotFound: () => VNode; + onCancel: () => void; } export default function Token({ @@ -38,6 +39,7 @@ export default function Token({ onChange, onUnauthorized, onNotFound, + onCancel, }: Props): VNode { const { i18n } = useTranslationContext(); @@ -68,6 +70,7 @@ export default function Token({ <NotificationCard notification={notif} /> <DetailPage instanceId={id} + onBack={onCancel} hasToken={hasToken} onClearToken={async (currentToken): Promise<void> => { try { |