fix(ui): учитывать права на операции с серверами

This commit is contained in:
Denozordec committed 2026-09-21 15:00:13 +07:00
1 parent e9e5030047
commit 61950638bc
6 files changed
+121 -18

No files matched your search

+68
View File
@@ -441,3 +441,71 @@ test("URL серверов: черновик не публикуется, быс
await expect(search).toHaveValue("192.0.2.2")
await expect(page.locator("tr[data-row-id]")).toHaveCount(1)
})
// Claims are UI fixtures only; HTTP mocks do not verify JWT signatures.
function permissionToken(permission: string, isAdmin = false) {
return `fixture.${Buffer.from(JSON.stringify({ sub: "test", apps: ["mm"], permissions: [permission], is_admin: isAdmin, exp: Math.floor(Date.now() / 1000) + 3600 })).toString("base64url")}.fixture`
}
for (const isAdmin of [false, true]) {
test(`права серверов: read, is_admin=${isAdmin}, только просмотр без записи`, async ({ page }) => {
await page.addInitScript(token => localStorage.setItem("mmapp_token", token), permissionToken("mm:servers:read", isAdmin))
const writes: string[] = []
await setup(page, async (route, path) => {
if (path === "/api/auth/config") { await route.fulfill({ json: { required: true } }); return true }
if (path.startsWith("/api/servers") && route.request().method() !== "GET") writes.push(path)
return false
})
await expect(page.getByText("Только просмотр", { exact: true })).toBeVisible()
await expect(page.getByRole("button", { name: "Добавить сервер", exact: true })).toBeDisabled()
await expect(page.getByRole("button", { name: "Проверить все", exact: true })).toBeDisabled()
await page.getByRole("button", { name: "Действия: Проверка 1", exact: true }).click()
for (const name of ["Редактировать", "Опросить", "Отключить", "Удалить"]) {
await expect(page.getByRole("menuitem", { name, exact: true })).toBeDisabled()
}
await expect(page.getByRole("menuitem", { name: "Открыть WebFig", exact: true })).toBeEnabled()
await page.keyboard.press("Escape")
await page.getByRole("button", { name: "Раскрыть: Проверка 1", exact: true }).click()
await expect(page.getByText("Модель: Test router", { exact: true })).toBeVisible()
await expect(page.getByRole("button", { name: "Опросить сейчас", exact: true })).toBeDisabled()
expect(writes).toEqual([])
})
}
for (const permission of ["mm:servers:write", "mm:servers:admin"]) {
test(`права серверов: ${permission}, серверный 403 сохраняет форму`, async ({ page }) => {
await page.addInitScript(token => localStorage.setItem("mmapp_token", token), permissionToken(permission))
await setup(page, async (route, path) => {
if (path === "/api/auth/config") { await route.fulfill({ json: { required: true } }); return true }
if (path === "/api/servers/1" && route.request().method() === "PUT") {
await route.fulfill({ status: 403, json: { error: "Forbidden" } }); return true
}
return false
})
await expect(page.getByRole("button", { name: "Добавить сервер", exact: true })).toBeEnabled()
await expect(page.getByRole("button", { name: "Проверить все", exact: true })).toBeEnabled()
await edit(page)
await finalStep(page)
await page.getByRole("button", { name: "Сохранить", exact: true }).click()
await expect(page.getByRole("dialog")).toBeVisible()
await expect(page.getByRole("alert")).toContainText("Недостаточно прав")
})
}
test("права серверов: отзыв перед сохранением блокирует запрос и сохраняет форму", async ({ page }) => {
await page.addInitScript(token => localStorage.setItem("mmapp_token", token), permissionToken("mm:servers:write"))
let writes = 0
await setup(page, async (route, path) => {
if (path === "/api/auth/config") { await route.fulfill({ json: { required: true } }); return true }
if (path.startsWith("/api/servers") && route.request().method() !== "GET") writes++
return false
})
await edit(page)
await finalStep(page)
await page.evaluate(token => localStorage.setItem("mmapp_token", token), permissionToken("mm:servers:read"))
await page.getByRole("button", { name: "Сохранить", exact: true }).click()
await expect(page.getByRole("dialog")).toBeVisible()
await expect(page.getByRole("alert")).toContainText("Недостаточно прав")
await expect(page.getByRole("button", { name: "Сохранить", exact: true })).toBeDisabled()
expect(writes).toBe(0)
})