123 lines
3.4 KiB
TypeScript
123 lines
3.4 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import {
|
|
type Consent,
|
|
installDevApiMock,
|
|
makeClient,
|
|
seedAuth,
|
|
} from "./helpers/devfront-fixtures";
|
|
|
|
test.describe("DevFront security and isolation", () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
page.on("dialog", async (dialog) => {
|
|
await dialog.accept();
|
|
});
|
|
await seedAuth(page);
|
|
});
|
|
|
|
test("tenant isolation: forbidden client shows blocked error", async ({
|
|
page,
|
|
}) => {
|
|
const state = {
|
|
clients: [makeClient("tenant-a-client", { name: "Tenant A app" })],
|
|
consents: [] as Consent[],
|
|
auditLogsByCursor: undefined,
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.goto("/clients/tenant-b-client");
|
|
await expect(
|
|
page.getByText(
|
|
/Error loading (app|client)|앱 정보를 불러오지 못했습니다|클라이언트 정보를 불러오지 못했습니다/i,
|
|
),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test("RBAC: user without manage_all permission should not see private apps", async ({
|
|
page,
|
|
}) => {
|
|
const state = {
|
|
clients: [
|
|
makeClient("pkce-client", {
|
|
name: "PKCE only app",
|
|
type: "pkce",
|
|
}),
|
|
],
|
|
consents: [] as Consent[],
|
|
auditLogsByCursor: undefined,
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.goto("/clients");
|
|
await expect(page.getByText("PKCE only app")).toBeVisible();
|
|
await expect(page.getByText("Server side App")).not.toBeVisible();
|
|
});
|
|
|
|
test("tenant_member user is blocked at AuthGuard", async ({ page }) => {
|
|
await seedAuth(page, "tenant_member");
|
|
|
|
await page.goto("/clients");
|
|
await expect(
|
|
page.getByText(/DevFront는 관리자 전용 화면입니다|administrator access/i),
|
|
).toBeVisible();
|
|
await expect(page).toHaveURL(/\/clients$/);
|
|
});
|
|
|
|
test("rp_admin receives 403 on clients list and sees ForbiddenMessage", async ({
|
|
page,
|
|
}) => {
|
|
await seedAuth(page, "rp_admin");
|
|
|
|
const state = {
|
|
clients: [] as ReturnType<typeof makeClient>[],
|
|
consents: [] as Consent[],
|
|
auditLogsByCursor: undefined,
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.route("**/api/v1/dev/clients", async (route) => {
|
|
if (route.request().method() === "GET") {
|
|
return route.fulfill({
|
|
status: 403,
|
|
contentType: "application/json",
|
|
body: '{"error": "forbidden"}',
|
|
});
|
|
}
|
|
return route.fallback();
|
|
});
|
|
|
|
await page.goto("/clients");
|
|
await expect(
|
|
page.getByText(/RP 관리자는|RP administrators can only access/i),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test("tenant_admin receives 403 on audit logs and sees ForbiddenMessage", async ({
|
|
page,
|
|
}) => {
|
|
await seedAuth(page, "tenant_admin");
|
|
|
|
const state = {
|
|
clients: [] as ReturnType<typeof makeClient>[],
|
|
consents: [] as Consent[],
|
|
auditLogsByCursor: undefined,
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.route("**/api/v1/dev/audit-logs*", async (route) => {
|
|
if (route.request().method() === "GET") {
|
|
return route.fulfill({
|
|
status: 403,
|
|
contentType: "application/json",
|
|
body: '{"error": "forbidden"}',
|
|
});
|
|
}
|
|
return route.fallback();
|
|
});
|
|
|
|
await page.goto("/audit-logs");
|
|
await expect(
|
|
page.getByText(/테넌트 관리자 권한|Tenant administrator permissions/i),
|
|
).toBeVisible();
|
|
});
|
|
});
|