feat: admin user management routes
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { buildTestApp, setupAdmin, getCookie, auth } from './helpers.js'
|
||||
import { buildTestApp, setupAdmin, getCookie, auth, loginAs } from './helpers.js'
|
||||
|
||||
describe('auth routes', () => {
|
||||
it('setup creates admin when no users exist, then is closed', async () => {
|
||||
@@ -72,3 +72,73 @@ describe('auth routes', () => {
|
||||
await app.close()
|
||||
})
|
||||
})
|
||||
|
||||
describe('user admin', () => {
|
||||
async function adminApp() {
|
||||
const app = await buildTestApp()
|
||||
const cookie = await setupAdmin(app)
|
||||
return { app, cookie }
|
||||
}
|
||||
|
||||
it('admin creates a user and lists users', async () => {
|
||||
const { app, cookie } = await adminApp()
|
||||
const created = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/users',
|
||||
...auth(cookie),
|
||||
payload: { username: 'bob', password: 'bobpass123' },
|
||||
})
|
||||
expect(created.statusCode).toBe(200)
|
||||
expect(created.json()).toEqual({ id: 2, username: 'bob', isAdmin: false })
|
||||
|
||||
const list = await app.inject({ method: 'GET', url: '/api/users', ...auth(cookie) })
|
||||
expect(list.json().users.map((u: { username: string }) => u.username)).toEqual(['admin', 'bob'])
|
||||
await app.close()
|
||||
})
|
||||
|
||||
it('non-admin cannot list or create users', async () => {
|
||||
const { app, cookie } = await adminApp()
|
||||
const bobCookie = await loginAs(app, cookie, 'bob', 'bobpass123')
|
||||
const list = await app.inject({ method: 'GET', url: '/api/users', ...auth(bobCookie) })
|
||||
expect(list.statusCode).toBe(403)
|
||||
const create = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/users',
|
||||
...auth(bobCookie),
|
||||
payload: { username: 'eve', password: 'evepass123' },
|
||||
})
|
||||
expect(create.statusCode).toBe(403)
|
||||
await app.close()
|
||||
})
|
||||
|
||||
it('cannot delete self; deleting another user works and cascades settings', async () => {
|
||||
const { app, cookie } = await adminApp()
|
||||
await loginAs(app, cookie, 'bob', 'bobpass123')
|
||||
const selfDelete = await app.inject({ method: 'DELETE', url: '/api/users/1', ...auth(cookie) })
|
||||
expect(selfDelete.statusCode).toBe(400)
|
||||
|
||||
const del = await app.inject({ method: 'DELETE', url: '/api/users/2', ...auth(cookie) })
|
||||
expect(del.statusCode).toBe(200)
|
||||
const list = await app.inject({ method: 'GET', url: '/api/users', ...auth(cookie) })
|
||||
expect(list.json().users).toHaveLength(1)
|
||||
await app.close()
|
||||
})
|
||||
|
||||
it('rejects duplicate username', async () => {
|
||||
const { app, cookie } = await adminApp()
|
||||
await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/users',
|
||||
...auth(cookie),
|
||||
payload: { username: 'bob', password: 'bobpass123' },
|
||||
})
|
||||
const again = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/users',
|
||||
...auth(cookie),
|
||||
payload: { username: 'bob', password: 'otherpass123' },
|
||||
})
|
||||
expect(again.statusCode).toBe(409)
|
||||
await app.close()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user