61 lines
2.2 KiB
JavaScript
61 lines
2.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
import test from "node:test";
|
|
|
|
const migrationUrl = new URL(
|
|
"../migrations/002_device_project_access.sql",
|
|
import.meta.url,
|
|
);
|
|
const repositoryUrl = new URL("../src/postgres-repository.mjs", import.meta.url);
|
|
|
|
test("project access migration defines owner, project, collection and grant boundaries", async () => {
|
|
const sql = await readFile(migrationUrl, "utf8");
|
|
|
|
for (const table of [
|
|
"device_owner_scopes",
|
|
"device_projects",
|
|
"device_collections",
|
|
"device_collection_members",
|
|
"device_project_grants",
|
|
]) {
|
|
assert.match(sql, new RegExp(`create table if not exists ${table}`));
|
|
}
|
|
|
|
assert.match(sql, /scope_kind in \('company', 'personal'\)/);
|
|
assert.match(sql, /principal_kind in \('user', 'group'\)/);
|
|
assert.match(
|
|
sql,
|
|
/project_role in \('viewer', 'operator', 'engineer', 'admin', 'owner'\)/,
|
|
);
|
|
assert.match(sql, /unique \(scope_kind, owner_ref\)/);
|
|
assert.match(sql, /unique \(owner_scope_id, project_key\)/);
|
|
assert.match(sql, /unique \(project_id, principal_kind, principal_ref\)/);
|
|
assert.match(sql, /not \(capability_allow && capability_deny\)/);
|
|
assert.match(
|
|
sql,
|
|
/foreign key \(collection_id, project_id\)\s+references device_collections\(id, project_id\)/,
|
|
);
|
|
assert.match(
|
|
sql,
|
|
/foreign key \(device_id, project_id\)\s+references device_instances\(id, project_id\)/,
|
|
);
|
|
});
|
|
|
|
test("project access migration contains no tenant, device or credential seed", async () => {
|
|
const sql = await readFile(migrationUrl, "utf8");
|
|
|
|
assert.doesNotMatch(sql, /insert\s+into/i);
|
|
assert.doesNotMatch(sql, /dcctouch|arusnavi|b2|imei/i);
|
|
assert.doesNotMatch(sql, /password|secret|token|credential_ref/i);
|
|
});
|
|
|
|
test("repository applies project access migration after the foundation", async () => {
|
|
const source = await readFile(repositoryUrl, "utf8");
|
|
const foundationIndex = source.indexOf("001_device_plane_foundation.sql");
|
|
const projectAccessIndex = source.indexOf("002_device_project_access.sql");
|
|
|
|
assert.notEqual(foundationIndex, -1);
|
|
assert.notEqual(projectAccessIndex, -1);
|
|
assert.ok(foundationIndex < projectAccessIndex);
|
|
});
|