feat: gate full notes behind auth on single session endpoint
Made-with: Cursor
This commit is contained in:
@@ -6,6 +6,7 @@ const { triggerWebhook } = require('../utils/webhooks');
|
|||||||
const { getWebSocketManager } = require('../utils/websocket-manager');
|
const { getWebSocketManager } = require('../utils/websocket-manager');
|
||||||
const { startMonitor, stopMonitor, getMonitorSnapshot } = require('../utils/ecast-shard-client');
|
const { startMonitor, stopMonitor, getMonitorSnapshot } = require('../utils/ecast-shard-client');
|
||||||
const { computeNotesPreview } = require('../utils/notes-preview');
|
const { computeNotesPreview } = require('../utils/notes-preview');
|
||||||
|
const { optionalAuthenticateToken } = require('../middleware/optional-auth');
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ router.get('/active', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Get single session by ID
|
// Get single session by ID
|
||||||
router.get('/:id', (req, res) => {
|
router.get('/:id', optionalAuthenticateToken, (req, res) => {
|
||||||
try {
|
try {
|
||||||
const session = db.prepare(`
|
const session = db.prepare(`
|
||||||
SELECT
|
SELECT
|
||||||
@@ -87,7 +88,14 @@ router.get('/:id', (req, res) => {
|
|||||||
return res.status(404).json({ error: 'Session not found' });
|
return res.status(404).json({ error: 'Session not found' });
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(session);
|
const { has_notes, notes_preview } = computeNotesPreview(session.notes);
|
||||||
|
|
||||||
|
if (req.user) {
|
||||||
|
res.json({ ...session, has_notes, notes_preview });
|
||||||
|
} else {
|
||||||
|
const { notes, ...publicSession } = session;
|
||||||
|
res.json({ ...publicSession, has_notes, notes_preview });
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
res.status(500).json({ error: error.message });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ describe('GET /api/sessions (regression)', () => {
|
|||||||
cleanDb();
|
cleanDb();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('GET /api/sessions/:id returns session object', async () => {
|
test('GET /api/sessions/:id returns session object with preview for unauthenticated', async () => {
|
||||||
const session = seedSession({ is_active: 1, notes: 'Test session' });
|
const session = seedSession({ is_active: 1, notes: 'Test session' });
|
||||||
|
|
||||||
const res = await request(app).get(`/api/sessions/${session.id}`);
|
const res = await request(app).get(`/api/sessions/${session.id}`);
|
||||||
@@ -17,9 +17,11 @@ describe('GET /api/sessions (regression)', () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: session.id,
|
id: session.id,
|
||||||
is_active: 1,
|
is_active: 1,
|
||||||
notes: 'Test session',
|
has_notes: true,
|
||||||
|
notes_preview: 'Test session',
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
expect(res.body.notes).toBeUndefined();
|
||||||
expect(res.body).toHaveProperty('games_played');
|
expect(res.body).toHaveProperty('games_played');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -104,3 +104,44 @@ describe('GET /api/sessions list', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('GET /api/sessions/:id notes visibility', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cleanDb();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns full notes when authenticated', async () => {
|
||||||
|
const session = seedSession({ notes: '**Full notes** here\n\nSecond paragraph' });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.get(`/api/sessions/${session.id}`)
|
||||||
|
.set('Authorization', getAuthHeader());
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.notes).toBe('**Full notes** here\n\nSecond paragraph');
|
||||||
|
expect(res.body.has_notes).toBe(true);
|
||||||
|
expect(res.body.notes_preview).toBe('Full notes here');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns only preview when unauthenticated', async () => {
|
||||||
|
const session = seedSession({ notes: '**Full notes** here\n\nSecond paragraph' });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.get(`/api/sessions/${session.id}`);
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.notes).toBeUndefined();
|
||||||
|
expect(res.body.has_notes).toBe(true);
|
||||||
|
expect(res.body.notes_preview).toBe('Full notes here');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns has_notes false when no notes', async () => {
|
||||||
|
const session = seedSession({ notes: null });
|
||||||
|
|
||||||
|
const res = await request(app)
|
||||||
|
.get(`/api/sessions/${session.id}`);
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.body.has_notes).toBe(false);
|
||||||
|
expect(res.body.notes_preview).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user