github →

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.

Issue

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 canAccessFullAdminPanel for any user
  • Grant/revoke canImpersonate for 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 canAccessFullAdminPanel or canImpersonate, 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
Assessmentadvisory
feature●●● hard80% confidence

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.

Likely files
  • 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
Create the request

This opens a fresh agent run and a draft PR for issue #19785.

Cancel