@payloadcms/ui 3.90.2 → 3.91.0-internal.c1569dc

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.
Files changed (76) hide show
  1. package/dist/elements/FolderView/FolderFileTable/index.d.ts.map +1 -1
  2. package/dist/elements/FolderView/FolderFileTable/index.js +12 -2
  3. package/dist/elements/FolderView/FolderFileTable/index.js.map +1 -1
  4. package/dist/elements/FolderView/FolderFileTable/index.scss +14 -0
  5. package/dist/elements/Thumbnail/index.d.ts +1 -0
  6. package/dist/elements/Thumbnail/index.d.ts.map +1 -1
  7. package/dist/elements/Thumbnail/index.js +2 -0
  8. package/dist/elements/Thumbnail/index.js.map +1 -1
  9. package/dist/exports/client/index.d.ts +2 -1
  10. package/dist/exports/client/index.d.ts.map +1 -1
  11. package/dist/exports/client/index.js +24 -24
  12. package/dist/exports/client/index.js.map +4 -4
  13. package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.d.ts.map +1 -1
  14. package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.js +12 -4
  15. package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.js.map +1 -1
  16. package/dist/providers/Auth/AuthSessionDebug/index.d.ts +13 -0
  17. package/dist/providers/Auth/AuthSessionDebug/index.d.ts.map +1 -0
  18. package/dist/providers/Auth/AuthSessionDebug/index.js +93 -0
  19. package/dist/providers/Auth/AuthSessionDebug/index.js.map +1 -0
  20. package/dist/providers/Auth/AuthSessionDebug/index.scss +49 -0
  21. package/dist/providers/Auth/AuthSessionDebug/utilities.d.ts +21 -0
  22. package/dist/providers/Auth/AuthSessionDebug/utilities.d.ts.map +1 -0
  23. package/dist/providers/Auth/AuthSessionDebug/utilities.js +53 -0
  24. package/dist/providers/Auth/AuthSessionDebug/utilities.js.map +1 -0
  25. package/dist/providers/Auth/authSessionRequests.d.ts +27 -0
  26. package/dist/providers/Auth/authSessionRequests.d.ts.map +1 -0
  27. package/dist/providers/Auth/authSessionRequests.js +119 -0
  28. package/dist/providers/Auth/authSessionRequests.js.map +1 -0
  29. package/dist/providers/Auth/authSessionRequests.spec.js +121 -0
  30. package/dist/providers/Auth/authSessionRequests.spec.js.map +1 -0
  31. package/dist/providers/Auth/index.d.ts +3 -57
  32. package/dist/providers/Auth/index.d.ts.map +1 -1
  33. package/dist/providers/Auth/index.js +290 -135
  34. package/dist/providers/Auth/index.js.map +1 -1
  35. package/dist/providers/Auth/sessionActivity.d.ts +23 -0
  36. package/dist/providers/Auth/sessionActivity.d.ts.map +1 -0
  37. package/dist/providers/Auth/sessionActivity.js +49 -0
  38. package/dist/providers/Auth/sessionActivity.js.map +1 -0
  39. package/dist/providers/Auth/sessionActivity.spec.js +44 -0
  40. package/dist/providers/Auth/sessionActivity.spec.js.map +1 -0
  41. package/dist/providers/Auth/sessionTiming.d.ts +11 -0
  42. package/dist/providers/Auth/sessionTiming.d.ts.map +1 -0
  43. package/dist/providers/Auth/sessionTiming.js +18 -0
  44. package/dist/providers/Auth/sessionTiming.js.map +1 -0
  45. package/dist/providers/Auth/tabSessionSync/index.d.ts +17 -0
  46. package/dist/providers/Auth/tabSessionSync/index.d.ts.map +1 -0
  47. package/dist/providers/Auth/tabSessionSync/index.js +263 -0
  48. package/dist/providers/Auth/tabSessionSync/index.js.map +1 -0
  49. package/dist/providers/Auth/tabSessionSync/index.spec.js +463 -0
  50. package/dist/providers/Auth/tabSessionSync/index.spec.js.map +1 -0
  51. package/dist/providers/Auth/tabSessionSync/types.d.ts +107 -0
  52. package/dist/providers/Auth/tabSessionSync/types.d.ts.map +1 -0
  53. package/dist/providers/Auth/tabSessionSync/types.js +6 -0
  54. package/dist/providers/Auth/tabSessionSync/types.js.map +1 -0
  55. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.d.ts +11 -0
  56. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.d.ts.map +1 -0
  57. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.js +90 -0
  58. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.js.map +1 -0
  59. package/dist/providers/Auth/tabSessionSync/utilities.d.ts +26 -0
  60. package/dist/providers/Auth/tabSessionSync/utilities.d.ts.map +1 -0
  61. package/dist/providers/Auth/tabSessionSync/utilities.js +159 -0
  62. package/dist/providers/Auth/tabSessionSync/utilities.js.map +1 -0
  63. package/dist/providers/Auth/types.d.ts +70 -0
  64. package/dist/providers/Auth/types.d.ts.map +1 -0
  65. package/dist/providers/Auth/types.js +2 -0
  66. package/dist/providers/Auth/types.js.map +1 -0
  67. package/dist/providers/Auth/types.spec.js +8 -0
  68. package/dist/providers/Auth/types.spec.js.map +1 -0
  69. package/dist/providers/Auth/useAuthSessionTimers.d.ts +26 -0
  70. package/dist/providers/Auth/useAuthSessionTimers.d.ts.map +1 -0
  71. package/dist/providers/Auth/useAuthSessionTimers.js +203 -0
  72. package/dist/providers/Auth/useAuthSessionTimers.js.map +1 -0
  73. package/dist/providers/Auth/useAuthSessionTimers.spec.js +311 -0
  74. package/dist/providers/Auth/useAuthSessionTimers.spec.js.map +1 -0
  75. package/dist/styles.css +1 -1
  76. package/package.json +5 -5
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { jsx as _jsx } from "react/jsx-runtime";
4
4
  import { useModal } from '@faceless-ui/modal';
5
- import { usePathname, useRouter } from 'next/navigation.js';
5
+ import { usePathname, useRouter, useSearchParams } from 'next/navigation.js';
6
6
  import { formatAdminURL } from 'payload/shared';
7
7
  import * as qs from 'qs-esm';
8
8
  import React, { createContext, use, useCallback, useEffect, useState } from 'react';
@@ -13,8 +13,11 @@ import { useTranslation } from '../../providers/Translation/index.js';
13
13
  import { requests } from '../../utilities/api.js';
14
14
  import { useConfig } from '../Config/index.js';
15
15
  import { useRouteTransition } from '../RouteTransition/index.js';
16
+ import { createAuthSessionRequests } from './authSessionRequests.js';
17
+ import { TAB_SESSION_EVENT_TYPES } from './tabSessionSync/index.js';
18
+ import { useTabSessionSync } from './tabSessionSync/useTabSessionSync.js';
19
+ import { useAuthSessionTimers } from './useAuthSessionTimers.js';
16
20
  const Context = /*#__PURE__*/createContext({});
17
- const maxTimeoutMs = 2147483647;
18
21
  export function AuthProvider({
19
22
  children,
20
23
  permissions: initialPermissions,
@@ -22,6 +25,8 @@ export function AuthProvider({
22
25
  }) {
23
26
  const pathname = usePathname();
24
27
  const router = useRouter();
28
+ const searchParams = useSearchParams();
29
+ const route = `${pathname}?${searchParams.toString()}`;
25
30
  const {
26
31
  config
27
32
  } = useConfig();
@@ -30,7 +35,8 @@ export function AuthProvider({
30
35
  autoLogin,
31
36
  autoRefresh,
32
37
  routes: {
33
- inactivity: logoutInactivityRoute
38
+ inactivity: logoutInactivityRoute,
39
+ login: loginRoute
34
40
  },
35
41
  user: userSlug
36
42
  },
@@ -51,14 +57,12 @@ export function AuthProvider({
51
57
  } = useRouteTransition();
52
58
  const [user, setUserInMemory] = useState(initialUser);
53
59
  const [tokenInMemory, setTokenInMemory] = useState();
54
- const [tokenExpirationMs, setTokenExpirationMs] = useState();
60
+ const [authSession, setAuthSession] = useState();
55
61
  const [permissions, setPermissions] = useState(initialPermissions);
56
- const [forceLogoutBufferMs, setForceLogoutBufferMs] = useState(120_000);
57
62
  const [fetchedUserOnMount, setFetchedUserOnMount] = useState(false);
58
- const refreshTokenTimeoutRef = React.useRef(null);
59
- const reminderTimeoutRef = React.useRef(null);
60
- const forceLogOutTimeoutRef = React.useRef(null);
61
- const id = user?.id;
63
+ const [authRequests] = useState(createAuthSessionRequests);
64
+ const userRef = React.useRef(initialUser);
65
+ const isAuthenticated = Boolean(user);
62
66
  const redirectToInactivityRoute = useCallback(() => {
63
67
  const baseAdminRoute = formatAdminURL({
64
68
  adminRoute,
@@ -70,111 +74,227 @@ export function AuthProvider({
70
74
  })));
71
75
  closeAllModals();
72
76
  }, [router, adminRoute, logoutInactivityRoute, closeAllModals, startRouteTransition]);
73
- const revokeTokenAndExpire = useCallback(() => {
74
- setUserInMemory(null);
75
- setTokenInMemory(undefined);
76
- setTokenExpirationMs(undefined);
77
- clearTimeout(refreshTokenTimeoutRef.current);
78
- }, []);
79
- // Handler for reminder timeout - uses useEffectEvent to capture latest autoRefresh value
80
- const handleReminderTimeout = useEffectEvent(() => {
77
+ const redirectToLoginRoute = useCallback(() => {
78
+ startRouteTransition(() => router.replace(formatAdminURL({
79
+ adminRoute,
80
+ path: loginRoute
81
+ })));
82
+ closeAllModals();
83
+ }, [adminRoute, closeAllModals, loginRoute, router, startRouteTransition]);
84
+ function onSessionActivity() {
85
+ setAuthSession(currentAuthSession => {
86
+ if (!currentAuthSession || currentAuthSession.activityRecorded) {
87
+ return currentAuthSession;
88
+ }
89
+ return {
90
+ ...currentAuthSession,
91
+ activityRecorded: true
92
+ };
93
+ });
94
+ }
95
+ function onSessionActivityRefresh() {
96
+ void refreshSession({
97
+ isActivityRefresh: true
98
+ });
99
+ }
100
+ function onSessionExpiration(expirationMs) {
101
+ const collection = userRef.current?.collection;
102
+ tabSessionSync.broadcast({
103
+ type: TAB_SESSION_EVENT_TYPES.EXPIRED,
104
+ expiredTokenAt: expirationMs
105
+ });
106
+ void logOutSession({
107
+ collection
108
+ }).then(redirectToInactivityRoute);
109
+ }
110
+ function onSessionReminder() {
81
111
  if (autoRefresh) {
82
- refreshCookieEvent();
112
+ sessionTimers.scheduleRefresh();
83
113
  } else {
84
114
  openModal(stayLoggedInModalSlug);
85
115
  }
116
+ }
117
+ const sessionTimers = useAuthSessionTimers({
118
+ isAuthenticated,
119
+ onActivity: onSessionActivity,
120
+ onActivityRefresh: onSessionActivityRefresh,
121
+ onExpire: onSessionExpiration,
122
+ onReminder: onSessionReminder
86
123
  });
87
- const setNewUser = useCallback(userResponse => {
88
- clearTimeout(reminderTimeoutRef.current);
89
- clearTimeout(forceLogOutTimeoutRef.current);
90
- if (userResponse?.user) {
91
- setUserInMemory(userResponse.user);
92
- setTokenInMemory(userResponse.token ?? userResponse.refreshedToken);
93
- setTokenExpirationMs(userResponse.exp * 1000);
94
- const expiresInMs = Math.max(0, Math.min((userResponse.exp ?? 0) * 1000 - Date.now(), maxTimeoutMs));
95
- if (expiresInMs) {
96
- const nextForceLogoutBufferMs = Math.min(60_000, expiresInMs / 2);
97
- setForceLogoutBufferMs(nextForceLogoutBufferMs);
98
- reminderTimeoutRef.current = setTimeout(handleReminderTimeout, Math.max(expiresInMs - nextForceLogoutBufferMs, 0));
99
- forceLogOutTimeoutRef.current = setTimeout(() => {
100
- revokeTokenAndExpire();
101
- redirectToInactivityRoute();
102
- }, expiresInMs);
124
+ useEffect(() => {
125
+ sessionTimers.recordActivity('route');
126
+ }, [route, sessionTimers]);
127
+ const clearUserInMemory = useCallback(() => {
128
+ userRef.current = null;
129
+ setUserInMemory(null);
130
+ setTokenInMemory(undefined);
131
+ setAuthSession(undefined);
132
+ sessionTimers.clear();
133
+ }, [sessionTimers]);
134
+ const setLocalSession = useCallback(session => {
135
+ if (session?.user) {
136
+ const expirationMs_0 = typeof session.exp === 'number' && Number.isFinite(session.exp) ? session.exp * 1000 : undefined;
137
+ const nextSessionTiming = expirationMs_0 !== undefined ? sessionTimers.setExpiration(expirationMs_0) : undefined;
138
+ if (expirationMs_0 === undefined) {
139
+ sessionTimers.clear();
140
+ setAuthSession(undefined);
141
+ }
142
+ userRef.current = session.user;
143
+ setUserInMemory(session.user);
144
+ setTokenInMemory(session.token ?? session.refreshedToken);
145
+ if (nextSessionTiming) {
146
+ setAuthSession({
147
+ ...nextSessionTiming,
148
+ activityRecorded: false
149
+ });
103
150
  }
104
151
  } else {
105
- revokeTokenAndExpire();
152
+ clearUserInMemory();
106
153
  }
107
- }, [redirectToInactivityRoute, revokeTokenAndExpire]);
108
- const refreshCookie = useCallback(forceRefresh => {
109
- if (!id) {
110
- return;
154
+ }, [clearUserInMemory, sessionTimers]);
155
+ const setUser = useCallback(session_0 => {
156
+ authRequests.discardPendingResults();
157
+ setLocalSession(session_0);
158
+ }, [authRequests, setLocalSession]);
159
+ const tabSessionSync = useTabSessionSync({
160
+ getTokenExpirationMs: sessionTimers.getCurrentExpirationMs,
161
+ onSessionExpired: () => {
162
+ const collection_0 = userRef.current?.collection;
163
+ void logOutSession({
164
+ collection: collection_0
165
+ }).then(redirectToInactivityRoute);
166
+ },
167
+ onSessionLoggedOut: () => {
168
+ const collection_1 = userRef.current?.collection;
169
+ void logOutSession({
170
+ collection: collection_1
171
+ }).then(redirectToLoginRoute);
172
+ },
173
+ onSessionRefreshed: session_1 => {
174
+ if (!authRequests.isLoggingOut()) {
175
+ authRequests.discardPendingResults();
176
+ setLocalSession(session_1);
177
+ }
178
+ },
179
+ onTabSessionUnauthenticated: () => {
180
+ redirectToInactivityRoute();
181
+ },
182
+ reconcileSession: async options => {
183
+ const result = await fetchFullUserResult(options);
184
+ if (result.status === 'authenticated' && result.expirationMs !== undefined) {
185
+ return {
186
+ expirationMs: result.expirationMs,
187
+ status: result.status,
188
+ user: result.user
189
+ };
190
+ }
191
+ if (result.status === 'unauthenticated') {
192
+ return result;
193
+ }
194
+ return {
195
+ status: 'indeterminate'
196
+ };
111
197
  }
112
- const expiresInMs_0 = Math.max(0, (tokenExpirationMs ?? 0) - Date.now());
113
- if (forceRefresh || tokenExpirationMs && expiresInMs_0 < forceLogoutBufferMs * 2) {
114
- clearTimeout(refreshTokenTimeoutRef.current);
115
- refreshTokenTimeoutRef.current = setTimeout(async () => {
116
- try {
117
- const request = await requests.post(formatAdminURL({
118
- apiRoute,
119
- path: `/${userSlug}/refresh-token?refresh`
120
- }), {
121
- headers: {
122
- 'Accept-Language': i18n.language
123
- }
124
- });
125
- if (request.status === 200) {
126
- const json = await request.json();
127
- setNewUser(json);
128
- } else {
129
- setNewUser(null);
130
- redirectToInactivityRoute();
198
+ });
199
+ const refreshSession = useCallback(({
200
+ isActivityRefresh
201
+ }) => {
202
+ return authRequests.refresh(async ({
203
+ acceptResult,
204
+ invalidateWhenIdle,
205
+ isResultStale
206
+ }) => {
207
+ if (isResultStale()) {
208
+ return null;
209
+ }
210
+ const handledExpiration = sessionTimers.getCurrentExpirationMs();
211
+ const handledUser = userRef.current;
212
+ try {
213
+ const refreshStartedAt = Date.now();
214
+ const request = await requests.post(formatAdminURL({
215
+ apiRoute,
216
+ path: `/${userSlug}/refresh-token${isActivityRefresh ? '?refresh' : ''}`
217
+ }), {
218
+ headers: {
219
+ 'Accept-Language': i18n.language
131
220
  }
132
- } catch (e) {
133
- toast.error(e.message);
221
+ });
222
+ if (isResultStale()) {
223
+ return null;
134
224
  }
135
- }, 1000);
136
- }
137
- }, [apiRoute, i18n.language, redirectToInactivityRoute, setNewUser, tokenExpirationMs, userSlug, forceLogoutBufferMs, id]);
138
- const refreshCookieAsync = useCallback(async skipSetUser => {
139
- try {
140
- const request_0 = await requests.post(formatAdminURL({
141
- apiRoute,
142
- path: `/${userSlug}/refresh-token`
143
- }), {
144
- headers: {
145
- 'Accept-Language': i18n.language
225
+ if (request.status === 200) {
226
+ const json = await request.json();
227
+ if (!acceptResult()) {
228
+ return null;
229
+ }
230
+ setLocalSession(json);
231
+ tabSessionSync.broadcast({
232
+ type: TAB_SESSION_EVENT_TYPES.REFRESHED,
233
+ refreshStartedAt,
234
+ session: json
235
+ });
236
+ return json.user;
146
237
  }
147
- });
148
- if (request_0.status === 200) {
149
- const json_0 = await request_0.json();
150
- if (!skipSetUser) {
151
- setNewUser(json_0);
238
+ if (handledUser) {
239
+ const invalidateSession = () => {
240
+ if (handledExpiration !== undefined) {
241
+ tabSessionSync.broadcast({
242
+ type: TAB_SESSION_EVENT_TYPES.EXPIRED,
243
+ expiredTokenAt: handledExpiration
244
+ });
245
+ }
246
+ setLocalSession(null);
247
+ redirectToInactivityRoute();
248
+ };
249
+ invalidateWhenIdle(invalidateSession);
152
250
  }
153
- return json_0.user;
251
+ } catch (e) {
252
+ toast.error(`Refreshing token failed: ${e.message}`);
154
253
  }
155
- if (user) {
156
- setNewUser(null);
157
- redirectToInactivityRoute();
254
+ return null;
255
+ });
256
+ }, [apiRoute, authRequests, tabSessionSync, i18n.language, redirectToInactivityRoute, sessionTimers, setLocalSession, userSlug]);
257
+ const refreshCookieAsync = useCallback(async () => {
258
+ return await refreshSession({
259
+ isActivityRefresh: false
260
+ });
261
+ }, [refreshSession]);
262
+ const logOutSession = useCallback(({
263
+ collection: collection_2
264
+ }) => {
265
+ return authRequests.logOut({
266
+ clearSession: () => {
267
+ authRequests.discardPendingResults();
268
+ setLocalSession(null);
269
+ },
270
+ request: async () => {
271
+ try {
272
+ if (collection_2) {
273
+ await requests.post(formatAdminURL({
274
+ apiRoute,
275
+ path: `/${collection_2}/logout`
276
+ }));
277
+ }
278
+ } catch (_) {
279
+ // Explicit logout always clears local state, even if server revocation fails.
280
+ }
158
281
  }
159
- } catch (e_0) {
160
- toast.error(`Refreshing token failed: ${e_0.message}`);
161
- }
162
- return null;
163
- }, [apiRoute, i18n.language, redirectToInactivityRoute, setNewUser, userSlug, user]);
282
+ });
283
+ }, [apiRoute, authRequests, setLocalSession]);
164
284
  const logOut = useCallback(async () => {
165
- try {
166
- if (user && user.collection) {
167
- setNewUser(null);
168
- await requests.post(formatAdminURL({
169
- apiRoute,
170
- path: `/${user.collection}/logout`
171
- }));
172
- }
173
- } catch (_) {
174
- // fail silently and log the user out in state
285
+ const logoutEvent = {
286
+ type: TAB_SESSION_EVENT_TYPES.LOGGED_OUT
287
+ };
288
+ const logoutPublication = tabSessionSync.broadcast(logoutEvent);
289
+ const collection_3 = userRef.current?.collection;
290
+ await logOutSession({
291
+ collection: collection_3
292
+ });
293
+ if (logoutPublication?.type === TAB_SESSION_EVENT_TYPES.LOGGED_OUT) {
294
+ tabSessionSync.broadcastLogoutSettlement(logoutPublication);
175
295
  }
176
296
  return true;
177
- }, [apiRoute, setNewUser, user]);
297
+ }, [tabSessionSync, logOutSession]);
178
298
  const refreshPermissions = useCallback(async ({
179
299
  locale
180
300
  } = {}) => {
@@ -184,7 +304,7 @@ export function AuthProvider({
184
304
  addQueryPrefix: true
185
305
  });
186
306
  try {
187
- const request_1 = await requests.get(formatAdminURL({
307
+ const request_0 = await requests.get(formatAdminURL({
188
308
  apiRoute,
189
309
  path: `/access${params}`
190
310
  }), {
@@ -192,42 +312,79 @@ export function AuthProvider({
192
312
  'Accept-Language': i18n.language
193
313
  }
194
314
  });
195
- if (request_1.status === 200) {
196
- const json_1 = await request_1.json();
197
- setPermissions(json_1);
315
+ if (request_0.status === 200) {
316
+ const json_0 = await request_0.json();
317
+ setPermissions(json_0);
198
318
  } else {
199
- throw new Error(`Fetching permissions failed with status code ${request_1.status}`);
319
+ throw new Error(`Fetching permissions failed with status code ${request_0.status}`);
200
320
  }
201
- } catch (e_1) {
202
- toast.error(`Refreshing permissions failed: ${e_1.message}`);
321
+ } catch (e_0) {
322
+ toast.error(`Refreshing permissions failed: ${e_0.message}`);
203
323
  }
204
324
  }, [apiRoute, i18n]);
205
- const fetchFullUser = React.useCallback(async () => {
206
- try {
207
- const request_2 = await requests.get(formatAdminURL({
208
- apiRoute,
209
- path: `/${userSlug}/me`
210
- }), {
211
- credentials: 'include',
212
- headers: {
213
- 'Accept-Language': i18n.language
325
+ const fetchFullUserResult = React.useCallback(({
326
+ isTabSessionEventStale
327
+ } = {}) => {
328
+ return authRequests.queue(async ({
329
+ acceptResult: acceptResult_0,
330
+ isResultStale: isResultStale_0
331
+ }) => {
332
+ const isResponseStale = () => isResultStale_0() || Boolean(isTabSessionEventStale?.());
333
+ if (isResponseStale()) {
334
+ return {
335
+ status: 'indeterminate'
336
+ };
337
+ }
338
+ try {
339
+ const request_1 = await requests.get(formatAdminURL({
340
+ apiRoute,
341
+ path: `/${userSlug}/me`
342
+ }), {
343
+ credentials: 'include',
344
+ headers: {
345
+ 'Accept-Language': i18n.language
346
+ }
347
+ });
348
+ if (request_1.status !== 200) {
349
+ return {
350
+ status: 'indeterminate'
351
+ };
214
352
  }
215
- });
216
- if (request_2.status === 200) {
217
- const json_2 = await request_2.json();
218
- setNewUser(json_2);
219
- return json_2?.user || null;
353
+ const json_1 = await request_1.json();
354
+ if (isResponseStale()) {
355
+ return {
356
+ status: 'indeterminate'
357
+ };
358
+ }
359
+ if (json_1?.user) {
360
+ if (!acceptResult_0()) {
361
+ return {
362
+ status: 'indeterminate'
363
+ };
364
+ }
365
+ setLocalSession(json_1);
366
+ return {
367
+ expirationMs: typeof json_1.exp === 'number' && Number.isFinite(json_1.exp) ? json_1.exp * 1000 : sessionTimers.getCurrentExpirationMs(),
368
+ status: 'authenticated',
369
+ user: json_1.user
370
+ };
371
+ }
372
+ setLocalSession(null);
373
+ return {
374
+ status: 'unauthenticated'
375
+ };
376
+ } catch (e_1) {
377
+ toast.error(`Fetching user failed: ${e_1.message}`);
220
378
  }
221
- } catch (e_2) {
222
- toast.error(`Fetching user failed: ${e_2.message}`);
223
- }
224
- return null;
225
- }, [apiRoute, userSlug, i18n.language, setNewUser]);
226
- const refreshCookieEvent = useEffectEvent(refreshCookie);
227
- useEffect(() => {
228
- // when location changes, refresh cookie
229
- refreshCookieEvent();
230
- }, [pathname]);
379
+ return {
380
+ status: 'indeterminate'
381
+ };
382
+ });
383
+ }, [apiRoute, authRequests, i18n.language, sessionTimers, setLocalSession, userSlug]);
384
+ const fetchFullUser = React.useCallback(async () => {
385
+ const result_0 = await fetchFullUserResult();
386
+ return result_0.status === 'authenticated' ? result_0.user : null;
387
+ }, [fetchFullUserResult]);
231
388
  const fetchFullUserEvent = useEffectEvent(fetchFullUser);
232
389
  useEffect(() => {
233
390
  async function fetchUserOnMount() {
@@ -242,26 +399,24 @@ export function AuthProvider({
242
399
  }
243
400
  }, [user, autoLogin]);
244
401
  useEffect(() => () => {
245
- // remove all timeouts on unmount
246
- clearTimeout(refreshTokenTimeoutRef.current);
247
- clearTimeout(reminderTimeoutRef.current);
248
- clearTimeout(forceLogOutTimeoutRef.current);
249
- }, []);
402
+ authRequests.discardPendingResults();
403
+ }, [authRequests]);
250
404
  if (!user && !fetchedUserOnMount) {
251
405
  return null;
252
406
  }
253
407
  return /*#__PURE__*/_jsx(Context, {
254
408
  value: {
409
+ authSession,
255
410
  fetchFullUser,
256
411
  logOut,
257
412
  permissions,
258
- refreshCookie,
413
+ refreshCookie: sessionTimers.scheduleRefresh,
259
414
  refreshCookieAsync,
260
415
  refreshPermissions,
261
416
  setPermissions,
262
- setUser: setNewUser,
417
+ setUser,
263
418
  token: tokenInMemory,
264
- tokenExpirationMs,
419
+ tokenExpirationMs: authSession?.expiresAt,
265
420
  user
266
421
  },
267
422
  children: children
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useModal","usePathname","useRouter","formatAdminURL","qs","React","createContext","use","useCallback","useEffect","useState","toast","stayLoggedInModalSlug","useEffectEvent","useTranslation","requests","useConfig","useRouteTransition","Context","maxTimeoutMs","AuthProvider","children","permissions","initialPermissions","user","initialUser","pathname","router","config","admin","autoLogin","autoRefresh","routes","inactivity","logoutInactivityRoute","userSlug","adminRoute","api","apiRoute","i18n","closeAllModals","openModal","startRouteTransition","setUserInMemory","tokenInMemory","setTokenInMemory","tokenExpirationMs","setTokenExpirationMs","setPermissions","forceLogoutBufferMs","setForceLogoutBufferMs","fetchedUserOnMount","setFetchedUserOnMount","refreshTokenTimeoutRef","useRef","reminderTimeoutRef","forceLogOutTimeoutRef","id","redirectToInactivityRoute","baseAdminRoute","path","replace","window","location","startsWith","encodeURIComponent","revokeTokenAndExpire","undefined","clearTimeout","current","handleReminderTimeout","refreshCookieEvent","setNewUser","userResponse","token","refreshedToken","exp","expiresInMs","Math","max","min","Date","now","nextForceLogoutBufferMs","setTimeout","refreshCookie","forceRefresh","request","post","headers","language","status","json","e","error","message","refreshCookieAsync","skipSetUser","logOut","collection","_","refreshPermissions","locale","params","stringify","addQueryPrefix","get","Error","fetchFullUser","credentials","fetchFullUserEvent","fetchUserOnMount","prefillOnly","_jsx","value","setUser","useAuth"],"sources":["../../../src/providers/Auth/index.tsx"],"sourcesContent":["'use client'\nimport type { ClientUser, SanitizedPermissions, TypedUser } from 'payload'\n\nimport { useModal } from '@faceless-ui/modal'\nimport { usePathname, useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React, { createContext, use, useCallback, useEffect, useState } from 'react'\nimport { toast } from 'sonner'\n\nimport { stayLoggedInModalSlug } from '../../elements/StayLoggedIn/index.js'\nimport { useEffectEvent } from '../../hooks/useEffectEvent.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { requests } from '../../utilities/api.js'\nimport { useConfig } from '../Config/index.js'\nimport { useRouteTransition } from '../RouteTransition/index.js'\n\nexport type UserWithToken<T = ClientUser> = {\n /** seconds until expiration */\n exp: number\n refreshedToken?: string\n token?: string\n user: T\n}\n\nexport type AuthContext<T = ClientUser> = {\n fetchFullUser: () => Promise<null | TypedUser>\n logOut: () => Promise<boolean>\n /**\n * These are the permissions for the current user from a global scope.\n *\n * When checking for permissions on document specific level, use the `useDocumentInfo` hook instead.\n *\n * @example\n *\n * ```tsx\n * import { useAuth } from 'payload/ui'\n *\n * const MyComponent: React.FC = () => {\n * const { permissions } = useAuth()\n *\n * if (permissions?.collections?.myCollection?.create) {\n * // user can create documents in 'myCollection'\n * }\n *\n * return null\n * }\n * ```\n *\n * with useDocumentInfo:\n *\n * ```tsx\n * import { useDocumentInfo } from 'payload/ui'\n *\n * const MyComponent: React.FC = () => {\n * const { docPermissions } = useDocumentInfo()\n * if (docPermissions?.create) {\n * // user can create this document\n * }\n * return null\n * } ```\n */\n permissions?: SanitizedPermissions\n refreshCookie: (forceRefresh?: boolean) => void\n refreshCookieAsync: () => Promise<ClientUser>\n refreshPermissions: () => Promise<void>\n setPermissions: (permissions: SanitizedPermissions) => void\n setUser: (user: null | UserWithToken<T>) => void\n strategy?: string\n token?: string\n tokenExpirationMs?: number\n user?: null | T\n}\n\nconst Context = createContext({} as AuthContext)\n\nconst maxTimeoutMs = 2147483647\n\ntype Props = {\n children: React.ReactNode\n permissions?: SanitizedPermissions\n user?: ClientUser | null\n}\n\nexport function AuthProvider({\n children,\n permissions: initialPermissions,\n user: initialUser,\n}: Props) {\n const pathname = usePathname()\n const router = useRouter()\n\n const { config } = useConfig()\n\n const {\n admin: {\n autoLogin,\n autoRefresh,\n routes: { inactivity: logoutInactivityRoute },\n user: userSlug,\n },\n routes: { admin: adminRoute, api: apiRoute },\n } = config\n\n const { i18n } = useTranslation()\n const { closeAllModals, openModal } = useModal()\n const { startRouteTransition } = useRouteTransition()\n\n const [user, setUserInMemory] = useState<ClientUser | null>(initialUser)\n const [tokenInMemory, setTokenInMemory] = useState<string>()\n const [tokenExpirationMs, setTokenExpirationMs] = useState<number>()\n const [permissions, setPermissions] = useState<SanitizedPermissions>(initialPermissions)\n const [forceLogoutBufferMs, setForceLogoutBufferMs] = useState<number>(120_000)\n const [fetchedUserOnMount, setFetchedUserOnMount] = useState(false)\n\n const refreshTokenTimeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null)\n const reminderTimeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null)\n const forceLogOutTimeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null)\n\n const id = user?.id\n\n const redirectToInactivityRoute = useCallback(() => {\n const baseAdminRoute = formatAdminURL({ adminRoute, path: '' })\n startRouteTransition(() =>\n router.replace(\n formatAdminURL({\n adminRoute,\n path: `${logoutInactivityRoute}${window.location.pathname.startsWith(baseAdminRoute) ? `?redirect=${encodeURIComponent(window.location.pathname)}` : ''}`,\n }),\n ),\n )\n\n closeAllModals()\n }, [router, adminRoute, logoutInactivityRoute, closeAllModals, startRouteTransition])\n\n const revokeTokenAndExpire = useCallback(() => {\n setUserInMemory(null)\n setTokenInMemory(undefined)\n setTokenExpirationMs(undefined)\n clearTimeout(refreshTokenTimeoutRef.current)\n }, [])\n\n // Handler for reminder timeout - uses useEffectEvent to capture latest autoRefresh value\n const handleReminderTimeout = useEffectEvent(() => {\n if (autoRefresh) {\n refreshCookieEvent()\n } else {\n openModal(stayLoggedInModalSlug)\n }\n })\n\n const setNewUser = useCallback(\n (userResponse: null | UserWithToken) => {\n clearTimeout(reminderTimeoutRef.current)\n clearTimeout(forceLogOutTimeoutRef.current)\n\n if (userResponse?.user) {\n setUserInMemory(userResponse.user)\n setTokenInMemory(userResponse.token ?? userResponse.refreshedToken)\n setTokenExpirationMs(userResponse.exp * 1000)\n\n const expiresInMs = Math.max(\n 0,\n Math.min((userResponse.exp ?? 0) * 1000 - Date.now(), maxTimeoutMs),\n )\n\n if (expiresInMs) {\n const nextForceLogoutBufferMs = Math.min(60_000, expiresInMs / 2)\n setForceLogoutBufferMs(nextForceLogoutBufferMs)\n\n reminderTimeoutRef.current = setTimeout(\n handleReminderTimeout,\n Math.max(expiresInMs - nextForceLogoutBufferMs, 0),\n )\n\n forceLogOutTimeoutRef.current = setTimeout(() => {\n revokeTokenAndExpire()\n redirectToInactivityRoute()\n }, expiresInMs)\n }\n } else {\n revokeTokenAndExpire()\n }\n },\n [redirectToInactivityRoute, revokeTokenAndExpire],\n )\n\n const refreshCookie = useCallback(\n (forceRefresh?: boolean) => {\n if (!id) {\n return\n }\n\n const expiresInMs = Math.max(0, (tokenExpirationMs ?? 0) - Date.now())\n\n if (forceRefresh || (tokenExpirationMs && expiresInMs < forceLogoutBufferMs * 2)) {\n clearTimeout(refreshTokenTimeoutRef.current)\n refreshTokenTimeoutRef.current = setTimeout(async () => {\n try {\n const request = await requests.post(\n formatAdminURL({\n apiRoute,\n path: `/${userSlug}/refresh-token?refresh`,\n }),\n {\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n setNewUser(json)\n } else {\n setNewUser(null)\n redirectToInactivityRoute()\n }\n } catch (e) {\n toast.error(e.message)\n }\n }, 1000)\n }\n },\n [\n apiRoute,\n i18n.language,\n redirectToInactivityRoute,\n setNewUser,\n tokenExpirationMs,\n userSlug,\n forceLogoutBufferMs,\n id,\n ],\n )\n\n const refreshCookieAsync = useCallback(\n async (skipSetUser?: boolean): Promise<ClientUser> => {\n try {\n const request = await requests.post(\n formatAdminURL({\n apiRoute,\n path: `/${userSlug}/refresh-token`,\n }),\n {\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n if (!skipSetUser) {\n setNewUser(json)\n }\n return json.user\n }\n\n if (user) {\n setNewUser(null)\n redirectToInactivityRoute()\n }\n } catch (e) {\n toast.error(`Refreshing token failed: ${e.message}`)\n }\n return null\n },\n [apiRoute, i18n.language, redirectToInactivityRoute, setNewUser, userSlug, user],\n )\n\n const logOut = useCallback(async () => {\n try {\n if (user && user.collection) {\n setNewUser(null)\n await requests.post(\n formatAdminURL({\n apiRoute,\n path: `/${user.collection}/logout`,\n }),\n )\n }\n } catch (_) {\n // fail silently and log the user out in state\n }\n\n return true\n }, [apiRoute, setNewUser, user])\n\n const refreshPermissions = useCallback(\n async ({ locale }: { locale?: string } = {}) => {\n const params = qs.stringify(\n {\n locale,\n },\n {\n addQueryPrefix: true,\n },\n )\n\n try {\n const request = await requests.get(\n formatAdminURL({\n apiRoute,\n path: `/access${params}`,\n }),\n {\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status === 200) {\n const json: SanitizedPermissions = await request.json()\n setPermissions(json)\n } else {\n throw new Error(`Fetching permissions failed with status code ${request.status}`)\n }\n } catch (e) {\n toast.error(`Refreshing permissions failed: ${e.message}`)\n }\n },\n [apiRoute, i18n],\n )\n\n const fetchFullUser = React.useCallback(async () => {\n try {\n const request = await requests.get(\n formatAdminURL({\n apiRoute,\n path: `/${userSlug}/me`,\n }),\n {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n setNewUser(json)\n return json?.user || null\n }\n } catch (e) {\n toast.error(`Fetching user failed: ${e.message}`)\n }\n\n return null\n }, [apiRoute, userSlug, i18n.language, setNewUser])\n\n const refreshCookieEvent = useEffectEvent(refreshCookie)\n useEffect(() => {\n // when location changes, refresh cookie\n refreshCookieEvent()\n }, [pathname])\n\n const fetchFullUserEvent = useEffectEvent(fetchFullUser)\n useEffect(() => {\n async function fetchUserOnMount() {\n await fetchFullUserEvent()\n setFetchedUserOnMount(true)\n }\n\n void fetchUserOnMount()\n }, [])\n\n useEffect(() => {\n if (!user && autoLogin && !autoLogin.prefillOnly) {\n void fetchFullUserEvent()\n }\n }, [user, autoLogin])\n\n useEffect(\n () => () => {\n // remove all timeouts on unmount\n clearTimeout(refreshTokenTimeoutRef.current)\n clearTimeout(reminderTimeoutRef.current)\n clearTimeout(forceLogOutTimeoutRef.current)\n },\n [],\n )\n\n if (!user && !fetchedUserOnMount) {\n return null\n }\n\n return (\n <Context\n value={{\n fetchFullUser,\n logOut,\n permissions,\n refreshCookie,\n refreshCookieAsync,\n refreshPermissions,\n setPermissions,\n setUser: setNewUser,\n token: tokenInMemory,\n tokenExpirationMs,\n user,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport const useAuth = <T = ClientUser,>(): AuthContext<T> => use(Context) as AuthContext<T>\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useModal","usePathname","useRouter","useSearchParams","formatAdminURL","qs","React","createContext","use","useCallback","useEffect","useState","toast","stayLoggedInModalSlug","useEffectEvent","useTranslation","requests","useConfig","useRouteTransition","createAuthSessionRequests","TAB_SESSION_EVENT_TYPES","useTabSessionSync","useAuthSessionTimers","Context","AuthProvider","children","permissions","initialPermissions","user","initialUser","pathname","router","searchParams","route","toString","config","admin","autoLogin","autoRefresh","routes","inactivity","logoutInactivityRoute","login","loginRoute","userSlug","adminRoute","api","apiRoute","i18n","closeAllModals","openModal","startRouteTransition","setUserInMemory","tokenInMemory","setTokenInMemory","authSession","setAuthSession","setPermissions","fetchedUserOnMount","setFetchedUserOnMount","authRequests","userRef","useRef","isAuthenticated","Boolean","redirectToInactivityRoute","baseAdminRoute","path","replace","window","location","startsWith","encodeURIComponent","redirectToLoginRoute","onSessionActivity","currentAuthSession","activityRecorded","onSessionActivityRefresh","refreshSession","isActivityRefresh","onSessionExpiration","expirationMs","collection","current","tabSessionSync","broadcast","type","EXPIRED","expiredTokenAt","logOutSession","then","onSessionReminder","sessionTimers","scheduleRefresh","onActivity","onActivityRefresh","onExpire","onReminder","recordActivity","clearUserInMemory","undefined","clear","setLocalSession","session","exp","Number","isFinite","nextSessionTiming","setExpiration","token","refreshedToken","setUser","discardPendingResults","getTokenExpirationMs","getCurrentExpirationMs","onSessionExpired","onSessionLoggedOut","onSessionRefreshed","isLoggingOut","onTabSessionUnauthenticated","reconcileSession","options","result","fetchFullUserResult","status","refresh","acceptResult","invalidateWhenIdle","isResultStale","handledExpiration","handledUser","refreshStartedAt","Date","now","request","post","headers","language","json","REFRESHED","invalidateSession","e","error","message","refreshCookieAsync","logOut","clearSession","_","logoutEvent","LOGGED_OUT","logoutPublication","broadcastLogoutSettlement","refreshPermissions","locale","params","stringify","addQueryPrefix","get","Error","isTabSessionEventStale","queue","isResponseStale","credentials","fetchFullUser","fetchFullUserEvent","fetchUserOnMount","prefillOnly","_jsx","value","refreshCookie","tokenExpirationMs","expiresAt","useAuth"],"sources":["../../../src/providers/Auth/index.tsx"],"sourcesContent":["'use client'\nimport type { ClientUser, SanitizedPermissions, TypedUser } from 'payload'\n\nimport { useModal } from '@faceless-ui/modal'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React, { createContext, use, useCallback, useEffect, useState } from 'react'\nimport { toast } from 'sonner'\n\nimport type { TabSessionReconciliationOptions } from './tabSessionSync/index.js'\nimport type { AuthContext, AuthSession, UserWithToken } from './types.js'\n\nimport { stayLoggedInModalSlug } from '../../elements/StayLoggedIn/index.js'\nimport { useEffectEvent } from '../../hooks/useEffectEvent.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { requests } from '../../utilities/api.js'\nimport { useConfig } from '../Config/index.js'\nimport { useRouteTransition } from '../RouteTransition/index.js'\nimport { createAuthSessionRequests } from './authSessionRequests.js'\nimport { TAB_SESSION_EVENT_TYPES } from './tabSessionSync/index.js'\nimport { useTabSessionSync } from './tabSessionSync/useTabSessionSync.js'\nimport { useAuthSessionTimers } from './useAuthSessionTimers.js'\n\nexport type { AuthContext, AuthSession, UserWithToken } from './types.js'\n\nconst Context = createContext({} as AuthContext)\n\ntype Props = {\n children: React.ReactNode\n permissions?: SanitizedPermissions\n user?: ClientUser | null\n}\n\ntype FetchFullUserResult =\n | {\n expirationMs?: number\n status: 'authenticated'\n user: ClientUser\n }\n | {\n status: 'indeterminate'\n }\n | {\n status: 'unauthenticated'\n }\n\ntype UserResponse = {\n exp?: number\n refreshedToken?: string\n token?: string\n user?: ClientUser | null\n}\n\nexport function AuthProvider({\n children,\n permissions: initialPermissions,\n user: initialUser,\n}: Props) {\n const pathname = usePathname()\n const router = useRouter()\n const searchParams = useSearchParams()\n const route = `${pathname}?${searchParams.toString()}`\n\n const { config } = useConfig()\n\n const {\n admin: {\n autoLogin,\n autoRefresh,\n routes: { inactivity: logoutInactivityRoute, login: loginRoute },\n user: userSlug,\n },\n routes: { admin: adminRoute, api: apiRoute },\n } = config\n\n const { i18n } = useTranslation()\n const { closeAllModals, openModal } = useModal()\n const { startRouteTransition } = useRouteTransition()\n\n const [user, setUserInMemory] = useState<ClientUser | null>(initialUser)\n const [tokenInMemory, setTokenInMemory] = useState<string>()\n const [authSession, setAuthSession] = useState<AuthSession>()\n const [permissions, setPermissions] = useState<SanitizedPermissions>(initialPermissions)\n const [fetchedUserOnMount, setFetchedUserOnMount] = useState(false)\n\n const [authRequests] = useState(createAuthSessionRequests)\n const userRef = React.useRef<ClientUser | null>(initialUser)\n\n const isAuthenticated = Boolean(user)\n\n const redirectToInactivityRoute = useCallback(() => {\n const baseAdminRoute = formatAdminURL({ adminRoute, path: '' })\n startRouteTransition(() =>\n router.replace(\n formatAdminURL({\n adminRoute,\n path: `${logoutInactivityRoute}${window.location.pathname.startsWith(baseAdminRoute) ? `?redirect=${encodeURIComponent(window.location.pathname)}` : ''}`,\n }),\n ),\n )\n\n closeAllModals()\n }, [router, adminRoute, logoutInactivityRoute, closeAllModals, startRouteTransition])\n\n const redirectToLoginRoute = useCallback(() => {\n startRouteTransition(() =>\n router.replace(\n formatAdminURL({\n adminRoute,\n path: loginRoute,\n }),\n ),\n )\n\n closeAllModals()\n }, [adminRoute, closeAllModals, loginRoute, router, startRouteTransition])\n\n function onSessionActivity() {\n setAuthSession((currentAuthSession) => {\n if (!currentAuthSession || currentAuthSession.activityRecorded) {\n return currentAuthSession\n }\n\n return {\n ...currentAuthSession,\n activityRecorded: true,\n }\n })\n }\n\n function onSessionActivityRefresh() {\n void refreshSession({ isActivityRefresh: true })\n }\n\n function onSessionExpiration(expirationMs: number) {\n const collection = userRef.current?.collection\n\n tabSessionSync.broadcast({\n type: TAB_SESSION_EVENT_TYPES.EXPIRED,\n expiredTokenAt: expirationMs,\n })\n void logOutSession({ collection }).then(redirectToInactivityRoute)\n }\n\n function onSessionReminder() {\n if (autoRefresh) {\n sessionTimers.scheduleRefresh()\n } else {\n openModal(stayLoggedInModalSlug)\n }\n }\n\n const sessionTimers = useAuthSessionTimers({\n isAuthenticated,\n onActivity: onSessionActivity,\n onActivityRefresh: onSessionActivityRefresh,\n onExpire: onSessionExpiration,\n onReminder: onSessionReminder,\n })\n\n useEffect(() => {\n sessionTimers.recordActivity('route')\n }, [route, sessionTimers])\n\n const clearUserInMemory = useCallback(() => {\n userRef.current = null\n setUserInMemory(null)\n setTokenInMemory(undefined)\n setAuthSession(undefined)\n sessionTimers.clear()\n }, [sessionTimers])\n\n const setLocalSession = useCallback(\n (session: null | UserResponse) => {\n if (session?.user) {\n const expirationMs =\n typeof session.exp === 'number' && Number.isFinite(session.exp)\n ? session.exp * 1000\n : undefined\n const nextSessionTiming =\n expirationMs !== undefined ? sessionTimers.setExpiration(expirationMs) : undefined\n\n if (expirationMs === undefined) {\n sessionTimers.clear()\n setAuthSession(undefined)\n }\n\n userRef.current = session.user\n setUserInMemory(session.user)\n setTokenInMemory(session.token ?? session.refreshedToken)\n\n if (nextSessionTiming) {\n setAuthSession({\n ...nextSessionTiming,\n activityRecorded: false,\n })\n }\n } else {\n clearUserInMemory()\n }\n },\n [clearUserInMemory, sessionTimers],\n )\n\n const setUser = useCallback(\n (session: null | UserWithToken) => {\n authRequests.discardPendingResults()\n setLocalSession(session)\n },\n [authRequests, setLocalSession],\n )\n\n const tabSessionSync = useTabSessionSync({\n getTokenExpirationMs: sessionTimers.getCurrentExpirationMs,\n onSessionExpired: () => {\n const collection = userRef.current?.collection\n\n void logOutSession({ collection }).then(redirectToInactivityRoute)\n },\n onSessionLoggedOut: () => {\n const collection = userRef.current?.collection\n\n void logOutSession({ collection }).then(redirectToLoginRoute)\n },\n onSessionRefreshed: (session) => {\n if (!authRequests.isLoggingOut()) {\n authRequests.discardPendingResults()\n setLocalSession(session)\n }\n },\n onTabSessionUnauthenticated: () => {\n redirectToInactivityRoute()\n },\n reconcileSession: async (options) => {\n const result = await fetchFullUserResult(options)\n\n if (result.status === 'authenticated' && result.expirationMs !== undefined) {\n return {\n expirationMs: result.expirationMs,\n status: result.status,\n user: result.user,\n }\n }\n\n if (result.status === 'unauthenticated') {\n return result\n }\n\n return { status: 'indeterminate' }\n },\n })\n\n const refreshSession = useCallback(\n ({ isActivityRefresh }: { isActivityRefresh: boolean }): Promise<ClientUser | null> => {\n return authRequests.refresh(async ({ acceptResult, invalidateWhenIdle, isResultStale }) => {\n if (isResultStale()) {\n return null\n }\n\n const handledExpiration = sessionTimers.getCurrentExpirationMs()\n const handledUser = userRef.current\n\n try {\n const refreshStartedAt = Date.now()\n const request = await requests.post(\n formatAdminURL({\n apiRoute,\n path: `/${userSlug}/refresh-token${isActivityRefresh ? '?refresh' : ''}`,\n }),\n {\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (isResultStale()) {\n return null\n }\n\n if (request.status === 200) {\n const json: UserWithToken = await request.json()\n\n if (!acceptResult()) {\n return null\n }\n\n setLocalSession(json)\n tabSessionSync.broadcast({\n type: TAB_SESSION_EVENT_TYPES.REFRESHED,\n refreshStartedAt,\n session: json,\n })\n return json.user\n }\n\n if (handledUser) {\n const invalidateSession = () => {\n if (handledExpiration !== undefined) {\n tabSessionSync.broadcast({\n type: TAB_SESSION_EVENT_TYPES.EXPIRED,\n expiredTokenAt: handledExpiration,\n })\n }\n\n setLocalSession(null)\n redirectToInactivityRoute()\n }\n\n invalidateWhenIdle(invalidateSession)\n }\n } catch (e) {\n toast.error(`Refreshing token failed: ${e.message}`)\n }\n\n return null\n })\n },\n [\n apiRoute,\n authRequests,\n tabSessionSync,\n i18n.language,\n redirectToInactivityRoute,\n sessionTimers,\n setLocalSession,\n userSlug,\n ],\n )\n\n const refreshCookieAsync = useCallback(async (): Promise<ClientUser> => {\n return await refreshSession({ isActivityRefresh: false })\n }, [refreshSession])\n\n const logOutSession = useCallback(\n ({ collection }: { collection?: string }): Promise<void> => {\n return authRequests.logOut({\n clearSession: () => {\n authRequests.discardPendingResults()\n setLocalSession(null)\n },\n request: async () => {\n try {\n if (collection) {\n await requests.post(\n formatAdminURL({\n apiRoute,\n path: `/${collection}/logout`,\n }),\n )\n }\n } catch (_) {\n // Explicit logout always clears local state, even if server revocation fails.\n }\n },\n })\n },\n [apiRoute, authRequests, setLocalSession],\n )\n\n const logOut = useCallback(async () => {\n const logoutEvent = { type: TAB_SESSION_EVENT_TYPES.LOGGED_OUT } as const\n const logoutPublication = tabSessionSync.broadcast(logoutEvent)\n const collection = userRef.current?.collection\n\n await logOutSession({ collection })\n\n if (logoutPublication?.type === TAB_SESSION_EVENT_TYPES.LOGGED_OUT) {\n tabSessionSync.broadcastLogoutSettlement(logoutPublication)\n }\n\n return true\n }, [tabSessionSync, logOutSession])\n\n const refreshPermissions = useCallback(\n async ({ locale }: { locale?: string } = {}) => {\n const params = qs.stringify(\n {\n locale,\n },\n {\n addQueryPrefix: true,\n },\n )\n\n try {\n const request = await requests.get(\n formatAdminURL({\n apiRoute,\n path: `/access${params}`,\n }),\n {\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status === 200) {\n const json: SanitizedPermissions = await request.json()\n setPermissions(json)\n } else {\n throw new Error(`Fetching permissions failed with status code ${request.status}`)\n }\n } catch (e) {\n toast.error(`Refreshing permissions failed: ${e.message}`)\n }\n },\n [apiRoute, i18n],\n )\n\n const fetchFullUserResult = React.useCallback(\n ({\n isTabSessionEventStale,\n }: Partial<TabSessionReconciliationOptions> = {}): Promise<FetchFullUserResult> => {\n return authRequests.queue(async ({ acceptResult, isResultStale }) => {\n const isResponseStale = () => isResultStale() || Boolean(isTabSessionEventStale?.())\n\n if (isResponseStale()) {\n return { status: 'indeterminate' }\n }\n\n try {\n const request = await requests.get(\n formatAdminURL({\n apiRoute,\n path: `/${userSlug}/me`,\n }),\n {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (request.status !== 200) {\n return { status: 'indeterminate' }\n }\n\n const json: null | UserResponse = await request.json()\n\n if (isResponseStale()) {\n return { status: 'indeterminate' }\n }\n\n if (json?.user) {\n if (!acceptResult()) {\n return { status: 'indeterminate' }\n }\n\n setLocalSession(json)\n\n return {\n expirationMs:\n typeof json.exp === 'number' && Number.isFinite(json.exp)\n ? json.exp * 1000\n : sessionTimers.getCurrentExpirationMs(),\n status: 'authenticated',\n user: json.user,\n }\n }\n\n setLocalSession(null)\n\n return { status: 'unauthenticated' }\n } catch (e) {\n toast.error(`Fetching user failed: ${e.message}`)\n }\n\n return { status: 'indeterminate' }\n })\n },\n [apiRoute, authRequests, i18n.language, sessionTimers, setLocalSession, userSlug],\n )\n\n const fetchFullUser = React.useCallback(async (): Promise<null | TypedUser> => {\n const result = await fetchFullUserResult()\n\n return result.status === 'authenticated' ? (result.user as TypedUser) : null\n }, [fetchFullUserResult])\n\n const fetchFullUserEvent = useEffectEvent(fetchFullUser)\n\n useEffect(() => {\n async function fetchUserOnMount() {\n await fetchFullUserEvent()\n setFetchedUserOnMount(true)\n }\n\n void fetchUserOnMount()\n }, [])\n\n useEffect(() => {\n if (!user && autoLogin && !autoLogin.prefillOnly) {\n void fetchFullUserEvent()\n }\n }, [user, autoLogin])\n\n useEffect(\n () => () => {\n authRequests.discardPendingResults()\n },\n [authRequests],\n )\n\n if (!user && !fetchedUserOnMount) {\n return null\n }\n\n return (\n <Context\n value={{\n authSession,\n fetchFullUser,\n logOut,\n permissions,\n refreshCookie: sessionTimers.scheduleRefresh,\n refreshCookieAsync,\n refreshPermissions,\n setPermissions,\n setUser,\n token: tokenInMemory,\n tokenExpirationMs: authSession?.expiresAt,\n user,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport const useAuth = <T = ClientUser,>(): AuthContext<T> => use(Context) as AuthContext<T>\n"],"mappings":"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","ignoreList":[]}