Skip to content

Commit 59576d0

Browse files
baozhoutaoos-zhuang
authored andcommitted
fix(auth): restore admin gate on OAuth toggle-disabled after ADR-0068
The /admin/oauth-application/toggle-disabled route still gated on `session.user.role !== 'admin'`, a signal ADR-0068 stopped synthesizing. Mirror the sibling /admin/unlock-user gate (isPlatformAdmin / platform_admin in roles[] / legacy role scalar). Also correct the stale customSession() doc comment that still described the removed user.role overwrite.
1 parent afe913a commit 59576d0

3 files changed

Lines changed: 40 additions & 15 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@objectstack/plugin-auth': patch
3+
---
4+
5+
fix(auth): restore the admin gate on POST /admin/oauth-application/toggle-disabled after ADR-0068
6+
7+
ADR-0068 stopped `customSession` from synthesizing `user.role = 'admin'`;
8+
canonical roles now arrive in `user.roles[]` with `user.isPlatformAdmin` as a
9+
derived alias. The OAuth-client enable/disable route was missed in that
10+
migration and still gated on `session.user.role !== 'admin'`, which now rejects
11+
even platform admins (the scalar is no longer synthesized). It now mirrors the
12+
sibling /admin/unlock-user gate: `isPlatformAdmin` / `platform_admin` in
13+
`roles[]`, with the legacy `role` scalar as a fallback.
14+
15+
Also corrects the now-stale `customSession()` doc comment in auth-manager that
16+
still described the removed `user.role = 'admin'` overwrite.

packages/plugins/plugin-auth/src/auth-manager.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,18 +1539,19 @@ export class AuthManager {
15391539
}));
15401540
}
15411541

1542-
// customSession() — augments the session payload with a derived `role`
1543-
// field so frontend gating (e.g. AppShell's `isAdmin = user.role === 'admin'`)
1544-
// works without each consumer having to re-query permission sets.
1542+
// customSession() — augments the session payload with the canonical
1543+
// `roles: string[]` array (ADR-0068 D1/D2): the stored `user.role` scalar
1544+
// split on commas, PLUS the active membership mapped to canonical
1545+
// `org_owner`/`org_admin`/`org_member`, PLUS `platform_admin` when the user
1546+
// holds the admin_full_access permission set. `user.isPlatformAdmin` is a
1547+
// derived alias of `'platform_admin' in roles`.
15451548
//
1546-
// It also returns a `roles: string[]` array: the stored `user.role`
1547-
// string split on commas (the admin plugin stores multi-role users as
1548-
// e.g. `"admin,manager"`), with `'admin'` appended (deduplicated) when
1549-
// the user is promoted below. Consumers that match on individual role
1550-
// names (e.g. the Console approvals inbox resolving `role:<name>`
1551-
// approvers) must read `roles` — `user.role` is *replaced* by the
1552-
// literal `'admin'` on promotion, so business roles such as `manager`
1553-
// only survive in the array.
1549+
// IMPORTANT: `user.role` is NOT overwritten anymore — consumers must gate
1550+
// on `roles[]` / `isPlatformAdmin` (e.g. via objectui's useIsWorkspaceAdmin),
1551+
// never on `user.role === 'admin'`. Consumers that match individual role
1552+
// names (e.g. the Console approvals inbox resolving `role:<name>` approvers)
1553+
// also read `roles` — business roles such as `manager` survive only there.
1554+
// The raw membership role stays on the organization plugin's `member` payload.
15541555
//
15551556
// Better-auth's `sys_user` table doesn't carry a `role` column. We derive
15561557
// it from two sources:

packages/plugins/plugin-auth/src/auth-plugin.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -940,10 +940,18 @@ export class AuthPlugin implements Plugin {
940940
if (!session?.user?.id) {
941941
return c.json({ success: false, error: { code: 'unauthorized', message: 'Sign in first' } }, 401);
942942
}
943-
// The customSession plugin synthesizes `user.role = 'admin'` for
944-
// platform admins (admin_full_access permission set) and active-org
945-
// owners/admins; anyone else is denied.
946-
if ((session.user as any).role !== 'admin') {
943+
// Platform-admin gate. ADR-0068 removed the `user.role = 'admin'`
944+
// synthesis, so a stale `role === 'admin'` check now rejects even
945+
// platform admins. Accept the canonical signals customSession carries
946+
// (the derived `isPlatformAdmin` alias / `platform_admin` in roles[]),
947+
// with the legacy admin-plugin `role` scalar as a fallback. Mirrors the
948+
// /admin/unlock-user gate below.
949+
const u: any = session.user;
950+
const isAdmin =
951+
u?.isPlatformAdmin === true ||
952+
(Array.isArray(u?.roles) && u.roles.includes('platform_admin')) ||
953+
u?.role === 'admin';
954+
if (!isAdmin) {
947955
return c.json({ success: false, error: { code: 'forbidden', message: 'Admin role required' } }, 403);
948956
}
949957

0 commit comments

Comments
 (0)