perf(ux): request-cached permission checks (dedupe RPC fan-out)

New React cache()-wrapped hasPermission(uid,sid,perm): identical checks
resolve once per server render, so the (app) layout's nav-permission
resolution and a page's checks for the same perm (door.manage,
forms.manage) no longer double-round-trip user_has_permission. Pure
dedupe -- semantics unchanged, permission logic stays in SQL/RLS.
Adopted in the layout + members page.
This commit is contained in:
Moheeb Zara
2026-05-17 01:36:54 -07:00
parent ca498d5163
commit b8440e9c9e
3 changed files with 27 additions and 19 deletions
+3 -4
View File
@@ -2,6 +2,7 @@ import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
import { AppSidebar } from '@/components/app-sidebar'
import { CommandPalette } from '@/components/command-palette'
import { hasPermission } from '@/lib/permissions-cache'
import { ConfirmProvider } from '@/components/ui/confirm'
import { getRoleLabelMap } from '@/lib/role-labels'
@@ -69,11 +70,9 @@ export default async function AppLayout({ children }: { children: React.ReactNod
const navPerms: Record<string, boolean> = {}
if (!isAdminRole) {
const results = await Promise.all(
NAV_PERM_CODES.map(perm =>
supabase.rpc('user_has_permission', { uid: user.id, sid: member.space_id, perm }),
),
NAV_PERM_CODES.map(perm => hasPermission(user.id, member.space_id, perm)),
)
NAV_PERM_CODES.forEach((perm, i) => { navPerms[perm] = !!results[i].data })
NAV_PERM_CODES.forEach((perm, i) => { navPerms[perm] = results[i] })
}
return (