@geekapps/auth-nextjs 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -2
- package/dist/actions.js +17 -7
- package/dist/actions.js.map +1 -1
- package/dist/client.d.ts +173 -3
- package/dist/client.js +140 -3
- package/dist/client.js.map +1 -1
- package/dist/middleware.js +22 -12
- package/dist/middleware.js.map +1 -1
- package/dist/server.d.ts +13 -4
- package/dist/server.js +9 -3
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -224,7 +224,8 @@ function GeekappsAuthProvider({
|
|
|
224
224
|
const url = new URL(buildUrl(basePath, "/sign-in"), window.location.origin);
|
|
225
225
|
if (options?.redirectTo) url.searchParams.set("redirectTo", options.redirectTo);
|
|
226
226
|
if (options?.authorizationFlowId) url.searchParams.set("flow_id", options.authorizationFlowId);
|
|
227
|
-
|
|
227
|
+
const prompt = options?.prompt ?? (options?.silentLogin === false ? "login" : void 0);
|
|
228
|
+
if (prompt) url.searchParams.set("prompt", prompt);
|
|
228
229
|
redirectTo(url.toString());
|
|
229
230
|
},
|
|
230
231
|
[basePath]
|
|
@@ -235,7 +236,8 @@ function GeekappsAuthProvider({
|
|
|
235
236
|
const url = new URL(buildUrl(basePath, "/sign-up"), window.location.origin);
|
|
236
237
|
if (options?.redirectTo) url.searchParams.set("redirectTo", options.redirectTo);
|
|
237
238
|
if (options?.authorizationFlowId) url.searchParams.set("flow_id", options.authorizationFlowId);
|
|
238
|
-
|
|
239
|
+
const prompt = options?.prompt ?? (options?.silentLogin === false ? "login" : void 0);
|
|
240
|
+
if (prompt) url.searchParams.set("prompt", prompt);
|
|
239
241
|
redirectTo(url.toString());
|
|
240
242
|
},
|
|
241
243
|
[basePath]
|
|
@@ -277,6 +279,67 @@ function GeekappsAuthProvider({
|
|
|
277
279
|
return { success: false, error: error instanceof Error ? error.message : "Unexpected error" };
|
|
278
280
|
}
|
|
279
281
|
}
|
|
282
|
+
const getInvitePreview = useCallback(
|
|
283
|
+
(token) => request(`/organizations/invites/${encodeURIComponent(token)}`),
|
|
284
|
+
[request]
|
|
285
|
+
);
|
|
286
|
+
const acceptInvite = useCallback(
|
|
287
|
+
async (token) => {
|
|
288
|
+
const response = await fetch(buildUrl(basePath, "/organizations/invites/accept"), {
|
|
289
|
+
method: "POST",
|
|
290
|
+
credentials: "include",
|
|
291
|
+
headers: { "content-type": "application/json" },
|
|
292
|
+
body: JSON.stringify({ token })
|
|
293
|
+
});
|
|
294
|
+
const data = await response.json().catch(() => null);
|
|
295
|
+
if (response.ok && data) {
|
|
296
|
+
return { success: true, organizationName: data.organizationName, websiteUrl: data.websiteUrl ?? null };
|
|
297
|
+
}
|
|
298
|
+
if (response.status === 409 && data?.error === "wrong_account") {
|
|
299
|
+
return {
|
|
300
|
+
success: false,
|
|
301
|
+
wrongAccount: true,
|
|
302
|
+
currentEmail: String(data.currentEmail ?? ""),
|
|
303
|
+
invitedEmail: String(data.invitedEmail ?? "")
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
if (response.status === 401 && data?.error === "login_required") {
|
|
307
|
+
return { success: false, wrongAccount: false, loginRequired: true };
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
success: false,
|
|
311
|
+
wrongAccount: false,
|
|
312
|
+
loginRequired: false,
|
|
313
|
+
error: typeof data?.error === "string" ? data.error : `HTTP ${response.status}`
|
|
314
|
+
};
|
|
315
|
+
},
|
|
316
|
+
[basePath]
|
|
317
|
+
);
|
|
318
|
+
const rejectInvite = useCallback(
|
|
319
|
+
async (token) => {
|
|
320
|
+
const response = await fetch(buildUrl(basePath, "/organizations/invites/reject"), {
|
|
321
|
+
method: "POST",
|
|
322
|
+
credentials: "include",
|
|
323
|
+
headers: { "content-type": "application/json" },
|
|
324
|
+
body: JSON.stringify({ token })
|
|
325
|
+
});
|
|
326
|
+
if (response.ok) return { success: true };
|
|
327
|
+
const data = await response.json().catch(() => null);
|
|
328
|
+
return { success: false, error: typeof data?.error === "string" ? data.error : `HTTP ${response.status}` };
|
|
329
|
+
},
|
|
330
|
+
[basePath]
|
|
331
|
+
);
|
|
332
|
+
const getMyJoinRequest = useCallback(
|
|
333
|
+
async (organizationId) => {
|
|
334
|
+
const response = await fetch(buildUrl(basePath, `/organizations/${organizationId}/join-requests/me`), {
|
|
335
|
+
credentials: "include"
|
|
336
|
+
});
|
|
337
|
+
if (response.status === 404) return null;
|
|
338
|
+
if (!response.ok) throw new Error(await parseError(response));
|
|
339
|
+
return response.json();
|
|
340
|
+
},
|
|
341
|
+
[basePath]
|
|
342
|
+
);
|
|
280
343
|
const value = useMemo(
|
|
281
344
|
() => ({
|
|
282
345
|
basePath,
|
|
@@ -396,6 +459,19 @@ function GeekappsAuthProvider({
|
|
|
396
459
|
return null;
|
|
397
460
|
}),
|
|
398
461
|
listMembers: (organizationId) => request(`/organizations/${organizationId}/members`),
|
|
462
|
+
getMember: (organizationId, memberId) => request(`/organizations/${organizationId}/members/${memberId}`),
|
|
463
|
+
addMember: (organizationId, input) => toAuthResult(
|
|
464
|
+
() => request(`/organizations/${organizationId}/members`, {
|
|
465
|
+
method: "POST",
|
|
466
|
+
body: input
|
|
467
|
+
})
|
|
468
|
+
),
|
|
469
|
+
updateMember: (organizationId, memberId, input) => toAuthResult(
|
|
470
|
+
() => request(`/organizations/${organizationId}/members/${memberId}`, {
|
|
471
|
+
method: "PATCH",
|
|
472
|
+
body: input
|
|
473
|
+
})
|
|
474
|
+
),
|
|
399
475
|
updateMemberRole: (organizationId, memberId, input) => toAuthResult(
|
|
400
476
|
() => request(`/organizations/${organizationId}/members/${memberId}`, {
|
|
401
477
|
method: "PATCH",
|
|
@@ -416,14 +492,43 @@ function GeekappsAuthProvider({
|
|
|
416
492
|
revokeInvite: (organizationId, inviteId) => toAuthResult(async () => {
|
|
417
493
|
await request(`/organizations/${organizationId}/invites/${inviteId}`, { method: "DELETE" });
|
|
418
494
|
return null;
|
|
419
|
-
})
|
|
495
|
+
}),
|
|
496
|
+
listPublicOrganizations: () => request("/organizations/public"),
|
|
497
|
+
requestToJoin: (organizationId, input) => toAuthResult(
|
|
498
|
+
() => request(`/organizations/${organizationId}/join-requests`, {
|
|
499
|
+
method: "POST",
|
|
500
|
+
body: input ?? {}
|
|
501
|
+
})
|
|
502
|
+
),
|
|
503
|
+
getMyJoinRequest,
|
|
504
|
+
cancelJoinRequest: (organizationId) => toAuthResult(async () => {
|
|
505
|
+
await request(`/organizations/${organizationId}/join-requests/me`, { method: "DELETE" });
|
|
506
|
+
return null;
|
|
507
|
+
}),
|
|
508
|
+
listJoinRequests: (organizationId) => request(`/organizations/${organizationId}/join-requests`),
|
|
509
|
+
approveJoinRequest: (organizationId, requestId) => toAuthResult(
|
|
510
|
+
() => request(`/organizations/${organizationId}/join-requests/${requestId}/approve`, {
|
|
511
|
+
method: "POST"
|
|
512
|
+
})
|
|
513
|
+
),
|
|
514
|
+
rejectJoinRequest: (organizationId, requestId) => toAuthResult(
|
|
515
|
+
() => request(`/organizations/${organizationId}/join-requests/${requestId}/reject`, {
|
|
516
|
+
method: "POST"
|
|
517
|
+
})
|
|
518
|
+
),
|
|
519
|
+
getInvitePreview,
|
|
520
|
+
acceptInvite,
|
|
521
|
+
rejectInvite
|
|
420
522
|
}),
|
|
421
523
|
[
|
|
422
524
|
accounts,
|
|
525
|
+
acceptInvite,
|
|
423
526
|
addAccount,
|
|
424
527
|
basePath,
|
|
425
528
|
currentOrg,
|
|
426
529
|
currentOrgId,
|
|
530
|
+
getInvitePreview,
|
|
531
|
+
getMyJoinRequest,
|
|
427
532
|
isLoading,
|
|
428
533
|
isLoadingAccounts,
|
|
429
534
|
isLoadingOrganizations,
|
|
@@ -431,6 +536,7 @@ function GeekappsAuthProvider({
|
|
|
431
536
|
refreshAccounts,
|
|
432
537
|
refreshOrganizations,
|
|
433
538
|
refreshUser,
|
|
539
|
+
rejectInvite,
|
|
434
540
|
request,
|
|
435
541
|
setCurrentOrg,
|
|
436
542
|
signIn,
|
|
@@ -513,6 +619,9 @@ function useMembers() {
|
|
|
513
619
|
const context = useAuth();
|
|
514
620
|
return {
|
|
515
621
|
listMembers: context.listMembers,
|
|
622
|
+
getMember: context.getMember,
|
|
623
|
+
addMember: context.addMember,
|
|
624
|
+
updateMember: context.updateMember,
|
|
516
625
|
updateMemberRole: context.updateMemberRole,
|
|
517
626
|
removeMember: context.removeMember,
|
|
518
627
|
inviteMember: context.inviteMember,
|
|
@@ -520,6 +629,31 @@ function useMembers() {
|
|
|
520
629
|
revokeInvite: context.revokeInvite
|
|
521
630
|
};
|
|
522
631
|
}
|
|
632
|
+
function usePublicOrganizations() {
|
|
633
|
+
const context = useAuth();
|
|
634
|
+
return {
|
|
635
|
+
listPublicOrganizations: context.listPublicOrganizations
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function useJoinRequests() {
|
|
639
|
+
const context = useAuth();
|
|
640
|
+
return {
|
|
641
|
+
requestToJoin: context.requestToJoin,
|
|
642
|
+
getMyJoinRequest: context.getMyJoinRequest,
|
|
643
|
+
cancelJoinRequest: context.cancelJoinRequest,
|
|
644
|
+
listJoinRequests: context.listJoinRequests,
|
|
645
|
+
approveJoinRequest: context.approveJoinRequest,
|
|
646
|
+
rejectJoinRequest: context.rejectJoinRequest
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
function useInvites() {
|
|
650
|
+
const context = useAuth();
|
|
651
|
+
return {
|
|
652
|
+
getInvitePreview: context.getInvitePreview,
|
|
653
|
+
acceptInvite: context.acceptInvite,
|
|
654
|
+
rejectInvite: context.rejectInvite
|
|
655
|
+
};
|
|
656
|
+
}
|
|
523
657
|
function useServiceAccount() {
|
|
524
658
|
const { request } = useAuth();
|
|
525
659
|
const listServiceAccounts = useCallback(
|
|
@@ -575,9 +709,12 @@ export {
|
|
|
575
709
|
startGoogleLogin,
|
|
576
710
|
useAccounts,
|
|
577
711
|
useAuth,
|
|
712
|
+
useInvites,
|
|
713
|
+
useJoinRequests,
|
|
578
714
|
useMembers,
|
|
579
715
|
useOrg,
|
|
580
716
|
usePermissions,
|
|
717
|
+
usePublicOrganizations,
|
|
581
718
|
useRoles,
|
|
582
719
|
useServiceAccount,
|
|
583
720
|
useSessions,
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nexport type UserStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OrganizationStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OAuthClientType = \"public\" | \"confidential\";\n\nexport type AuthResult<T = unknown> =\n | { success: true; data: T }\n | { success: false; error: string; status?: number };\n\nexport type User = {\n id: string;\n email: string;\n name: string | null;\n phone: string | null;\n imageUrl: string | null;\n status?: UserStatus;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type ConnectedAccount = {\n id: string;\n sessionId?: string;\n isActive: boolean;\n user: User;\n};\n\nexport type Permission = {\n id: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description: string | null;\n category: string | null;\n isSystem: boolean;\n isActive: boolean;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RolePermission = {\n permissionDefinition: Permission;\n};\n\nexport type Role = {\n id: string;\n applicationId?: string | null;\n /** Present only on custom roles */\n organizationId?: string | null;\n /** \"system\" | \"custom\" */\n type?: string;\n key: string;\n name: string;\n description: string | null;\n isSystem?: boolean;\n isDefault?: boolean;\n isActive: boolean;\n permissions: RolePermission[];\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RoleAssignment = {\n id: string;\n roleDefinitionId?: string | null;\n customRoleId?: string | null;\n roleDefinition?: Role | null;\n customRole?: Role | null;\n};\n\nexport type OrganizationMember = {\n id: string;\n organizationId?: string;\n userId?: string;\n createdAt?: string | Date;\n user: User;\n roleAssignments?: RoleAssignment[];\n};\n\nexport type OrganizationInvite = {\n id: string;\n organizationId: string;\n email: string;\n roleId?: string | null;\n status: \"pending\" | \"accepted\" | \"expired\" | \"revoked\";\n expiresAt: string | Date;\n createdAt?: string | Date;\n};\n\nexport type MemberInviteInput = {\n email: string;\n roleId?: string;\n};\n\nexport type UpdateMemberRoleInput = {\n roleId: string;\n};\n\nexport type OrganizationOwnedApplication = {\n id: string;\n name: string;\n description: string | null;\n imageUrl: string | null;\n type?: OAuthClientType;\n organizationId: string;\n isFirstParty: boolean;\n ssoEnabled: boolean;\n status?: \"active\" | \"inactive\" | \"suspended\";\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type Organization = {\n id: string;\n name: string;\n description: string | null;\n slug: string;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n status: OrganizationStatus;\n members?: OrganizationMember[];\n ownedApplications?: OrganizationOwnedApplication[];\n applicationLinks?: Array<{\n id: string;\n status: OrganizationStatus;\n createdAt?: string | Date;\n application: OrganizationOwnedApplication;\n }>;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nexport type SessionApplication = {\n id: string;\n createdAt: string | Date;\n expiresAt: string | Date;\n application: {\n id: string;\n name: string;\n organizationId: string;\n };\n};\n\nexport type UserSession = {\n id: string;\n userId: string;\n organizationId: string | null;\n deviceAgent: string | null;\n deviceId: string | null;\n deviceName: string | null;\n ip: string | null;\n authState?: unknown;\n authTime?: string | Date;\n expiresAt: string | Date;\n createdAt: string | Date;\n updatedAt: string | Date;\n user?: User;\n applicationSessions?: SessionApplication[];\n};\n\nexport type UserInput = {\n name?: string | null;\n email?: string;\n phone?: string | null;\n imageUrl?: string | null;\n password?: string;\n organizationId?: string | null;\n status?: UserStatus;\n};\n\nexport type OrganizationInput = {\n name: string;\n description?: string | null;\n slug: string;\n domain?: string | null;\n imageUrl?: string | null;\n faviconUrl?: string | null;\n};\n\nexport type OrganizationUpdateInput = Partial<OrganizationInput> & {\n status?: OrganizationStatus;\n};\n\nexport type RoleInput = {\n organizationId: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n permissionDefinitionIds?: string[];\n};\n\nexport type RoleUpdateInput = {\n name?: string;\n description?: string | null;\n isActive?: boolean;\n permissionDefinitionIds?: string[];\n};\n\nexport type PermissionInput = {\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n category?: string | null;\n};\n\nexport type PermissionUpdateInput = {\n name?: string;\n description?: string | null;\n category?: string | null;\n isActive?: boolean;\n};\n\nexport type SignInOptions = {\n redirectTo?: string;\n authorizationFlowId?: string;\n /** When false, forces the IDP to show the login screen even if a session exists. Defaults to true (silent). */\n silentLogin?: boolean;\n};\n\nexport type SignInInput = SignInOptions | MouseEvent<HTMLElement>;\n\nexport type CallbackUrlOptions = SignInOptions & {\n callbackUrl?: string;\n};\n\nexport type PermissionCheckOptions = {\n permission: string;\n organizationId?: string | null;\n applicationId?: string | null;\n resourceId?: string | null;\n};\n\nexport type LoginResponse = {\n user: User;\n redirectTo?: string | null;\n};\n\nexport type RegisterResponse = User;\n\nexport type GeekappsAuthProviderProps = {\n children: ReactNode;\n basePath?: string;\n initialUser?: User | null;\n initialOrganizations?: Organization[];\n initialCurrentOrgId?: string | null;\n};\n\ntype RequestOptions = {\n body?: unknown;\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n};\n\nfunction normalizeBasePath(basePath: string) {\n return basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n}\n\nfunction buildUrl(basePath: string, path: string) {\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${normalizeBasePath(basePath)}${normalizedPath}`;\n}\n\nasync function parseError(response: Response) {\n const data = await response.json().catch(() => null);\n return (\n data?.error_description ??\n data?.error ??\n data?.message ??\n `Request failed with status ${response.status}`\n );\n}\n\nfunction redirectTo(path: string) {\n window.location.assign(path);\n}\n\nfunction isMouseEvent(value: unknown): value is MouseEvent<HTMLElement> {\n return Boolean(value && typeof value === \"object\" && \"preventDefault\" in value);\n}\n\nfunction normalizeSignInOptions(input?: SignInInput): SignInOptions | undefined {\n if (!input) return undefined;\n if (isMouseEvent(input)) {\n input.preventDefault();\n return undefined;\n }\n return input;\n}\n\n\ntype ClientActionOptions = {\n basePath?: string;\n};\n\nasync function clientRequest<T>(\n path: string,\n options: RequestOptions = {},\n basePath = \"/api/auth\",\n): Promise<T> {\n const response = await fetch(buildUrl(basePath, path), {\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n method: options.method ?? \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n}\n\nasync function toStandaloneAuthResult<T>(\n fn: () => Promise<T>,\n): Promise<AuthResult<T>> {\n try {\n return {\n success: true,\n data: await fn(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Auth request failed\",\n };\n }\n}\n\nexport async function loginWithPassword(\n params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<LoginResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<LoginResponse>(\n \"/login/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo ?? data.redirectTo) {\n redirectTo(params.redirectTo ?? data.redirectTo!);\n }\n\n return data;\n });\n}\n\nexport async function registerWithPassword(\n params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<RegisterResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<RegisterResponse>(\n \"/register/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo) {\n redirectTo(params.redirectTo);\n }\n\n return data;\n });\n}\n\nexport function startGoogleLogin(\n params?: CallbackUrlOptions,\n options?: ClientActionOptions,\n) {\n const basePath = options?.basePath ?? \"/api/auth\";\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n\n if (params?.callbackUrl) {\n url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n }\n\n if (params?.redirectTo) {\n url.searchParams.set(\"redirectTo\", params.redirectTo);\n }\n\n if (params?.authorizationFlowId) {\n url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n }\n\n redirectTo(url.toString());\n}\n\nexport async function requestPasswordlessLink(\n params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult> {\n return toStandaloneAuthResult(() =>\n clientRequest(\n \"/passwordless/link\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n ),\n );\n}\n\nexport type GeekappsAuthContextValue = {\n basePath: string;\n user: User | null;\n isAuthenticated: boolean;\n isLoading: boolean;\n accounts: ConnectedAccount[];\n isLoadingAccounts: boolean;\n organizations: Organization[];\n currentOrg: Organization | null;\n currentOrgId: string | null;\n isLoadingOrganizations: boolean;\n\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n\n signIn: (options?: SignInInput) => Promise<void>;\n signUp: (options?: SignInInput) => Promise<void>;\n addAccount: (options?: SignInInput) => Promise<void>;\n signOut: () => Promise<void>;\n signOutAll: () => Promise<void>;\n refreshUser: () => Promise<void>;\n refreshAccounts: () => Promise<void>;\n switchAccount: (sessionId: string, options?: SignInOptions) => Promise<void>;\n\n loginWithPassword: (params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n }) => Promise<AuthResult<LoginResponse>>;\n registerWithPassword: (params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n }) => Promise<AuthResult<RegisterResponse>>;\n startGoogleLogin: (params?: CallbackUrlOptions) => void;\n requestPasswordlessLink: (params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n }) => Promise<AuthResult>;\n\n refreshOrganizations: () => Promise<void>;\n setCurrentOrg: (organizationId: string | null) => Promise<void>;\n createOrganization: (input: OrganizationInput) => Promise<AuthResult<Organization>>;\n updateOrganization: (id: string, input: OrganizationUpdateInput) => Promise<AuthResult<Organization>>;\n deleteOrganization: (id: string) => Promise<AuthResult<null>>;\n hasPermission: (options: PermissionCheckOptions) => Promise<boolean>;\n\n listUsers: (params?: { organizationId?: string | null }) => Promise<User[]>;\n getUser: (id: string) => Promise<User>;\n createUser: (input: UserInput) => Promise<AuthResult<User>>;\n updateUser: (id: string, input: UserInput) => Promise<AuthResult<User>>;\n deleteUser: (id: string) => Promise<AuthResult<null>>;\n\n listRoles: (params?: { organizationId?: string; applicationId?: string; type?: \"system\" | \"custom\" | \"all\" }) => Promise<{ systemRoles: Role[]; customRoles: Role[] }>;\n getRole: (id: string, type: \"system\" | \"custom\") => Promise<Role>;\n createRole: (input: RoleInput) => Promise<AuthResult<Role>>;\n updateRole: (id: string, input: RoleUpdateInput) => Promise<AuthResult<Role>>;\n deleteRole: (id: string) => Promise<AuthResult<null>>;\n\n listPermissions: (params?: { applicationId?: string; roleId?: string | null }) => Promise<Permission[]>;\n createPermission: (input: PermissionInput) => Promise<AuthResult<Permission>>;\n updatePermission: (id: string, input: PermissionUpdateInput) => Promise<AuthResult<Permission>>;\n deletePermission: (id: string) => Promise<AuthResult<null>>;\n\n listUserSessions: (params?: { userId?: string; organizationId?: string | null }) => Promise<UserSession[]>;\n revokeUserSession: (sessionId: string) => Promise<AuthResult<null>>;\n\n listMembers: (organizationId: string) => Promise<OrganizationMember[]>;\n updateMemberRole: (\n organizationId: string,\n memberId: string,\n input: UpdateMemberRoleInput,\n ) => Promise<AuthResult<OrganizationMember>>;\n removeMember: (organizationId: string, memberId: string) => Promise<AuthResult<null>>;\n inviteMember: (organizationId: string, input: MemberInviteInput) => Promise<AuthResult<OrganizationInvite>>;\n listInvites: (organizationId: string) => Promise<OrganizationInvite[]>;\n revokeInvite: (organizationId: string, inviteId: string) => Promise<AuthResult<null>>;\n};\n\nexport type UseOrgResult = Pick<\n GeekappsAuthContextValue,\n | \"organizations\"\n | \"currentOrg\"\n | \"currentOrgId\"\n | \"isLoadingOrganizations\"\n | \"refreshOrganizations\"\n | \"setCurrentOrg\"\n | \"createOrganization\"\n | \"updateOrganization\"\n | \"deleteOrganization\"\n | \"hasPermission\"\n>;\n\nexport type UseAccountsResult = Pick<\n GeekappsAuthContextValue,\n \"accounts\" | \"addAccount\" | \"isLoadingAccounts\" | \"refreshAccounts\" | \"switchAccount\"\n>;\n\nexport type UseUsersResult = Pick<\n GeekappsAuthContextValue,\n \"listUsers\" | \"getUser\" | \"createUser\" | \"updateUser\" | \"deleteUser\"\n>;\n\nexport type UseRolesResult = Pick<\n GeekappsAuthContextValue,\n \"listRoles\" | \"getRole\" | \"createRole\" | \"updateRole\" | \"deleteRole\"\n>;\n\nexport type UsePermissionsResult = Pick<\n GeekappsAuthContextValue,\n \"listPermissions\" | \"createPermission\" | \"updatePermission\" | \"deletePermission\"\n>;\n\nexport type UseSessionsResult = Pick<\n GeekappsAuthContextValue,\n \"listUserSessions\" | \"revokeUserSession\"\n>;\n\nexport type UseMembersResult = Pick<\n GeekappsAuthContextValue,\n | \"listMembers\"\n | \"updateMemberRole\"\n | \"removeMember\"\n | \"inviteMember\"\n | \"listInvites\"\n | \"revokeInvite\"\n>;\n\nconst GeekappsAuthContext = createContext<GeekappsAuthContextValue | null>(null);\n\nexport function GeekappsAuthProvider({\n children,\n basePath = \"/api/auth\",\n initialUser = null,\n initialOrganizations = [],\n initialCurrentOrgId = null,\n}: GeekappsAuthProviderProps): ReactElement {\n const [user, setUser] = useState<User | null>(initialUser);\n const [isLoading, setIsLoading] = useState(true);\n const [accounts, setAccounts] = useState<ConnectedAccount[]>([]);\n const [isLoadingAccounts, setIsLoadingAccounts] = useState(true);\n const [organizations, setOrganizations] = useState<Organization[]>(initialOrganizations);\n const [currentOrgId, setCurrentOrgId] = useState<string | null>(initialCurrentOrgId);\n const [isLoadingOrganizations, setIsLoadingOrganizations] = useState(true);\n\n const request = useCallback(\n async <T,>(path: string, options: RequestOptions = {}) => {\n const response = await fetch(buildUrl(basePath, path), {\n method: options.method ?? \"GET\",\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n },\n [basePath],\n );\n\n const refreshUser = useCallback(async () => {\n setIsLoading(true);\n try {\n const { user: u } = await request<{ user: User | null }>(\"/me\");\n setUser(u);\n } catch {\n setUser(null);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const refreshAccounts = useCallback(async () => {\n setIsLoadingAccounts(true);\n try {\n const { accounts: a } = await request<{ accounts: ConnectedAccount[] }>(\n \"/accounts\",\n );\n setAccounts(a);\n } catch {\n setAccounts([]);\n } finally {\n setIsLoadingAccounts(false);\n }\n }, []);\n\n const refreshOrganizations = useCallback(async () => {\n setIsLoadingOrganizations(true);\n try {\n const { organizations: orgs, currentOrgId: nextCurrentOrgId } =\n await request<{\n organizations: Organization[];\n currentOrgId?: string | null;\n }>(\"/organizations\");\n setOrganizations(orgs);\n setCurrentOrgId((current) => {\n if (nextCurrentOrgId !== undefined) return nextCurrentOrgId ?? null;\n if (current && orgs.some((org) => org.id === current)) return current;\n return orgs[0]?.id ?? null;\n });\n } catch {\n setOrganizations([]);\n setCurrentOrgId(null);\n } finally {\n setIsLoadingOrganizations(false);\n }\n }, []);\n\n useEffect(() => {\n void refreshUser();\n void refreshAccounts();\n void refreshOrganizations();\n }, [refreshAccounts, refreshOrganizations, refreshUser]);\n\n const currentOrg = useMemo(\n () => organizations.find((organization) => organization.id === currentOrgId) ?? null,\n [currentOrgId, organizations],\n );\n\n const setCurrentOrg = useCallback(\n async (organizationId: string | null) => {\n await request(\"/organizations/active\", {\n method: \"POST\",\n body: { organizationId },\n });\n setCurrentOrgId(organizationId);\n },\n [request],\n );\n\n const signIn = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-in\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n if (options?.silentLogin === false) url.searchParams.set(\"silentLogin\", \"false\");\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signUp = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-up\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n if (options?.silentLogin === false) url.searchParams.set(\"silentLogin\", \"false\");\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const addAccount = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/add-account\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signOut = useCallback(async () => {\n await request(\"/sign-out\", { method: \"POST\" });\n setUser(null);\n await refreshAccounts();\n }, [refreshAccounts, request]);\n\n const signOutAll = useCallback(async () => {\n await request(\"/sign-out-all\", { method: \"POST\" });\n setUser(null);\n setAccounts([]);\n }, [request]);\n\n const switchAccount = useCallback(\n async (sessionId: string, options?: SignInOptions) => {\n await request(\"/accounts/switch\", {\n method: \"POST\",\n body: { sessionId },\n });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (options?.redirectTo) redirectTo(options.redirectTo);\n },\n [refreshAccounts, refreshOrganizations, refreshUser, request],\n );\n\n async function toAuthResult<T>(fn: () => Promise<T>): Promise<AuthResult<T>> {\n try {\n return { success: true, data: await fn() };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : \"Unexpected error\" };\n }\n }\n\n const value = useMemo<GeekappsAuthContextValue>(\n () => ({\n basePath,\n user,\n isAuthenticated: !isLoading && user !== null,\n isLoading,\n accounts,\n isLoadingAccounts,\n organizations,\n currentOrg,\n currentOrgId,\n isLoadingOrganizations,\n request,\n signIn,\n signUp,\n addAccount,\n signOut,\n signOutAll,\n refreshUser,\n refreshAccounts,\n switchAccount,\n loginWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<LoginResponse>(\"/login/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo ?? data.redirectTo) redirectTo(params.redirectTo ?? data.redirectTo!);\n return data;\n }),\n registerWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<RegisterResponse>(\"/register/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo) redirectTo(params.redirectTo);\n return data;\n }),\n startGoogleLogin: (params) => {\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n if (params?.callbackUrl) url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n if (params?.redirectTo) url.searchParams.set(\"redirectTo\", params.redirectTo);\n if (params?.authorizationFlowId) url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n redirectTo(url.toString());\n },\n requestPasswordlessLink: (params) =>\n toAuthResult(() => request(\"/passwordless/link\", { method: \"POST\", body: params })),\n refreshOrganizations,\n setCurrentOrg,\n createOrganization: (input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(\"/organizations\", { method: \"POST\", body: input });\n await refreshOrganizations();\n setCurrentOrgId(organization.id);\n return organization;\n }),\n updateOrganization: (id, input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(`/organizations/${id}`, { method: \"PATCH\", body: input });\n await refreshOrganizations();\n return organization;\n }),\n deleteOrganization: (id) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${id}`, { method: \"DELETE\" });\n await refreshOrganizations();\n return null;\n }),\n hasPermission: async (options) => {\n try {\n const data = await request<{ allowed: boolean }>(\"/permissions/check\", {\n method: \"POST\",\n body: options,\n });\n return data.allowed;\n } catch {\n return false;\n }\n },\n listUsers: (params) => {\n const query = new URLSearchParams();\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<User[]>(`/users${query.size ? `?${query.toString()}` : \"\"}`);\n },\n getUser: (id) => request<User>(`/users/${id}`),\n createUser: (input) => toAuthResult(() => request<User>(\"/users\", { method: \"POST\", body: input })),\n updateUser: (id, input) => toAuthResult(() => request<User>(`/users/${id}`, { method: \"PATCH\", body: input })),\n deleteUser: (id) =>\n toAuthResult(async () => {\n await request<null>(`/users/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listRoles: (params) => {\n const query = new URLSearchParams();\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n if (params?.applicationId) query.set(\"applicationId\", params.applicationId);\n if (params?.type) query.set(\"type\", params.type);\n return request<{ systemRoles: Role[]; customRoles: Role[] }>(`/roles${query.size ? `?${query.toString()}` : \"\"}`);\n },\n getRole: (id, type) => request<Role>(type === \"custom\" ? `/roles/custom/${id}` : `/roles/definitions/${id}`),\n createRole: (input) => toAuthResult(() => request<Role>(\"/roles\", { method: \"POST\", body: input })),\n updateRole: (id, input) => toAuthResult(() => request<Role>(`/roles/custom/${id}`, { method: \"PATCH\", body: input })),\n deleteRole: (id) =>\n toAuthResult(async () => {\n await request<null>(`/roles/custom/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listPermissions: (params) => {\n const query = new URLSearchParams();\n if (params?.applicationId) query.set(\"applicationId\", params.applicationId);\n if (params?.roleId) query.set(\"roleId\", params.roleId);\n return request<Permission[]>(`/permissions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n createPermission: (input) =>\n toAuthResult(() => request<Permission>(\"/permissions\", { method: \"POST\", body: input })),\n updatePermission: (id, input) =>\n toAuthResult(() => request<Permission>(`/permissions/${id}`, { method: \"PATCH\", body: input })),\n deletePermission: (id) =>\n toAuthResult(async () => {\n await request<null>(`/permissions/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listUserSessions: (params) => {\n const query = new URLSearchParams();\n if (params?.userId) query.set(\"userId\", params.userId);\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<UserSession[]>(`/sessions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n revokeUserSession: (sessionId) =>\n toAuthResult(async () => {\n await request<null>(`/sessions/${sessionId}`, { method: \"DELETE\" });\n return null;\n }),\n listMembers: (organizationId) =>\n request<OrganizationMember[]>(`/organizations/${organizationId}/members`),\n updateMemberRole: (organizationId, memberId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`, {\n method: \"PATCH\",\n body: input,\n }),\n ),\n removeMember: (organizationId, memberId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/members/${memberId}`, { method: \"DELETE\" });\n return null;\n }),\n inviteMember: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationInvite>(`/organizations/${organizationId}/invites`, {\n method: \"POST\",\n body: input,\n }),\n ),\n listInvites: (organizationId) =>\n request<OrganizationInvite[]>(`/organizations/${organizationId}/invites`),\n revokeInvite: (organizationId, inviteId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/invites/${inviteId}`, { method: \"DELETE\" });\n return null;\n }),\n }),\n [\n accounts,\n addAccount,\n basePath,\n currentOrg,\n currentOrgId,\n isLoading,\n isLoadingAccounts,\n isLoadingOrganizations,\n organizations,\n refreshAccounts,\n refreshOrganizations,\n refreshUser,\n request,\n setCurrentOrg,\n signIn,\n signOut,\n signOutAll,\n signUp,\n switchAccount,\n user,\n ],\n );\n\n return <GeekappsAuthContext.Provider value={value}>{children}</GeekappsAuthContext.Provider>;\n}\n\nexport function useAuth(): GeekappsAuthContextValue {\n const context = useContext(GeekappsAuthContext);\n if (!context) throw new Error(\"useAuth must be used inside GeekappsAuthProvider\");\n return context;\n}\n\nexport function useOrg(): UseOrgResult {\n const context = useAuth();\n return {\n organizations: context.organizations,\n currentOrg: context.currentOrg,\n currentOrgId: context.currentOrgId,\n isLoadingOrganizations: context.isLoadingOrganizations,\n refreshOrganizations: context.refreshOrganizations,\n setCurrentOrg: context.setCurrentOrg,\n createOrganization: context.createOrganization,\n updateOrganization: context.updateOrganization,\n deleteOrganization: context.deleteOrganization,\n hasPermission: context.hasPermission,\n };\n}\n\nexport function useAccounts(): UseAccountsResult {\n const context = useAuth();\n return {\n accounts: context.accounts,\n addAccount: context.addAccount,\n isLoadingAccounts: context.isLoadingAccounts,\n refreshAccounts: context.refreshAccounts,\n switchAccount: context.switchAccount,\n };\n}\n\nexport function useUsers(): UseUsersResult {\n const context = useAuth();\n return {\n listUsers: context.listUsers,\n getUser: context.getUser,\n createUser: context.createUser,\n updateUser: context.updateUser,\n deleteUser: context.deleteUser,\n };\n}\n\nexport function useRoles(): UseRolesResult {\n const context = useAuth();\n return {\n listRoles: context.listRoles,\n getRole: context.getRole,\n createRole: context.createRole,\n updateRole: context.updateRole,\n deleteRole: context.deleteRole,\n };\n}\n\nexport function usePermissions(): UsePermissionsResult {\n const context = useAuth();\n return {\n listPermissions: context.listPermissions,\n createPermission: context.createPermission,\n updatePermission: context.updatePermission,\n deletePermission: context.deletePermission,\n };\n}\n\nexport function useSessions(): UseSessionsResult {\n const context = useAuth();\n return {\n listUserSessions: context.listUserSessions,\n revokeUserSession: context.revokeUserSession,\n };\n}\n\nexport function useMembers(): UseMembersResult {\n const context = useAuth();\n return {\n listMembers: context.listMembers,\n updateMemberRole: context.updateMemberRole,\n removeMember: context.removeMember,\n inviteMember: context.inviteMember,\n listInvites: context.listInvites,\n revokeInvite: context.revokeInvite,\n };\n}\n\n// ── Service Accounts ─────────────────────────────────────────────────────────\n\nexport type ServiceAccount = {\n id: string;\n membershipId: string;\n organizationId: string;\n applicationId: string | null;\n name: string;\n status: \"active\" | \"inactive\" | \"suspended\";\n serviceId: string | null;\n roleAssignment: { role: { id: string; key: string; name: string } } | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type ServiceAccountWithSecret = ServiceAccount & { serviceSecret: string };\n\nexport type CreateServiceAccountInput = {\n organizationId: string;\n applicationId?: string;\n name: string;\n description?: string;\n roleId?: string;\n};\n\nexport type UseServiceAccountResult = {\n listServiceAccounts: (params: { organizationId: string; applicationId?: string }) => Promise<ServiceAccount[]>;\n createServiceAccount: (input: CreateServiceAccountInput) => Promise<ServiceAccountWithSecret>;\n updateServiceAccountRole: (id: string, roleId: string | null) => Promise<void>;\n revokeServiceAccount: (id: string) => Promise<void>;\n rotateServiceAccountSecret: (id: string) => Promise<{ serviceId: string; serviceSecret: string }>;\n deleteServiceAccount: (id: string) => Promise<void>;\n};\n\nexport function useServiceAccount(): UseServiceAccountResult {\n const { request } = useAuth();\n\n const listServiceAccounts = useCallback(\n (params: { organizationId: string; applicationId?: string }) => {\n const query = new URLSearchParams({ organizationId: params.organizationId });\n if (params.applicationId) query.set(\"applicationId\", params.applicationId);\n return request<ServiceAccount[]>(`/service-accounts?${query.toString()}`);\n },\n [request],\n );\n\n const createServiceAccount = useCallback(\n (input: CreateServiceAccountInput) =>\n request<ServiceAccountWithSecret>(\"/service-accounts\", { method: \"POST\", body: input }),\n [request],\n );\n\n const updateServiceAccountRole = useCallback(\n async (id: string, roleId: string | null) => {\n await request<void>(`/service-accounts/${id}`, { method: \"PATCH\", body: { roleId } });\n },\n [request],\n );\n\n const revokeServiceAccount = useCallback(\n async (id: string) => {\n await request<void>(`/service-accounts/${id}/revoke`, { method: \"POST\" });\n },\n [request],\n );\n\n const rotateServiceAccountSecret = useCallback(\n (id: string) =>\n request<{ serviceId: string; serviceSecret: string }>(`/service-accounts/${id}/rotate-secret`, {\n method: \"POST\",\n }),\n [request],\n );\n\n const deleteServiceAccount = useCallback(\n async (id: string) => {\n await request<null>(`/service-accounts/${id}`, { method: \"DELETE\" });\n },\n [request],\n );\n\n return {\n listServiceAccounts,\n createServiceAccount,\n updateServiceAccountRole,\n revokeServiceAccount,\n rotateServiceAccountSecret,\n deleteServiceAccount,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nexport type UserStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OrganizationStatus = \"active\" | \"inactive\" | \"suspended\";\nexport type OAuthClientType = \"public\" | \"confidential\";\n\nexport type AuthResult<T = unknown> =\n | { success: true; data: T }\n | { success: false; error: string; status?: number };\n\nexport type User = {\n id: string;\n email: string;\n name: string | null;\n phone: string | null;\n imageUrl: string | null;\n status?: UserStatus;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type ConnectedAccount = {\n id: string;\n sessionId?: string;\n isActive: boolean;\n user: User;\n};\n\nexport type Permission = {\n id: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description: string | null;\n category: string | null;\n isSystem: boolean;\n isActive: boolean;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RolePermission = {\n permissionDefinition: Permission;\n};\n\nexport type Role = {\n id: string;\n applicationId?: string | null;\n /** Present only on custom roles */\n organizationId?: string | null;\n /** \"system\" | \"custom\" */\n type?: string;\n key: string;\n name: string;\n description: string | null;\n isSystem?: boolean;\n isDefault?: boolean;\n isActive: boolean;\n permissions: RolePermission[];\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type RoleAssignment = {\n id: string;\n roleDefinitionId?: string | null;\n customRoleId?: string | null;\n roleDefinition?: Role | null;\n customRole?: Role | null;\n};\n\nexport type OrganizationMember = {\n id: string;\n organizationId?: string;\n userId?: string;\n createdAt?: string | Date;\n user: User;\n roleAssignments?: RoleAssignment[];\n};\n\nexport type OrganizationInvite = {\n id: string;\n organizationId: string;\n email: string;\n roleId?: string | null;\n status: \"pending\" | \"accepted\" | \"expired\" | \"revoked\";\n expiresAt: string | Date;\n createdAt?: string | Date;\n};\n\nexport type MemberInviteInput = {\n email: string;\n roleId?: string;\n /**\n * URI pra onde o link do e-mail manda o usuário — precisa estar cadastrada\n * em Application.redirectUris (mesma validação do /authorize). Este app\n * deve expor uma rota nessa URI que trata o `?invite_token=` anexado (ver\n * useJoinRequests/inviteApi.preview|accept|reject abaixo).\n */\n redirectUri: string;\n emailTitle?: string;\n emailSubtitle?: string;\n emailMessage?: string;\n};\n\nexport type AddMemberInput = {\n userId: string;\n roleId?: string;\n};\n\nexport type UpdateMemberInput = {\n status?: \"active\" | \"inactive\" | \"suspended\";\n roleId?: string | null;\n};\n\n/** @deprecated use UpdateMemberInput */\nexport type UpdateMemberRoleInput = {\n roleId: string;\n};\n\nexport type PublicOrganization = {\n id: string;\n name: string;\n slug: string;\n description: string | null;\n imageUrl: string | null;\n createdAt: string | Date;\n};\n\nexport type OrganizationInvitePreview =\n | {\n alreadyAccepted: true;\n organizationName: string;\n applicationName: string;\n applicationImageUrl: string | null;\n applicationImageFileId: string | null;\n organizationImageUrl: string | null;\n organizationImageFileId: string | null;\n websiteUrl: string | null;\n }\n | {\n alreadyAccepted?: false;\n email: string;\n organizationName: string;\n applicationName: string;\n applicationId: string;\n applicationImageUrl: string | null;\n applicationImageFileId: string | null;\n organizationImageUrl: string | null;\n organizationImageFileId: string | null;\n websiteUrl: string | null;\n redirectUri: string | null;\n appStoreUrl: string | null;\n playStoreUrl: string | null;\n currentAccount: { email: string; name: string | null } | null;\n };\n\nexport type AcceptInviteResult =\n | { success: true; organizationName: string; websiteUrl: string | null }\n | { success: false; wrongAccount: true; currentEmail: string; invitedEmail: string }\n | { success: false; wrongAccount: false; loginRequired: true }\n | { success: false; wrongAccount: false; loginRequired: false; error: string };\n\nexport type JoinRequestStatus = \"pending\" | \"approved\" | \"rejected\" | \"cancelled\";\n\nexport type OrganizationJoinRequest = {\n id: string;\n organizationId: string;\n userId: string;\n status: JoinRequestStatus;\n message: string | null;\n reviewedByUserId: string | null;\n reviewedAt: string | null;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nexport type OrganizationOwnedApplication = {\n id: string;\n name: string;\n description: string | null;\n imageUrl: string | null;\n type?: OAuthClientType;\n organizationId: string;\n isFirstParty: boolean;\n ssoEnabled: boolean;\n status?: \"active\" | \"inactive\" | \"suspended\";\n createdAt?: string | Date;\n updatedAt?: string | Date;\n};\n\nexport type Organization = {\n id: string;\n name: string;\n description: string | null;\n slug: string;\n domain: string | null;\n imageUrl: string | null;\n faviconUrl: string | null;\n status: OrganizationStatus;\n /** \"private\" (padrão) nunca sai em listPublicOrganizations(); \"public\" sai, e aceita join requests. */\n visibility?: \"public\" | \"private\";\n members?: OrganizationMember[];\n ownedApplications?: OrganizationOwnedApplication[];\n applicationLinks?: Array<{\n id: string;\n status: OrganizationStatus;\n createdAt?: string | Date;\n application: OrganizationOwnedApplication;\n }>;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nexport type SessionApplication = {\n id: string;\n createdAt: string | Date;\n expiresAt: string | Date;\n application: {\n id: string;\n name: string;\n organizationId: string;\n };\n};\n\nexport type UserSession = {\n id: string;\n userId: string;\n organizationId: string | null;\n deviceAgent: string | null;\n deviceId: string | null;\n deviceName: string | null;\n ip: string | null;\n authState?: unknown;\n authTime?: string | Date;\n expiresAt: string | Date;\n createdAt: string | Date;\n updatedAt: string | Date;\n user?: User;\n applicationSessions?: SessionApplication[];\n};\n\nexport type UserInput = {\n name?: string | null;\n email?: string;\n phone?: string | null;\n imageUrl?: string | null;\n password?: string;\n organizationId?: string | null;\n status?: UserStatus;\n};\n\nexport type OrganizationInput = {\n name: string;\n description?: string | null;\n slug: string;\n domain?: string | null;\n imageUrl?: string | null;\n faviconUrl?: string | null;\n};\n\nexport type OrganizationUpdateInput = Partial<OrganizationInput> & {\n status?: OrganizationStatus;\n};\n\nexport type RoleInput = {\n organizationId: string;\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n permissionDefinitionIds?: string[];\n};\n\nexport type RoleUpdateInput = {\n name?: string;\n description?: string | null;\n isActive?: boolean;\n permissionDefinitionIds?: string[];\n};\n\nexport type PermissionInput = {\n applicationId?: string | null;\n key: string;\n name: string;\n description?: string | null;\n category?: string | null;\n};\n\nexport type PermissionUpdateInput = {\n name?: string;\n description?: string | null;\n category?: string | null;\n isActive?: boolean;\n};\n\n/**\n * OIDC `prompt` values understood by the Geekapps Auth Server. These control\n * whether — and how — the IDP shows UI during `signIn()`/`signUp()`/`addAccount()`.\n *\n * - `\"login\"` — Forces the login screen, even if the user already has an active\n * session. Use this for a fresh login, unrelated to whatever session already\n * exists (equivalent to the old `silentLogin: false`).\n * - `\"select_account\"` — Shows the account picker so the user can choose among\n * their connected accounts, or add a new one. Use this when you want to let\n * the user switch accounts explicitly.\n * - `\"none\"` — Never shows any UI. The IDP authenticates silently if there is\n * exactly one active session (and no other interaction — like consent or a\n * security check — is pending); otherwise it fails immediately with an OIDC\n * error (`login_required`, `account_selection_required`, `consent_required`,\n * or `interaction_required`) instead of prompting the user. Use this for\n * silent-auth checks (e.g. \"is the user still logged in?\") where you don't\n * want to interrupt them with a screen.\n * - `\"consent\"` — Forces the consent screen even if the user already granted\n * the requested scopes before.\n *\n * Omitting `prompt` entirely runs the IDP's default flow: reuse a single\n * existing session silently, ask the user to pick when there are multiple\n * connected accounts, or show the login screen when there's none.\n */\nexport type OidcPrompt = \"login\" | \"select_account\" | \"none\" | \"consent\";\n\nexport type SignInOptions = {\n redirectTo?: string;\n authorizationFlowId?: string;\n /**\n * Controls whether the IDP shows UI, and which screen, during sign-in. See\n * {@link OidcPrompt} for what each value does. Omit it to run the default flow.\n */\n prompt?: OidcPrompt;\n /**\n * @deprecated Use `prompt: \"login\"` instead. Kept for backwards compatibility —\n * `silentLogin: false` is equivalent to `prompt: \"login\"`.\n */\n silentLogin?: boolean;\n};\n\nexport type SignInInput = SignInOptions | MouseEvent<HTMLElement>;\n\nexport type CallbackUrlOptions = SignInOptions & {\n callbackUrl?: string;\n};\n\nexport type PermissionCheckOptions = {\n permission: string;\n organizationId?: string | null;\n applicationId?: string | null;\n resourceId?: string | null;\n};\n\nexport type LoginResponse = {\n user: User;\n redirectTo?: string | null;\n};\n\nexport type RegisterResponse = User;\n\nexport type GeekappsAuthProviderProps = {\n children: ReactNode;\n basePath?: string;\n initialUser?: User | null;\n initialOrganizations?: Organization[];\n initialCurrentOrgId?: string | null;\n};\n\ntype RequestOptions = {\n body?: unknown;\n method?: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n};\n\nfunction normalizeBasePath(basePath: string) {\n return basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n}\n\nfunction buildUrl(basePath: string, path: string) {\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${normalizeBasePath(basePath)}${normalizedPath}`;\n}\n\nasync function parseError(response: Response) {\n const data = await response.json().catch(() => null);\n return (\n data?.error_description ??\n data?.error ??\n data?.message ??\n `Request failed with status ${response.status}`\n );\n}\n\nfunction redirectTo(path: string) {\n window.location.assign(path);\n}\n\nfunction isMouseEvent(value: unknown): value is MouseEvent<HTMLElement> {\n return Boolean(value && typeof value === \"object\" && \"preventDefault\" in value);\n}\n\nfunction normalizeSignInOptions(input?: SignInInput): SignInOptions | undefined {\n if (!input) return undefined;\n if (isMouseEvent(input)) {\n input.preventDefault();\n return undefined;\n }\n return input;\n}\n\n\ntype ClientActionOptions = {\n basePath?: string;\n};\n\nasync function clientRequest<T>(\n path: string,\n options: RequestOptions = {},\n basePath = \"/api/auth\",\n): Promise<T> {\n const response = await fetch(buildUrl(basePath, path), {\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n method: options.method ?? \"GET\",\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n}\n\nasync function toStandaloneAuthResult<T>(\n fn: () => Promise<T>,\n): Promise<AuthResult<T>> {\n try {\n return {\n success: true,\n data: await fn(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Auth request failed\",\n };\n }\n}\n\nexport async function loginWithPassword(\n params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<LoginResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<LoginResponse>(\n \"/login/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo ?? data.redirectTo) {\n redirectTo(params.redirectTo ?? data.redirectTo!);\n }\n\n return data;\n });\n}\n\nexport async function registerWithPassword(\n params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult<RegisterResponse>> {\n return toStandaloneAuthResult(async () => {\n const data = await clientRequest<RegisterResponse>(\n \"/register/password\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n );\n\n if (params.redirectTo) {\n redirectTo(params.redirectTo);\n }\n\n return data;\n });\n}\n\nexport function startGoogleLogin(\n params?: CallbackUrlOptions,\n options?: ClientActionOptions,\n) {\n const basePath = options?.basePath ?? \"/api/auth\";\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n\n if (params?.callbackUrl) {\n url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n }\n\n if (params?.redirectTo) {\n url.searchParams.set(\"redirectTo\", params.redirectTo);\n }\n\n if (params?.authorizationFlowId) {\n url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n }\n\n redirectTo(url.toString());\n}\n\nexport async function requestPasswordlessLink(\n params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n },\n options?: ClientActionOptions,\n): Promise<AuthResult> {\n return toStandaloneAuthResult(() =>\n clientRequest(\n \"/passwordless/link\",\n {\n body: params,\n method: \"POST\",\n },\n options?.basePath,\n ),\n );\n}\n\nexport type GeekappsAuthContextValue = {\n basePath: string;\n user: User | null;\n isAuthenticated: boolean;\n isLoading: boolean;\n accounts: ConnectedAccount[];\n isLoadingAccounts: boolean;\n organizations: Organization[];\n currentOrg: Organization | null;\n currentOrgId: string | null;\n isLoadingOrganizations: boolean;\n\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n\n signIn: (options?: SignInInput) => Promise<void>;\n signUp: (options?: SignInInput) => Promise<void>;\n addAccount: (options?: SignInInput) => Promise<void>;\n signOut: () => Promise<void>;\n signOutAll: () => Promise<void>;\n refreshUser: () => Promise<void>;\n refreshAccounts: () => Promise<void>;\n switchAccount: (sessionId: string, options?: SignInOptions) => Promise<void>;\n\n loginWithPassword: (params: {\n identifier?: string;\n email?: string;\n phone?: string;\n password: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n }) => Promise<AuthResult<LoginResponse>>;\n registerWithPassword: (params: {\n name: string;\n email: string;\n phone?: string;\n imageUrl?: string;\n address?: Record<string, unknown>;\n password: string;\n redirectTo?: string;\n }) => Promise<AuthResult<RegisterResponse>>;\n startGoogleLogin: (params?: CallbackUrlOptions) => void;\n requestPasswordlessLink: (params: {\n email: string;\n authorizationFlowId?: string;\n redirectTo?: string;\n callbackUrl?: string;\n }) => Promise<AuthResult>;\n\n refreshOrganizations: () => Promise<void>;\n setCurrentOrg: (organizationId: string | null) => Promise<void>;\n createOrganization: (input: OrganizationInput) => Promise<AuthResult<Organization>>;\n updateOrganization: (id: string, input: OrganizationUpdateInput) => Promise<AuthResult<Organization>>;\n deleteOrganization: (id: string) => Promise<AuthResult<null>>;\n hasPermission: (options: PermissionCheckOptions) => Promise<boolean>;\n\n /** Organizações públicas e ativas deste app — nunca inclui privadas, não exige membership. Separado de `organizations` (só as do próprio usuário). */\n listPublicOrganizations: () => Promise<PublicOrganization[]>;\n\n requestToJoin: (organizationId: string, input?: { message?: string | null }) => Promise<AuthResult<OrganizationJoinRequest>>;\n getMyJoinRequest: (organizationId: string) => Promise<OrganizationJoinRequest | null>;\n cancelJoinRequest: (organizationId: string) => Promise<AuthResult<null>>;\n listJoinRequests: (organizationId: string) => Promise<OrganizationJoinRequest[]>;\n approveJoinRequest: (organizationId: string, requestId: string) => Promise<AuthResult<OrganizationJoinRequest>>;\n rejectJoinRequest: (organizationId: string, requestId: string) => Promise<AuthResult<OrganizationJoinRequest>>;\n\n /** Preview do convite por token — funciona com ou sem sessão (currentAccount vem null se deslogado). */\n getInvitePreview: (token: string) => Promise<OrganizationInvitePreview>;\n /** Aceita o convite. loginRequired:true significa que signIn() precisa rodar antes. */\n acceptInvite: (token: string) => Promise<AcceptInviteResult>;\n /** Recusa o convite — não exige estar logado. */\n rejectInvite: (token: string) => Promise<{ success: true } | { success: false; error: string }>;\n\n listUsers: (params?: { organizationId?: string | null }) => Promise<User[]>;\n getUser: (id: string) => Promise<User>;\n createUser: (input: UserInput) => Promise<AuthResult<User>>;\n updateUser: (id: string, input: UserInput) => Promise<AuthResult<User>>;\n deleteUser: (id: string) => Promise<AuthResult<null>>;\n\n listRoles: (params?: { organizationId?: string; applicationId?: string; type?: \"system\" | \"custom\" | \"all\" }) => Promise<{ systemRoles: Role[]; customRoles: Role[] }>;\n getRole: (id: string, type: \"system\" | \"custom\") => Promise<Role>;\n createRole: (input: RoleInput) => Promise<AuthResult<Role>>;\n updateRole: (id: string, input: RoleUpdateInput) => Promise<AuthResult<Role>>;\n deleteRole: (id: string) => Promise<AuthResult<null>>;\n\n listPermissions: (params?: { applicationId?: string; roleId?: string | null }) => Promise<Permission[]>;\n createPermission: (input: PermissionInput) => Promise<AuthResult<Permission>>;\n updatePermission: (id: string, input: PermissionUpdateInput) => Promise<AuthResult<Permission>>;\n deletePermission: (id: string) => Promise<AuthResult<null>>;\n\n listUserSessions: (params?: { userId?: string; organizationId?: string | null }) => Promise<UserSession[]>;\n revokeUserSession: (sessionId: string) => Promise<AuthResult<null>>;\n\n listMembers: (organizationId: string) => Promise<OrganizationMember[]>;\n getMember: (organizationId: string, memberId: string) => Promise<OrganizationMember>;\n addMember: (organizationId: string, input: AddMemberInput) => Promise<AuthResult<OrganizationMember>>;\n updateMember: (\n organizationId: string,\n memberId: string,\n input: UpdateMemberInput,\n ) => Promise<AuthResult<OrganizationMember>>;\n /** @deprecated use updateMember */\n updateMemberRole: (\n organizationId: string,\n memberId: string,\n input: UpdateMemberRoleInput,\n ) => Promise<AuthResult<OrganizationMember>>;\n removeMember: (organizationId: string, memberId: string) => Promise<AuthResult<null>>;\n inviteMember: (organizationId: string, input: MemberInviteInput) => Promise<AuthResult<OrganizationInvite>>;\n listInvites: (organizationId: string) => Promise<OrganizationInvite[]>;\n revokeInvite: (organizationId: string, inviteId: string) => Promise<AuthResult<null>>;\n};\n\nexport type UseOrgResult = Pick<\n GeekappsAuthContextValue,\n | \"organizations\"\n | \"currentOrg\"\n | \"currentOrgId\"\n | \"isLoadingOrganizations\"\n | \"refreshOrganizations\"\n | \"setCurrentOrg\"\n | \"createOrganization\"\n | \"updateOrganization\"\n | \"deleteOrganization\"\n | \"hasPermission\"\n>;\n\nexport type UseAccountsResult = Pick<\n GeekappsAuthContextValue,\n \"accounts\" | \"addAccount\" | \"isLoadingAccounts\" | \"refreshAccounts\" | \"switchAccount\"\n>;\n\nexport type UseUsersResult = Pick<\n GeekappsAuthContextValue,\n \"listUsers\" | \"getUser\" | \"createUser\" | \"updateUser\" | \"deleteUser\"\n>;\n\nexport type UseRolesResult = Pick<\n GeekappsAuthContextValue,\n \"listRoles\" | \"getRole\" | \"createRole\" | \"updateRole\" | \"deleteRole\"\n>;\n\nexport type UsePermissionsResult = Pick<\n GeekappsAuthContextValue,\n \"listPermissions\" | \"createPermission\" | \"updatePermission\" | \"deletePermission\"\n>;\n\nexport type UseSessionsResult = Pick<\n GeekappsAuthContextValue,\n \"listUserSessions\" | \"revokeUserSession\"\n>;\n\nexport type UseMembersResult = Pick<\n GeekappsAuthContextValue,\n | \"listMembers\"\n | \"getMember\"\n | \"addMember\"\n | \"updateMember\"\n | \"updateMemberRole\"\n | \"removeMember\"\n | \"inviteMember\"\n | \"listInvites\"\n | \"revokeInvite\"\n>;\n\nexport type UsePublicOrganizationsResult = Pick<GeekappsAuthContextValue, \"listPublicOrganizations\">;\n\nexport type UseJoinRequestsResult = Pick<\n GeekappsAuthContextValue,\n | \"requestToJoin\"\n | \"getMyJoinRequest\"\n | \"cancelJoinRequest\"\n | \"listJoinRequests\"\n | \"approveJoinRequest\"\n | \"rejectJoinRequest\"\n>;\n\nexport type UseInvitesResult = Pick<GeekappsAuthContextValue, \"getInvitePreview\" | \"acceptInvite\" | \"rejectInvite\">;\n\nconst GeekappsAuthContext = createContext<GeekappsAuthContextValue | null>(null);\n\nexport function GeekappsAuthProvider({\n children,\n basePath = \"/api/auth\",\n initialUser = null,\n initialOrganizations = [],\n initialCurrentOrgId = null,\n}: GeekappsAuthProviderProps): ReactElement {\n const [user, setUser] = useState<User | null>(initialUser);\n const [isLoading, setIsLoading] = useState(true);\n const [accounts, setAccounts] = useState<ConnectedAccount[]>([]);\n const [isLoadingAccounts, setIsLoadingAccounts] = useState(true);\n const [organizations, setOrganizations] = useState<Organization[]>(initialOrganizations);\n const [currentOrgId, setCurrentOrgId] = useState<string | null>(initialCurrentOrgId);\n const [isLoadingOrganizations, setIsLoadingOrganizations] = useState(true);\n\n const request = useCallback(\n async <T,>(path: string, options: RequestOptions = {}) => {\n const response = await fetch(buildUrl(basePath, path), {\n method: options.method ?? \"GET\",\n credentials: \"include\",\n headers:\n options.body === undefined\n ? undefined\n : {\n \"content-type\": \"application/json\",\n },\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n });\n\n if (!response.ok) {\n throw new Error(await parseError(response));\n }\n\n if (response.status === 204) {\n return null as T;\n }\n\n return (await response.json()) as T;\n },\n [basePath],\n );\n\n const refreshUser = useCallback(async () => {\n setIsLoading(true);\n try {\n const { user: u } = await request<{ user: User | null }>(\"/me\");\n setUser(u);\n } catch {\n setUser(null);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const refreshAccounts = useCallback(async () => {\n setIsLoadingAccounts(true);\n try {\n const { accounts: a } = await request<{ accounts: ConnectedAccount[] }>(\n \"/accounts\",\n );\n setAccounts(a);\n } catch {\n setAccounts([]);\n } finally {\n setIsLoadingAccounts(false);\n }\n }, []);\n\n const refreshOrganizations = useCallback(async () => {\n setIsLoadingOrganizations(true);\n try {\n const { organizations: orgs, currentOrgId: nextCurrentOrgId } =\n await request<{\n organizations: Organization[];\n currentOrgId?: string | null;\n }>(\"/organizations\");\n setOrganizations(orgs);\n setCurrentOrgId((current) => {\n if (nextCurrentOrgId !== undefined) return nextCurrentOrgId ?? null;\n if (current && orgs.some((org) => org.id === current)) return current;\n return orgs[0]?.id ?? null;\n });\n } catch {\n setOrganizations([]);\n setCurrentOrgId(null);\n } finally {\n setIsLoadingOrganizations(false);\n }\n }, []);\n\n useEffect(() => {\n void refreshUser();\n void refreshAccounts();\n void refreshOrganizations();\n }, [refreshAccounts, refreshOrganizations, refreshUser]);\n\n const currentOrg = useMemo(\n () => organizations.find((organization) => organization.id === currentOrgId) ?? null,\n [currentOrgId, organizations],\n );\n\n const setCurrentOrg = useCallback(\n async (organizationId: string | null) => {\n await request(\"/organizations/active\", {\n method: \"POST\",\n body: { organizationId },\n });\n setCurrentOrgId(organizationId);\n },\n [request],\n );\n\n const signIn = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-in\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n const prompt = options?.prompt ?? (options?.silentLogin === false ? \"login\" : undefined);\n if (prompt) url.searchParams.set(\"prompt\", prompt);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signUp = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/sign-up\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n if (options?.authorizationFlowId) url.searchParams.set(\"flow_id\", options.authorizationFlowId);\n const prompt = options?.prompt ?? (options?.silentLogin === false ? \"login\" : undefined);\n if (prompt) url.searchParams.set(\"prompt\", prompt);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const addAccount = useCallback(\n async (input?: SignInInput) => {\n const options = normalizeSignInOptions(input);\n const url = new URL(buildUrl(basePath, \"/add-account\"), window.location.origin);\n if (options?.redirectTo) url.searchParams.set(\"redirectTo\", options.redirectTo);\n redirectTo(url.toString());\n },\n [basePath],\n );\n\n const signOut = useCallback(async () => {\n await request(\"/sign-out\", { method: \"POST\" });\n setUser(null);\n await refreshAccounts();\n }, [refreshAccounts, request]);\n\n const signOutAll = useCallback(async () => {\n await request(\"/sign-out-all\", { method: \"POST\" });\n setUser(null);\n setAccounts([]);\n }, [request]);\n\n const switchAccount = useCallback(\n async (sessionId: string, options?: SignInOptions) => {\n await request(\"/accounts/switch\", {\n method: \"POST\",\n body: { sessionId },\n });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (options?.redirectTo) redirectTo(options.redirectTo);\n },\n [refreshAccounts, refreshOrganizations, refreshUser, request],\n );\n\n async function toAuthResult<T>(fn: () => Promise<T>): Promise<AuthResult<T>> {\n try {\n return { success: true, data: await fn() };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : \"Unexpected error\" };\n }\n }\n\n // ── Invites: precisam do status HTTP cru (401/404/409), não só uma\n // mensagem — request()/toAuthResult() não bastam aqui.\n const getInvitePreview = useCallback(\n (token: string) => request<OrganizationInvitePreview>(`/organizations/invites/${encodeURIComponent(token)}`),\n [request],\n );\n\n const acceptInvite = useCallback(\n async (token: string): Promise<AcceptInviteResult> => {\n const response = await fetch(buildUrl(basePath, \"/organizations/invites/accept\"), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n const data = await response.json().catch(() => null);\n\n if (response.ok && data) {\n return { success: true, organizationName: data.organizationName, websiteUrl: data.websiteUrl ?? null };\n }\n if (response.status === 409 && data?.error === \"wrong_account\") {\n return {\n success: false,\n wrongAccount: true,\n currentEmail: String(data.currentEmail ?? \"\"),\n invitedEmail: String(data.invitedEmail ?? \"\"),\n };\n }\n if (response.status === 401 && data?.error === \"login_required\") {\n return { success: false, wrongAccount: false, loginRequired: true };\n }\n return {\n success: false,\n wrongAccount: false,\n loginRequired: false,\n error: typeof data?.error === \"string\" ? data.error : `HTTP ${response.status}`,\n };\n },\n [basePath],\n );\n\n const rejectInvite = useCallback(\n async (token: string): Promise<{ success: true } | { success: false; error: string }> => {\n const response = await fetch(buildUrl(basePath, \"/organizations/invites/reject\"), {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n if (response.ok) return { success: true };\n const data = await response.json().catch(() => null);\n return { success: false, error: typeof data?.error === \"string\" ? data.error : `HTTP ${response.status}` };\n },\n [basePath],\n );\n\n const getMyJoinRequest = useCallback(\n async (organizationId: string): Promise<OrganizationJoinRequest | null> => {\n const response = await fetch(buildUrl(basePath, `/organizations/${organizationId}/join-requests/me`), {\n credentials: \"include\",\n });\n if (response.status === 404) return null;\n if (!response.ok) throw new Error(await parseError(response));\n return response.json();\n },\n [basePath],\n );\n\n const value = useMemo<GeekappsAuthContextValue>(\n () => ({\n basePath,\n user,\n isAuthenticated: !isLoading && user !== null,\n isLoading,\n accounts,\n isLoadingAccounts,\n organizations,\n currentOrg,\n currentOrgId,\n isLoadingOrganizations,\n request,\n signIn,\n signUp,\n addAccount,\n signOut,\n signOutAll,\n refreshUser,\n refreshAccounts,\n switchAccount,\n loginWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<LoginResponse>(\"/login/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo ?? data.redirectTo) redirectTo(params.redirectTo ?? data.redirectTo!);\n return data;\n }),\n registerWithPassword: (params) =>\n toAuthResult(async () => {\n const data = await request<RegisterResponse>(\"/register/password\", { method: \"POST\", body: params });\n await Promise.all([refreshUser(), refreshAccounts(), refreshOrganizations()]);\n if (params.redirectTo) redirectTo(params.redirectTo);\n return data;\n }),\n startGoogleLogin: (params) => {\n const url = new URL(buildUrl(basePath, \"/login/google\"), window.location.origin);\n if (params?.callbackUrl) url.searchParams.set(\"callbackUrl\", params.callbackUrl);\n if (params?.redirectTo) url.searchParams.set(\"redirectTo\", params.redirectTo);\n if (params?.authorizationFlowId) url.searchParams.set(\"flow_id\", params.authorizationFlowId);\n redirectTo(url.toString());\n },\n requestPasswordlessLink: (params) =>\n toAuthResult(() => request(\"/passwordless/link\", { method: \"POST\", body: params })),\n refreshOrganizations,\n setCurrentOrg,\n createOrganization: (input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(\"/organizations\", { method: \"POST\", body: input });\n await refreshOrganizations();\n setCurrentOrgId(organization.id);\n return organization;\n }),\n updateOrganization: (id, input) =>\n toAuthResult(async () => {\n const organization = await request<Organization>(`/organizations/${id}`, { method: \"PATCH\", body: input });\n await refreshOrganizations();\n return organization;\n }),\n deleteOrganization: (id) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${id}`, { method: \"DELETE\" });\n await refreshOrganizations();\n return null;\n }),\n hasPermission: async (options) => {\n try {\n const data = await request<{ allowed: boolean }>(\"/permissions/check\", {\n method: \"POST\",\n body: options,\n });\n return data.allowed;\n } catch {\n return false;\n }\n },\n listUsers: (params) => {\n const query = new URLSearchParams();\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<User[]>(`/users${query.size ? `?${query.toString()}` : \"\"}`);\n },\n getUser: (id) => request<User>(`/users/${id}`),\n createUser: (input) => toAuthResult(() => request<User>(\"/users\", { method: \"POST\", body: input })),\n updateUser: (id, input) => toAuthResult(() => request<User>(`/users/${id}`, { method: \"PATCH\", body: input })),\n deleteUser: (id) =>\n toAuthResult(async () => {\n await request<null>(`/users/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listRoles: (params) => {\n const query = new URLSearchParams();\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n if (params?.applicationId) query.set(\"applicationId\", params.applicationId);\n if (params?.type) query.set(\"type\", params.type);\n return request<{ systemRoles: Role[]; customRoles: Role[] }>(`/roles${query.size ? `?${query.toString()}` : \"\"}`);\n },\n getRole: (id, type) => request<Role>(type === \"custom\" ? `/roles/custom/${id}` : `/roles/definitions/${id}`),\n createRole: (input) => toAuthResult(() => request<Role>(\"/roles\", { method: \"POST\", body: input })),\n updateRole: (id, input) => toAuthResult(() => request<Role>(`/roles/custom/${id}`, { method: \"PATCH\", body: input })),\n deleteRole: (id) =>\n toAuthResult(async () => {\n await request<null>(`/roles/custom/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listPermissions: (params) => {\n const query = new URLSearchParams();\n if (params?.applicationId) query.set(\"applicationId\", params.applicationId);\n if (params?.roleId) query.set(\"roleId\", params.roleId);\n return request<Permission[]>(`/permissions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n createPermission: (input) =>\n toAuthResult(() => request<Permission>(\"/permissions\", { method: \"POST\", body: input })),\n updatePermission: (id, input) =>\n toAuthResult(() => request<Permission>(`/permissions/${id}`, { method: \"PATCH\", body: input })),\n deletePermission: (id) =>\n toAuthResult(async () => {\n await request<null>(`/permissions/${id}`, { method: \"DELETE\" });\n return null;\n }),\n listUserSessions: (params) => {\n const query = new URLSearchParams();\n if (params?.userId) query.set(\"userId\", params.userId);\n if (params?.organizationId) query.set(\"organizationId\", params.organizationId);\n return request<UserSession[]>(`/sessions${query.size ? `?${query.toString()}` : \"\"}`);\n },\n revokeUserSession: (sessionId) =>\n toAuthResult(async () => {\n await request<null>(`/sessions/${sessionId}`, { method: \"DELETE\" });\n return null;\n }),\n listMembers: (organizationId) =>\n request<OrganizationMember[]>(`/organizations/${organizationId}/members`),\n getMember: (organizationId, memberId) =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`),\n addMember: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members`, {\n method: \"POST\",\n body: input,\n }),\n ),\n updateMember: (organizationId, memberId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`, {\n method: \"PATCH\",\n body: input,\n }),\n ),\n updateMemberRole: (organizationId, memberId, input) =>\n toAuthResult(() =>\n request<OrganizationMember>(`/organizations/${organizationId}/members/${memberId}`, {\n method: \"PATCH\",\n body: input,\n }),\n ),\n removeMember: (organizationId, memberId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/members/${memberId}`, { method: \"DELETE\" });\n return null;\n }),\n inviteMember: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationInvite>(`/organizations/${organizationId}/invites`, {\n method: \"POST\",\n body: input,\n }),\n ),\n listInvites: (organizationId) =>\n request<OrganizationInvite[]>(`/organizations/${organizationId}/invites`),\n revokeInvite: (organizationId, inviteId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/invites/${inviteId}`, { method: \"DELETE\" });\n return null;\n }),\n listPublicOrganizations: () => request<PublicOrganization[]>(\"/organizations/public\"),\n requestToJoin: (organizationId, input) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests`, {\n method: \"POST\",\n body: input ?? {},\n }),\n ),\n getMyJoinRequest,\n cancelJoinRequest: (organizationId) =>\n toAuthResult(async () => {\n await request<null>(`/organizations/${organizationId}/join-requests/me`, { method: \"DELETE\" });\n return null;\n }),\n listJoinRequests: (organizationId) =>\n request<OrganizationJoinRequest[]>(`/organizations/${organizationId}/join-requests`),\n approveJoinRequest: (organizationId, requestId) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests/${requestId}/approve`, {\n method: \"POST\",\n }),\n ),\n rejectJoinRequest: (organizationId, requestId) =>\n toAuthResult(() =>\n request<OrganizationJoinRequest>(`/organizations/${organizationId}/join-requests/${requestId}/reject`, {\n method: \"POST\",\n }),\n ),\n getInvitePreview,\n acceptInvite,\n rejectInvite,\n }),\n [\n accounts,\n acceptInvite,\n addAccount,\n basePath,\n currentOrg,\n currentOrgId,\n getInvitePreview,\n getMyJoinRequest,\n isLoading,\n isLoadingAccounts,\n isLoadingOrganizations,\n organizations,\n refreshAccounts,\n refreshOrganizations,\n refreshUser,\n rejectInvite,\n request,\n setCurrentOrg,\n signIn,\n signOut,\n signOutAll,\n signUp,\n switchAccount,\n user,\n ],\n );\n\n return <GeekappsAuthContext.Provider value={value}>{children}</GeekappsAuthContext.Provider>;\n}\n\nexport function useAuth(): GeekappsAuthContextValue {\n const context = useContext(GeekappsAuthContext);\n if (!context) throw new Error(\"useAuth must be used inside GeekappsAuthProvider\");\n return context;\n}\n\nexport function useOrg(): UseOrgResult {\n const context = useAuth();\n return {\n organizations: context.organizations,\n currentOrg: context.currentOrg,\n currentOrgId: context.currentOrgId,\n isLoadingOrganizations: context.isLoadingOrganizations,\n refreshOrganizations: context.refreshOrganizations,\n setCurrentOrg: context.setCurrentOrg,\n createOrganization: context.createOrganization,\n updateOrganization: context.updateOrganization,\n deleteOrganization: context.deleteOrganization,\n hasPermission: context.hasPermission,\n };\n}\n\nexport function useAccounts(): UseAccountsResult {\n const context = useAuth();\n return {\n accounts: context.accounts,\n addAccount: context.addAccount,\n isLoadingAccounts: context.isLoadingAccounts,\n refreshAccounts: context.refreshAccounts,\n switchAccount: context.switchAccount,\n };\n}\n\nexport function useUsers(): UseUsersResult {\n const context = useAuth();\n return {\n listUsers: context.listUsers,\n getUser: context.getUser,\n createUser: context.createUser,\n updateUser: context.updateUser,\n deleteUser: context.deleteUser,\n };\n}\n\nexport function useRoles(): UseRolesResult {\n const context = useAuth();\n return {\n listRoles: context.listRoles,\n getRole: context.getRole,\n createRole: context.createRole,\n updateRole: context.updateRole,\n deleteRole: context.deleteRole,\n };\n}\n\nexport function usePermissions(): UsePermissionsResult {\n const context = useAuth();\n return {\n listPermissions: context.listPermissions,\n createPermission: context.createPermission,\n updatePermission: context.updatePermission,\n deletePermission: context.deletePermission,\n };\n}\n\nexport function useSessions(): UseSessionsResult {\n const context = useAuth();\n return {\n listUserSessions: context.listUserSessions,\n revokeUserSession: context.revokeUserSession,\n };\n}\n\nexport function useMembers(): UseMembersResult {\n const context = useAuth();\n return {\n listMembers: context.listMembers,\n getMember: context.getMember,\n addMember: context.addMember,\n updateMember: context.updateMember,\n updateMemberRole: context.updateMemberRole,\n removeMember: context.removeMember,\n inviteMember: context.inviteMember,\n listInvites: context.listInvites,\n revokeInvite: context.revokeInvite,\n };\n}\n\n/**\n * Descoberta de organizações PÚBLICAS do app — bem separado de `useOrg()`,\n * que lida com as organizações do próprio usuário (as que ele já é\n * membro/dono). `usePublicOrganizations()` nunca retorna organizações\n * privadas, e não exige que o usuário já pertença a elas.\n */\nexport function usePublicOrganizations(): UsePublicOrganizationsResult {\n const context = useAuth();\n return {\n listPublicOrganizations: context.listPublicOrganizations,\n };\n}\n\n/**\n * Solicitações de entrada em organizações públicas: um usuário pede pra\n * entrar (requestToJoin) e um admin da organização aprova/rejeita\n * (approveJoinRequest/rejectJoinRequest, exigem permissão org:members:add).\n */\nexport function useJoinRequests(): UseJoinRequestsResult {\n const context = useAuth();\n return {\n requestToJoin: context.requestToJoin,\n getMyJoinRequest: context.getMyJoinRequest,\n cancelJoinRequest: context.cancelJoinRequest,\n listJoinRequests: context.listJoinRequests,\n approveJoinRequest: context.approveJoinRequest,\n rejectJoinRequest: context.rejectJoinRequest,\n };\n}\n\n/**\n * Aceite/recusa de convite por email — chamadas a partir do ?invite_token=\n * que este app recebe na sua própria redirectUri (a que foi passada em\n * useMembers().inviteMember). getInvitePreview funciona sem sessão\n * (currentAccount vem null); rejectInvite não exige login; acceptInvite\n * retorna loginRequired:true se não houver sessão.\n */\nexport function useInvites(): UseInvitesResult {\n const context = useAuth();\n return {\n getInvitePreview: context.getInvitePreview,\n acceptInvite: context.acceptInvite,\n rejectInvite: context.rejectInvite,\n };\n}\n\n// ── Service Accounts ─────────────────────────────────────────────────────────\n\nexport type ServiceAccount = {\n id: string;\n membershipId: string;\n organizationId: string;\n applicationId: string | null;\n name: string;\n status: \"active\" | \"inactive\" | \"suspended\";\n serviceId: string | null;\n roleAssignment: { role: { id: string; key: string; name: string } } | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type ServiceAccountWithSecret = ServiceAccount & { serviceSecret: string };\n\nexport type CreateServiceAccountInput = {\n organizationId: string;\n applicationId?: string;\n name: string;\n description?: string;\n roleId?: string;\n};\n\nexport type UseServiceAccountResult = {\n listServiceAccounts: (params: { organizationId: string; applicationId?: string }) => Promise<ServiceAccount[]>;\n createServiceAccount: (input: CreateServiceAccountInput) => Promise<ServiceAccountWithSecret>;\n updateServiceAccountRole: (id: string, roleId: string | null) => Promise<void>;\n revokeServiceAccount: (id: string) => Promise<void>;\n rotateServiceAccountSecret: (id: string) => Promise<{ serviceId: string; serviceSecret: string }>;\n deleteServiceAccount: (id: string) => Promise<void>;\n};\n\nexport function useServiceAccount(): UseServiceAccountResult {\n const { request } = useAuth();\n\n const listServiceAccounts = useCallback(\n (params: { organizationId: string; applicationId?: string }) => {\n const query = new URLSearchParams({ organizationId: params.organizationId });\n if (params.applicationId) query.set(\"applicationId\", params.applicationId);\n return request<ServiceAccount[]>(`/service-accounts?${query.toString()}`);\n },\n [request],\n );\n\n const createServiceAccount = useCallback(\n (input: CreateServiceAccountInput) =>\n request<ServiceAccountWithSecret>(\"/service-accounts\", { method: \"POST\", body: input }),\n [request],\n );\n\n const updateServiceAccountRole = useCallback(\n async (id: string, roleId: string | null) => {\n await request<void>(`/service-accounts/${id}`, { method: \"PATCH\", body: { roleId } });\n },\n [request],\n );\n\n const revokeServiceAccount = useCallback(\n async (id: string) => {\n await request<void>(`/service-accounts/${id}/revoke`, { method: \"POST\" });\n },\n [request],\n );\n\n const rotateServiceAccountSecret = useCallback(\n (id: string) =>\n request<{ serviceId: string; serviceSecret: string }>(`/service-accounts/${id}/rotate-secret`, {\n method: \"POST\",\n }),\n [request],\n );\n\n const deleteServiceAccount = useCallback(\n async (id: string) => {\n await request<null>(`/service-accounts/${id}`, { method: \"DELETE\" });\n },\n [request],\n );\n\n return {\n listServiceAccounts,\n createServiceAccount,\n updateServiceAccountRole,\n revokeServiceAccount,\n rotateServiceAccountSecret,\n deleteServiceAccount,\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/middleware.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// src/middleware.ts
|
|
2
|
+
import { NextResponse as NextResponse2 } from "next/server";
|
|
3
|
+
import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
|
|
4
|
+
|
|
5
|
+
// src/server.ts
|
|
6
|
+
import { cookies, headers } from "next/headers";
|
|
7
|
+
import { redirect } from "next/navigation";
|
|
2
8
|
import { NextResponse } from "next/server";
|
|
3
9
|
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
10
|
+
var GEEKAPPS_AUTH_SERVER_URL = "https://accounts-api.geekapps.com.br";
|
|
11
|
+
|
|
12
|
+
// src/middleware.ts
|
|
4
13
|
function env(name) {
|
|
5
14
|
const value = process.env[name];
|
|
6
15
|
return value && value.trim().length > 0 ? value : void 0;
|
|
@@ -14,7 +23,8 @@ function normalizeBasePath(path = "/api/auth") {
|
|
|
14
23
|
}
|
|
15
24
|
function resolveIssuer(input) {
|
|
16
25
|
return normalizeBaseUrl(
|
|
17
|
-
input.issuer ??
|
|
26
|
+
input.issuer ?? // Deprecated: kept for backwards compatibility during the auth-server rename.
|
|
27
|
+
env("GEEKAPPS_AUTH_ISSUER") ?? env("GEEKAPPS_AUTH_API_URL") ?? GEEKAPPS_AUTH_SERVER_URL
|
|
18
28
|
);
|
|
19
29
|
}
|
|
20
30
|
function hashClientId(clientId) {
|
|
@@ -52,13 +62,13 @@ function resolveAppOrigin(request, appUrl) {
|
|
|
52
62
|
var _jwksCache = /* @__PURE__ */ new Map();
|
|
53
63
|
function getRemoteJWKS(issuer) {
|
|
54
64
|
if (!_jwksCache.has(issuer)) {
|
|
55
|
-
_jwksCache.set(issuer,
|
|
65
|
+
_jwksCache.set(issuer, createRemoteJWKSet2(new URL(`${issuer}/.well-known/jwks.json`)));
|
|
56
66
|
}
|
|
57
67
|
return _jwksCache.get(issuer);
|
|
58
68
|
}
|
|
59
69
|
async function verifyAccessToken(token, issuer) {
|
|
60
70
|
try {
|
|
61
|
-
await
|
|
71
|
+
await jwtVerify2(token, getRemoteJWKS(issuer), { algorithms: ["RS256"], issuer });
|
|
62
72
|
return "valid";
|
|
63
73
|
} catch (err) {
|
|
64
74
|
if (err instanceof TypeError) return "network_error";
|
|
@@ -80,7 +90,7 @@ function createAuthMiddleware(input = {}) {
|
|
|
80
90
|
function redirectResponse(request, url) {
|
|
81
91
|
const isRsc = request.headers.has("rsc") || request.headers.has("next-router-prefetch") || request.nextUrl.searchParams.has("_rsc");
|
|
82
92
|
if (isRsc) {
|
|
83
|
-
return new
|
|
93
|
+
return new NextResponse2(null, {
|
|
84
94
|
status: 302,
|
|
85
95
|
headers: {
|
|
86
96
|
location: url.toString(),
|
|
@@ -89,11 +99,11 @@ function createAuthMiddleware(input = {}) {
|
|
|
89
99
|
}
|
|
90
100
|
});
|
|
91
101
|
}
|
|
92
|
-
return
|
|
102
|
+
return NextResponse2.redirect(url);
|
|
93
103
|
}
|
|
94
104
|
return async function authMiddleware(request) {
|
|
95
105
|
if (request.nextUrl.pathname.startsWith(basePath + "/") || request.nextUrl.pathname === basePath) {
|
|
96
|
-
return
|
|
106
|
+
return NextResponse2.next();
|
|
97
107
|
}
|
|
98
108
|
const countRaw = request.cookies.get(countCookie)?.value;
|
|
99
109
|
const count = countRaw ? Number.parseInt(countRaw, 10) : 0;
|
|
@@ -117,19 +127,19 @@ function createAuthMiddleware(input = {}) {
|
|
|
117
127
|
}
|
|
118
128
|
if (!accessToken && !refreshToken) {
|
|
119
129
|
if (input.forceLoginOnUnauthenticated) return redirectResponse(request, signInUrl);
|
|
120
|
-
return
|
|
130
|
+
return NextResponse2.next();
|
|
121
131
|
}
|
|
122
132
|
const exp = accessToken ? decodeJwtExp(accessToken) : null;
|
|
123
133
|
const nowSec = Math.floor(Date.now() / 1e3);
|
|
124
134
|
const expiredOrMissing = !exp || exp - nowSec < 60;
|
|
125
135
|
if (!expiredOrMissing) {
|
|
126
136
|
const verifyResult = await verifyAccessToken(accessToken, issuer);
|
|
127
|
-
if (verifyResult === "valid") return
|
|
128
|
-
if (verifyResult === "network_error") return
|
|
137
|
+
if (verifyResult === "valid") return NextResponse2.next();
|
|
138
|
+
if (verifyResult === "network_error") return NextResponse2.next();
|
|
129
139
|
}
|
|
130
140
|
if (!refreshToken) {
|
|
131
141
|
if (input.forceLoginOnUnauthenticated) return redirectResponse(request, signInUrl);
|
|
132
|
-
return
|
|
142
|
+
return NextResponse2.next();
|
|
133
143
|
}
|
|
134
144
|
const clientSecret = env("GEEKAPPS_AUTH_CLIENT_SECRET") ?? "";
|
|
135
145
|
const basicAuth = btoa(`${clientId ?? ""}:${clientSecret}`);
|
|
@@ -159,7 +169,7 @@ function createAuthMiddleware(input = {}) {
|
|
|
159
169
|
}
|
|
160
170
|
}
|
|
161
171
|
if (!newAccessToken) {
|
|
162
|
-
const response2 = input.forceLoginOnUnauthenticated ? redirectResponse(request, signInUrl) :
|
|
172
|
+
const response2 = input.forceLoginOnUnauthenticated ? redirectResponse(request, signInUrl) : NextResponse2.next();
|
|
163
173
|
const clearOpts = {
|
|
164
174
|
httpOnly: true,
|
|
165
175
|
secure: input.secureCookies ?? process.env.NODE_ENV === "production",
|
|
@@ -183,7 +193,7 @@ function createAuthMiddleware(input = {}) {
|
|
|
183
193
|
};
|
|
184
194
|
const requestHeaders = new Headers(request.headers);
|
|
185
195
|
requestHeaders.set("authorization", `Bearer ${newAccessToken}`);
|
|
186
|
-
const response =
|
|
196
|
+
const response = NextResponse2.next({ request: { headers: requestHeaders } });
|
|
187
197
|
response.cookies.set(slotAt(activeIdx), newAccessToken, cookieOptions);
|
|
188
198
|
if (newRefreshToken) response.cookies.set(slotRt(activeIdx), newRefreshToken, cookieOptions);
|
|
189
199
|
if (request.cookies.get(tokenPubCookie)?.value) {
|