149 lines
4.7 KiB
TypeScript
149 lines
4.7 KiB
TypeScript
import { after, before, describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { createTestDb, type TestDb } from "../helpers/sqlite.js";
|
|
import { createTestServer, type TestServer } from "../helpers/koa.js";
|
|
import { hashPassword } from "../../src/util/hash.js";
|
|
import type { ClientUser } from "../../src/db/types/User.js";
|
|
|
|
const PASSWORD = "user-visibility-password";
|
|
|
|
function basic(email: string): string {
|
|
return `Basic ${Buffer.from(`${email}:${PASSWORD}`).toString("base64")}`;
|
|
}
|
|
|
|
describe("API user email visibility", () => {
|
|
let testDb: TestDb;
|
|
let server: TestServer;
|
|
let admin: ClientUser;
|
|
let normal: ClientUser;
|
|
let coResident: ClientUser;
|
|
let abodeAdmin: ClientUser;
|
|
let aid: string;
|
|
|
|
before(async () => {
|
|
testDb = await createTestDb();
|
|
server = await createTestServer(testDb.db);
|
|
const password = await hashPassword(PASSWORD);
|
|
admin = await testDb.db.createUser({
|
|
email: "global-admin@test.example",
|
|
name: "Global Admin",
|
|
password,
|
|
flags: { admin: true },
|
|
});
|
|
normal = await testDb.db.createUser({
|
|
email: "normal@test.example",
|
|
name: "Normal",
|
|
password,
|
|
flags: {},
|
|
});
|
|
coResident = await testDb.db.createUser({
|
|
email: "co-resident@test.example",
|
|
name: "Co-resident",
|
|
password,
|
|
flags: {},
|
|
});
|
|
abodeAdmin = await testDb.db.createUser({
|
|
email: "abode-admin@test.example",
|
|
name: "Abode Admin",
|
|
password,
|
|
flags: {},
|
|
});
|
|
const abode = await testDb.db.createAbode(
|
|
{ name: "Shared abode" },
|
|
{ uid: admin.uid },
|
|
);
|
|
aid = abode.aid;
|
|
for (const user of [normal, coResident]) {
|
|
await testDb.db.createResident(
|
|
{ uid: user.uid, aid, flags: {} },
|
|
{ uid: admin.uid },
|
|
);
|
|
}
|
|
await testDb.db.createResident(
|
|
{ uid: abodeAdmin.uid, aid, flags: { admin: true } },
|
|
{ uid: admin.uid },
|
|
);
|
|
});
|
|
|
|
after(async () => {
|
|
await server.close();
|
|
testDb.close();
|
|
});
|
|
|
|
it("shows a normal caller only their own email in GET /users", async () => {
|
|
const response = await fetch(`${server.url}/users`, {
|
|
headers: { Authorization: basic(normal.email) },
|
|
});
|
|
assert.equal(response.status, 200);
|
|
const users = (await response.json()) as ClientUser[];
|
|
assert.equal(
|
|
users.find((user) => user.uid === normal.uid)?.email,
|
|
normal.email,
|
|
);
|
|
assert.ok(!("email" in users.find((user) => user.uid === coResident.uid)!));
|
|
});
|
|
|
|
it("hides another user's email in GET /users/:uid", async () => {
|
|
const response = await fetch(`${server.url}/users/${coResident.uid}`, {
|
|
headers: { Authorization: basic(normal.email) },
|
|
});
|
|
assert.equal(response.status, 200);
|
|
assert.ok(!("email" in ((await response.json()) as object)));
|
|
});
|
|
|
|
it("allows global admins to see user emails", async () => {
|
|
const response = await fetch(`${server.url}/users`, {
|
|
headers: { Authorization: basic(admin.email) },
|
|
});
|
|
assert.equal(response.status, 200);
|
|
const users = (await response.json()) as ClientUser[];
|
|
assert.equal(
|
|
users.find((user) => user.uid === coResident.uid)?.email,
|
|
coResident.email,
|
|
);
|
|
});
|
|
|
|
it("makes lookup by email global-admin-only", async () => {
|
|
const denied = await fetch(
|
|
`${server.url}/users/by-email?email=${encodeURIComponent(coResident.email)}`,
|
|
{ headers: { Authorization: basic(normal.email) } },
|
|
);
|
|
assert.equal(denied.status, 401);
|
|
|
|
const allowed = await fetch(
|
|
`${server.url}/users/by-email?email=${encodeURIComponent(coResident.email)}`,
|
|
{ headers: { Authorization: basic(admin.email) } },
|
|
);
|
|
assert.equal(allowed.status, 200);
|
|
assert.equal(
|
|
((await allowed.json()) as ClientUser).email,
|
|
coResident.email,
|
|
);
|
|
});
|
|
|
|
it("shows co-resident emails to an abode admin", async () => {
|
|
const response = await fetch(`${server.url}/abodes/${aid}/users`, {
|
|
headers: { Authorization: basic(abodeAdmin.email) },
|
|
});
|
|
assert.equal(response.status, 200);
|
|
const users = (await response.json()) as ClientUser[];
|
|
assert.equal(
|
|
users.find((user) => user.uid === coResident.uid)?.email,
|
|
coResident.email,
|
|
);
|
|
});
|
|
|
|
it("hides co-resident emails from a non-admin resident", async () => {
|
|
const response = await fetch(`${server.url}/abodes/${aid}/users`, {
|
|
headers: { Authorization: basic(normal.email) },
|
|
});
|
|
assert.equal(response.status, 200);
|
|
const users = (await response.json()) as ClientUser[];
|
|
assert.equal(
|
|
users.find((user) => user.uid === normal.uid)?.email,
|
|
normal.email,
|
|
);
|
|
assert.ok(!("email" in users.find((user) => user.uid === coResident.uid)!));
|
|
});
|
|
});
|