aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-09-14 12:14:21 -0300
committerSebastian <sebasjm@gmail.com>2023-09-14 12:14:21 -0300
commit1653130de893a0a1bdbdef785244aa6ae34ca4e7 (patch)
tree80e19e89e0ced0738ae182786250004ee3f53618
parentdd25740c914ed76afcb1206166033626f4469fa8 (diff)
update how access token management is handled
-rw-r--r--packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/backend.ts2
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/instance.ts20
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx77
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx37
5 files changed, 80 insertions, 58 deletions
diff --git a/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx b/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx
index 8bfbdb076..ebfa2b6d6 100644
--- a/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx
+++ b/packages/merchant-backoffice-ui/src/ApplicationReadyRoutes.tsx
@@ -114,7 +114,7 @@ export function ApplicationReadyRoutes(): VNode {
<NotificationCard
notification={{
message: i18n.str`Access denied`,
- description: i18n.str`Check your token is valid 1`,
+ description: i18n.str`Check your token is valid`,
type: "ERROR",
}}
/>
diff --git a/packages/merchant-backoffice-ui/src/hooks/backend.ts b/packages/merchant-backoffice-ui/src/hooks/backend.ts
index fe4155788..eaeede103 100644
--- a/packages/merchant-backoffice-ui/src/hooks/backend.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/backend.ts
@@ -266,7 +266,7 @@ export function useBackendBaseRequest(): useBackendBaseRequestType {
endpoint: string,
options: RequestOptions = {},
): Promise<HttpResponseOk<T>> {
- return requestHandler<T>(backend, endpoint, { token, ...options }).then(res => {
+ return requestHandler<T>(backend, endpoint, { ...options, token }).then(res => {
return res
}).catch(err => {
throw err
diff --git a/packages/merchant-backoffice-ui/src/hooks/instance.ts b/packages/merchant-backoffice-ui/src/hooks/instance.ts
index 50f9487a3..0677191db 100644
--- a/packages/merchant-backoffice-ui/src/hooks/instance.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/instance.ts
@@ -36,8 +36,8 @@ interface InstanceAPI {
data: MerchantBackend.Instances.InstanceReconfigurationMessage,
) => Promise<void>;
deleteInstance: () => Promise<void>;
- clearToken: () => Promise<void>;
- setNewToken: (token: AccessToken) => Promise<void>;
+ clearAccessToken: (currentToken: AccessToken | undefined) => Promise<void>;
+ setNewAccessToken: (currentToken: AccessToken | undefined, token: AccessToken) => Promise<void>;
}
export function useAdminAPI(): AdminAPI {
@@ -111,18 +111,20 @@ export function useManagementAPI(instanceId: string): InstanceAPI {
mutateAll(/\/management\/instances/);
};
- const clearToken = async (): Promise<void> => {
+ 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 setNewToken = async (newToken: AccessToken): Promise<void> => {
+ 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 },
});
@@ -137,7 +139,7 @@ export function useManagementAPI(instanceId: string): InstanceAPI {
mutateAll(/\/management\/instances/);
};
- return { updateInstance, deleteInstance, setNewToken, clearToken };
+ return { updateInstance, deleteInstance, setNewAccessToken, clearAccessToken };
}
export function useInstanceAPI(): InstanceAPI {
@@ -172,18 +174,20 @@ export function useInstanceAPI(): InstanceAPI {
mutate([`/private/`], null);
};
- const clearToken = async (): Promise<void> => {
+ const clearAccessToken = async (currentToken: AccessToken | undefined): Promise<void> => {
await request(`/private/auth`, {
method: "POST",
+ token: currentToken,
data: { method: "external" },
});
mutate([`/private/`], null);
};
- const setNewToken = async (newToken: AccessToken): Promise<void> => {
+ const setNewAccessToken = async (currentToken: AccessToken | undefined, newToken: AccessToken): Promise<void> => {
await request(`/private/auth`, {
method: "POST",
+ token: currentToken,
data: { method: "token", token: newToken },
});
@@ -198,7 +202,7 @@ export function useInstanceAPI(): InstanceAPI {
mutate([`/private/`], null);
};
- return { updateInstance, deleteInstance, setNewToken, clearToken };
+ return { updateInstance, deleteInstance, setNewAccessToken, clearAccessToken };
}
export function useInstanceDetails(): HttpResponse<
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 4b0db200a..89dba63b2 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
@@ -30,13 +30,13 @@ import { AccessToken } from "../../../declaration.js";
interface Props {
instanceId: string;
- currentToken: string | undefined;
- onClearToken: () => void;
- onNewToken: (s: AccessToken) => void;
+ hasToken: boolean | undefined;
+ onClearToken: (c: AccessToken | undefined) => void;
+ onNewToken: (c: AccessToken | undefined, s: AccessToken) => void;
onBack?: () => void;
}
-export function DetailPage({ instanceId, currentToken: oldToken, onBack, onNewToken, onClearToken }: Props): VNode {
+export function DetailPage({ instanceId, hasToken, onBack, onNewToken, onClearToken }: Props): VNode {
type State = { old_token: string; new_token: string; repeat_token: string };
const [form, setValue] = useState<Partial<State>>({
old_token: "",
@@ -45,11 +45,9 @@ export function DetailPage({ instanceId, currentToken: oldToken, onBack, onNewTo
});
const { i18n } = useTranslationContext();
- const hasOldtoken = !!oldToken
- const hasInputTheCorrectOldToken = hasOldtoken && oldToken !== form.old_token;
const errors = {
- old_token: hasInputTheCorrectOldToken
- ? i18n.str`is not the same as the current access token`
+ old_token: hasToken && !form.old_token
+ ? i18n.str`you need your access token to perform the operation`
: undefined,
new_token: !form.new_token
? i18n.str`cannot be empty`
@@ -72,8 +70,9 @@ export function DetailPage({ instanceId, currentToken: oldToken, onBack, onNewTo
async function submitForm() {
if (hasErrors) return;
+ const ot = hasToken ? `secret-token:${form.old_token}` as AccessToken : undefined;
const nt = `secret-token:${form.new_token}` as AccessToken;
- onNewToken(nt)
+ onNewToken(ot, nt)
}
return (
@@ -98,32 +97,38 @@ export function DetailPage({ instanceId, currentToken: oldToken, onBack, onNewTo
<div class="column" />
<div class="column is-four-fifths">
<FormProvider errors={errors} object={form} valueHandler={setValue}>
- {hasOldtoken && (
- <Input<State>
- name="old_token"
- label={i18n.str`Current access token`}
- tooltip={i18n.str`access token currently in use`}
- inputType="password"
- />
- )}
- {!hasInputTheCorrectOldToken && <Fragment>
- {hasOldtoken && <Fragment>
- <p>
- <i18n.Translate>
- Clearing the access token will mean public access to the instance.
- </i18n.Translate>
- </p>
- <div class="buttons is-right mt-5">
- <button
- disabled={!!hasInputTheCorrectOldToken}
- class="button"
- onClick={onClearToken}
- >
- <i18n.Translate>Clear token</i18n.Translate>
- </button>
- </div>
- </Fragment>
- }
+ <Fragment>
+ {hasToken && (
+ <Fragment>
+ <Input<State>
+ name="old_token"
+ label={i18n.str`Current access token`}
+ tooltip={i18n.str`access token currently in use`}
+ inputType="password"
+ />
+ <p>
+ <i18n.Translate>
+ Clearing the access token will mean public access to the instance.
+ </i18n.Translate>
+ </p>
+ <div class="buttons is-right mt-5">
+ <button
+ class="button"
+ onClick={() => {
+ if (hasToken) {
+ const ot = `secret-token:${form.old_token}` as AccessToken;
+ onClearToken(ot)
+ } else {
+ onClearToken(undefined)
+ }
+ }}
+ >
+ <i18n.Translate>Clear token</i18n.Translate>
+ </button>
+ </div>
+ </Fragment>
+ )}
+
<Input<State>
name="new_token"
@@ -137,7 +142,7 @@ export function DetailPage({ instanceId, currentToken: oldToken, onBack, onNewTo
tooltip={i18n.str`confirm the same access token`}
inputType="password"
/>
- </Fragment>}
+ </Fragment>
</FormProvider>
<div class="buttons is-right mt-5">
{onBack && (
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 0a49448f8..bc2bd9fa3 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
@@ -33,8 +33,6 @@ interface Props {
onNotFound: () => VNode;
}
-const PREFIX = "secret-token:"
-
export default function Token({
onLoadError,
onChange,
@@ -44,21 +42,36 @@ export default function Token({
const { i18n } = useTranslationContext();
const [notif, setNotif] = useState<Notification | undefined>(undefined);
- const { clearToken, setNewToken } = useInstanceAPI();
- const { token: rootToken } = useBackendContext();
- const { token: instanceToken, id, admin } = useInstanceContext();
+ const { clearAccessToken, setNewAccessToken } = useInstanceAPI();
+ const { id } = useInstanceContext();
+ const result = useInstanceDetails()
+
+ if (result.loading) return <Loading />;
+ if (!result.ok) {
+ if (
+ result.type === ErrorType.CLIENT &&
+ result.status === HttpStatusCode.Unauthorized
+ )
+ return onUnauthorized();
+ if (
+ result.type === ErrorType.CLIENT &&
+ result.status === HttpStatusCode.NotFound
+ )
+ return onNotFound();
+ return onLoadError(result);
+ }
+
+ const hasToken = result.data.auth.method === "token"
- const currentToken = !admin ? rootToken : instanceToken
- const hasPrefix = currentToken !== undefined && currentToken.token.startsWith(PREFIX)
return (
<Fragment>
<NotificationCard notification={notif} />
<DetailPage
instanceId={id}
- currentToken={hasPrefix ? currentToken.token.substring(PREFIX.length) : currentToken?.token}
- onClearToken={async (): Promise<void> => {
+ hasToken={hasToken}
+ onClearToken={async (currentToken): Promise<void> => {
try {
- await clearToken();
+ await clearAccessToken(currentToken);
onChange();
} catch (error) {
if (error instanceof Error) {
@@ -70,9 +83,9 @@ export default function Token({
}
}
}}
- onNewToken={async (newToken): Promise<void> => {
+ onNewToken={async (currentToken, newToken): Promise<void> => {
try {
- await setNewToken(newToken);
+ await setNewAccessToken(currentToken, newToken);
onChange();
} catch (error) {
if (error instanceof Error) {