/home/techb158/cosmic.abdallabala.com/tests
Edit: /home/techb158/cosmic.abdallabala.com/tests/access-control.test.js (5618B)
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const os = require("os");
const { spawn } = require("child_process");
const { JsonDatabase } = require("../src/storage/jsonDatabase.js");
const { AccessControlService } = require("../src/security/accessControl.js");
const root = path.join(__dirname, "..");
const sourceDb = path.join(root, "data", "database.json");
const tempDb = path.join(os.tmpdir(), `cosmic-access-db-${Date.now()}.json`);
fs.copyFileSync(sourceDb, tempDb);
const database = new JsonDatabase(tempDb);
const access = new AccessControlService(database);
const seeded = access.ensureDefaultRolesAndUsers("USER-SYSTEM");
assert.ok(seeded.roles.length >= 8, "Default role set should be available");
assert.ok(seeded.users.length >= 8, "Default user set should be available");
const admin = access.getUser("USER-SYSTEM");
const viewer = access.getUser("USER-VIEWER");
const riskOwner = access.getUser("USER-RISK");
assert.ok(admin.permissions.includes("*"), "System admin should have all permissions");
assert.strictEqual(access.hasPermission("USER-VIEWER", "project:read"), true, "Viewer should read projects");
assert.strictEqual(access.hasPermission("USER-VIEWER", "risk:write"), false, "Viewer should not write risks");
assert.strictEqual(access.hasPermission("USER-RISK", "risk:write"), true, "Risk owner should write risks");
assert.strictEqual(access.hasPermission("USER-RISK", "risk:delete"), false, "Risk owner should not delete risks");
assert.ok(viewer && riskOwner, "Seeded viewer and risk owner users should exist");
const port = 8290 + Math.floor(Math.random() * 100);
const baseUrl = `http://127.0.0.1:${port}`;
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function request(pathname, options = {}) {
const response = await fetch(`${baseUrl}${pathname}`, Object.assign({
headers: Object.assign({ "Content-Type": "application/json" }, options.headers || {})
}, options));
const body = await response.json().catch(() => ({}));
return { response, body };
}
async function waitForServer() {
const deadline = Date.now() + 8000;
let lastError;
while (Date.now() < deadline) {
try {
const { response } = await request("/api/health");
if (response.ok) return;
} catch (error) {
lastError = error;
}
await wait(150);
}
throw lastError || new Error("Server did not start");
}
(async () => {
const child = spawn(process.execPath, ["server.js"], {
cwd: root,
env: Object.assign({}, process.env, {
PORT: String(port),
COSMIC_DB_FILE: tempDb
}),
stdio: ["ignore", "pipe", "pipe"]
});
try {
await waitForServer();
const viewerDashboard = await request("/api/dashboard", {
headers: { "X-Cosmic-User-Id": "USER-VIEWER" }
});
assert.strictEqual(viewerDashboard.response.status, 200, "Viewer should read dashboard");
const viewerCreate = await request("/api/projects/cosmic-ai-risk-001/risks", {
method: "POST",
headers: { "X-Cosmic-User-Id": "USER-VIEWER" },
body: JSON.stringify({
title: "Viewer should not create this risk",
dimension: "Technical",
domain: "Technical risks",
lifecyclePhase: "Testing and performance evaluation",
probability: 3,
impact: 3,
detectability: 3
})
});
assert.strictEqual(viewerCreate.response.status, 403, "Viewer risk creation should be blocked");
assert.strictEqual(viewerCreate.body.permission, "risk:write", "403 response should explain missing permission");
const riskOwnerCreate = await request("/api/projects/cosmic-ai-risk-001/risks", {
method: "POST",
headers: { "X-Cosmic-User-Id": "USER-RISK" },
body: JSON.stringify({
title: "Risk owner can create risk",
dimension: "Technical",
domain: "Technical risks",
lifecyclePhase: "Testing and performance evaluation",
probability: 3,
impact: 3,
detectability: 3,
owner: "Risk Owner"
})
});
assert.strictEqual(riskOwnerCreate.response.status, 201, "Risk owner should create risk");
const createdRiskId = riskOwnerCreate.body.risk.id;
const riskOwnerDelete = await request(`/api/risks/${encodeURIComponent(createdRiskId)}`, {
method: "DELETE",
headers: { "X-Cosmic-User-Id": "USER-RISK" }
});
assert.strictEqual(riskOwnerDelete.response.status, 403, "Risk owner delete should be blocked");
assert.strictEqual(riskOwnerDelete.body.permission, "risk:delete", "Delete block should name risk:delete");
const adminDelete = await request(`/api/risks/${encodeURIComponent(createdRiskId)}`, {
method: "DELETE",
headers: { "X-Cosmic-User-Id": "USER-SYSTEM" }
});
assert.strictEqual(adminDelete.response.status, 200, "Admin should delete risk");
const integrationAdminOauth = await request("/api/oauth/providers", {
headers: { "X-Cosmic-User-Id": "USER-INTEGRATION" }
});
assert.strictEqual(integrationAdminOauth.response.status, 200, "Integration admin should read OAuth providers");
const viewerOauth = await request("/api/oauth/providers", {
headers: { "X-Cosmic-User-Id": "USER-VIEWER" }
});
assert.strictEqual(viewerOauth.response.status, 403, "Viewer OAuth provider access should be blocked");
console.log("All COSMIC AI-Risk access control tests passed.");
} finally {
child.kill("SIGTERM");
if (fs.existsSync(tempDb)) fs.unlinkSync(tempDb);
}
})().catch(error => {
console.error(error);
process.exit(1);
});