Merge pull request #762 from pikasTech/fix/issue753-auth-race
fix(web): bind login submit before session probe
This commit is contained in:
@@ -67,6 +67,40 @@ test("login uses cloud-api auth instead of local storage fallback", async () =>
|
||||
}
|
||||
});
|
||||
|
||||
test("login submit is wired before the initial session probe resolves", async () => {
|
||||
const sessionProbe = deferred();
|
||||
const harness = installAuthHarness({
|
||||
localSession: null,
|
||||
responses: {
|
||||
"/auth/session": sessionProbe.promise,
|
||||
"/auth/login": {
|
||||
authenticated: true,
|
||||
user: { username: "admin" },
|
||||
expiresAt: futureIso()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const pendingSession = ensureWorkbenchAuth({ loginShell: harness.loginShell, appShell: harness.appShell });
|
||||
await harness.waitForLoginReady();
|
||||
|
||||
harness.usernameInput.value = "admin";
|
||||
harness.passwordInput.value = "hwlab2026";
|
||||
await harness.submitLogin();
|
||||
|
||||
assert.deepEqual(harness.fetchCalls.map((call) => call.path), ["/auth/session", "/auth/login"]);
|
||||
sessionProbe.resolve({ authenticated: false });
|
||||
const session = await pendingSession;
|
||||
|
||||
assert.equal(session.authenticated, true);
|
||||
assert.equal(harness.loginShell.hidden, true);
|
||||
assert.equal(harness.appShell.hidden, false);
|
||||
} finally {
|
||||
harness.restore();
|
||||
}
|
||||
});
|
||||
|
||||
function installAuthHarness({ localSession, responses }) {
|
||||
const previous = {
|
||||
window: globalThis.window,
|
||||
@@ -108,13 +142,13 @@ function installAuthHarness({ localSession, responses }) {
|
||||
clearTimeout: () => {}
|
||||
};
|
||||
globalThis.fetch = async (path, options = {}) => {
|
||||
const response = responses[path] ?? { status: 404, authenticated: false };
|
||||
fetchCalls.push({
|
||||
path,
|
||||
method: options.method ?? "GET",
|
||||
body: options.body ?? null,
|
||||
credentials: options.credentials ?? null
|
||||
});
|
||||
const response = await (responses[path] ?? { status: 404, authenticated: false });
|
||||
const status = Number(response.status ?? (response.authenticated === false && response.error ? 401 : 200));
|
||||
return {
|
||||
status,
|
||||
@@ -153,6 +187,14 @@ function futureIso() {
|
||||
return new Date(Date.now() + 60 * 60 * 1000).toISOString();
|
||||
}
|
||||
|
||||
function deferred() {
|
||||
let resolve;
|
||||
const promise = new Promise((nextResolve) => {
|
||||
resolve = nextResolve;
|
||||
});
|
||||
return { promise, resolve };
|
||||
}
|
||||
|
||||
function elementStub() {
|
||||
return {
|
||||
hidden: false,
|
||||
|
||||
@@ -18,13 +18,7 @@ export async function ensureWorkbenchAuth({ loginShell, appShell }) {
|
||||
const config = resolveAuthConfig();
|
||||
hideWorkbench(appShell);
|
||||
showLogin(loginShell);
|
||||
|
||||
const session = await readActiveSession(config);
|
||||
if (session.authenticated) {
|
||||
return activateAuthenticatedWorkbench({ loginShell, appShell, session, config });
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const loginSession = new Promise((resolve) => {
|
||||
initLoginForm({
|
||||
loginShell,
|
||||
appShell,
|
||||
@@ -34,6 +28,13 @@ export async function ensureWorkbenchAuth({ loginShell, appShell }) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const session = await readActiveSession(config);
|
||||
if (session.authenticated) {
|
||||
return activateAuthenticatedWorkbench({ loginShell, appShell, session, config });
|
||||
}
|
||||
|
||||
return loginSession;
|
||||
}
|
||||
|
||||
export function initWorkbenchLogout(button) {
|
||||
|
||||
Reference in New Issue
Block a user