diff --git a/backend/src/__tests__/database/init.test.js b/backend/src/__tests__/database/init.test.js index caa6aace..56bbfcbe 100644 --- a/backend/src/__tests__/database/init.test.js +++ b/backend/src/__tests__/database/init.test.js @@ -98,7 +98,6 @@ describe('Database Initialization', () => { const runCalls = db.run.mock.calls; const queries = runCalls.map(call => call[0]); - expect(queries.some(q => q.includes('CREATE INDEX IF NOT EXISTS idx_clients_user_email'))).toBe(true); expect(queries.some(q => q.includes('CREATE INDEX IF NOT EXISTS idx_work_entries_client_id'))).toBe(true); expect(queries.some(q => q.includes('CREATE INDEX IF NOT EXISTS idx_work_entries_user_email'))).toBe(true); expect(queries.some(q => q.includes('CREATE INDEX IF NOT EXISTS idx_work_entries_date'))).toBe(true); diff --git a/backend/src/__tests__/routes/clients.test.js b/backend/src/__tests__/routes/clients.test.js index f8938961..3530c165 100644 --- a/backend/src/__tests__/routes/clients.test.js +++ b/backend/src/__tests__/routes/clients.test.js @@ -55,7 +55,7 @@ describe('Client Routes', () => { expect(response.body).toEqual({ clients: mockClients }); expect(mockDb.all).toHaveBeenCalledWith( expect.stringContaining('SELECT id, name, description'), - ['test@example.com'], + [], expect.any(Function) ); }); diff --git a/backend/src/__tests__/routes/reports.test.js b/backend/src/__tests__/routes/reports.test.js index fe51e7c7..4289b853 100644 --- a/backend/src/__tests__/routes/reports.test.js +++ b/backend/src/__tests__/routes/reports.test.js @@ -243,9 +243,8 @@ describe('Report Routes', () => { }); describe('Data Isolation', () => { - test('should only return data for authenticated user', async () => { + test('should return client data without user filtering but filter work entries by user', async () => { mockDb.get.mockImplementation((query, params, callback) => { - expect(params).toContain('test@example.com'); callback(null, { id: 1, name: 'Test Client' }); }); @@ -256,8 +255,15 @@ describe('Report Routes', () => { await request(app).get('/api/reports/client/1'); + // Client lookup should not include user_email expect(mockDb.get).toHaveBeenCalledWith( expect.any(String), + [1], + expect.any(Function) + ); + // Work entries should still be filtered by user_email + expect(mockDb.all).toHaveBeenCalledWith( + expect.stringContaining('user_email'), expect.arrayContaining(['test@example.com']), expect.any(Function) ); @@ -347,7 +353,7 @@ describe('Report Routes', () => { expect(mockDb.get).toHaveBeenCalledWith( expect.stringContaining('SELECT id, name FROM clients'), - expect.arrayContaining([1, 'test@example.com']), + [1], expect.any(Function) ); }); @@ -433,7 +439,7 @@ describe('Report Routes', () => { expect(mockDb.get).toHaveBeenCalledWith( expect.stringContaining('SELECT id, name FROM clients'), - expect.arrayContaining([1, 'test@example.com']), + [1], expect.any(Function) ); }); diff --git a/backend/src/__tests__/routes/workEntries.test.js b/backend/src/__tests__/routes/workEntries.test.js index 8e15562b..da559387 100644 --- a/backend/src/__tests__/routes/workEntries.test.js +++ b/backend/src/__tests__/routes/workEntries.test.js @@ -166,7 +166,7 @@ describe('Work Entry Routes', () => { }); expect(response.status).toBe(400); - expect(response.body).toEqual({ error: 'Client not found or does not belong to user' }); + expect(response.body).toEqual({ error: 'Client not found' }); }); test('should return 400 for missing required fields', async () => { @@ -305,7 +305,7 @@ describe('Work Entry Routes', () => { .send({ clientId: 999 }); expect(response.status).toBe(400); - expect(response.body).toEqual({ error: 'Client not found or does not belong to user' }); + expect(response.body).toEqual({ error: 'Client not found' }); }); }); diff --git a/backend/src/database/init.js b/backend/src/database/init.js index 2de9a347..f38b65e2 100644 --- a/backend/src/database/init.js +++ b/backend/src/database/init.js @@ -67,7 +67,6 @@ async function initializeDatabase() { `); // Create indexes for better performance - database.run(`CREATE INDEX IF NOT EXISTS idx_clients_user_email ON clients (user_email)`); database.run(`CREATE INDEX IF NOT EXISTS idx_work_entries_client_id ON work_entries (client_id)`); database.run(`CREATE INDEX IF NOT EXISTS idx_work_entries_user_email ON work_entries (user_email)`); database.run(`CREATE INDEX IF NOT EXISTS idx_work_entries_date ON work_entries (date)`); diff --git a/backend/src/routes/clients.js b/backend/src/routes/clients.js index d4798aa9..0f8de877 100644 --- a/backend/src/routes/clients.js +++ b/backend/src/routes/clients.js @@ -8,13 +8,13 @@ const router = express.Router(); // All routes require authentication router.use(authenticateUser); -// Get all clients for authenticated user +// Get all clients (shared across all users) router.get('/', (req, res) => { const db = getDatabase(); db.all( - 'SELECT id, name, description, department, email, created_at, updated_at FROM clients WHERE user_email = ? ORDER BY name', - [req.userEmail], + 'SELECT id, name, description, department, email, created_at, updated_at FROM clients ORDER BY name', + [], (err, rows) => { if (err) { console.error('Database error:', err); @@ -37,8 +37,8 @@ router.get('/:id', (req, res) => { const db = getDatabase(); db.get( - 'SELECT id, name, description, department, email, created_at, updated_at FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'SELECT id, name, description, department, email, created_at, updated_at FROM clients WHERE id = ?', + [clientId], (err, row) => { if (err) { console.error('Database error:', err); @@ -113,10 +113,10 @@ router.put('/:id', (req, res, next) => { const db = getDatabase(); - // Check if client exists and belongs to user + // Check if client exists db.get( - 'SELECT id FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'SELECT id FROM clients WHERE id = ?', + [clientId], (err, row) => { if (err) { console.error('Database error:', err); @@ -152,9 +152,9 @@ router.put('/:id', (req, res, next) => { } updates.push('updated_at = CURRENT_TIMESTAMP'); - values.push(clientId, req.userEmail); + values.push(clientId); - const query = `UPDATE clients SET ${updates.join(', ')} WHERE id = ? AND user_email = ?`; + const query = `UPDATE clients SET ${updates.join(', ')} WHERE id = ?`; db.run(query, values, function(err) { if (err) { @@ -186,27 +186,6 @@ router.put('/:id', (req, res, next) => { } }); -// Delete all clients for authenticated user -router.delete('/', (req, res) => { - const db = getDatabase(); - - db.run( - 'DELETE FROM clients WHERE user_email = ?', - [req.userEmail], - function(err) { - if (err) { - console.error('Database error:', err); - return res.status(500).json({ error: 'Failed to delete clients' }); - } - - res.json({ - message: 'All clients deleted successfully', - deletedCount: this.changes - }); - } - ); -}); - // Delete client router.delete('/:id', (req, res) => { const clientId = parseInt(req.params.id); @@ -217,10 +196,10 @@ router.delete('/:id', (req, res) => { const db = getDatabase(); - // Check if client exists and belongs to user + // Check if client exists db.get( - 'SELECT id FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'SELECT id FROM clients WHERE id = ?', + [clientId], (err, row) => { if (err) { console.error('Database error:', err); @@ -233,8 +212,8 @@ router.delete('/:id', (req, res) => { // Delete client (work entries will be deleted due to CASCADE) db.run( - 'DELETE FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'DELETE FROM clients WHERE id = ?', + [clientId], function(err) { if (err) { console.error('Database error:', err); diff --git a/backend/src/routes/reports.js b/backend/src/routes/reports.js index 98b67776..5a8693f6 100644 --- a/backend/src/routes/reports.js +++ b/backend/src/routes/reports.js @@ -21,10 +21,10 @@ router.get('/client/:clientId', (req, res) => { const db = getDatabase(); - // Verify client belongs to user + // Verify client exists db.get( - 'SELECT id, name FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'SELECT id, name FROM clients WHERE id = ?', + [clientId], (err, client) => { if (err) { console.error('Database error:', err); @@ -73,10 +73,10 @@ router.get('/export/csv/:clientId', (req, res) => { const db = getDatabase(); - // Verify client belongs to user and get data + // Verify client exists db.get( - 'SELECT id, name FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'SELECT id, name FROM clients WHERE id = ?', + [clientId], (err, client) => { if (err) { console.error('Database error:', err); @@ -156,10 +156,10 @@ router.get('/export/pdf/:clientId', (req, res) => { const db = getDatabase(); - // Verify client belongs to user and get data + // Verify client exists db.get( - 'SELECT id, name FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'SELECT id, name FROM clients WHERE id = ?', + [clientId], (err, client) => { if (err) { console.error('Database error:', err); diff --git a/backend/src/routes/workEntries.js b/backend/src/routes/workEntries.js index 63649d73..ac46b5bc 100644 --- a/backend/src/routes/workEntries.js +++ b/backend/src/routes/workEntries.js @@ -87,10 +87,10 @@ router.post('/', (req, res, next) => { const { clientId, hours, description, date } = value; const db = getDatabase(); - // Verify client exists and belongs to user + // Verify client exists db.get( - 'SELECT id FROM clients WHERE id = ? AND user_email = ?', - [clientId, req.userEmail], + 'SELECT id FROM clients WHERE id = ?', + [clientId], (err, row) => { if (err) { console.error('Database error:', err); @@ -98,7 +98,7 @@ router.post('/', (req, res, next) => { } if (!row) { - return res.status(400).json({ error: 'Client not found or does not belong to user' }); + return res.status(400).json({ error: 'Client not found' }); } // Create work entry @@ -170,11 +170,11 @@ router.put('/:id', (req, res, next) => { return res.status(404).json({ error: 'Work entry not found' }); } - // If clientId is being updated, verify it belongs to user + // If clientId is being updated, verify it exists if (value.clientId) { db.get( - 'SELECT id FROM clients WHERE id = ? AND user_email = ?', - [value.clientId, req.userEmail], + 'SELECT id FROM clients WHERE id = ?', + [value.clientId], (err, clientRow) => { if (err) { console.error('Database error:', err); @@ -182,7 +182,7 @@ router.put('/:id', (req, res, next) => { } if (!clientRow) { - return res.status(400).json({ error: 'Client not found or does not belong to user' }); + return res.status(400).json({ error: 'Client not found' }); } performUpdate(); diff --git a/docker/overrides/database/init.js b/docker/overrides/database/init.js index 958942c3..7bbe6258 100644 --- a/docker/overrides/database/init.js +++ b/docker/overrides/database/init.js @@ -80,7 +80,6 @@ async function initializeDatabase() { `); // Create indexes for better performance - database.run(`CREATE INDEX IF NOT EXISTS idx_clients_user_email ON clients (user_email)`); database.run(`CREATE INDEX IF NOT EXISTS idx_work_entries_client_id ON work_entries (client_id)`); database.run(`CREATE INDEX IF NOT EXISTS idx_work_entries_user_email ON work_entries (user_email)`); database.run(`CREATE INDEX IF NOT EXISTS idx_work_entries_date ON work_entries (date)`);