allow admins to delete approvals and activity entries

This commit is contained in:
2026-04-02 22:21:13 +02:00
parent 66b08693b9
commit bc2f972769
3 changed files with 223 additions and 5 deletions

View File

@@ -1137,6 +1137,80 @@ test("approvals list exposes account status and supports repeated decisions", as
}
});
test("admin can delete individual approval and activity entries", async (t) => {
const rootDir = path.resolve(__dirname, "..");
const dataDir = await fs.mkdtemp(path.join(os.tmpdir(), "rms-delete-entries-test-"));
const port = randomPort();
const baseUrl = `http://127.0.0.1:${port}`;
const server = spawn(process.execPath, ["server/index.js"], {
cwd: rootDir,
env: {
...process.env,
PORT: String(port),
DATA_DIR: dataDir,
ADMIN_EMAILS: "admin@arcg.at",
PRIMARY_EMAIL_DOMAIN: "arcg.at",
PUBLIC_BASE_URL: baseUrl
},
stdio: ["ignore", "pipe", "pipe"]
});
let serverStdErr = "";
server.stderr.on("data", (chunk) => {
serverStdErr += String(chunk);
});
t.after(async () => {
if (!server.killed) {
server.kill("SIGTERM");
}
await fs.rm(dataDir, { recursive: true, force: true });
});
await waitForServer(baseUrl);
const adminVerify = await requestAccessAndVerify(baseUrl, dataDir, "admin@arcg.at");
const adminHeaders = { Authorization: `Bearer ${adminVerify.accessToken}` };
const externalEmail = "deleteme@oevsv.at";
const verify = await requestAccessAndVerify(baseUrl, dataDir, externalEmail);
assert.equal(verify.approved, false);
const approvalsBefore = await requestJson(baseUrl, "/v1/approvals", { headers: adminHeaders });
const pending = (approvalsBefore.approvals || []).find((entry) => entry.email === externalEmail);
assert.ok(pending, "approval entry should exist before delete");
const deleteApproval = await requestJson(baseUrl, `/v1/approvals/${encodeURIComponent(pending.id)}`, {
method: "DELETE",
headers: adminHeaders
});
assert.equal(deleteApproval.ok, true);
assert.equal(deleteApproval.deletedId, pending.id);
const approvalsAfter = await requestJson(baseUrl, "/v1/approvals", { headers: adminHeaders });
assert.equal((approvalsAfter.approvals || []).some((entry) => entry.id === pending.id), false);
const activityBefore = await requestJson(baseUrl, "/v1/activity-log?limit=300", { headers: adminHeaders });
assert.ok(Array.isArray(activityBefore.entries));
const targetActivity = activityBefore.entries.find((entry) => entry && entry.id && entry.action === "auth.request_access");
assert.ok(targetActivity, "activity entry with id should exist before delete");
const deleteActivity = await requestJson(baseUrl, `/v1/activity-log/${encodeURIComponent(targetActivity.id)}`, {
method: "DELETE",
headers: adminHeaders
});
assert.equal(deleteActivity.ok, true);
assert.equal(deleteActivity.deletedId, targetActivity.id);
const activityAfter = await requestJson(baseUrl, "/v1/activity-log?limit=300", { headers: adminHeaders });
assert.equal((activityAfter.entries || []).some((entry) => entry.id === targetActivity.id), false);
if (server.exitCode !== null && server.exitCode !== 0) {
throw new Error(`Server exited unexpectedly: ${server.exitCode}\n${serverStdErr}`);
}
});
test("station usage is auto-ended after configured max usage time", async (t) => {
const rootDir = path.resolve(__dirname, "..");
const dataDir = await fs.mkdtemp(path.join(os.tmpdir(), "rms-station-timeout-test-"));