Skip to content

fix: make clients shared across all users#458

Open
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1776163128-fix-client-visibility
Open

fix: make clients shared across all users#458
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1776163128-fix-client-visibility

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot commented Apr 14, 2026

Summary

Clients created by one user were not visible to other users because the clients table had a user_email column and every client query filtered by WHERE user_email = ?. This PR removes user_email from the clients table and all client-related queries so that clients are shared globally, while keeping work entries scoped to individual users.

Schema change: Removed user_email column and its foreign key from the clients table. Removed the idx_clients_user_email index.

Query changes across 4 route files:

  • clients.js — Removed user_email filtering from all CRUD operations (GET, POST, PUT, DELETE)
  • reports.js — Removed user_email from client lookup queries; work entry queries still filter by user_email
  • workEntries.js — Removed user_email from client existence checks when creating/updating work entries; work entry ownership unchanged

Review & Testing Checklist for Human

  • DELETE /api/clients (bulk) now deletes ALL clients globally, not just the current user's. Previously this was scoped to WHERE user_email = ?. Verify this is acceptable — any authenticated user can wipe all clients for everyone.
  • PUT and DELETE /api/clients/:id have no ownership checks. Any authenticated user can now edit or delete any client. Consider whether some form of authorization (e.g., admin-only, or creator-only for destructive ops) is needed.
  • Verify the frontend does not send or rely on user_email in client-related API calls or responses. No frontend files were changed in this PR.
  • Test end-to-end: Log in as User A → create a client → log out → log in as User B → confirm the client is visible. Then create a work entry against that client as User B and confirm work entries remain isolated per-user.

Notes

  • This is an in-memory SQLite database, so no migration is needed — the schema is recreated on each server restart.
  • All 161 backend tests pass after the changes.

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/57b4fa950fbc4e099e30416513b8873d
Requested by: @VedantKh


Open with Devin

Root cause: The clients table had a user_email column and all client
queries filtered by WHERE user_email = ?, scoping clients to the user
who created them. Other users could not see those clients.

Changes:
- Remove user_email column from clients table schema
- Remove user_email filtering from all client CRUD queries
- Remove user_email filtering from client lookups in reports routes
- Remove user_email filtering from client existence checks in work entries
- Work entries remain scoped to individual users via their own user_email
- Update all tests to reflect the new shared client behavior
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment on lines 193 to +195
db.run(
'DELETE FROM clients WHERE user_email = ?',
[req.userEmail],
'DELETE FROM clients',
[],
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 DELETE /api/clients/ deletes ALL clients globally, cascading to ALL users' work entries

The DELETE / route now executes DELETE FROM clients with no WHERE clause. Previously it was scoped to WHERE user_email = ?, deleting only the authenticated user's clients. Now that clients are shared, any authenticated user hitting this endpoint (used by the frontend at frontend/src/pages/ClientsPage.tsx:84) wipes out every client in the system. Due to the ON DELETE CASCADE foreign key on work_entries.client_id (backend/src/database/init.js:62), this also cascades to delete ALL work entries for ALL users — a catastrophic data loss scenario triggered by a single user.

Prompt for agents
The DELETE / route on clients.js:189-208 now runs DELETE FROM clients with no filter. Since clients are shared across all users, this becomes a system-wide destructive operation that any authenticated user can trigger, also cascading to delete all work entries for all users via the ON DELETE CASCADE constraint.

Possible approaches:
1. Remove the DELETE / route entirely now that clients are shared — a single user should not be able to delete all shared resources.
2. Add an admin authorization check before allowing bulk deletion.
3. If bulk delete must remain, at minimum scope it so it only deletes clients that have no work entries from other users, or require an admin role.

The frontend calls this via apiClient.deleteAllClients() in frontend/src/pages/ClientsPage.tsx:84, so the UI trigger also needs to be reconsidered.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +222 to +223
'SELECT id FROM clients WHERE id = ?',
[clientId],
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 DELETE /api/clients/:id cascades deletion of other users' work entries

Any authenticated user can delete any shared client via DELETE /api/clients/:id. Because work_entries.client_id has ON DELETE CASCADE (backend/src/database/init.js:62), deleting a client also deletes all work entries linked to that client — including entries belonging to other users. Previously, the WHERE user_email = ? filter ensured only the owner could delete their own client. Now with shared clients, user A deleting a client causes user B's work entries for that client to be silently destroyed.

Prompt for agents
The DELETE /:id route in clients.js:210-249 allows any authenticated user to delete any shared client. Due to ON DELETE CASCADE on work_entries.client_id, this also destroys all work entries from ALL users that reference that client.

Possible approaches:
1. Add authorization so only an admin or the original creator of the client can delete it (this may require adding a created_by column to the clients table).
2. Before deleting, check if other users have work entries referencing this client and either prevent deletion or warn the user.
3. Change the cascade behavior — instead of ON DELETE CASCADE, use ON DELETE RESTRICT or SET NULL to prevent accidental data loss in work_entries.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants