feat(api): admin-users router with enriched roster + user creation
This commit is contained in:
116
apps/api/test/admin-users.test.ts
Normal file
116
apps/api/test/admin-users.test.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import type { Hono } from 'hono';
|
||||
import { createApp } from '../src/app';
|
||||
import { authToken, bearer } from './helpers';
|
||||
|
||||
const PASSWORD = 'sterk-wachtwoord-123';
|
||||
|
||||
async function signInStatus(app: Hono, email: string, password: string): Promise<number> {
|
||||
const res = await app.request('/api/auth/sign-in/email', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
return res.status;
|
||||
}
|
||||
|
||||
describe('GET /api/admin/users', () => {
|
||||
it('401s without a token, 403s for a worker', async () => {
|
||||
const app = createApp();
|
||||
expect((await app.request('/api/admin/users')).status).toBe(401);
|
||||
const workerTok = await authToken(app, 'users-list-worker@example.com');
|
||||
expect((await app.request('/api/admin/users', { headers: bearer(workerTok) })).status).toBe(
|
||||
403,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns each user with role and status', async () => {
|
||||
const app = createApp();
|
||||
const adminTok = await authToken(app, 'users-list-admin@example.com', 'admin');
|
||||
await authToken(app, 'users-list-w@example.com'); // a worker
|
||||
|
||||
const res = await app.request('/api/admin/users', { headers: bearer(adminTok) });
|
||||
expect(res.status).toBe(200);
|
||||
const users = await res.json();
|
||||
const admin = users.find((u: { email: string }) => u.email === 'users-list-admin@example.com');
|
||||
const worker = users.find((u: { email: string }) => u.email === 'users-list-w@example.com');
|
||||
expect(admin.role).toBe('admin');
|
||||
expect(admin.status).toBe('active');
|
||||
expect(worker.role).toBe('worker');
|
||||
expect(worker.status).toBe('active');
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /api/admin/users', () => {
|
||||
it('creates a user who can then sign in', async () => {
|
||||
const app = createApp();
|
||||
const adminTok = await authToken(app, 'users-create-admin@example.com', 'admin');
|
||||
const res = await app.request('/api/admin/users', {
|
||||
method: 'POST',
|
||||
headers: bearer(adminTok),
|
||||
body: JSON.stringify({
|
||||
email: 'created-worker@example.com',
|
||||
name: 'Nieuwe Werker',
|
||||
password: PASSWORD,
|
||||
role: 'worker',
|
||||
}),
|
||||
});
|
||||
expect(res.status).toBe(200);
|
||||
const created = await res.json();
|
||||
expect(created.email).toBe('created-worker@example.com');
|
||||
expect(created.role).toBe('worker');
|
||||
expect(created.status).toBe('active');
|
||||
expect(await signInStatus(app, 'created-worker@example.com', PASSWORD)).toBe(200);
|
||||
});
|
||||
|
||||
it('rejects a duplicate email with 409', async () => {
|
||||
const app = createApp();
|
||||
const adminTok = await authToken(app, 'users-dup-admin@example.com', 'admin');
|
||||
const body = JSON.stringify({
|
||||
email: 'dup@example.com',
|
||||
name: 'Dup',
|
||||
password: PASSWORD,
|
||||
role: 'worker',
|
||||
});
|
||||
expect(
|
||||
(await app.request('/api/admin/users', { method: 'POST', headers: bearer(adminTok), body }))
|
||||
.status,
|
||||
).toBe(200);
|
||||
expect(
|
||||
(await app.request('/api/admin/users', { method: 'POST', headers: bearer(adminTok), body }))
|
||||
.status,
|
||||
).toBe(409);
|
||||
});
|
||||
|
||||
it('rejects a too-short password with 400', async () => {
|
||||
const app = createApp();
|
||||
const adminTok = await authToken(app, 'users-shortpw-admin@example.com', 'admin');
|
||||
const res = await app.request('/api/admin/users', {
|
||||
method: 'POST',
|
||||
headers: bearer(adminTok),
|
||||
body: JSON.stringify({
|
||||
email: 'short@example.com',
|
||||
name: 'S',
|
||||
password: 'short',
|
||||
role: 'worker',
|
||||
}),
|
||||
});
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
|
||||
it('403s for a worker', async () => {
|
||||
const app = createApp();
|
||||
const workerTok = await authToken(app, 'users-create-worker@example.com');
|
||||
const res = await app.request('/api/admin/users', {
|
||||
method: 'POST',
|
||||
headers: bearer(workerTok),
|
||||
body: JSON.stringify({
|
||||
email: 'x@example.com',
|
||||
name: 'X',
|
||||
password: PASSWORD,
|
||||
role: 'worker',
|
||||
}),
|
||||
});
|
||||
expect(res.status).toBe(403);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user