From 799e037f39f5622750ba714f7a15830dc649e53f Mon Sep 17 00:00:00 2001 From: panteliselef Date: Mon, 14 Apr 2025 14:28:03 +0300 Subject: [PATCH 1/5] wip --- integration/models/longRunningApplication.ts | 2 ++ integration/presets/envs.ts | 8 ++++++++ integration/presets/longRunningApps.ts | 1 + .../next-app-router/src/app/api/settings/route.ts | 2 +- .../src/app/settings/auth-protect/page.tsx | 2 +- .../next-app-router/src/app/settings/rsc-protect/page.tsx | 2 +- .../next-app-router/src/app/settings/useAuth-has/page.tsx | 2 +- integration/templates/next-app-router/src/middleware.ts | 2 +- integration/tests/protect.test.ts | 6 +++++- packages/testing/src/common/setup.ts | 4 ++-- packages/testing/src/common/types.ts | 2 ++ 11 files changed, 25 insertions(+), 8 deletions(-) diff --git a/integration/models/longRunningApplication.ts b/integration/models/longRunningApplication.ts index 52c4ac4b6d3..de9eaa90559 100644 --- a/integration/models/longRunningApplication.ts +++ b/integration/models/longRunningApplication.ts @@ -62,6 +62,7 @@ export const longRunningApplication = (params: LongRunningApplicationParams) => try { const publishableKey = params.env.publicVariables.get('CLERK_PUBLISHABLE_KEY'); const secretKey = params.env.privateVariables.get('CLERK_SECRET_KEY'); + const apiUrl = params.env.privateVariables.get('CLERK_API_URL'); const { instanceType, frontendApi: frontendApiUrl } = parsePublishableKey(publishableKey); if (instanceType !== 'development') { @@ -71,6 +72,7 @@ export const longRunningApplication = (params: LongRunningApplicationParams) => publishableKey, frontendApiUrl, secretKey, + apiUrl, dotenv: false, }); } diff --git a/integration/presets/envs.ts b/integration/presets/envs.ts index 8254244547f..2ce9b117ee7 100644 --- a/integration/presets/envs.ts +++ b/integration/presets/envs.ts @@ -144,6 +144,13 @@ const withSessionTasks = base .setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('with-session-tasks').pk) .setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.E2E_CLERK_ENCRYPTION_KEY || 'a-key'); +const withBillingStaging = base + .clone() + .setId('withBillingStaging') + .setEnvVariable('private', 'CLERK_API_URL', 'https://api.clerkstage.dev') + .setEnvVariable('private', 'CLERK_SECRET_KEY', instanceKeys.get('with-billing-staging').sk) + .setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('with-billing-staging').pk); + export const envs = { base, withKeyless, @@ -165,4 +172,5 @@ export const envs = { withSignInOrUpEmailLinksFlow, withSignInOrUpwithRestrictedModeFlow, withSessionTasks, + withBillingStaging, } as const; diff --git a/integration/presets/longRunningApps.ts b/integration/presets/longRunningApps.ts index dabfbf72327..3f5a9cba354 100644 --- a/integration/presets/longRunningApps.ts +++ b/integration/presets/longRunningApps.ts @@ -42,6 +42,7 @@ export const createLongRunningApps = () => { config: next.appRouter, env: envs.withSessionTasks, }, + { id: 'next.appRouter.withBillingStaging', config: next.appRouter, env: envs.withBillingStaging }, { id: 'next.appRouter.withLegalConsent', config: next.appRouter, diff --git a/integration/templates/next-app-router/src/app/api/settings/route.ts b/integration/templates/next-app-router/src/app/api/settings/route.ts index 8e6d46017e6..895ccf2b2bb 100644 --- a/integration/templates/next-app-router/src/app/api/settings/route.ts +++ b/integration/templates/next-app-router/src/app/api/settings/route.ts @@ -1,6 +1,6 @@ import { auth } from '@clerk/nextjs/server'; export async function GET() { - const { userId } = await auth.protect((has: any) => has({ role: 'admin' }) || has({ role: 'org:editor' })); + const { userId } = await auth.protect((has: any) => has({ role: 'org:admin' }) || has({ role: 'org:editor' })); return new Response(JSON.stringify({ userId })); } diff --git a/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx b/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx index c7f9b76b514..4a8aec1143e 100644 --- a/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx +++ b/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx @@ -1,6 +1,6 @@ import { auth } from '@clerk/nextjs/server'; export default async function Page() { - await auth.protect({ role: 'admin' }); + await auth.protect({ role: 'org:admin' }); return

User has access

; } diff --git a/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx b/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx index 889e6e18fd3..9e21b23d034 100644 --- a/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx +++ b/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx @@ -3,7 +3,7 @@ import { Protect } from '@clerk/nextjs'; export default function Page() { return ( User is not admin

} >

User has access

diff --git a/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx b/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx index 14b2dbb1eef..36d5fd0774c 100644 --- a/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx +++ b/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx @@ -6,7 +6,7 @@ export default function Page() { if (!isLoaded) { return

Loading

; } - if (!has({ role: 'admin' })) { + if (!has({ role: 'org:admin' })) { return

User is not admin

; } return

User has access

; diff --git a/integration/templates/next-app-router/src/middleware.ts b/integration/templates/next-app-router/src/middleware.ts index 24c94de0e8e..7ccdcc1934b 100644 --- a/integration/templates/next-app-router/src/middleware.ts +++ b/integration/templates/next-app-router/src/middleware.ts @@ -18,7 +18,7 @@ export default clerkMiddleware(async (auth, req) => { } if (isAdminRoute(req)) { - await auth.protect({ role: 'admin' }); + await auth.protect({ role: 'org:admin' }); } if (isCSPRoute(req)) { diff --git a/integration/tests/protect.test.ts b/integration/tests/protect.test.ts index 2d85ae33221..647ead518ff 100644 --- a/integration/tests/protect.test.ts +++ b/integration/tests/protect.test.ts @@ -5,7 +5,9 @@ import { appConfigs } from '../presets'; import type { FakeOrganization, FakeUser } from '../testUtils'; import { createTestUtils, testAgainstRunningApps } from '../testUtils'; -testAgainstRunningApps({ withEnv: [appConfigs.envs.withCustomRoles] })('authorization @nextjs', ({ app }) => { +testAgainstRunningApps({ + withEnv: [appConfigs.envs.withCustomRoles, appConfigs.envs.withBillingStaging], +})('authorization @nextjs', ({ app }) => { test.describe.configure({ mode: 'serial' }); let fakeAdmin: FakeUser; @@ -40,6 +42,8 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withCustomRoles] })('authoriz await u.po.signIn.waitForMounted(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeAdmin.email, password: fakeAdmin.password }); await u.po.expect.toBeSignedIn(); + const jwtVersion = await page.evaluate(() => window.Clerk.session?.lastActiveToken?.jwt?.claims?.v); + expect(jwtVersion).toBe(app.env.id === 'withBillingStaging' ? 2 : undefined); await u.po.organizationSwitcher.goTo(); await u.po.organizationSwitcher.waitForMounted(); diff --git a/packages/testing/src/common/setup.ts b/packages/testing/src/common/setup.ts index 90397df5252..4ed0d30790d 100644 --- a/packages/testing/src/common/setup.ts +++ b/packages/testing/src/common/setup.ts @@ -5,7 +5,7 @@ import dotenv from 'dotenv'; import type { ClerkSetupOptions, ClerkSetupReturn } from './types'; export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise => { - const { debug = false, dotenv: loadDotEnv = true, ...rest } = options || {}; + const { debug = false, dotenv: loadDotEnv = true, apiUrl: apiUrlProp, ...rest } = options || {}; const log = (msg: string) => { if (debug) { @@ -48,7 +48,7 @@ export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise Date: Mon, 14 Apr 2025 15:08:40 +0300 Subject: [PATCH 2/5] changeset --- .changeset/purple-falcons-behave.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changeset/purple-falcons-behave.md diff --git a/.changeset/purple-falcons-behave.md b/.changeset/purple-falcons-behave.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/purple-falcons-behave.md @@ -0,0 +1,2 @@ +--- +--- From a334f5fa50e5da2b607847e7962b64b84ab23e3f Mon Sep 17 00:00:00 2001 From: panteliselef Date: Mon, 14 Apr 2025 15:13:47 +0300 Subject: [PATCH 3/5] add changeset for testing --- .changeset/silly-spies-cut.md | 5 +++++ packages/testing/src/common/types.ts | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/silly-spies-cut.md diff --git a/.changeset/silly-spies-cut.md b/.changeset/silly-spies-cut.md new file mode 100644 index 00000000000..448d18a5ba8 --- /dev/null +++ b/.changeset/silly-spies-cut.md @@ -0,0 +1,5 @@ +--- +'@clerk/testing': patch +--- + +Accept `apiUrl` from `clerkSetup()`. diff --git a/packages/testing/src/common/types.ts b/packages/testing/src/common/types.ts index 4f56906da4a..a67116579c9 100644 --- a/packages/testing/src/common/types.ts +++ b/packages/testing/src/common/types.ts @@ -29,6 +29,11 @@ export type ClerkSetupOptions = { */ secretKey?: string; + /* + * The backend API URL + * If not provided, the library will look for the key in the following environment variables: + * - CLERK_API_URL + */ apiUrl?: string; /* From 009156905df0b4206340802eb49cdcc00070390e Mon Sep 17 00:00:00 2001 From: panteliselef Date: Tue, 15 Apr 2025 10:17:20 +0300 Subject: [PATCH 4/5] remove types from testing package --- .changeset/silly-spies-cut.md | 3 --- integration/models/longRunningApplication.ts | 1 + packages/testing/src/common/setup.ts | 4 ++-- packages/testing/src/common/types.ts | 7 ------- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.changeset/silly-spies-cut.md b/.changeset/silly-spies-cut.md index 448d18a5ba8..a845151cc84 100644 --- a/.changeset/silly-spies-cut.md +++ b/.changeset/silly-spies-cut.md @@ -1,5 +1,2 @@ --- -'@clerk/testing': patch --- - -Accept `apiUrl` from `clerkSetup()`. diff --git a/integration/models/longRunningApplication.ts b/integration/models/longRunningApplication.ts index de9eaa90559..b7e17ced2df 100644 --- a/integration/models/longRunningApplication.ts +++ b/integration/models/longRunningApplication.ts @@ -72,6 +72,7 @@ export const longRunningApplication = (params: LongRunningApplicationParams) => publishableKey, frontendApiUrl, secretKey, + // @ts-expect-error apiUrl is not a typed option for clerkSetup, but it is accepted at runtime. apiUrl, dotenv: false, }); diff --git a/packages/testing/src/common/setup.ts b/packages/testing/src/common/setup.ts index 4ed0d30790d..36214347116 100644 --- a/packages/testing/src/common/setup.ts +++ b/packages/testing/src/common/setup.ts @@ -5,7 +5,7 @@ import dotenv from 'dotenv'; import type { ClerkSetupOptions, ClerkSetupReturn } from './types'; export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise => { - const { debug = false, dotenv: loadDotEnv = true, apiUrl: apiUrlProp, ...rest } = options || {}; + const { debug = false, dotenv: loadDotEnv = true, ...rest } = options || {}; const log = (msg: string) => { if (debug) { @@ -48,7 +48,7 @@ export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise Date: Wed, 16 Apr 2025 10:47:06 +0300 Subject: [PATCH 5/5] access safe --- packages/testing/src/common/setup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/testing/src/common/setup.ts b/packages/testing/src/common/setup.ts index 36214347116..480170e82fa 100644 --- a/packages/testing/src/common/setup.ts +++ b/packages/testing/src/common/setup.ts @@ -48,7 +48,7 @@ export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise