New request
#19785: Admin panel access: cache prevents granting canAccessFullAdminPanel via DB, needs in-app management
We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.
Problem
When granting canAccessFullAdminPanel to a user by directly updating the core.user table in the database, the change has no effect because the CoreEntityCacheService caches the user entity in both an in-memory local cache (30-minute TTL) and Redis (no TTL). The cache is only invalidated on user soft-delete, never on user updates.
This means:
- Self-hosters who follow the documented SQL command to grant admin access (
UPDATE core."user" SET "canAccessFullAdminPanel" = TRUE) will see no effect until they manually flush Redis and restart the server. - There is no in-app way to grant or revoke server-level admin rights (
canAccessFullAdminPanel,canImpersonate). - Debugging this is time-consuming since the frontend correctly reflects the DB value (fetched fresh), but the backend guards use the stale cached value.
Root cause
AdminPanelGuard reads request.user.canAccessFullAdminPanel, which comes from CoreEntityCacheService.get('user', userId). This cache is never invalidated when user fields are updated — only on soft-delete (user.service.ts).
Proposed solution
1. Add in-app admin management UI
Add a section in the admin panel (behind ServerLevelImpersonateGuard / canImpersonate) to:
- List all server-level admins (users with
canAccessFullAdminPanel = true) - Grant/revoke
canAccessFullAdminPanelfor any user - Grant/revoke
canImpersonatefor any user - Properly invalidate the user entity cache after any update
2. Security measures
When modifying server-level admin rights:
- Email notification to all existing admins whenever a user is granted or revoked
canAccessFullAdminPanelorcanImpersonate, so rogue grants are immediately visible. - Audit log entry for every admin rights change (who granted, to whom, when).
- Prevent self-revocation of the last admin to avoid lockout.
- Require re-authentication (password/SSO) before granting admin rights to prevent session hijacking escalation.
3. Fix cache invalidation
As a defense-in-depth measure, also invalidate the user entity cache whenever the user entity is updated (not just on soft-delete). This ensures direct DB changes propagate correctly after a Redis flush + server restart, and prevents similar stale-cache bugs for other user fields.
Impact
- Self-hosters cannot grant admin panel access without Redis access + server restart
- Debugging cost is high — the frontend shows the correct value while the backend rejects requests
- Security gap — direct DB changes to admin rights are unaudited and have no notification mechanism
The issue requests new in-app UI and backend mutations to grant/revoke server-level admin rights plus cache invalidation, constituting a cross-cutting feature spanning guards, cache layer, GraphQL resolvers, and React settings pages.
- packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.module.ts
- packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts
- packages/twenty-server/src/engine/core-modules/admin-panel/dtos/update-admin-access.input.ts
- packages/twenty-server/src/engine/core-modules/cache/cache.service.ts
- packages/twenty-front/src/modules/settings/admin-panel/components/AdminPanelAccessManager.tsx
- packages/twenty-front/src/modules/settings/admin-panel/hooks/useUpdateAdminAccess.ts
- packages/twenty-front/src/modules/settings/admin-panel/constants/AdminSettingsRoutes.ts
- packages/twenty-server/src/engine/guards/admin-panel.guard.ts