102 lines
4.8 KiB
JavaScript
102 lines
4.8 KiB
JavaScript
const assert = require("node:assert/strict");
|
|
const crypto = require("node:crypto");
|
|
const jwt = require("jsonwebtoken");
|
|
const db = require("../src/db/models");
|
|
const config = require("../src/config");
|
|
|
|
db.sequelize.options.logging = false;
|
|
|
|
const ids = {
|
|
coachA: crypto.randomUUID(),
|
|
coachB: crypto.randomUUID(),
|
|
clientUserA: crypto.randomUUID(),
|
|
clientUserB: crypto.randomUUID(),
|
|
disabledClient: crypto.randomUUID(),
|
|
clientA: crypto.randomUUID(),
|
|
clientB: crypto.randomUUID(),
|
|
sessionA: crypto.randomUUID(),
|
|
sessionB: crypto.randomUUID(),
|
|
};
|
|
|
|
function tokenFor(user) {
|
|
return jwt.sign({ user: { id: user.id, email: user.email } }, config.secret_key, { expiresIn: "5m" });
|
|
}
|
|
|
|
async function api(path, user) {
|
|
return fetch(`http://127.0.0.1:3000/api/coaching${path}`, {
|
|
headers: { Authorization: `Bearer ${tokenFor(user)}` },
|
|
});
|
|
}
|
|
|
|
async function cleanup() {
|
|
await db.sessions.destroy({ where: { id: [ids.sessionA, ids.sessionB] }, force: true });
|
|
await db.clients.destroy({ where: { id: [ids.clientA, ids.clientB] }, force: true });
|
|
await db.users.destroy({
|
|
where: { id: [ids.coachA, ids.coachB, ids.clientUserA, ids.clientUserB, ids.disabledClient] },
|
|
force: true,
|
|
});
|
|
}
|
|
|
|
async function run() {
|
|
const coachRole = await db.roles.findOne({ where: { name: "Coach" } });
|
|
const clientRole = await db.roles.findOne({ where: { name: "Client" } });
|
|
const adminRole = await db.roles.findOne({ where: { name: "Administrator" } });
|
|
assert.ok(coachRole && clientRole && adminRole, "Required roles must exist");
|
|
|
|
const admin = await db.users.findOne({ where: { app_roleId: adminRole.id, disabled: false } });
|
|
assert.ok(admin, "An enabled Administrator fixture must exist");
|
|
|
|
const [coachA, coachB, clientUserA, clientUserB, disabledClient] = await Promise.all([
|
|
db.users.create({ id: ids.coachA, email: `fixture-coach-a-${ids.coachA}@example.invalid`, app_roleId: coachRole.id, emailVerified: true }),
|
|
db.users.create({ id: ids.coachB, email: `fixture-coach-b-${ids.coachB}@example.invalid`, app_roleId: coachRole.id, emailVerified: true }),
|
|
db.users.create({ id: ids.clientUserA, email: `fixture-client-a-${ids.clientUserA}@example.invalid`, app_roleId: clientRole.id, emailVerified: true }),
|
|
db.users.create({ id: ids.clientUserB, email: `fixture-client-b-${ids.clientUserB}@example.invalid`, app_roleId: clientRole.id, emailVerified: true }),
|
|
db.users.create({ id: ids.disabledClient, email: `fixture-disabled-${ids.disabledClient}@example.invalid`, app_roleId: clientRole.id, emailVerified: true, disabled: true }),
|
|
]);
|
|
|
|
await db.clients.bulkCreate([
|
|
{ id: ids.clientA, name: "Synthetic Client A", email: clientUserA.email, ownerId: coachA.id, portalUserId: clientUserA.id, notes: "private-a" },
|
|
{ id: ids.clientB, name: "Synthetic Client B", email: clientUserB.email, ownerId: coachB.id, portalUserId: clientUserB.id, notes: "private-b" },
|
|
]);
|
|
await db.sessions.bulkCreate([
|
|
{ id: ids.sessionA, clientId: ids.clientA, title: "Synthetic Session A", status: "shared", shared_client_notes: "safe-a", private_coach_notes: "private-a" },
|
|
{ id: ids.sessionB, clientId: ids.clientB, title: "Synthetic Session B", status: "shared", shared_client_notes: "safe-b", private_coach_notes: "private-b" },
|
|
]);
|
|
|
|
const coachAListResponse = await api("/clients", coachA);
|
|
assert.equal(coachAListResponse.status, 200);
|
|
const coachAList = await coachAListResponse.json();
|
|
assert.equal(coachAList.some((client) => client.id === ids.clientA), true);
|
|
assert.equal(coachAList.some((client) => client.id === ids.clientB), false);
|
|
|
|
assert.equal((await api(`/clients/${ids.clientB}`, coachA)).status, 404);
|
|
assert.equal((await api(`/sessions/${ids.sessionB}`, coachA)).status, 404);
|
|
assert.equal((await api(`/sessions/${ids.sessionB}/audio`, coachA)).status, 404);
|
|
|
|
const portalAResponse = await api("/client-portal/me", clientUserA);
|
|
assert.equal(portalAResponse.status, 200);
|
|
const portalA = await portalAResponse.json();
|
|
assert.equal(portalA.id, ids.clientA);
|
|
assert.equal(portalA.sessions.some((session) => session.id === ids.sessionB), false);
|
|
assert.equal(Object.prototype.hasOwnProperty.call(portalA, "notes"), false);
|
|
assert.equal((await api(`/client-portal/${ids.clientB}`, clientUserA)).status, 404);
|
|
assert.equal((await api(`/clients/${ids.clientA}`, clientUserA)).status, 403);
|
|
|
|
assert.equal((await api(`/clients/${ids.clientB}`, admin)).status, 200);
|
|
assert.equal((await api("/client-portal/me", disabledClient)).status, 401);
|
|
|
|
const loggedOut = await fetch("http://127.0.0.1:3000/api/coaching/clients");
|
|
assert.equal(loggedOut.status, 401);
|
|
|
|
console.log("live_isolation_matrix=passed");
|
|
}
|
|
|
|
run()
|
|
.finally(cleanup)
|
|
.then(() => db.sequelize.close())
|
|
.catch(async (error) => {
|
|
console.error(error);
|
|
await db.sequelize.close();
|
|
process.exitCode = 1;
|
|
});
|