Skip to content

Commit c7e6d00

Browse files
authoredNov 6, 2023
feat(nextjs,clerk-react,types,clerk-js): Add experimental support for <Gate/> (#1942)
* feat(nextjs,clerk-react,types,clerk-js): Add experimental support for `<Gate/>` * chore(clerk-js): Remove references to permissions * fix(clerk-js): Edit internal Gate to use some instead of any * chore(clerk-js): Enable tests * chore(clerk-js): Add changeset * chore(types): Create experimental types * feat(nextjs): Export `<Experimental__Gate/>` * chore(chrome-extension): Update snapshot
1 parent 939a769 commit c7e6d00

File tree

19 files changed

+257
-67
lines changed

19 files changed

+257
-67
lines changed
 

‎.changeset/orange-pumpkins-poke.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@clerk/chrome-extension': minor
3+
'@clerk/clerk-js': minor
4+
'@clerk/backend': minor
5+
'@clerk/nextjs': minor
6+
'@clerk/clerk-react': minor
7+
'@clerk/types': minor
8+
---
9+
10+
Experimental support for `<Gate/>` with role checks.

‎packages/backend/src/tokens/authObjects.ts

+58-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { deprecated } from '@clerk/shared/deprecated';
2-
import type { ActClaim, JwtPayload, ServerGetToken, ServerGetTokenOptions } from '@clerk/types';
2+
import type {
3+
ActClaim,
4+
experimental__CheckAuthorizationWithoutPermission,
5+
JwtPayload,
6+
ServerGetToken,
7+
ServerGetTokenOptions,
8+
} from '@clerk/types';
39

410
import type { Organization, Session, User } from '../api';
511
import { createBackendApiClient } from '../api';
@@ -36,6 +42,10 @@ export type SignedInAuthObject = {
3642
orgSlug: string | undefined;
3743
organization: Organization | undefined;
3844
getToken: ServerGetToken;
45+
/**
46+
* @experimental The method is experimental and subject to change in future releases.
47+
*/
48+
experimental__has: experimental__CheckAuthorizationWithoutPermission;
3949
debug: AuthObjectDebug;
4050
};
4151

@@ -51,6 +61,10 @@ export type SignedOutAuthObject = {
5161
orgSlug: null;
5262
organization: null;
5363
getToken: ServerGetToken;
64+
/**
65+
* @experimental The method is experimental and subject to change in future releases.
66+
*/
67+
experimental__has: experimental__CheckAuthorizationWithoutPermission;
5468
debug: AuthObjectDebug;
5569
};
5670

@@ -110,6 +124,7 @@ export function signedInAuthObject(
110124
orgSlug,
111125
organization,
112126
getToken,
127+
experimental__has: createHasAuthorization({ orgId, orgRole, userId }),
113128
debug: createDebug({ ...options, ...debugData }),
114129
};
115130
}
@@ -131,11 +146,21 @@ export function signedOutAuthObject(debugData?: AuthObjectDebugData): SignedOutA
131146
orgSlug: null,
132147
organization: null,
133148
getToken: () => Promise.resolve(null),
149+
experimental__has: () => false,
134150
debug: createDebug(debugData),
135151
};
136152
}
137153

138-
export function prunePrivateMetadata(resource?: { private_metadata: any } | { privateMetadata: any } | null) {
154+
export function prunePrivateMetadata(
155+
resource?:
156+
| {
157+
private_metadata: any;
158+
}
159+
| {
160+
privateMetadata: any;
161+
}
162+
| null,
163+
) {
139164
// Delete sensitive private metadata from resource before rendering in SSR
140165
if (resource) {
141166
// @ts-ignore
@@ -190,3 +215,34 @@ const createGetToken: CreateGetToken = params => {
190215
return sessionToken;
191216
};
192217
};
218+
219+
const createHasAuthorization =
220+
({
221+
orgId,
222+
orgRole,
223+
userId,
224+
}: {
225+
userId: string;
226+
orgId: string | undefined;
227+
orgRole: string | undefined;
228+
}): experimental__CheckAuthorizationWithoutPermission =>
229+
params => {
230+
if (!orgId || !userId) {
231+
return false;
232+
}
233+
234+
if (params.role) {
235+
return orgRole === params.role;
236+
}
237+
238+
if (params.some) {
239+
return !!params.some.find(permObj => {
240+
if (permObj.role) {
241+
return orgRole === permObj.role;
242+
}
243+
return false;
244+
});
245+
}
246+
247+
return false;
248+
};

‎packages/chrome-extension/src/__snapshots__/exports.test.ts.snap

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ exports[`public exports should not include a breaking change 1`] = `
88
"ClerkProvider",
99
"CreateOrganization",
1010
"EmailLinkErrorCode",
11+
"Experimental__Gate",
1112
"MagicLinkErrorCode",
1213
"MultisessionAppSupport",
1314
"OrganizationList",

‎packages/clerk-js/src/core/resources/Session.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ describe('Session', () => {
7373
updated_at: new Date().getTime(),
7474
} as SessionJSON);
7575

76-
const isAuthorized = await session.isAuthorized({ permission: 'org:sys_profile:delete' });
76+
const isAuthorized = await session.experimental__checkAuthorization({ permission: 'org:sys_profile:delete' });
7777

7878
expect(isAuthorized).toBe(true);
7979
});
@@ -93,7 +93,7 @@ describe('Session', () => {
9393
updated_at: new Date().getTime(),
9494
} as SessionJSON);
9595

96-
const isAuthorized = await session.isAuthorized({ permission: 'org:sys_profile:delete' });
96+
const isAuthorized = await session.experimental__checkAuthorization({ permission: 'org:sys_profile:delete' });
9797

9898
expect(isAuthorized).toBe(false);
9999
});

‎packages/clerk-js/src/core/resources/Session.ts

+33-39
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { runWithExponentialBackOff } from '@clerk/shared';
22
import { is4xxError } from '@clerk/shared/error';
33
import type {
44
ActJWTClaim,
5+
CheckAuthorization,
56
GetToken,
67
GetTokenOptions,
7-
IsAuthorized,
88
SessionJSON,
99
SessionResource,
1010
SessionStatus,
@@ -69,8 +69,6 @@ export class Session extends BaseResource implements SessionResource {
6969
return SessionTokenCache.clear();
7070
};
7171

72-
// TODO: Fix this eslint error
73-
7472
getToken: GetToken = async (options?: GetTokenOptions): Promise<string | null> => {
7573
return runWithExponentialBackOff(() => this._getToken(options), {
7674
shouldRetry: (error: unknown, currentIteration: number) => !is4xxError(error) && currentIteration < 4,
@@ -80,48 +78,44 @@ export class Session extends BaseResource implements SessionResource {
8078
/**
8179
* @experimental The method is experimental and subject to change in future releases.
8280
*/
83-
isAuthorized: IsAuthorized = async params => {
84-
return new Promise((resolve, reject) => {
85-
// if there is no active organization user can not be authorized
86-
if (!this.lastActiveOrganizationId || !this.user) {
87-
return resolve(false);
88-
}
81+
experimental__checkAuthorization: CheckAuthorization = params => {
82+
// if there is no active organization user can not be authorized
83+
if (!this.lastActiveOrganizationId || !this.user) {
84+
return false;
85+
}
8986

90-
// loop through organizationMemberships from client piggybacking
91-
const orgMemberships = this.user.organizationMemberships || [];
92-
const activeMembership = orgMemberships.find(mem => mem.organization.id === this.lastActiveOrganizationId);
87+
// loop through organizationMemberships from client piggybacking
88+
const orgMemberships = this.user.organizationMemberships || [];
89+
const activeMembership = orgMemberships.find(mem => mem.organization.id === this.lastActiveOrganizationId);
9390

94-
// Based on FAPI this should never happen, but we handle it anyway
95-
if (!activeMembership) {
96-
return resolve(false);
97-
}
91+
// Based on FAPI this should never happen, but we handle it anyway
92+
if (!activeMembership) {
93+
return false;
94+
}
9895

99-
const activeOrganizationPermissions = activeMembership.permissions;
100-
const activeOrganizationRole = activeMembership.role;
96+
const activeOrganizationPermissions = activeMembership.permissions;
97+
const activeOrganizationRole = activeMembership.role;
10198

102-
if (params.permission) {
103-
return resolve(activeOrganizationPermissions.includes(params.permission));
104-
}
105-
if (params.role) {
106-
return resolve(activeOrganizationRole === params.role);
107-
}
99+
if (params.permission) {
100+
return activeOrganizationPermissions.includes(params.permission);
101+
}
102+
if (params.role) {
103+
return activeOrganizationRole === params.role;
104+
}
108105

109-
if (params.any) {
110-
return resolve(
111-
!!params.any.find(permObj => {
112-
if (permObj.permission) {
113-
return activeOrganizationPermissions.includes(permObj.permission);
114-
}
115-
if (permObj.role) {
116-
return activeOrganizationRole === permObj.role;
117-
}
118-
return false;
119-
}),
120-
);
121-
}
106+
if (params.some) {
107+
return !!params.some.find(permObj => {
108+
if (permObj.permission) {
109+
return activeOrganizationPermissions.includes(permObj.permission);
110+
}
111+
if (permObj.role) {
112+
return activeOrganizationRole === permObj.role;
113+
}
114+
return false;
115+
});
116+
}
122117

123-
return reject();
124-
});
118+
return false;
125119
};
126120

127121
#hydrateCache = (token: TokenResource | null) => {

‎packages/clerk-js/src/ui/common/Gate.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import type { IsAuthorized } from '@clerk/types';
1+
import type { CheckAuthorization } from '@clerk/types';
22
import type { ComponentType, PropsWithChildren, ReactNode } from 'react';
33
import React, { useEffect } from 'react';
44

55
import { useCoreSession } from '../contexts';
6-
import { useFetch } from '../hooks';
76
import { useRouter } from '../router';
87

9-
type GateParams = Parameters<IsAuthorized>[0];
8+
type GateParams = Parameters<CheckAuthorization>[0];
109
type GateProps = PropsWithChildren<
1110
GateParams & {
1211
fallback?: ReactNode;
@@ -15,11 +14,10 @@ type GateProps = PropsWithChildren<
1514
>;
1615

1716
export const useGate = (params: GateParams) => {
18-
const { isAuthorized } = useCoreSession();
19-
const { data: isAuthorizedUser } = useFetch(isAuthorized, params);
17+
const { experimental__checkAuthorization } = useCoreSession();
2018

2119
return {
22-
isAuthorizedUser,
20+
isAuthorizedUser: experimental__checkAuthorization(params),
2321
};
2422
};
2523

‎packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfileRoutes.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export const OrganizationProfileRoutes = (props: PropsOfComponent<typeof Profile
7777
</Route>
7878
<Route path=':id'>
7979
<Gate
80-
any={[{ permission: 'org:sys_domains:manage' }, { permission: 'org:sys_domains:delete' }]}
80+
some={[{ permission: 'org:sys_domains:manage' }, { permission: 'org:sys_domains:delete' }]}
8181
redirectTo='../../'
8282
>
8383
<VerifiedDomainPage />

‎packages/clerk-js/src/ui/utils/test/mockHelpers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const mockClerkMethods = (clerk: LoadedClerk): DeepJestMocked<LoadedClerk
3535
mockMethodsOf(clerk.client.signUp);
3636
clerk.client.sessions.forEach(session => {
3737
mockMethodsOf(session, {
38-
exclude: ['isAuthorized'],
38+
exclude: ['experimental__checkAuthorization'],
3939
});
4040
mockMethodsOf(session.user);
4141
session.user?.emailAddresses.forEach(m => mockMethodsOf(m));

‎packages/nextjs/src/app-router/server/controlComponents.tsx

+37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { experimental__CheckAuthorizationWithoutPermission } from '@clerk/types';
2+
import { redirect } from 'next/navigation';
13
import React from 'react';
24

35
import { auth } from './auth';
@@ -13,3 +15,38 @@ export function SignedOut(props: React.PropsWithChildren) {
1315
const { userId } = auth();
1416
return userId ? null : <>{children}</>;
1517
}
18+
19+
type GateServerComponentProps = React.PropsWithChildren<
20+
Parameters<experimental__CheckAuthorizationWithoutPermission>[0] & {
21+
fallback?: React.ReactNode;
22+
redirectTo?: string;
23+
}
24+
>;
25+
26+
/**
27+
* @experimental The component is experimental and subject to change in future releases.
28+
*/
29+
export function experimental__Gate(gateProps: GateServerComponentProps) {
30+
const { children, fallback, redirectTo, ...restAuthorizedParams } = gateProps;
31+
const { experimental__has } = auth();
32+
33+
const isAuthorizedUser = experimental__has(restAuthorizedParams);
34+
35+
const handleFallback = () => {
36+
if (!redirectTo && !fallback) {
37+
throw new Error('Provide `<Gate />` with a `fallback` or `redirectTo`');
38+
}
39+
40+
if (redirectTo) {
41+
return redirect(redirectTo);
42+
}
43+
44+
return <>{fallback}</>;
45+
};
46+
47+
if (!isAuthorizedUser) {
48+
return handleFallback();
49+
}
50+
51+
return <>{children}</>;
52+
}

‎packages/nextjs/src/client-boundary/controlComponents.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export {
55
ClerkLoading,
66
SignedOut,
77
SignedIn,
8+
Experimental__Gate,
89
RedirectToSignIn,
910
RedirectToSignUp,
1011
RedirectToUserProfile,
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { ClerkProvider } from './client-boundary/ClerkProvider';
2-
export { SignedIn, SignedOut } from './client-boundary/controlComponents';
2+
export { SignedIn, SignedOut, Experimental__Gate } from './client-boundary/controlComponents';
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { ClerkProvider } from './app-router/server/ClerkProvider';
2-
import { SignedIn, SignedOut } from './app-router/server/controlComponents';
2+
import { experimental__Gate, SignedIn, SignedOut } from './app-router/server/controlComponents';
33

4-
export { ClerkProvider, SignedOut, SignedIn };
4+
export { ClerkProvider, SignedOut, SignedIn, experimental__Gate as Experimental__Gate };
55

66
export type ServerComponentsServerModuleTypes = {
77
ClerkProvider: typeof ClerkProvider;
88
SignedIn: typeof SignedIn;
99
SignedOut: typeof SignedOut;
10+
Experimental__Gate: typeof experimental__Gate;
1011
};

‎packages/nextjs/src/index.ts

+6
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ export const ClerkProvider = ComponentsModule.ClerkProvider as ServerComponentsS
9090
export const SignedIn = ComponentsModule.SignedIn as ServerComponentsServerModuleTypes['SignedIn'];
9191
export const SignedOut = ComponentsModule.SignedOut as ServerComponentsServerModuleTypes['SignedOut'];
9292

93+
/**
94+
* @experimental
95+
*/
96+
export const Experimental__Gate =
97+
ComponentsModule.Experimental__Gate as ServerComponentsServerModuleTypes['Experimental__Gate'];
98+
9399
export const auth = ServerHelperModule.auth as ServerHelpersServerModuleTypes['auth'];
94100
export const currentUser = ServerHelperModule.currentUser as ServerHelpersServerModuleTypes['currentUser'];
95101
// export const getAuth = ServerHelperModule.getAuth as ServerHelpersServerModuleTypes['getAuth'];

‎packages/react/src/components/controlComponents.tsx

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import type { HandleOAuthCallbackParams } from '@clerk/types';
1+
import type { experimental__CheckAuthorizationWithoutPermission, HandleOAuthCallbackParams } from '@clerk/types';
22
import React from 'react';
33

44
import { useAuthContext } from '../contexts/AuthContext';
55
import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext';
66
import { useSessionContext } from '../contexts/SessionContext';
77
import { LoadedGuarantee } from '../contexts/StructureContext';
8+
import { useAuth } from '../hooks';
89
import type { RedirectToSignInProps, RedirectToSignUpProps, WithClerkProp } from '../types';
910
import { withClerk } from './withClerk';
1011

@@ -40,6 +41,25 @@ export const ClerkLoading = ({ children }: React.PropsWithChildren<unknown>): JS
4041
return <>{children}</>;
4142
};
4243

44+
type GateProps = React.PropsWithChildren<
45+
Parameters<experimental__CheckAuthorizationWithoutPermission>[0] & {
46+
fallback?: React.ReactNode;
47+
}
48+
>;
49+
50+
/**
51+
* @experimental The component is experimental and subject to change in future releases.
52+
*/
53+
export const experimental__Gate = ({ children, fallback, ...restAuthorizedParams }: GateProps) => {
54+
const { experimental__has } = useAuth();
55+
56+
if (experimental__has(restAuthorizedParams)) {
57+
return <>{children}</>;
58+
}
59+
60+
return <>{fallback ?? null}</>;
61+
};
62+
4363
export const RedirectToSignIn = withClerk(({ clerk, ...props }: WithClerkProp<RedirectToSignInProps>) => {
4464
const { client, session } = clerk;
4565
// TODO: Remove temp use of __unstable__environment

‎packages/react/src/components/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export {
1414
ClerkLoading,
1515
SignedOut,
1616
SignedIn,
17+
experimental__Gate as Experimental__Gate,
1718
RedirectToSignIn,
1819
RedirectToSignUp,
1920
RedirectToUserProfile,

‎packages/react/src/hooks/useAuth.ts

+49-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import type { ActJWTClaim, GetToken, MembershipRole, SignOut } from '@clerk/types';
1+
import type {
2+
ActJWTClaim,
3+
experimental__CheckAuthorizationWithoutPermission,
4+
GetToken,
5+
MembershipRole,
6+
SignOut,
7+
} from '@clerk/types';
28
import { useCallback } from 'react';
39

410
import { useAuthContext } from '../contexts/AuthContext';
@@ -7,6 +13,10 @@ import { invalidStateError } from '../errors';
713
import type IsomorphicClerk from '../isomorphicClerk';
814
import { createGetToken, createSignOut } from './utils';
915

16+
type experimental__CheckAuthorizationSignedOut = (
17+
params?: Parameters<experimental__CheckAuthorizationWithoutPermission>[0],
18+
) => false;
19+
1020
type UseAuthReturn =
1121
| {
1222
isLoaded: false;
@@ -17,6 +27,10 @@ type UseAuthReturn =
1727
orgId: undefined;
1828
orgRole: undefined;
1929
orgSlug: undefined;
30+
/**
31+
* @experimental The method is experimental and subject to change in future releases.
32+
*/
33+
experimental__has: experimental__CheckAuthorizationSignedOut;
2034
signOut: SignOut;
2135
getToken: GetToken;
2236
}
@@ -29,6 +43,10 @@ type UseAuthReturn =
2943
orgId: null;
3044
orgRole: null;
3145
orgSlug: null;
46+
/**
47+
* @experimental The method is experimental and subject to change in future releases.
48+
*/
49+
experimental__has: experimental__CheckAuthorizationSignedOut;
3250
signOut: SignOut;
3351
getToken: GetToken;
3452
}
@@ -41,6 +59,10 @@ type UseAuthReturn =
4159
orgId: null;
4260
orgRole: null;
4361
orgSlug: null;
62+
/**
63+
* @experimental The method is experimental and subject to change in future releases.
64+
*/
65+
experimental__has: experimental__CheckAuthorizationSignedOut;
4466
signOut: SignOut;
4567
getToken: GetToken;
4668
}
@@ -53,6 +75,10 @@ type UseAuthReturn =
5375
orgId: string;
5476
orgRole: MembershipRole;
5577
orgSlug: string | null;
78+
/**
79+
* @experimental The method is experimental and subject to change in future releases.
80+
*/
81+
experimental__has: experimental__CheckAuthorizationWithoutPermission;
5682
signOut: SignOut;
5783
getToken: GetToken;
5884
};
@@ -105,6 +131,24 @@ export const useAuth: UseAuth = () => {
105131
const getToken: GetToken = useCallback(createGetToken(isomorphicClerk), [isomorphicClerk]);
106132
const signOut: SignOut = useCallback(createSignOut(isomorphicClerk), [isomorphicClerk]);
107133

134+
const has = useCallback(
135+
(params?: Parameters<experimental__CheckAuthorizationWithoutPermission>[0]) => {
136+
if (!orgId || !userId || !orgRole) {
137+
return false;
138+
}
139+
140+
if (!params) {
141+
return false;
142+
}
143+
144+
if (params.role) {
145+
return orgRole === params.role;
146+
}
147+
return false;
148+
},
149+
[orgId, orgRole, userId],
150+
);
151+
108152
if (sessionId === undefined && userId === undefined) {
109153
return {
110154
isLoaded: false,
@@ -115,6 +159,7 @@ export const useAuth: UseAuth = () => {
115159
orgId: undefined,
116160
orgRole: undefined,
117161
orgSlug: undefined,
162+
experimental__has: () => false,
118163
signOut,
119164
getToken,
120165
};
@@ -130,6 +175,7 @@ export const useAuth: UseAuth = () => {
130175
orgId: null,
131176
orgRole: null,
132177
orgSlug: null,
178+
experimental__has: () => false,
133179
signOut,
134180
getToken,
135181
};
@@ -145,6 +191,7 @@ export const useAuth: UseAuth = () => {
145191
orgId,
146192
orgRole,
147193
orgSlug: orgSlug || null,
194+
experimental__has: has,
148195
signOut,
149196
getToken,
150197
};
@@ -160,6 +207,7 @@ export const useAuth: UseAuth = () => {
160207
orgId: null,
161208
orgRole: null,
162209
orgSlug: null,
210+
experimental__has: () => false,
163211
signOut,
164212
getToken,
165213
};

‎packages/react/src/utils/deriveState.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ export const deriveState = (clerkLoaded: boolean, state: Resources, initialState
1010

1111
const deriveFromSsrInitialState = (initialState: InitialState) => {
1212
const userId = initialState.userId;
13-
const user = initialState.user as any as UserResource;
13+
const user = initialState.user as UserResource;
1414
const sessionId = initialState.sessionId;
15-
const session = initialState.session as any as ActiveSessionResource;
16-
const organization = initialState.organization as any as OrganizationResource;
15+
const session = initialState.session as ActiveSessionResource;
16+
const organization = initialState.organization as OrganizationResource;
1717
const orgId = initialState.orgId;
1818
const orgRole = initialState.orgRole as MembershipRole;
1919
const orgSlug = initialState.orgSlug;
@@ -46,6 +46,7 @@ const deriveFromClientSideState = (state: Resources) => {
4646
const membership = organization
4747
? user?.organizationMemberships?.find(om => om.organization.id === orgId)
4848
: organization;
49+
const orgPermissions = membership ? membership.permissions : membership;
4950
const orgRole = membership ? membership.role : membership;
5051

5152
const lastOrganizationInvitation = state.lastOrganizationInvitation;
@@ -60,6 +61,7 @@ const deriveFromClientSideState = (state: Resources) => {
6061
orgId,
6162
orgRole,
6263
orgSlug,
64+
orgPermissions,
6365
actor,
6466
lastOrganizationInvitation,
6567
lastOrganizationMember,

‎packages/types/src/jwtv2.ts

+1
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,6 @@ export interface JwtPayload extends CustomJwtSessionClaims {
112112
*/
113113
export interface ActClaim {
114114
sub: string;
115+
115116
[x: string]: unknown;
116117
}

‎packages/types/src/session.ts

+22-8
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,27 @@ import type { ClerkResource } from './resource';
44
import type { TokenResource } from './token';
55
import type { UserResource } from './user';
66

7-
export type IsAuthorized = (isAuthorizedParams: IsAuthorizedParams) => Promise<IsAuthorizedReturnValues>;
7+
export type experimental__CheckAuthorizationWithoutPermission = (
8+
isAuthorizedParams: CheckAuthorizationParamsWithoutPermission,
9+
) => boolean;
810

9-
type IsAuthorizedParams =
11+
type CheckAuthorizationParamsWithoutPermission =
1012
| {
11-
any: (
13+
some: {
14+
role: string;
15+
}[];
16+
role?: never;
17+
}
18+
| {
19+
some?: never;
20+
role: string;
21+
};
22+
23+
export type CheckAuthorization = (isAuthorizedParams: CheckAuthorizationParams) => boolean;
24+
25+
type CheckAuthorizationParams =
26+
| {
27+
some: (
1228
| {
1329
role: string;
1430
permission?: never;
@@ -24,20 +40,18 @@ type IsAuthorizedParams =
2440
permission?: never;
2541
}
2642
| {
27-
any?: never;
43+
some?: never;
2844
role: string;
2945
permission?: never;
3046
}
3147
| {
32-
any?: never;
48+
some?: never;
3349
role?: never;
3450
// Adding (string & {}) allows for getting eslint autocomplete but also accepts any string
3551
// eslint-disable-next-line
3652
permission: OrganizationPermission | (string & {});
3753
};
3854

39-
type IsAuthorizedReturnValues = boolean;
40-
4155
export interface SessionResource extends ClerkResource {
4256
id: string;
4357
status: SessionStatus;
@@ -56,7 +70,7 @@ export interface SessionResource extends ClerkResource {
5670
/**
5771
* @experimental The method is experimental and subject to change in future releases.
5872
*/
59-
isAuthorized: IsAuthorized;
73+
experimental__checkAuthorization: CheckAuthorization;
6074
clearCache: () => void;
6175
createdAt: Date;
6276
updatedAt: Date;

0 commit comments

Comments
 (0)
Please sign in to comment.