This commit is contained in:
@@ -234,10 +234,32 @@ describe('browser authentication guard', () => {
|
||||
['operator', '/api/hosts/[id]', 'PATCH', 403],
|
||||
['operator', '/api/users', 'GET', 403],
|
||||
['admin', '/api/hosts/[id]', 'PATCH', 200],
|
||||
['admin', '/api/users', 'GET', 200]
|
||||
['admin', '/api/users', 'GET', 200],
|
||||
['super_viewer', '/api/users', 'GET', 200],
|
||||
['super_viewer', '/api/users/audit', 'GET', 200],
|
||||
['super_viewer', '/api/server-keys', 'HEAD', 200],
|
||||
['super_viewer', '/api/configs/[id]', 'GET', 200],
|
||||
['super_viewer', '/api/servers/[name]/rcon-diagnostics', 'GET', 200],
|
||||
['super_viewer', '/api/servers/[name]/logs/[file]', 'GET', 200],
|
||||
['super_viewer', '/api/servers/[name]/telemetry-requests', 'GET', 200],
|
||||
['super_viewer', '/api/users', 'POST', 403],
|
||||
['super_viewer', '/api/users/[id]', 'PATCH', 403],
|
||||
['super_viewer', '/api/users/[id]/revoke-sessions', 'POST', 403],
|
||||
['super_viewer', '/api/server-keys', 'POST', 403],
|
||||
['super_viewer', '/api/servers', 'POST', 403],
|
||||
['super_viewer', '/api/provisioning/[id]/override', 'POST', 403],
|
||||
['super_viewer', '/api/hosts/[id]', 'PATCH', 403],
|
||||
['super_viewer', '/api/servers/[name]/probe-rcon', 'POST', 403],
|
||||
['super_viewer', '/api/configs/inspect', 'POST', 403],
|
||||
['super_viewer', '/api/settings/retention/preview', 'POST', 200],
|
||||
['super_viewer', '/api/auth/password', 'POST', 200],
|
||||
['super_viewer', '/api/auth/logout', 'POST', 200]
|
||||
] as const)('enforces %s role for %s %s', async (role, routeId, method, expectedStatus) => {
|
||||
const session = signIn(role);
|
||||
const call = requestFor(routeId, { method, body: method === 'GET' ? undefined : {} });
|
||||
const call = requestFor(routeId, {
|
||||
method,
|
||||
body: ['GET', 'HEAD'].includes(method) ? undefined : {}
|
||||
});
|
||||
const response = await call.invoke();
|
||||
expect(response.status).toBe(expectedStatus);
|
||||
if (expectedStatus === 200) {
|
||||
@@ -245,14 +267,28 @@ describe('browser authentication guard', () => {
|
||||
expect(call.event.locals.user).toEqual(session.user);
|
||||
} else expect(call.resolve).not.toHaveBeenCalled();
|
||||
});
|
||||
it.each(['GET', 'HEAD'])(
|
||||
'restricts global settings %s requests to administrators',
|
||||
it.each(['/settings', '/settings/users', '/server-keys', '/configs/[id]'])(
|
||||
'allows Super Viewer pages and page-data requests at %s',
|
||||
async (route) => {
|
||||
signIn('super_viewer');
|
||||
for (const path of [route, `${route}/__data.json`]) {
|
||||
const call = requestFor(route, { path });
|
||||
expect((await call.invoke()).status).toBe(200);
|
||||
expect(call.resolve).toHaveBeenCalledOnce();
|
||||
}
|
||||
}
|
||||
);
|
||||
it.each(['GET', 'HEAD', 'POST', 'PATCH', 'DELETE'])(
|
||||
'permits only administrators to write settings and Super Viewers to read them',
|
||||
async (method) => {
|
||||
for (const role of ['viewer', 'operator', 'admin'] as const) {
|
||||
for (const role of ['viewer', 'super_viewer', 'operator', 'admin'] as const) {
|
||||
signIn(role);
|
||||
const call = requestFor('/api/settings', { method });
|
||||
expect((await call.invoke()).status).toBe(role === 'admin' ? 200 : 403);
|
||||
if (role === 'admin') expect(call.resolve).toHaveBeenCalledOnce();
|
||||
const allowed =
|
||||
role === 'admin' ||
|
||||
(role === 'super_viewer' && ['GET', 'HEAD'].includes(method));
|
||||
expect((await call.invoke()).status).toBe(allowed ? 200 : 403);
|
||||
if (allowed) expect(call.resolve).toHaveBeenCalledOnce();
|
||||
else expect(call.resolve).not.toHaveBeenCalled();
|
||||
}
|
||||
}
|
||||
@@ -260,7 +296,7 @@ describe('browser authentication guard', () => {
|
||||
it.each(['GET', 'HEAD'])(
|
||||
'restricts raw beta file %s requests to operators and administrators',
|
||||
async (method) => {
|
||||
for (const role of ['viewer', 'operator', 'admin'] as const) {
|
||||
for (const role of ['viewer', 'super_viewer', 'operator', 'admin'] as const) {
|
||||
signIn(role);
|
||||
const call = requestFor('/api/betas/[id]/revisions/[revision]/files/[scriptId]', {
|
||||
method,
|
||||
@@ -282,11 +318,12 @@ describe('browser authentication guard', () => {
|
||||
expect((await anonymous.invoke()).status).toBe(401);
|
||||
expect(anonymous.resolve).not.toHaveBeenCalled();
|
||||
|
||||
for (const role of ['viewer', 'operator', 'admin'] as const) {
|
||||
for (const role of ['viewer', 'super_viewer', 'operator', 'admin'] as const) {
|
||||
signIn(role);
|
||||
const call = requestFor(route, { method });
|
||||
expect((await call.invoke()).status).toBe(role === 'viewer' ? 403 : 200);
|
||||
if (role === 'viewer') expect(call.resolve).not.toHaveBeenCalled();
|
||||
const allowed = role === 'operator' || role === 'admin';
|
||||
expect((await call.invoke()).status).toBe(allowed ? 200 : 403);
|
||||
if (!allowed) expect(call.resolve).not.toHaveBeenCalled();
|
||||
else expect(call.resolve).toHaveBeenCalledOnce();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user