Skip to content

Commit aa098bd

Browse files
authored
fix(clerk-js): Do not trigger roles query when the current user's membership lacks permissions (#6703)
1 parent 45d69c5 commit aa098bd

File tree

5 files changed

+18
-10
lines changed

5 files changed

+18
-10
lines changed

.changeset/clean-apes-invent.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
---
4+
5+
Do not trigger organization roles query when the current user's membership lacks the required permissions (`org:sys_memberships:read` or `org:sys_memberships:manage`).
6+
7+
This fixes an issue where the `OrganizationSwitcher` component was making unnecessary API calls to fetch roles, resulting in HTTP 403 errors.

packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherPopover.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ export const OrganizationSwitcherPopover = React.forwardRef<HTMLDivElement, Orga
137137
elementId={'organizationSwitcherActiveOrganization'}
138138
organization={currentOrg}
139139
user={user}
140-
fetchRoles
141140
mainIdentifierVariant='buttonLarge'
142141
sx={t => ({
143142
padding: `${t.space.$4} ${t.space.$5}`,
@@ -177,7 +176,6 @@ export const OrganizationSwitcherPopover = React.forwardRef<HTMLDivElement, Orga
177176
elementId={'organizationSwitcherActiveOrganization'}
178177
organization={currentOrg}
179178
user={user}
180-
fetchRoles
181179
mainIdentifierVariant='buttonLarge'
182180
sx={t => ({
183181
padding: `${t.space.$4} ${t.space.$5}`,

packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherTrigger.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ export const OrganizationSwitcherTrigger = withAvatarShimmer(
5656
elementId={'organizationSwitcherTrigger'}
5757
gap={3}
5858
size='xs'
59-
fetchRoles
6059
organization={organization}
6160
sx={{ maxWidth: '30ch' }}
6261
/>

packages/clerk-js/src/ui/elements/OrganizationPreview.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { OrganizationPreviewId, UserOrganizationInvitationResource, UserRes
22
import React from 'react';
33

44
import { descriptors, Flex, Text } from '../customizables';
5-
import { useFetchRoles, useLocalizeCustomRoles } from '../hooks/useFetchRoles';
5+
import { useLocalizeCustomRoles } from '../hooks/useFetchRoles';
66
import type { PropsOfComponent, ThemableCssProp } from '../styledSystem';
77
import { OrganizationAvatar } from './OrganizationAvatar';
88

@@ -17,7 +17,6 @@ export type OrganizationPreviewProps = Omit<PropsOfComponent<typeof Flex>, 'elem
1717
badge?: React.ReactNode;
1818
rounded?: boolean;
1919
elementId?: OrganizationPreviewId;
20-
fetchRoles?: boolean;
2120
};
2221

2322
export const OrganizationPreview = (props: OrganizationPreviewProps) => {
@@ -26,7 +25,6 @@ export const OrganizationPreview = (props: OrganizationPreviewProps) => {
2625
size = 'md',
2726
icon,
2827
rounded = false,
29-
fetchRoles = false,
3028
badge,
3129
sx,
3230
user,
@@ -38,10 +36,9 @@ export const OrganizationPreview = (props: OrganizationPreviewProps) => {
3836
} = props;
3937

4038
const { localizeCustomRole } = useLocalizeCustomRoles();
41-
const { options } = useFetchRoles(fetchRoles);
42-
4339
const membership = user?.organizationMemberships.find(membership => membership.organization.id === organization.id);
44-
const unlocalizedRoleLabel = options?.find(a => a.value === membership?.role)?.label;
40+
41+
const unlocalizedRoleLabel = membership?.roleName;
4542
const roleLabel = localizeCustomRole(membership?.role) || unlocalizedRoleLabel;
4643

4744
const mainTextSize =

packages/clerk-js/src/ui/hooks/useFetchRoles.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useOrganization } from '@clerk/shared/react';
22
import type { GetRolesParams } from '@clerk/types';
33

4+
import { useProtect } from '../common';
45
import { useLocalizations } from '../localization';
56
import { customRoleLocalizationKey, roleLocalizationKey } from '../utils/roleLocalizationKey';
67
import { useFetch } from './useFetch';
@@ -14,9 +15,15 @@ const getRolesParams = {
1415
};
1516
export const useFetchRoles = (enabled = true) => {
1617
const { organization } = useOrganization();
18+
const canManageMemberships = useProtect({ permission: 'org:sys_memberships:manage' });
19+
const canReadMemberships = useProtect({ permission: 'org:sys_memberships:read' });
20+
1721
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1822
const getRoles = ({ pageSize, initialPage }: GetRolesParams) => organization!.getRoles({ pageSize, initialPage });
19-
const { data, isLoading } = useFetch(enabled && !!organization?.id ? getRoles : undefined, {
23+
24+
const hasSystemPermissions = canManageMemberships || canReadMemberships;
25+
const shouldFetchRoles = enabled && !!organization?.id && hasSystemPermissions;
26+
const { data, isLoading } = useFetch(shouldFetchRoles ? getRoles : undefined, {
2027
...getRolesParams,
2128
orgId: organization?.id,
2229
});

0 commit comments

Comments
 (0)