@payloadcms/ui 4.0.0-canary.20 → 4.0.0-canary.21

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 (86) hide show
  1. package/dist/elements/CopyToClipboard/index.d.ts +1 -0
  2. package/dist/elements/CopyToClipboard/index.d.ts.map +1 -1
  3. package/dist/elements/CopyToClipboard/index.js +10 -8
  4. package/dist/elements/CopyToClipboard/index.js.map +1 -1
  5. package/dist/elements/FileManager/FileToolbar/index.d.ts.map +1 -1
  6. package/dist/elements/FileManager/FileToolbar/index.js +3 -0
  7. package/dist/elements/FileManager/FileToolbar/index.js.map +1 -1
  8. package/dist/exports/client/index.d.ts +2 -1
  9. package/dist/exports/client/index.d.ts.map +1 -1
  10. package/dist/exports/client/index.js +1 -1
  11. package/dist/exports/client/index.js.map +3 -3
  12. package/dist/forms/Form/index.d.ts.map +1 -1
  13. package/dist/forms/Form/index.js +4 -1
  14. package/dist/forms/Form/index.js.map +1 -1
  15. package/dist/providers/Auth/AuthSessionDebug/index.css +48 -0
  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/utilities.d.ts +21 -0
  21. package/dist/providers/Auth/AuthSessionDebug/utilities.d.ts.map +1 -0
  22. package/dist/providers/Auth/AuthSessionDebug/utilities.js +53 -0
  23. package/dist/providers/Auth/AuthSessionDebug/utilities.js.map +1 -0
  24. package/dist/providers/Auth/authSessionRequests.d.ts +27 -0
  25. package/dist/providers/Auth/authSessionRequests.d.ts.map +1 -0
  26. package/dist/providers/Auth/authSessionRequests.js +119 -0
  27. package/dist/providers/Auth/authSessionRequests.js.map +1 -0
  28. package/dist/providers/Auth/authSessionRequests.spec.js +121 -0
  29. package/dist/providers/Auth/authSessionRequests.spec.js.map +1 -0
  30. package/dist/providers/Auth/index.d.ts +2 -56
  31. package/dist/providers/Auth/index.d.ts.map +1 -1
  32. package/dist/providers/Auth/index.js +283 -135
  33. package/dist/providers/Auth/index.js.map +1 -1
  34. package/dist/providers/Auth/sessionActivity.d.ts +23 -0
  35. package/dist/providers/Auth/sessionActivity.d.ts.map +1 -0
  36. package/dist/providers/Auth/sessionActivity.js +49 -0
  37. package/dist/providers/Auth/sessionActivity.js.map +1 -0
  38. package/dist/providers/Auth/sessionActivity.spec.js +44 -0
  39. package/dist/providers/Auth/sessionActivity.spec.js.map +1 -0
  40. package/dist/providers/Auth/sessionTiming.d.ts +11 -0
  41. package/dist/providers/Auth/sessionTiming.d.ts.map +1 -0
  42. package/dist/providers/Auth/sessionTiming.js +18 -0
  43. package/dist/providers/Auth/sessionTiming.js.map +1 -0
  44. package/dist/providers/Auth/tabSessionSync/index.d.ts +17 -0
  45. package/dist/providers/Auth/tabSessionSync/index.d.ts.map +1 -0
  46. package/dist/providers/Auth/tabSessionSync/index.js +263 -0
  47. package/dist/providers/Auth/tabSessionSync/index.js.map +1 -0
  48. package/dist/providers/Auth/tabSessionSync/index.spec.js +463 -0
  49. package/dist/providers/Auth/tabSessionSync/index.spec.js.map +1 -0
  50. package/dist/providers/Auth/tabSessionSync/types.d.ts +107 -0
  51. package/dist/providers/Auth/tabSessionSync/types.d.ts.map +1 -0
  52. package/dist/providers/Auth/tabSessionSync/types.js +6 -0
  53. package/dist/providers/Auth/tabSessionSync/types.js.map +1 -0
  54. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.d.ts +11 -0
  55. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.d.ts.map +1 -0
  56. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.js +90 -0
  57. package/dist/providers/Auth/tabSessionSync/useTabSessionSync.js.map +1 -0
  58. package/dist/providers/Auth/tabSessionSync/utilities.d.ts +26 -0
  59. package/dist/providers/Auth/tabSessionSync/utilities.d.ts.map +1 -0
  60. package/dist/providers/Auth/tabSessionSync/utilities.js +159 -0
  61. package/dist/providers/Auth/tabSessionSync/utilities.js.map +1 -0
  62. package/dist/providers/Auth/types.d.ts +66 -0
  63. package/dist/providers/Auth/types.d.ts.map +1 -0
  64. package/dist/providers/Auth/types.js +2 -0
  65. package/dist/providers/Auth/types.js.map +1 -0
  66. package/dist/providers/Auth/useAuthSessionTimers.d.ts +26 -0
  67. package/dist/providers/Auth/useAuthSessionTimers.d.ts.map +1 -0
  68. package/dist/providers/Auth/useAuthSessionTimers.js +203 -0
  69. package/dist/providers/Auth/useAuthSessionTimers.js.map +1 -0
  70. package/dist/providers/Auth/useAuthSessionTimers.spec.js +311 -0
  71. package/dist/providers/Auth/useAuthSessionTimers.spec.js.map +1 -0
  72. package/dist/providers/FormErrorHandler/index.d.ts +5 -1
  73. package/dist/providers/FormErrorHandler/index.d.ts.map +1 -1
  74. package/dist/providers/FormErrorHandler/index.js.map +1 -1
  75. package/dist/providers/Root/index.js +4 -4
  76. package/dist/providers/Root/index.js.map +1 -1
  77. package/dist/providers/RouteTransition/ProgressBar/index.js +4 -1
  78. package/dist/providers/RouteTransition/ProgressBar/index.js.map +1 -1
  79. package/dist/providers/RouteTransition/ProgressBar/index.spec.js +44 -0
  80. package/dist/providers/RouteTransition/ProgressBar/index.spec.js.map +1 -0
  81. package/dist/providers/RouteTransition/index.d.ts +2 -0
  82. package/dist/providers/RouteTransition/index.d.ts.map +1 -1
  83. package/dist/providers/RouteTransition/index.js +42 -14
  84. package/dist/providers/RouteTransition/index.js.map +1 -1
  85. package/dist/styles.css +1 -1
  86. package/package.json +5 -5
@@ -11,10 +11,13 @@ import { useEffectEvent } from '../../hooks/useEffectEvent.js';
11
11
  import { useTranslation } from '../../providers/Translation/index.js';
12
12
  import { requests } from '../../utilities/api.js';
13
13
  import { useConfig } from '../Config/index.js';
14
- import { usePathname, useRouter } from '../RouterAdapter/index.js';
14
+ import { usePathname, useRouter, useSearchParams } from '../RouterAdapter/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,221 @@ 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
+ userRef.current = session.user;
139
+ setUserInMemory(session.user);
140
+ setTokenInMemory(session.token ?? session.refreshedToken);
141
+ if (nextSessionTiming) {
142
+ setAuthSession({
143
+ ...nextSessionTiming,
144
+ activityRecorded: false
145
+ });
103
146
  }
104
147
  } else {
105
- revokeTokenAndExpire();
148
+ clearUserInMemory();
106
149
  }
107
- }, [redirectToInactivityRoute, revokeTokenAndExpire]);
108
- const refreshCookie = useCallback(forceRefresh => {
109
- if (!id) {
110
- return;
150
+ }, [clearUserInMemory, sessionTimers]);
151
+ const setUser = useCallback(session_0 => {
152
+ authRequests.discardPendingResults();
153
+ setLocalSession(session_0);
154
+ }, [authRequests, setLocalSession]);
155
+ const tabSessionSync = useTabSessionSync({
156
+ getTokenExpirationMs: sessionTimers.getCurrentExpirationMs,
157
+ onSessionExpired: () => {
158
+ const collection_0 = userRef.current?.collection;
159
+ void logOutSession({
160
+ collection: collection_0
161
+ }).then(redirectToInactivityRoute);
162
+ },
163
+ onSessionLoggedOut: () => {
164
+ const collection_1 = userRef.current?.collection;
165
+ void logOutSession({
166
+ collection: collection_1
167
+ }).then(redirectToLoginRoute);
168
+ },
169
+ onSessionRefreshed: session_1 => {
170
+ if (!authRequests.isLoggingOut()) {
171
+ authRequests.discardPendingResults();
172
+ setLocalSession(session_1);
173
+ }
174
+ },
175
+ onTabSessionUnauthenticated: () => {
176
+ redirectToInactivityRoute();
177
+ },
178
+ reconcileSession: async options => {
179
+ const result = await fetchFullUserResult(options);
180
+ if (result.status === 'authenticated' && result.expirationMs !== undefined) {
181
+ return {
182
+ expirationMs: result.expirationMs,
183
+ status: result.status,
184
+ user: result.user
185
+ };
186
+ }
187
+ if (result.status === 'unauthenticated') {
188
+ return result;
189
+ }
190
+ return {
191
+ status: 'indeterminate'
192
+ };
111
193
  }
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();
194
+ });
195
+ const refreshSession = useCallback(({
196
+ isActivityRefresh
197
+ }) => {
198
+ return authRequests.refresh(async ({
199
+ acceptResult,
200
+ invalidateWhenIdle,
201
+ isResultStale
202
+ }) => {
203
+ if (isResultStale()) {
204
+ return null;
205
+ }
206
+ const handledExpiration = sessionTimers.getCurrentExpirationMs();
207
+ const handledUser = userRef.current;
208
+ try {
209
+ const refreshStartedAt = Date.now();
210
+ const request = await requests.post(formatAdminURL({
211
+ apiRoute,
212
+ path: `/${userSlug}/refresh-token${isActivityRefresh ? '?refresh' : ''}`
213
+ }), {
214
+ headers: {
215
+ 'Accept-Language': i18n.language
131
216
  }
132
- } catch (e) {
133
- toast.error(e.message);
217
+ });
218
+ if (isResultStale()) {
219
+ return null;
134
220
  }
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
221
+ if (request.status === 200) {
222
+ const json = await request.json();
223
+ if (!acceptResult()) {
224
+ return null;
225
+ }
226
+ setLocalSession(json);
227
+ tabSessionSync.broadcast({
228
+ type: TAB_SESSION_EVENT_TYPES.REFRESHED,
229
+ refreshStartedAt,
230
+ session: json
231
+ });
232
+ return json.user;
146
233
  }
147
- });
148
- if (request_0.status === 200) {
149
- const json_0 = await request_0.json();
150
- if (!skipSetUser) {
151
- setNewUser(json_0);
234
+ if (handledUser) {
235
+ const invalidateSession = () => {
236
+ if (handledExpiration !== undefined) {
237
+ tabSessionSync.broadcast({
238
+ type: TAB_SESSION_EVENT_TYPES.EXPIRED,
239
+ expiredTokenAt: handledExpiration
240
+ });
241
+ }
242
+ setLocalSession(null);
243
+ redirectToInactivityRoute();
244
+ };
245
+ invalidateWhenIdle(invalidateSession);
152
246
  }
153
- return json_0.user;
247
+ } catch (e) {
248
+ toast.error(`Refreshing token failed: ${e.message}`);
154
249
  }
155
- if (user) {
156
- setNewUser(null);
157
- redirectToInactivityRoute();
250
+ return null;
251
+ });
252
+ }, [apiRoute, authRequests, tabSessionSync, i18n.language, redirectToInactivityRoute, sessionTimers, setLocalSession, userSlug]);
253
+ const refreshCookieAsync = useCallback(() => refreshSession({
254
+ isActivityRefresh: false
255
+ }), [refreshSession]);
256
+ const logOutSession = useCallback(({
257
+ collection: collection_2
258
+ }) => {
259
+ return authRequests.logOut({
260
+ clearSession: () => {
261
+ authRequests.discardPendingResults();
262
+ setLocalSession(null);
263
+ },
264
+ request: async () => {
265
+ try {
266
+ if (collection_2) {
267
+ await requests.post(formatAdminURL({
268
+ apiRoute,
269
+ path: `/${collection_2}/logout`
270
+ }));
271
+ }
272
+ } catch (_) {
273
+ // Explicit logout always clears local state, even if server revocation fails.
274
+ }
158
275
  }
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]);
276
+ });
277
+ }, [apiRoute, authRequests, setLocalSession]);
164
278
  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
279
+ const logoutEvent = {
280
+ type: TAB_SESSION_EVENT_TYPES.LOGGED_OUT
281
+ };
282
+ const logoutPublication = tabSessionSync.broadcast(logoutEvent);
283
+ const collection_3 = userRef.current?.collection;
284
+ await logOutSession({
285
+ collection: collection_3
286
+ });
287
+ if (logoutPublication?.type === TAB_SESSION_EVENT_TYPES.LOGGED_OUT) {
288
+ tabSessionSync.broadcastLogoutSettlement(logoutPublication);
175
289
  }
176
290
  return true;
177
- }, [apiRoute, setNewUser, user]);
291
+ }, [tabSessionSync, logOutSession]);
178
292
  const refreshPermissions = useCallback(async ({
179
293
  locale
180
294
  } = {}) => {
@@ -184,7 +298,7 @@ export function AuthProvider({
184
298
  addQueryPrefix: true
185
299
  });
186
300
  try {
187
- const request_1 = await requests.get(formatAdminURL({
301
+ const request_0 = await requests.get(formatAdminURL({
188
302
  apiRoute,
189
303
  path: `/access${params}`
190
304
  }), {
@@ -192,42 +306,79 @@ export function AuthProvider({
192
306
  'Accept-Language': i18n.language
193
307
  }
194
308
  });
195
- if (request_1.status === 200) {
196
- const json_1 = await request_1.json();
197
- setPermissions(json_1);
309
+ if (request_0.status === 200) {
310
+ const json_0 = await request_0.json();
311
+ setPermissions(json_0);
198
312
  } else {
199
- throw new Error(`Fetching permissions failed with status code ${request_1.status}`);
313
+ throw new Error(`Fetching permissions failed with status code ${request_0.status}`);
200
314
  }
201
- } catch (e_1) {
202
- toast.error(`Refreshing permissions failed: ${e_1.message}`);
315
+ } catch (e_0) {
316
+ toast.error(`Refreshing permissions failed: ${e_0.message}`);
203
317
  }
204
318
  }, [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
319
+ const fetchFullUserResult = React.useCallback(({
320
+ isTabSessionEventStale
321
+ } = {}) => {
322
+ return authRequests.queue(async ({
323
+ acceptResult: acceptResult_0,
324
+ isResultStale: isResultStale_0
325
+ }) => {
326
+ const isResponseStale = () => isResultStale_0() || Boolean(isTabSessionEventStale?.());
327
+ if (isResponseStale()) {
328
+ return {
329
+ status: 'indeterminate'
330
+ };
331
+ }
332
+ try {
333
+ const request_1 = await requests.get(formatAdminURL({
334
+ apiRoute,
335
+ path: `/${userSlug}/me`
336
+ }), {
337
+ credentials: 'include',
338
+ headers: {
339
+ 'Accept-Language': i18n.language
340
+ }
341
+ });
342
+ if (request_1.status !== 200) {
343
+ return {
344
+ status: 'indeterminate'
345
+ };
214
346
  }
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;
347
+ const json_1 = await request_1.json();
348
+ if (isResponseStale()) {
349
+ return {
350
+ status: 'indeterminate'
351
+ };
352
+ }
353
+ if (json_1?.user) {
354
+ if (!acceptResult_0()) {
355
+ return {
356
+ status: 'indeterminate'
357
+ };
358
+ }
359
+ setLocalSession(json_1);
360
+ return {
361
+ expirationMs: typeof json_1.exp === 'number' && Number.isFinite(json_1.exp) ? json_1.exp * 1000 : sessionTimers.getCurrentExpirationMs(),
362
+ status: 'authenticated',
363
+ user: json_1.user
364
+ };
365
+ }
366
+ setLocalSession(null);
367
+ return {
368
+ status: 'unauthenticated'
369
+ };
370
+ } catch (e_1) {
371
+ toast.error(`Fetching user failed: ${e_1.message}`);
220
372
  }
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]);
373
+ return {
374
+ status: 'indeterminate'
375
+ };
376
+ });
377
+ }, [apiRoute, authRequests, i18n.language, sessionTimers, setLocalSession, userSlug]);
378
+ const fetchFullUser = React.useCallback(async () => {
379
+ const result_0 = await fetchFullUserResult();
380
+ return result_0.status === 'authenticated' ? result_0.user : null;
381
+ }, [fetchFullUserResult]);
231
382
  const fetchFullUserEvent = useEffectEvent(fetchFullUser);
232
383
  useEffect(() => {
233
384
  async function fetchUserOnMount() {
@@ -242,26 +393,23 @@ export function AuthProvider({
242
393
  }
243
394
  }, [user, autoLogin]);
244
395
  useEffect(() => () => {
245
- // remove all timeouts on unmount
246
- clearTimeout(refreshTokenTimeoutRef.current);
247
- clearTimeout(reminderTimeoutRef.current);
248
- clearTimeout(forceLogOutTimeoutRef.current);
249
- }, []);
396
+ authRequests.discardPendingResults();
397
+ }, [authRequests]);
250
398
  if (!user && !fetchedUserOnMount) {
251
399
  return null;
252
400
  }
253
401
  return /*#__PURE__*/_jsx(Context, {
254
402
  value: {
403
+ authSession,
255
404
  fetchFullUser,
256
405
  logOut,
257
406
  permissions,
258
- refreshCookie,
407
+ refreshCookie: sessionTimers.scheduleRefresh,
259
408
  refreshCookieAsync,
260
409
  refreshPermissions,
261
410
  setPermissions,
262
- setUser: setNewUser,
411
+ setUser,
263
412
  token: tokenInMemory,
264
- tokenExpirationMs,
265
413
  user
266
414
  },
267
415
  children: children
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useModal","formatAdminURL","qs","React","createContext","use","useCallback","useEffect","useState","toast","stayLoggedInModalSlug","useEffectEvent","useTranslation","requests","useConfig","usePathname","useRouter","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 { AuthenticatedUser, SanitizedPermissions } from 'payload'\n\nimport { useModal } from '@faceless-ui/modal'\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 { usePathname, useRouter } from '../RouterAdapter/index.js'\nimport { useRouteTransition } from '../RouteTransition/index.js'\n\nexport type UserWithToken<T = AuthenticatedUser> = {\n /** seconds until expiration */\n exp: number\n refreshedToken?: string\n token?: string\n user: T\n}\n\nexport type AuthContext<T = AuthenticatedUser> = {\n fetchFullUser: () => Promise<null | T>\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<null | T>\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?: AuthenticatedUser | 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<AuthenticatedUser | 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<AuthenticatedUser | null> => {\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 = AuthenticatedUser,>(): AuthContext<T> => use(Context) as AuthContext<T>\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useModal","formatAdminURL","qs","React","createContext","use","useCallback","useEffect","useState","toast","stayLoggedInModalSlug","useEffectEvent","useTranslation","requests","useConfig","usePathname","useRouter","useSearchParams","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","useAuth"],"sources":["../../../src/providers/Auth/index.tsx"],"sourcesContent":["'use client'\nimport type { AuthenticatedUser, SanitizedPermissions } from 'payload'\n\nimport { useModal } from '@faceless-ui/modal'\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 { usePathname, useRouter, useSearchParams } from '../RouterAdapter/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?: AuthenticatedUser | null\n}\n\ntype FetchFullUserResult =\n | {\n expirationMs?: number\n status: 'authenticated'\n user: AuthenticatedUser\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?: AuthenticatedUser | 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<AuthenticatedUser | 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<AuthenticatedUser | 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 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<AuthenticatedUser | 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(\n (): Promise<AuthenticatedUser | null> => refreshSession({ isActivityRefresh: false }),\n [refreshSession],\n )\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<AuthenticatedUser | null> => {\n const result = await fetchFullUserResult()\n\n return result.status === 'authenticated' ? result.user : 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 user,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport const useAuth = <T = AuthenticatedUser,>(): AuthContext<T> => use(Context) as AuthContext<T>\n"],"mappings":"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","ignoreList":[]}