54 lines
2.3 KiB
JavaScript
54 lines
2.3 KiB
JavaScript
// @ts-check
|
|
// Fix #147: Vor der Änderung konnte jeder eingeloggte Benutzer über
|
|
// /useradmin beliebige Konten anlegen, Passwörter setzen oder löschen
|
|
// (Privilege Escalation). Dieser Test prüft die Durchsetzung auf HTTP-Ebene,
|
|
// die die PHP-Suite nicht erreicht (Router-Guard, Redirect, Nav-Rendering).
|
|
|
|
const { test, expect } = require('@playwright/test')
|
|
const { uniqueTag, gotoOk, acceptDialogs } = require('../helpers/app')
|
|
|
|
test.describe('Autorisierung: Benutzerverwaltung nur für Admins (Fix #147)', () => {
|
|
test('Neu angelegter Benutzer ohne Admin-Rolle wird von /useradmin ausgesperrt', async ({ page, browser }) => {
|
|
const username = uniqueTag('noadmin').toLowerCase().replace(/[^a-z0-9-]/g, '').slice(0, 64)
|
|
const password = 'TempPass123!'
|
|
|
|
await gotoOk(page, '/useradmin')
|
|
await page.fill('#field-username', username)
|
|
await page.fill('#field-password', password)
|
|
await page.click('#submit-btn')
|
|
await page.waitForURL('/useradmin')
|
|
await expect(page.locator('body')).toContainText('Benutzer angelegt.')
|
|
|
|
const row = page.locator('tr', { hasText: username })
|
|
await expect(row).toBeVisible()
|
|
|
|
try {
|
|
// Eigener, unangemeldeter Kontext: Der neu angelegte Benutzer meldet
|
|
// sich selbst an und ist per Default kein Admin.
|
|
const context = await browser.newContext({ storageState: { cookies: [], origins: [] } })
|
|
const userPage = await context.newPage()
|
|
await userPage.goto('/login')
|
|
await userPage.fill('#username', username)
|
|
await userPage.fill('#password', password)
|
|
await userPage.click('form[action="/login"] button[type="submit"]')
|
|
await userPage.waitForURL(url => !url.pathname.startsWith('/login'))
|
|
|
|
// Kosmetischer Schutz: der Nav-Link ist für Nicht-Admins ausgeblendet.
|
|
await expect(userPage.locator('a[href="/useradmin"]')).toHaveCount(0)
|
|
|
|
// Serverseitige Durchsetzung: direkter Aufruf bleibt trotzdem gesperrt.
|
|
const response = await userPage.goto('/useradmin')
|
|
expect(response?.status()).toBe(403)
|
|
await expect(userPage.locator('body')).toContainText('Kein Zugriff')
|
|
|
|
await context.close()
|
|
} finally {
|
|
acceptDialogs(page)
|
|
const delForm = row.locator('form[action$="/delete"]')
|
|
if (await delForm.count() > 0) {
|
|
await delForm.locator('button[type="submit"]').click()
|
|
await page.waitForLoadState('networkidle')
|
|
}
|
|
}
|
|
})
|
|
})
|