commit 3a84bdbfa0957620be6721546dd6cdd902ceaa5b
parent e699cd5c2b5caec7c07d098b19cb7e29bd4e8460
Author: Sebastian <sebasjm@gmail.com>
Date: Thu, 1 May 2025 12:35:38 -0300
fix #9795
Diffstat:
5 files changed, 71 insertions(+), 26 deletions(-)
diff --git a/packages/merchant-backoffice-ui/build.mjs b/packages/merchant-backoffice-ui/build.mjs
@@ -19,6 +19,7 @@ import { build } from "@gnu-taler/web-util/build";
await build({
type: "production",
+ importMeta: import.meta,
source: {
js: ["src/index.tsx","src/lang.ts"],
assets: [{base:"src",files:["src/index.html"]}],
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputSecured.stories.tsx b/packages/merchant-backoffice-ui/src/components/form/InputSecured.stories.tsx
@@ -36,7 +36,7 @@ export const InitialValueEmpty = (): VNode => {
return (
<FormProvider<T> object={state} errors={{}} valueHandler={setState}>
Initial value: ''
- <InputSecured<T> name="auth_token" label="Access token" />
+ <InputSecured<T> name="auth_token" label="Password" />
</FormProvider>
);
};
@@ -45,7 +45,7 @@ export const InitialValueToken = (): VNode => {
const [state, setState] = useState<Partial<T>>({ auth_token: "token" });
return (
<FormProvider<T> object={state} errors={{}} valueHandler={setState}>
- <InputSecured<T> name="auth_token" label="Access token" />
+ <InputSecured<T> name="auth_token" label="Password" />
</FormProvider>
);
};
@@ -55,7 +55,7 @@ export const InitialValueNull = (): VNode => {
return (
<FormProvider<T> object={state} errors={{}} valueHandler={setState}>
Initial value: ''
- <InputSecured<T> name="auth_token" label="Access token" />
+ <InputSecured<T> name="auth_token" label="Password" />
</FormProvider>
);
};
diff --git a/packages/merchant-backoffice-ui/src/components/modal/index.tsx b/packages/merchant-backoffice-ui/src/components/modal/index.tsx
@@ -792,7 +792,7 @@ export function UpdateTokenModal({
const hasInputTheCorrectOldToken = oldToken && oldToken !== form.old_token;
const errors = undefinedIfEmpty({
old_token: hasInputTheCorrectOldToken
- ? i18n.str`Is not the same as the current access token`
+ ? i18n.str`Is not the same as the current password`
: undefined,
new_token: !form.new_token
? i18n.str`Required`
@@ -809,7 +809,7 @@ export function UpdateTokenModal({
const { state } = useSessionContext();
- const text = i18n.str`You are updating the access token for the instance with ID ${state.instance}`;
+ const text = i18n.str`You are updating the password for the instance with ID ${state.instance}`;
return (
<ClearConfirmModal
@@ -825,27 +825,27 @@ export function UpdateTokenModal({
{oldToken && (
<Input<State>
name="old_token"
- label={i18n.str`Old access token`}
- tooltip={i18n.str`Access token currently in use`}
+ label={i18n.str`Old password`}
+ tooltip={i18n.str`Password currently in use`}
inputType="password"
/>
)}
<Input<State>
name="new_token"
- label={i18n.str`New access token`}
- tooltip={i18n.str`Next access token to be used`}
+ label={i18n.str`New password`}
+ tooltip={i18n.str`Next password to be used`}
inputType="password"
/>
<Input<State>
name="repeat_token"
- label={i18n.str`Repeat access token`}
- tooltip={i18n.str`Confirm the same access token`}
+ label={i18n.str`Repeat password`}
+ tooltip={i18n.str`Confirm the same password`}
inputType="password"
/>
</FormProvider>
<p>
<i18n.Translate>
- Clearing the access token will mean public access to the instance
+ Clearing the password will mean public access to the instance
</i18n.Translate>
</p>
</div>
@@ -871,7 +871,7 @@ export function SetTokenNewInstanceModal({
new_token: !form.new_token
? i18n.str`Required`
: form.new_token === form.old_token
- ? i18n.str`Can't be the same as the old access token`
+ ? i18n.str`Can't be the same as the old password`
: undefined,
repeat_token:
form.new_token !== form.repeat_token
@@ -886,7 +886,7 @@ export function SetTokenNewInstanceModal({
<div class="modal-background " onClick={onCancel} />
<div class="modal-card">
<header class="modal-card-head">
- <p class="modal-card-title">{i18n.str`You are setting the access token for the new instance`}</p>
+ <p class="modal-card-title">{i18n.str`You are setting the password for the new instance`}</p>
<button class="delete " aria-label="close" onClick={onCancel} />
</header>
<section class="modal-card-body is-main-section">
@@ -900,14 +900,14 @@ export function SetTokenNewInstanceModal({
>
<Input<State>
name="new_token"
- label={i18n.str`New access token`}
- tooltip={i18n.str`Next access token to be used`}
+ label={i18n.str`New password`}
+ tooltip={i18n.str`Next password to be used`}
inputType="password"
/>
<Input<State>
name="repeat_token"
- label={i18n.str`Repeat access token`}
- tooltip={i18n.str`Confirm the same access token`}
+ label={i18n.str`Repeat password`}
+ tooltip={i18n.str`Confirm the same password`}
inputType="password"
/>
</FormProvider>
@@ -940,7 +940,7 @@ export function SetTokenNewInstanceModal({
onClick={() => onConfirm(form.new_token!)}
disabled={hasErrors}
>
- <i18n.Translate>Set access token</i18n.Translate>
+ <i18n.Translate>Set password</i18n.Translate>
</button>
</div>
</footer>
diff --git a/packages/merchant-backoffice-ui/src/context/session.ts b/packages/merchant-backoffice-ui/src/context/session.ts
@@ -89,6 +89,11 @@ function inferInstanceName(url: URL) {
return !match || !match[1] ? DEFAULT_ADMIN_USERNAME : match[1];
}
+function recalculateUrlForAnotherUser(original: URL, user:string) {
+ const match = INSTANCE_ID_LOOKUP.exec(original.href);
+ return !match || !match[1] ? DEFAULT_ADMIN_USERNAME : match[1];
+}
+
export const defaultState = (url: URL): SavedSession => {
return {
backendUrl: url,
@@ -114,7 +119,7 @@ export interface SessionStateHandler {
* from any to loggedIn
* @param info
*/
- logIn(token: AccessToken | undefined): void;
+ logIn(username: string, token: AccessToken | undefined): void;
/**
* from loggedIn to impersonate
* @param info
@@ -200,7 +205,7 @@ export const SessionContextProvider = ({
state: {
backendUrl: state.backendUrl,
token: state.token,
- impersonated: doingImpersonation,
+ impersonated: false, // doingImpersonation, FIXME: removing impersonation feature for 1.2
instance: currentInstance,
isAdmin: currentInstance === DEFAULT_ADMIN_USERNAME,
status: status,
@@ -237,12 +242,18 @@ export const SessionContextProvider = ({
setStatus("loggedIn");
cleanAllCache();
},
- logIn(token) {
+ logIn(username, token) {
cleanAllCache();
setStatus("loggedIn");
+ let backendUrl: URL;
+ if (currentInstance !== username) {
+ backendUrl = new URL(rootLib.subInstanceApi(username).instance.baseUrl)
+ } else {
+ backendUrl = state.backendUrl
+ }
update({
- backendUrl: state.backendUrl,
- token: token,
+ backendUrl,
+ token,
prevToken: state.prevToken,
});
},
diff --git a/packages/merchant-backoffice-ui/src/paths/login/index.tsx b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
@@ -47,17 +47,24 @@ export function LoginPage(_p: Props): VNode {
const [token, setToken] = useState("");
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { lib, state, logIn } = useSessionContext();
+ const [username, setUsername] = useState(state.instance);
const { i18n } = useTranslationContext();
async function doLoginImpl() {
- const result = await lib.instance.createAuthTokenFromToken(
+ console.log(state.instance !== username, state.instance, username);
+ const api =
+ state.instance !== username
+ ? lib.subInstanceApi(username).instance
+ : lib.instance;
+
+ const result = await api.createAuthTokenFromToken(
createRFC8959AccessTokenEncoded(token),
tokenRequest,
);
if (result.type === "ok") {
const { token } = result.body;
- logIn(token);
+ logIn(username, token);
return;
} else {
switch (result.case) {
@@ -102,6 +109,32 @@ export function LoginPage(_p: Props): VNode {
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">
+ <i18n.Translate>Username</i18n.Translate>
+ </label>
+ </div>
+ <div class="field-body">
+ <div class="field">
+ <p class="control is-expanded">
+ <input
+ class="input"
+ type="text"
+ placeholder={"instance name"}
+ name="username"
+ onKeyPress={(e) =>
+ e.keyCode === 13 ? doLoginImpl() : null
+ }
+ value={username}
+ onInput={(e): void =>
+ setUsername(e?.currentTarget.value)
+ }
+ />
+ </p>
+ </div>
+ </div>
+ </div>
+ <div class="field is-horizontal">
+ <div class="field-label is-normal">
+ <label class="label">
<i18n.Translate>Password</i18n.Translate>
</label>
</div>