feat: add PUT and DELETE /api/sessions/:id/notes endpoints
Made-with: Cursor
This commit is contained in:
@@ -245,6 +245,48 @@ router.delete('/:id', authenticateToken, (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update session notes (admin only)
|
||||||
|
router.put('/:id/notes', authenticateToken, (req, res) => {
|
||||||
|
try {
|
||||||
|
const { notes } = req.body;
|
||||||
|
|
||||||
|
const session = db.prepare('SELECT id FROM sessions WHERE id = ?').get(req.params.id);
|
||||||
|
if (!session) {
|
||||||
|
return res.status(404).json({ error: 'Session not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
db.prepare('UPDATE sessions SET notes = ? WHERE id = ?').run(notes, req.params.id);
|
||||||
|
|
||||||
|
const updated = db.prepare(`
|
||||||
|
SELECT s.*, COUNT(sg.id) as games_played
|
||||||
|
FROM sessions s
|
||||||
|
LEFT JOIN session_games sg ON s.id = sg.session_id
|
||||||
|
WHERE s.id = ?
|
||||||
|
GROUP BY s.id
|
||||||
|
`).get(req.params.id);
|
||||||
|
|
||||||
|
res.json(updated);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear session notes (admin only)
|
||||||
|
router.delete('/:id/notes', authenticateToken, (req, res) => {
|
||||||
|
try {
|
||||||
|
const session = db.prepare('SELECT id FROM sessions WHERE id = ?').get(req.params.id);
|
||||||
|
if (!session) {
|
||||||
|
return res.status(404).json({ error: 'Session not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
db.prepare('UPDATE sessions SET notes = NULL WHERE id = ?').run(req.params.id);
|
||||||
|
|
||||||
|
res.json({ success: true });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Get games played in a session
|
// Get games played in a session
|
||||||
router.get('/:id/games', (req, res) => {
|
router.get('/:id/games', (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -145,3 +145,115 @@ describe('GET /api/sessions/:id notes visibility', () => {
|
|||||||
expect(res.body.notes_preview).toBeNull();
|
expect(res.body.notes_preview).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('PUT /api/sessions/:id/notes', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cleanDb();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('updates notes when authenticated', async () => {
|
||||||
|
const session = seedSession({ notes: 'Old notes' });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.put(`/api/sessions/${session.id}/notes`)
|
||||||
|
.set('Authorization', getAuthHeader())
|
||||||
|
.send({ notes: 'New notes here' });
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.notes).toBe('New notes here');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('overwrites notes completely (no merge)', async () => {
|
||||||
|
const session = seedSession({ notes: 'Original notes' });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.put(`/api/sessions/${session.id}/notes`)
|
||||||
|
.set('Authorization', getAuthHeader())
|
||||||
|
.send({ notes: 'Replacement' });
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.notes).toBe('Replacement');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns 404 for nonexistent session', async () => {
|
||||||
|
const res = await request(app)
|
||||||
|
.put('/api/sessions/99999/notes')
|
||||||
|
.set('Authorization', getAuthHeader())
|
||||||
|
.send({ notes: 'test' });
|
||||||
|
|
||||||
|
expect(res.status).toBe(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns 401 without auth header', async () => {
|
||||||
|
const session = seedSession({});
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.put(`/api/sessions/${session.id}/notes`)
|
||||||
|
.send({ notes: 'test' });
|
||||||
|
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns 403 with invalid token', async () => {
|
||||||
|
const session = seedSession({});
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.put(`/api/sessions/${session.id}/notes`)
|
||||||
|
.set('Authorization', 'Bearer invalid-token')
|
||||||
|
.send({ notes: 'test' });
|
||||||
|
|
||||||
|
expect(res.status).toBe(403);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DELETE /api/sessions/:id/notes', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cleanDb();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('clears notes when authenticated', async () => {
|
||||||
|
const session = seedSession({ notes: 'Some notes' });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.delete(`/api/sessions/${session.id}/notes`)
|
||||||
|
.set('Authorization', getAuthHeader());
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.success).toBe(true);
|
||||||
|
|
||||||
|
// Verify notes are actually cleared
|
||||||
|
const check = await request(app)
|
||||||
|
.get(`/api/sessions/${session.id}`)
|
||||||
|
.set('Authorization', getAuthHeader());
|
||||||
|
expect(check.body.notes).toBeNull();
|
||||||
|
expect(check.body.has_notes).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns 404 for nonexistent session', async () => {
|
||||||
|
const res = await request(app)
|
||||||
|
.delete('/api/sessions/99999/notes')
|
||||||
|
.set('Authorization', getAuthHeader());
|
||||||
|
|
||||||
|
expect(res.status).toBe(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns 401 without auth header', async () => {
|
||||||
|
const session = seedSession({ notes: 'test' });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.delete(`/api/sessions/${session.id}/notes`);
|
||||||
|
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns 403 with invalid token', async () => {
|
||||||
|
const session = seedSession({ notes: 'test' });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.delete(`/api/sessions/${session.id}/notes`)
|
||||||
|
.set('Authorization', 'Bearer invalid-token');
|
||||||
|
|
||||||
|
expect(res.status).toBe(403);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user