ed9d40815e
Co-authored-by: root <root@lyon.remote>
77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { createHash } from "node:crypto";
|
|
import { test } from "bun:test";
|
|
|
|
import { createCloudApiServer } from "./server.ts";
|
|
|
|
test("preset user login keeps YAML nav claims when OpenFGA tuple sync is unavailable", async () => {
|
|
const password = "preset-user-password";
|
|
const server = createCloudApiServer({
|
|
env: {
|
|
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
|
|
HWLAB_ACCESS_CONTROL_USERS_JSON: JSON.stringify([
|
|
{
|
|
id: "usr_v03_huiggao",
|
|
username: "huiggao@163.com",
|
|
displayName: "huiggao@163.com",
|
|
email: "huiggao@163.com",
|
|
role: "user",
|
|
status: "active",
|
|
navProfile: "code-mdtodo-only",
|
|
passwordHashEnv: "HWLAB_PRESET_USER_HUIGGAO_PASSWORD_HASH"
|
|
}
|
|
]),
|
|
HWLAB_ACCESS_CONTROL_NAV_PROFILES_JSON: JSON.stringify([
|
|
{ id: "code-mdtodo-only", allowedIds: ["workbench.code", "project.mdtodo"] }
|
|
]),
|
|
HWLAB_PRESET_USER_HUIGGAO_PASSWORD_HASH: stablePasswordHash(password)
|
|
},
|
|
openFgaAuthorizer: throwingOpenFgaAuthorizer()
|
|
});
|
|
await listen(server);
|
|
try {
|
|
const { port } = server.address() as { port: number };
|
|
const login = await fetch(`http://127.0.0.1:${port}/auth/login`, {
|
|
method: "POST",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify({ username: "huiggao@163.com", password })
|
|
});
|
|
assert.equal(login.status, 200);
|
|
const loginBody = await login.json();
|
|
assert.deepEqual(loginBody.access.nav.allowedIds, ["workbench.code", "project.mdtodo"]);
|
|
|
|
const cookie = login.headers.get("set-cookie")?.split(";")[0] ?? "";
|
|
assert.match(cookie, /^hwlab_session=/u);
|
|
const session = await fetch(`http://127.0.0.1:${port}/auth/session`, { headers: { cookie } });
|
|
assert.equal(session.status, 200);
|
|
const sessionBody = await session.json();
|
|
assert.equal(sessionBody.actor.username, "huiggao@163.com");
|
|
assert.deepEqual(sessionBody.access.nav.allowedIds, ["workbench.code", "project.mdtodo"]);
|
|
} finally {
|
|
await close(server);
|
|
}
|
|
});
|
|
|
|
function stablePasswordHash(password: string) {
|
|
const salt = "preset-user-test-salt";
|
|
return `sha256:${salt}:${createHash("sha256").update(`${salt}:${password}`).digest("hex")}`;
|
|
}
|
|
|
|
function throwingOpenFgaAuthorizer() {
|
|
const error = Object.assign(new Error("openfga unavailable"), { code: "openfga_unavailable" });
|
|
return {
|
|
async describe() { return { ok: false, code: "openfga_unavailable" }; },
|
|
async check() { throw error; },
|
|
async writeTuple() { throw error; },
|
|
async deleteTuple() { throw error; }
|
|
};
|
|
}
|
|
|
|
function listen(server: any) {
|
|
return new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
}
|
|
|
|
function close(server: any) {
|
|
return new Promise<void>((resolve, reject) => server.close((error: Error | undefined) => (error ? reject(error) : resolve())));
|
|
}
|