@@ -18,8 +18,6 @@ import { createLogger } from '@sim/logger'
1818import { getErrorMessage } from '@sim/utils/errors'
1919import { useParams } from 'next/navigation'
2020import { useQueryState } from 'nuqs'
21- import { isEnterprise } from '@/lib/billing/plan-helpers'
22- import { useDeploymentShape } from '@/lib/core/config/deployment-shape'
2321import {
2422 groupIdParam ,
2523 groupIdUrlKeys ,
@@ -47,9 +45,7 @@ import {
4745 useCreatePermissionGroup ,
4846 useOrganizationWorkspaces ,
4947 usePermissionGroups ,
50- useUserPermissionConfig ,
5148} from '@/ee/access-control/hooks/permission-groups'
52- import { useOrganizationBilling } from '@/hooks/queries/organization'
5349
5450const logger = createLogger ( 'AccessControl' )
5551
@@ -65,57 +61,21 @@ export function AccessControl({
6561 requestsHref,
6662} : AccessControlProps ) {
6763 const params = useParams ( )
68- const { features } = useDeploymentShape ( )
6964 const workspaceId = typeof params ?. workspaceId === 'string' ? params . workspaceId : undefined
7065
71- /**
72- * Access control is governed by the workspace's OWNING organization, which may
73- * differ from the caller's active org (e.g. external members). Resolve the org
74- * id and the caller's admin status server-side from the workspace so gating is
75- * never keyed off the session's active org.
76- */
77- const {
78- data : userPermissionConfig ,
79- isPending : entitlementLoading ,
80- error : entitlementError ,
81- } = useUserPermissionConfig ( workspaceId )
82- const {
83- data : organizationBillingData ,
84- isPending : organizationBillingLoading ,
85- error : organizationBillingError ,
86- } = useOrganizationBilling ( organizationId , {
87- enabled : ! features . accessControl && ! userPermissionConfig ?. entitled ,
88- } )
89- const currentUserIsOrgAdmin = isOrganizationAdmin
90-
9166 const {
92- data : permissionGroups = [ ] ,
67+ data : permissionGroupsData ,
9368 isPending : groupsLoading ,
9469 error : groupsError ,
9570 isFetching : groupsFetching ,
9671 refetch : refetchGroups ,
97- } = usePermissionGroups ( organizationId , ! ! organizationId && currentUserIsOrgAdmin )
72+ } = usePermissionGroups ( organizationId , ! ! organizationId && isOrganizationAdmin )
73+ const permissionGroups = permissionGroupsData ?? [ ]
9874 const { data : organizationWorkspaces = [ ] , isPending : workspacesLoading } =
99- useOrganizationWorkspaces ( organizationId , ! ! organizationId && currentUserIsOrgAdmin )
75+ useOrganizationWorkspaces ( organizationId , ! ! organizationId && isOrganizationAdmin )
10076
101- /**
102- * Must be the resolved flag, not the raw `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED`
103- * read. The settings nav decides visibility from the same resolver, so
104- * reading the bare var here let a deployment with only `ENTERPRISE_ENABLED`
105- * set show the section and then refuse to manage it.
106- */
107- const isEntitled =
108- features . accessControl ||
109- ! ! userPermissionConfig ?. entitled ||
110- isEnterprise ( organizationBillingData ?. data ?. subscriptionPlan )
111- const canManage = isEntitled && currentUserIsOrgAdmin && ! ! organizationId
112- const organizationEntitlementLoading =
113- ! features . accessControl && ! userPermissionConfig ?. entitled && organizationBillingLoading
114-
115- const isLoading =
116- ( workspaceId ? entitlementLoading : false ) ||
117- organizationEntitlementLoading ||
118- ( ! ! organizationId && currentUserIsOrgAdmin && groupsLoading )
77+ const canManage = isOrganizationAdmin && ! ! organizationId
78+ const isLoading = canManage && groupsLoading
11979
12080 const createPermissionGroup = useCreatePermissionGroup ( )
12181
@@ -225,22 +185,24 @@ export function AccessControl({
225185 } ,
226186 ]
227187
188+ const groupsErrorState = groupsError ? (
189+ < SettingsQueryErrorState
190+ error = { groupsError }
191+ fallback = {
192+ permissionGroupsData === undefined
193+ ? 'Failed to load permission groups'
194+ : 'Failed to refresh permission groups'
195+ }
196+ isRetrying = { groupsFetching }
197+ onRetry = { ( ) => void refetchGroups ( ) }
198+ variant = { permissionGroupsData === undefined ? 'fill' : 'inline' }
199+ />
200+ ) : null
201+
228202 if ( isLoading ) {
229203 return < SettingsPanel search = { listSearch } actions = { listActions } />
230204 }
231205
232- const entitlementLoadError = isEntitled
233- ? null
234- : ( ( userPermissionConfig === undefined ? entitlementError : null ) ??
235- ( organizationBillingData === undefined ? organizationBillingError : null ) )
236- if ( entitlementLoadError ) {
237- return (
238- < SettingsEmptyState tone = 'error' >
239- { getErrorMessage ( entitlementLoadError , 'Failed to load Access Control access' ) }
240- </ SettingsEmptyState >
241- )
242- }
243-
244206 if ( ! canManage ) {
245207 return (
246208 < SettingsEmptyState >
@@ -251,38 +213,33 @@ export function AccessControl({
251213 )
252214 }
253215
254- if ( groupsError ) {
255- return (
256- < SettingsPanel search = { listSearch } >
257- < SettingsQueryErrorState
258- error = { groupsError }
259- fallback = 'Failed to load permission groups'
260- isRetrying = { groupsFetching }
261- onRetry = { ( ) => void refetchGroups ( ) }
262- />
263- </ SettingsPanel >
264- )
216+ if ( groupsError && permissionGroupsData === undefined ) {
217+ return < SettingsPanel search = { listSearch } > { groupsErrorState } </ SettingsPanel >
265218 }
266219
267220 if ( selectedGroup && organizationId ) {
268221 return (
269- < GroupDetail
270- key = { selectedGroup . id }
271- group = { selectedGroup }
272- organizationId = { organizationId }
273- workspaceId = { workspaceId }
274- workspaceOptions = { workspaceOptions }
275- organizationWorkspaces = { organizationWorkspaces }
276- workspacesLoading = { workspacesLoading }
277- onBack = { closeGroupDetail }
278- onDeleted = { closeGroupDetail }
279- />
222+ < >
223+ { groupsErrorState }
224+ < GroupDetail
225+ key = { selectedGroup . id }
226+ group = { selectedGroup }
227+ organizationId = { organizationId }
228+ workspaceId = { workspaceId }
229+ workspaceOptions = { workspaceOptions }
230+ organizationWorkspaces = { organizationWorkspaces }
231+ workspacesLoading = { workspacesLoading }
232+ onBack = { closeGroupDetail }
233+ onDeleted = { closeGroupDetail }
234+ />
235+ </ >
280236 )
281237 }
282238
283239 return (
284240 < >
285241 < SettingsPanel search = { listSearch } actions = { listActions } >
242+ { groupsErrorState }
286243 < SettingsSection
287244 label = { `Permission groups (${ permissionGroups . length } )` }
288245 action = { < ChipLink href = { requestsHref } > Review requests</ ChipLink > }
0 commit comments