bba1df32cb
git-subtree-dir: cms/core git-subtree-split: 59b9e2075ac48cf017db38009d54dbe56a98fffc
68 lines
2.9 KiB
JavaScript
68 lines
2.9 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { rm, readFile } from 'node:fs/promises';
|
|
|
|
// Isolated users file + a known secret BEFORE importing the module (it reads env
|
|
// at import time). No Supabase needed — this is the DB-less path.
|
|
const USERS = join(tmpdir(), `cms-users-${process.pid}.json`);
|
|
process.env.USERS_FILE = USERS;
|
|
process.env.JWT_SECRET ||= 'test-secret-xyz';
|
|
|
|
const local = await import('../src/auth-local.js');
|
|
const { verify } = await import('hono/jwt');
|
|
|
|
test.after(async () => { await rm(USERS, { force: true }); });
|
|
|
|
test('create → list → login mints a GoTrue-shaped, verifiable token', async () => {
|
|
const id = await local.createUser({ email: 'Karim@Example.com', password: 'hunter2', role: 'admin' });
|
|
assert.ok(id);
|
|
const list = await local.listUsers(['someone@else.com']);
|
|
assert.equal(list.length, 1);
|
|
assert.equal(list[0].email, 'Karim@Example.com');
|
|
assert.equal(list[0].role, 'admin');
|
|
|
|
// wrong password rejected, right password accepted (case-insensitive email)
|
|
assert.equal(await local.login('karim@example.com', 'nope'), null);
|
|
const res = await local.login('karim@example.com', 'hunter2');
|
|
assert.ok(res?.access_token);
|
|
assert.equal(res.user.email, 'Karim@Example.com');
|
|
|
|
const claims = await verify(res.access_token, process.env.JWT_SECRET, 'HS256');
|
|
assert.equal(claims.sub, id);
|
|
assert.equal(claims.email, 'Karim@Example.com');
|
|
assert.equal(claims.app_metadata.role, 'admin'); // same shape auth.js/roleOf read
|
|
assert.ok(claims.exp > Math.floor(Date.now() / 1000));
|
|
});
|
|
|
|
test('passwords are bcrypt-hashed at rest (never plaintext)', async () => {
|
|
const raw = JSON.parse(await readFile(USERS, 'utf8'));
|
|
assert.match(raw[0].password, /^\$2[aby]\$/); // bcrypt hash prefix
|
|
assert.notEqual(raw[0].password, 'hunter2');
|
|
});
|
|
|
|
test('countByRole reflects roles; fixed-admin email forced to admin', async () => {
|
|
await local.createUser({ email: 'red@x.com', password: 'pw', role: 'editor' });
|
|
const counts = await local.countByRole([]);
|
|
assert.equal(counts.total, 2);
|
|
assert.equal(counts.admin, 1);
|
|
assert.equal(counts.editor, 1);
|
|
// an env-admin email overrides the stored role in the listing
|
|
const forced = await local.listUsers(['red@x.com']);
|
|
assert.equal(forced.find((u) => u.email === 'red@x.com').role, 'admin');
|
|
});
|
|
|
|
test('update + delete', async () => {
|
|
const id = await local.createUser({ email: 'tmp@x.com', password: 'pw' });
|
|
await local.updateUser(id, { role: 'editor' });
|
|
assert.equal((await local.listUsers([])).find((u) => u.id === id).role, 'editor');
|
|
await local.deleteUser(id);
|
|
assert.equal((await local.listUsers([])).some((u) => u.id === id), false);
|
|
await assert.rejects(() => local.deleteUser('nope'), /nicht gefunden/);
|
|
});
|
|
|
|
test('duplicate email rejected', async () => {
|
|
await assert.rejects(() => local.createUser({ email: 'red@x.com', password: 'pw' }), /existiert bereits/);
|
|
});
|