@djangocfg/api 2.1.621 → 2.1.623
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.cjs +147 -80
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +6 -1
- package/dist/auth.d.ts +6 -1
- package/dist/auth.mjs +94 -29
- package/dist/auth.mjs.map +1 -1
- package/dist/index.cjs +72 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +72 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/auth/__tests__/sharedContext.test.ts +16 -0
- package/src/auth/__tests__/trace.test.ts +38 -0
- package/src/auth/context/AccountsContext.tsx +3 -2
- package/src/auth/context/AuthContext.tsx +2 -2
- package/src/auth/context/sharedContext.ts +16 -0
- package/src/auth/trace.ts +75 -5
package/dist/auth.cjs
CHANGED
|
@@ -240,6 +240,7 @@ __export(auth_exports, {
|
|
|
240
240
|
peekSavedRedirect: () => peekSavedRedirect,
|
|
241
241
|
readAuthTrace: () => readAuthTrace,
|
|
242
242
|
readOAuthFailure: () => readOAuthFailure,
|
|
243
|
+
resetAuthTraceForTests: () => resetAuthTraceForTests,
|
|
243
244
|
resolveAuthError: () => resolveAuthError,
|
|
244
245
|
resolveAuthStatus: () => resolveAuthStatus,
|
|
245
246
|
resolveGuardIsAuthenticated: () => resolveGuardIsAuthenticated,
|
|
@@ -292,7 +293,10 @@ var KEY = "cfg.auth.trace";
|
|
|
292
293
|
var MAX = 200;
|
|
293
294
|
var MAX_STRING = 120;
|
|
294
295
|
var SENSITIVE = /token|otp|code|email|password|secret|cookie|authorization|key|identifier/i;
|
|
295
|
-
var TAB =
|
|
296
|
+
var TAB = (() => {
|
|
297
|
+
const g = globalThis;
|
|
298
|
+
return g.__cfgAuthTab ??= Math.random().toString(36).slice(2, 6);
|
|
299
|
+
})();
|
|
296
300
|
var hasWindow = typeof window !== "undefined";
|
|
297
301
|
var memory = [];
|
|
298
302
|
var loaded = false;
|
|
@@ -341,10 +345,30 @@ function clean(fields) {
|
|
|
341
345
|
return Object.keys(out).length ? out : void 0;
|
|
342
346
|
}
|
|
343
347
|
__name(clean, "clean");
|
|
348
|
+
function refresh() {
|
|
349
|
+
try {
|
|
350
|
+
const raw = backend()?.getItem(KEY);
|
|
351
|
+
const parsed = raw ? JSON.parse(raw) : null;
|
|
352
|
+
if (Array.isArray(parsed)) memory = parsed.filter((e) => typeof e === "object" && e !== null);
|
|
353
|
+
} catch {
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
__name(refresh, "refresh");
|
|
344
357
|
function record(at, ev, fields) {
|
|
345
|
-
|
|
358
|
+
load();
|
|
359
|
+
refresh();
|
|
360
|
+
const entries = memory;
|
|
346
361
|
const p = hasWindow && typeof performance !== "undefined" ? Math.round(performance.now()) : 0;
|
|
347
|
-
|
|
362
|
+
const f2 = clean(fields);
|
|
363
|
+
const last = entries[entries.length - 1];
|
|
364
|
+
if (last && last.tab === TAB && last.ev === ev && JSON.stringify(last.f) === JSON.stringify(f2)) {
|
|
365
|
+
last.n = (last.n ?? 1) + 1;
|
|
366
|
+
last.t = at;
|
|
367
|
+
last.p = p;
|
|
368
|
+
persist();
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
entries.push({ t: at, p, tab: TAB, ev, f: f2 });
|
|
348
372
|
if (entries.length > MAX) entries.splice(0, entries.length - MAX);
|
|
349
373
|
persist();
|
|
350
374
|
}
|
|
@@ -357,6 +381,11 @@ function authTrace(ev, fields) {
|
|
|
357
381
|
}
|
|
358
382
|
}
|
|
359
383
|
__name(authTrace, "authTrace");
|
|
384
|
+
function resetAuthTraceForTests() {
|
|
385
|
+
memory = [];
|
|
386
|
+
loaded = true;
|
|
387
|
+
}
|
|
388
|
+
__name(resetAuthTraceForTests, "resetAuthTraceForTests");
|
|
360
389
|
function readAuthTrace() {
|
|
361
390
|
return load().slice();
|
|
362
391
|
}
|
|
@@ -372,7 +401,8 @@ function clearAuthTrace() {
|
|
|
372
401
|
__name(clearAuthTrace, "clearAuthTrace");
|
|
373
402
|
function context() {
|
|
374
403
|
if (!hasWindow) return [];
|
|
375
|
-
const
|
|
404
|
+
const copies = globalThis.__cfgAuthCopies ?? 1;
|
|
405
|
+
const lines = [`url: ${window.location.href.split("?")[0]}`, `copies: ${String(copies)}`, `online: ${navigator.onLine}`, `ua: ${navigator.userAgent}`];
|
|
376
406
|
try {
|
|
377
407
|
const auth2 = globalThis.__cfgAuthNow;
|
|
378
408
|
const now = auth2?.();
|
|
@@ -388,7 +418,7 @@ function dumpAuthTrace() {
|
|
|
388
418
|
const rows = entries.map((e) => {
|
|
389
419
|
const fields = e.f ? ` ${Object.entries(e.f).map(([k2, v]) => `${k2}=${String(v)}`).join(" ")}` : "";
|
|
390
420
|
const at = new Date(e.t).toISOString().slice(11, 23);
|
|
391
|
-
return `${at} +${String(e.t - first).padStart(6)}ms [${e.tab} p${e.p}] ${e.ev}${fields}`;
|
|
421
|
+
return `${at} +${String(e.t - first).padStart(6)}ms [${e.tab} p${e.p}] ${e.ev}${fields}${e.n && e.n > 1 ? ` x${e.n}` : ""}`;
|
|
392
422
|
});
|
|
393
423
|
return [`# cfg auth trace, ${entries.length} events`, ...context(), "", ...rows].join("\n");
|
|
394
424
|
}
|
|
@@ -404,7 +434,21 @@ function installAuthTrace() {
|
|
|
404
434
|
console.log(text);
|
|
405
435
|
return text;
|
|
406
436
|
}, "dump"),
|
|
407
|
-
clear: clearAuthTrace
|
|
437
|
+
clear: clearAuthTrace,
|
|
438
|
+
/** Put the dump on the clipboard (works when the console output is blocked or too long to select). */
|
|
439
|
+
copy: /* @__PURE__ */ __name(() => {
|
|
440
|
+
const text = dumpAuthTrace();
|
|
441
|
+
void navigator.clipboard?.writeText(text);
|
|
442
|
+
return `${text.split("\n").length} lines copied`;
|
|
443
|
+
}, "copy"),
|
|
444
|
+
/** Download the raw trace as a JSON file. */
|
|
445
|
+
download: /* @__PURE__ */ __name(() => {
|
|
446
|
+
const blob = new Blob([JSON.stringify(readAuthTrace(), null, 1)], { type: "application/json" });
|
|
447
|
+
const a = document.createElement("a");
|
|
448
|
+
a.href = URL.createObjectURL(blob);
|
|
449
|
+
a.download = `auth-trace-${Date.now()}.json`;
|
|
450
|
+
a.click();
|
|
451
|
+
}, "download")
|
|
408
452
|
};
|
|
409
453
|
const queued = g.__cfgAuthTraceQ;
|
|
410
454
|
if (Array.isArray(queued)) {
|
|
@@ -420,11 +464,25 @@ function installAuthTrace() {
|
|
|
420
464
|
}
|
|
421
465
|
}
|
|
422
466
|
__name(installAuthTrace, "installAuthTrace");
|
|
467
|
+
function registerCopy() {
|
|
468
|
+
if (!hasWindow) return;
|
|
469
|
+
const g = globalThis;
|
|
470
|
+
const n = (g.__cfgAuthCopies ?? 0) + 1;
|
|
471
|
+
g.__cfgAuthCopies = n;
|
|
472
|
+
if (n > 1) {
|
|
473
|
+
authTrace("dup.copy", { copies: n });
|
|
474
|
+
if (n === 2) {
|
|
475
|
+
console.warn("[@djangocfg/api] more than one copy of the auth package is loaded; see __cfgAuth.dump() (dup.copy). Align the peer set so pnpm installs one instance.");
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
__name(registerCopy, "registerCopy");
|
|
480
|
+
registerCopy();
|
|
423
481
|
installAuthTrace();
|
|
424
482
|
|
|
425
483
|
// src/auth/context/AuthContext.tsx
|
|
426
484
|
var import_navigation4 = require("next/navigation");
|
|
427
|
-
var
|
|
485
|
+
var import_react21 = require("react");
|
|
428
486
|
|
|
429
487
|
// src/_api/generated/helpers/errors.ts
|
|
430
488
|
var APIError = class extends Error {
|
|
@@ -826,10 +884,10 @@ function adoptLegacySession() {
|
|
|
826
884
|
if (_storage.get(ACCESS_KEY) !== null || _storage.get(REFRESH_KEY) !== null) return;
|
|
827
885
|
const legacy = backendFor("localStorage");
|
|
828
886
|
const access = legacy.get(ACCESS_KEY);
|
|
829
|
-
const
|
|
830
|
-
if (access === null &&
|
|
887
|
+
const refresh2 = legacy.get(REFRESH_KEY);
|
|
888
|
+
if (access === null && refresh2 === null) return;
|
|
831
889
|
if (access !== null) _storage.set(ACCESS_KEY, access);
|
|
832
|
-
if (
|
|
890
|
+
if (refresh2 !== null) _storage.set(REFRESH_KEY, refresh2);
|
|
833
891
|
legacy.set(ACCESS_KEY, null);
|
|
834
892
|
legacy.set(REFRESH_KEY, null);
|
|
835
893
|
} catch {
|
|
@@ -914,12 +972,12 @@ function jwtExpMs(token) {
|
|
|
914
972
|
__name(jwtExpMs, "jwtExpMs");
|
|
915
973
|
function computeSnapshot() {
|
|
916
974
|
const access = _storage.get(ACCESS_KEY);
|
|
917
|
-
const
|
|
975
|
+
const refresh2 = _storage.get(REFRESH_KEY);
|
|
918
976
|
const now = Date.now();
|
|
919
977
|
const accessExp = access ? jwtExpMs(access) : null;
|
|
920
978
|
const accessAlive = access !== null && (accessExp === null || accessExp > now);
|
|
921
|
-
const refreshExp =
|
|
922
|
-
const refreshAlive =
|
|
979
|
+
const refreshExp = refresh2 ? jwtExpMs(refresh2) : null;
|
|
980
|
+
const refreshAlive = refresh2 !== null && (refreshExp === null || refreshExp > now);
|
|
923
981
|
return {
|
|
924
982
|
status: accessAlive || refreshAlive ? "authenticated" : "anonymous",
|
|
925
983
|
accessExpiresAt: accessExp
|
|
@@ -942,9 +1000,9 @@ function scheduleExpiryFlip() {
|
|
|
942
1000
|
const now = Date.now();
|
|
943
1001
|
const exps = [];
|
|
944
1002
|
const access = _storage.get(ACCESS_KEY);
|
|
945
|
-
const
|
|
1003
|
+
const refresh2 = _storage.get(REFRESH_KEY);
|
|
946
1004
|
const accessExp = access ? jwtExpMs(access) : null;
|
|
947
|
-
const refreshExp =
|
|
1005
|
+
const refreshExp = refresh2 ? jwtExpMs(refresh2) : null;
|
|
948
1006
|
if (accessExp !== null && accessExp > now) exps.push(accessExp);
|
|
949
1007
|
if (refreshExp !== null && refreshExp > now) exps.push(refreshExp);
|
|
950
1008
|
if (!exps.length) return;
|
|
@@ -1213,9 +1271,9 @@ async function tryRefresh() {
|
|
|
1213
1271
|
if (_refreshInflight) return _refreshInflight;
|
|
1214
1272
|
if (!_refreshHandler) return null;
|
|
1215
1273
|
const runRefresh = /* @__PURE__ */ __name(async () => {
|
|
1216
|
-
const
|
|
1217
|
-
if (!
|
|
1218
|
-
const result = await _refreshHandler(
|
|
1274
|
+
const refresh2 = auth.getRefreshToken();
|
|
1275
|
+
if (!refresh2) return null;
|
|
1276
|
+
const result = await _refreshHandler(refresh2);
|
|
1219
1277
|
if (!result?.access) {
|
|
1220
1278
|
trace("refresh", { ok: false, why: "no-access" });
|
|
1221
1279
|
return null;
|
|
@@ -1416,7 +1474,7 @@ function installAuthOnClient(client2) {
|
|
|
1416
1474
|
}
|
|
1417
1475
|
__name(installAuthOnClient, "installAuthOnClient");
|
|
1418
1476
|
var REFRESH_ENDPOINT = "/cfg/accounts/token/refresh/";
|
|
1419
|
-
auth.setRefreshHandler(async (
|
|
1477
|
+
auth.setRefreshHandler(async (refresh2) => {
|
|
1420
1478
|
try {
|
|
1421
1479
|
const url = `${auth.getBaseUrl()}${REFRESH_ENDPOINT}`;
|
|
1422
1480
|
const headers = { "Content-Type": "application/json" };
|
|
@@ -1428,11 +1486,11 @@ auth.setRefreshHandler(async (refresh) => {
|
|
|
1428
1486
|
method: "POST",
|
|
1429
1487
|
headers,
|
|
1430
1488
|
credentials: auth.getWithCredentials() ? "include" : "same-origin",
|
|
1431
|
-
body: JSON.stringify({ refresh })
|
|
1489
|
+
body: JSON.stringify({ refresh: refresh2 })
|
|
1432
1490
|
});
|
|
1433
1491
|
if (!res.ok) return null;
|
|
1434
1492
|
const data = await res.json();
|
|
1435
|
-
return data?.access ? { access: data.access, refresh: data.refresh ??
|
|
1493
|
+
return data?.access ? { access: data.access, refresh: data.refresh ?? refresh2 } : null;
|
|
1436
1494
|
} catch {
|
|
1437
1495
|
return null;
|
|
1438
1496
|
}
|
|
@@ -1703,7 +1761,7 @@ function useCfgRouter() {
|
|
|
1703
1761
|
const forward = (0, import_react3.useCallback)(() => {
|
|
1704
1762
|
router.forward();
|
|
1705
1763
|
}, [router]);
|
|
1706
|
-
const
|
|
1764
|
+
const refresh2 = (0, import_react3.useCallback)(() => {
|
|
1707
1765
|
router.refresh();
|
|
1708
1766
|
}, [router]);
|
|
1709
1767
|
return {
|
|
@@ -1714,7 +1772,7 @@ function useCfgRouter() {
|
|
|
1714
1772
|
prefetch,
|
|
1715
1773
|
back,
|
|
1716
1774
|
forward,
|
|
1717
|
-
refresh
|
|
1775
|
+
refresh: refresh2
|
|
1718
1776
|
};
|
|
1719
1777
|
}
|
|
1720
1778
|
__name(useCfgRouter, "useCfgRouter");
|
|
@@ -4893,7 +4951,7 @@ function resolveAuthStatus(s) {
|
|
|
4893
4951
|
__name(resolveAuthStatus, "resolveAuthStatus");
|
|
4894
4952
|
|
|
4895
4953
|
// src/auth/context/AccountsContext.tsx
|
|
4896
|
-
var
|
|
4954
|
+
var import_react20 = require("react");
|
|
4897
4955
|
|
|
4898
4956
|
// src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRegenerateCreate.ts
|
|
4899
4957
|
var import_mutation = __toESM(require("swr/mutation"), 1);
|
|
@@ -5240,6 +5298,15 @@ __name(useCfgAccountsTokenCreate, "useCfgAccountsTokenCreate");
|
|
|
5240
5298
|
// src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenRefreshCreate.ts
|
|
5241
5299
|
var import_mutation19 = __toESM(require("swr/mutation"), 1);
|
|
5242
5300
|
|
|
5301
|
+
// src/auth/context/sharedContext.ts
|
|
5302
|
+
var import_react19 = require("react");
|
|
5303
|
+
function sharedContext(key, initial) {
|
|
5304
|
+
const g = globalThis;
|
|
5305
|
+
const registry = g.__cfgAuthContexts ??= {};
|
|
5306
|
+
return registry[key] ??= (0, import_react19.createContext)(initial);
|
|
5307
|
+
}
|
|
5308
|
+
__name(sharedContext, "sharedContext");
|
|
5309
|
+
|
|
5243
5310
|
// src/auth/context/AccountsContext.tsx
|
|
5244
5311
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
5245
5312
|
function hasApiOrigin() {
|
|
@@ -5253,9 +5320,9 @@ function hasApiOrigin() {
|
|
|
5253
5320
|
}
|
|
5254
5321
|
}
|
|
5255
5322
|
__name(hasApiOrigin, "hasApiOrigin");
|
|
5256
|
-
var AccountsContext = (
|
|
5323
|
+
var AccountsContext = sharedContext("accounts", void 0);
|
|
5257
5324
|
function AccountsProvider({ children }) {
|
|
5258
|
-
const [profile, setProfile] = (0,
|
|
5325
|
+
const [profile, setProfile] = (0, import_react20.useState)(() => {
|
|
5259
5326
|
if (!auth.isAuthenticated()) {
|
|
5260
5327
|
clearProfileCache();
|
|
5261
5328
|
return void 0;
|
|
@@ -5263,15 +5330,15 @@ function AccountsProvider({ children }) {
|
|
|
5263
5330
|
const cached = getCachedProfile();
|
|
5264
5331
|
return cached || void 0;
|
|
5265
5332
|
});
|
|
5266
|
-
const [isLoadingProfile, setIsLoadingProfile] = (0,
|
|
5267
|
-
const [profileError, setProfileError] = (0,
|
|
5268
|
-
const profileRef = (0,
|
|
5269
|
-
const isLoadingRef = (0,
|
|
5270
|
-
const fetchSeqRef = (0,
|
|
5271
|
-
(0,
|
|
5333
|
+
const [isLoadingProfile, setIsLoadingProfile] = (0, import_react20.useState)(false);
|
|
5334
|
+
const [profileError, setProfileError] = (0, import_react20.useState)(null);
|
|
5335
|
+
const profileRef = (0, import_react20.useRef)(profile);
|
|
5336
|
+
const isLoadingRef = (0, import_react20.useRef)(false);
|
|
5337
|
+
const fetchSeqRef = (0, import_react20.useRef)(0);
|
|
5338
|
+
(0, import_react20.useEffect)(() => {
|
|
5272
5339
|
profileRef.current = profile;
|
|
5273
5340
|
}, [profile]);
|
|
5274
|
-
(0,
|
|
5341
|
+
(0, import_react20.useEffect)(() => {
|
|
5275
5342
|
isLoadingRef.current = isLoadingProfile;
|
|
5276
5343
|
}, [isLoadingProfile]);
|
|
5277
5344
|
const { trigger: triggerProfileUpdate } = useCfgAccountsProfileUpdateUpdate();
|
|
@@ -5280,7 +5347,7 @@ function AccountsProvider({ children }) {
|
|
|
5280
5347
|
const { trigger: triggerOtpRequest } = useCfgAccountsOtpRequestCreate();
|
|
5281
5348
|
const { trigger: triggerOtpVerify } = useCfgAccountsOtpVerifyCreate();
|
|
5282
5349
|
const { trigger: triggerPasswordLogin } = useCfgAccountsTokenCreate();
|
|
5283
|
-
const refreshProfile = (0,
|
|
5350
|
+
const refreshProfile = (0, import_react20.useCallback)(async (options) => {
|
|
5284
5351
|
const { callerId, force } = options || {};
|
|
5285
5352
|
if (!hasApiOrigin()) {
|
|
5286
5353
|
authLogger.debug(`No API origin configured, skipping profile fetch (caller: ${callerId})`);
|
|
@@ -5314,26 +5381,26 @@ function AccountsProvider({ children }) {
|
|
|
5314
5381
|
}
|
|
5315
5382
|
}
|
|
5316
5383
|
}, []);
|
|
5317
|
-
const updateProfile = (0,
|
|
5384
|
+
const updateProfile = (0, import_react20.useCallback)(async (data) => {
|
|
5318
5385
|
await triggerProfileUpdate({ body: data });
|
|
5319
5386
|
const user = await refreshProfile({ callerId: "updateProfile", force: true });
|
|
5320
5387
|
return user;
|
|
5321
5388
|
}, [triggerProfileUpdate, refreshProfile]);
|
|
5322
|
-
const partialUpdateProfile = (0,
|
|
5389
|
+
const partialUpdateProfile = (0, import_react20.useCallback)(async (data) => {
|
|
5323
5390
|
await triggerProfilePartialUpdate({ body: data });
|
|
5324
5391
|
const user = await refreshProfile({ callerId: "partialUpdateProfile", force: true });
|
|
5325
5392
|
return user;
|
|
5326
5393
|
}, [triggerProfilePartialUpdate, refreshProfile]);
|
|
5327
|
-
const uploadAvatar = (0,
|
|
5394
|
+
const uploadAvatar = (0, import_react20.useCallback)(async (avatar) => {
|
|
5328
5395
|
await triggerAvatar({ body: { avatar } });
|
|
5329
5396
|
const user = await refreshProfile({ callerId: "uploadAvatar", force: true });
|
|
5330
5397
|
return user;
|
|
5331
5398
|
}, [triggerAvatar, refreshProfile]);
|
|
5332
|
-
const requestOTP = (0,
|
|
5399
|
+
const requestOTP = (0, import_react20.useCallback)(async (data) => {
|
|
5333
5400
|
const result = await triggerOtpRequest({ body: data });
|
|
5334
5401
|
return result;
|
|
5335
5402
|
}, [triggerOtpRequest]);
|
|
5336
|
-
const settleLoginEnvelope = (0,
|
|
5403
|
+
const settleLoginEnvelope = (0, import_react20.useCallback)(async (result, callerId) => {
|
|
5337
5404
|
if (result.requires_2fa && result.session_id) {
|
|
5338
5405
|
authLogger.info("2FA required, session:", result.session_id);
|
|
5339
5406
|
return;
|
|
@@ -5348,20 +5415,20 @@ function AccountsProvider({ children }) {
|
|
|
5348
5415
|
}
|
|
5349
5416
|
}
|
|
5350
5417
|
}, [refreshProfile]);
|
|
5351
|
-
const verifyOTP = (0,
|
|
5418
|
+
const verifyOTP = (0, import_react20.useCallback)(async (data) => {
|
|
5352
5419
|
const result = await triggerOtpVerify({ body: data });
|
|
5353
5420
|
await settleLoginEnvelope(result, "verifyOTP");
|
|
5354
5421
|
return result;
|
|
5355
5422
|
}, [triggerOtpVerify, settleLoginEnvelope]);
|
|
5356
|
-
const loginWithPassword = (0,
|
|
5423
|
+
const loginWithPassword = (0, import_react20.useCallback)(async (data) => {
|
|
5357
5424
|
const result = await triggerPasswordLogin({ body: data });
|
|
5358
5425
|
await settleLoginEnvelope(result, "loginWithPassword");
|
|
5359
5426
|
return result;
|
|
5360
5427
|
}, [triggerPasswordLogin, settleLoginEnvelope]);
|
|
5361
|
-
const logout = (0,
|
|
5362
|
-
const
|
|
5363
|
-
if (
|
|
5364
|
-
CfgAccountsAuth.cfgAccountsTokenBlacklistCreate({ body: { refresh } }).catch(() => {
|
|
5428
|
+
const logout = (0, import_react20.useCallback)(() => {
|
|
5429
|
+
const refresh2 = auth.getRefreshToken();
|
|
5430
|
+
if (refresh2) {
|
|
5431
|
+
CfgAccountsAuth.cfgAccountsTokenBlacklistCreate({ body: { refresh: refresh2 } }).catch(() => {
|
|
5365
5432
|
authLogger.warn("Refresh-token blacklist failed (logged out locally anyway)");
|
|
5366
5433
|
});
|
|
5367
5434
|
}
|
|
@@ -5371,7 +5438,7 @@ function AccountsProvider({ children }) {
|
|
|
5371
5438
|
setProfileError(null);
|
|
5372
5439
|
clearProfileCache();
|
|
5373
5440
|
}, []);
|
|
5374
|
-
const value = (0,
|
|
5441
|
+
const value = (0, import_react20.useMemo)(() => ({
|
|
5375
5442
|
profile,
|
|
5376
5443
|
isLoadingProfile,
|
|
5377
5444
|
profileError,
|
|
@@ -5400,7 +5467,7 @@ function AccountsProvider({ children }) {
|
|
|
5400
5467
|
}
|
|
5401
5468
|
__name(AccountsProvider, "AccountsProvider");
|
|
5402
5469
|
function useAccountsContext() {
|
|
5403
|
-
const context2 = (0,
|
|
5470
|
+
const context2 = (0, import_react20.useContext)(AccountsContext);
|
|
5404
5471
|
if (!context2) {
|
|
5405
5472
|
throw new Error("useAccountsContext must be used within AccountsProvider");
|
|
5406
5473
|
}
|
|
@@ -5421,7 +5488,7 @@ var resolveAuthRoutes = /* @__PURE__ */ __name((routes) => ({
|
|
|
5421
5488
|
defaultAuthCallback: routes?.defaultAuthCallback || routes?.auth || defaultRoutes.defaultAuthCallback
|
|
5422
5489
|
}), "resolveAuthRoutes");
|
|
5423
5490
|
var EMAIL_STORAGE_KEY = CFG_KEYS.email.key;
|
|
5424
|
-
var AuthContext = (
|
|
5491
|
+
var AuthContext = sharedContext("auth", void 0);
|
|
5425
5492
|
var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
5426
5493
|
const accounts = useAccountsContext();
|
|
5427
5494
|
const session = useSession();
|
|
@@ -5433,28 +5500,28 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5433
5500
|
EMAIL_STORAGE_KEY,
|
|
5434
5501
|
null
|
|
5435
5502
|
);
|
|
5436
|
-
const routes = (0,
|
|
5437
|
-
const routesRef = (0,
|
|
5438
|
-
(0,
|
|
5503
|
+
const routes = (0, import_react21.useMemo)(() => resolveAuthRoutes(config?.routes), [config?.routes]);
|
|
5504
|
+
const routesRef = (0, import_react21.useRef)(routes);
|
|
5505
|
+
(0, import_react21.useEffect)(() => {
|
|
5439
5506
|
routesRef.current = routes;
|
|
5440
5507
|
}, [routes]);
|
|
5441
5508
|
const redirectManager = useAuthRedirectManager({
|
|
5442
5509
|
fallbackUrl: routes.defaultCallback,
|
|
5443
5510
|
clearOnUse: true
|
|
5444
5511
|
});
|
|
5445
|
-
const configRef = (0,
|
|
5446
|
-
(0,
|
|
5512
|
+
const configRef = (0, import_react21.useRef)(config);
|
|
5513
|
+
(0, import_react21.useEffect)(() => {
|
|
5447
5514
|
configRef.current = config;
|
|
5448
5515
|
}, [config]);
|
|
5449
|
-
const accountsRef = (0,
|
|
5450
|
-
(0,
|
|
5516
|
+
const accountsRef = (0, import_react21.useRef)(accounts);
|
|
5517
|
+
(0, import_react21.useEffect)(() => {
|
|
5451
5518
|
accountsRef.current = accounts;
|
|
5452
5519
|
}, [accounts]);
|
|
5453
|
-
const pendingManualNavRef = (0,
|
|
5454
|
-
const [profileSettled, setProfileSettled] = (0,
|
|
5520
|
+
const pendingManualNavRef = (0, import_react21.useRef)(false);
|
|
5521
|
+
const [profileSettled, setProfileSettled] = (0, import_react21.useState)(false);
|
|
5455
5522
|
const hasProfile = Boolean(accounts.profile);
|
|
5456
|
-
const profileAttemptedRef = (0,
|
|
5457
|
-
(0,
|
|
5523
|
+
const profileAttemptedRef = (0, import_react21.useRef)(false);
|
|
5524
|
+
(0, import_react21.useEffect)(() => {
|
|
5458
5525
|
if (!isAuthenticated) {
|
|
5459
5526
|
profileAttemptedRef.current = false;
|
|
5460
5527
|
const hasTokens = Boolean(auth.getToken() || auth.getRefreshToken());
|
|
@@ -5492,9 +5559,9 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5492
5559
|
};
|
|
5493
5560
|
}, [isAuthenticated, hasProfile]);
|
|
5494
5561
|
const isLoading = !profileSettled;
|
|
5495
|
-
const [clientReady, setClientReady] = (0,
|
|
5496
|
-
const [timedOut, setTimedOut] = (0,
|
|
5497
|
-
(0,
|
|
5562
|
+
const [clientReady, setClientReady] = (0, import_react21.useState)(false);
|
|
5563
|
+
const [timedOut, setTimedOut] = (0, import_react21.useState)(false);
|
|
5564
|
+
(0, import_react21.useEffect)(() => {
|
|
5498
5565
|
setClientReady(true);
|
|
5499
5566
|
const timer = setTimeout(() => setTimedOut(true), 8e3);
|
|
5500
5567
|
return () => clearTimeout(timer);
|
|
@@ -5506,8 +5573,8 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5506
5573
|
profileSettled,
|
|
5507
5574
|
timedOut
|
|
5508
5575
|
});
|
|
5509
|
-
const lastStatusRef = (0,
|
|
5510
|
-
(0,
|
|
5576
|
+
const lastStatusRef = (0, import_react21.useRef)("");
|
|
5577
|
+
(0, import_react21.useEffect)(() => {
|
|
5511
5578
|
if (lastStatusRef.current === status) return;
|
|
5512
5579
|
lastStatusRef.current = status;
|
|
5513
5580
|
authTrace("status", {
|
|
@@ -5519,7 +5586,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5519
5586
|
path: pathname ?? ""
|
|
5520
5587
|
});
|
|
5521
5588
|
}, [status, isAuthenticated, profileSettled, timedOut, pathname]);
|
|
5522
|
-
(0,
|
|
5589
|
+
(0, import_react21.useEffect)(() => {
|
|
5523
5590
|
globalThis.__cfgAuthNow = () => ({
|
|
5524
5591
|
status,
|
|
5525
5592
|
snapshot: isAuthenticated,
|
|
@@ -5530,7 +5597,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5530
5597
|
timedOut
|
|
5531
5598
|
});
|
|
5532
5599
|
}, [status, isAuthenticated, profileSettled, timedOut]);
|
|
5533
|
-
(0,
|
|
5600
|
+
(0, import_react21.useEffect)(() => {
|
|
5534
5601
|
const unsubscribe = auth.onSessionExpired(() => {
|
|
5535
5602
|
authTrace("expired.handler", { path: pathname ?? "" });
|
|
5536
5603
|
authLogger.warn("Session expired (terminal 401) \u2014 redirecting to login");
|
|
@@ -5542,7 +5609,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5542
5609
|
});
|
|
5543
5610
|
return unsubscribe;
|
|
5544
5611
|
}, [router, pathname]);
|
|
5545
|
-
(0,
|
|
5612
|
+
(0, import_react21.useEffect)(() => {
|
|
5546
5613
|
if (!isAuthenticated || pendingManualNavRef.current) return;
|
|
5547
5614
|
if (pathname === routes.auth && !queryParams.get("flow")) {
|
|
5548
5615
|
const saved = redirectManager.hasRedirect() ? redirectManager.getRedirect() : null;
|
|
@@ -5551,7 +5618,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5551
5618
|
router.push(saved || routes.defaultCallback);
|
|
5552
5619
|
}
|
|
5553
5620
|
}, [isAuthenticated, pathname, queryParams, routes, router, redirectManager]);
|
|
5554
|
-
const loadCurrentProfile = (0,
|
|
5621
|
+
const loadCurrentProfile = (0, import_react21.useCallback)(async (callerId) => {
|
|
5555
5622
|
if (!auth.isAuthenticated()) {
|
|
5556
5623
|
throw new Error("No valid authentication token");
|
|
5557
5624
|
}
|
|
@@ -5559,7 +5626,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5559
5626
|
callerId: callerId || "AuthContext.loadCurrentProfile"
|
|
5560
5627
|
});
|
|
5561
5628
|
}, []);
|
|
5562
|
-
const checkAuthAndRedirect = (0,
|
|
5629
|
+
const checkAuthAndRedirect = (0, import_react21.useCallback)(async () => {
|
|
5563
5630
|
if (auth.isAuthenticated()) {
|
|
5564
5631
|
try {
|
|
5565
5632
|
await loadCurrentProfile("checkAuthAndRedirect");
|
|
@@ -5571,7 +5638,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5571
5638
|
router.push(routesRef.current.defaultAuthCallback);
|
|
5572
5639
|
}
|
|
5573
5640
|
}, [loadCurrentProfile, router]);
|
|
5574
|
-
const requestOTP = (0,
|
|
5641
|
+
const requestOTP = (0, import_react21.useCallback)(
|
|
5575
5642
|
async (identifier, sourceUrl, consent) => {
|
|
5576
5643
|
authTrace("otp.request");
|
|
5577
5644
|
auth.clearSession();
|
|
@@ -5614,7 +5681,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5614
5681
|
},
|
|
5615
5682
|
[]
|
|
5616
5683
|
);
|
|
5617
|
-
const verifyOTP = (0,
|
|
5684
|
+
const verifyOTP = (0, import_react21.useCallback)(
|
|
5618
5685
|
async (identifier, otpCode, sourceUrl, redirectUrl, skipRedirect) => {
|
|
5619
5686
|
try {
|
|
5620
5687
|
pendingManualNavRef.current = Boolean(skipRedirect);
|
|
@@ -5675,7 +5742,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5675
5742
|
},
|
|
5676
5743
|
[setStoredEmail, redirectManager, router]
|
|
5677
5744
|
);
|
|
5678
|
-
const login = (0,
|
|
5745
|
+
const login = (0, import_react21.useCallback)(
|
|
5679
5746
|
async (email, password, options) => {
|
|
5680
5747
|
const { redirectUrl, skipRedirect } = options || {};
|
|
5681
5748
|
try {
|
|
@@ -5741,7 +5808,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5741
5808
|
},
|
|
5742
5809
|
[setStoredEmail, redirectManager, router]
|
|
5743
5810
|
);
|
|
5744
|
-
const refreshToken = (0,
|
|
5811
|
+
const refreshToken = (0, import_react21.useCallback)(async () => {
|
|
5745
5812
|
const access = await auth.refreshNow();
|
|
5746
5813
|
if (access) {
|
|
5747
5814
|
Analytics.event("auth_token_refresh" /* AUTH_TOKEN_REFRESH */, {
|
|
@@ -5754,7 +5821,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5754
5821
|
});
|
|
5755
5822
|
return { success: false, message: "Error refreshing token" };
|
|
5756
5823
|
}, []);
|
|
5757
|
-
const logout = (0,
|
|
5824
|
+
const logout = (0, import_react21.useCallback)(() => {
|
|
5758
5825
|
authTrace("logout");
|
|
5759
5826
|
Analytics.event("auth_logout" /* AUTH_LOGOUT */, {
|
|
5760
5827
|
category: "auth" /* AUTH */
|
|
@@ -5764,21 +5831,21 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
5764
5831
|
}, [router]);
|
|
5765
5832
|
const user = accounts.profile ?? null;
|
|
5766
5833
|
const isAdminUser = Boolean(user?.is_staff || user?.is_superuser);
|
|
5767
|
-
(0,
|
|
5834
|
+
(0, import_react21.useEffect)(() => {
|
|
5768
5835
|
applyRoleLogPolicy({ isAdmin: isAdminUser });
|
|
5769
5836
|
}, [isAdminUser]);
|
|
5770
|
-
const updateProfile = (0,
|
|
5837
|
+
const updateProfile = (0, import_react21.useCallback)(
|
|
5771
5838
|
async (data) => {
|
|
5772
5839
|
const result = await accountsRef.current.partialUpdateProfile(data);
|
|
5773
5840
|
return result;
|
|
5774
5841
|
},
|
|
5775
5842
|
[]
|
|
5776
5843
|
);
|
|
5777
|
-
const uploadAvatar = (0,
|
|
5844
|
+
const uploadAvatar = (0, import_react21.useCallback)(async (avatar) => {
|
|
5778
5845
|
const result = await accountsRef.current.uploadAvatar(avatar);
|
|
5779
5846
|
return result;
|
|
5780
5847
|
}, []);
|
|
5781
|
-
const value = (0,
|
|
5848
|
+
const value = (0, import_react21.useMemo)(
|
|
5782
5849
|
() => ({
|
|
5783
5850
|
user,
|
|
5784
5851
|
isLoading,
|
|
@@ -5836,7 +5903,7 @@ function AuthProviderRaw({ children, config, enabled = true }) {
|
|
|
5836
5903
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AccountsProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthProviderInternal, { config, children }) });
|
|
5837
5904
|
}
|
|
5838
5905
|
__name(AuthProviderRaw, "AuthProviderRaw");
|
|
5839
|
-
var AuthProvider = (0,
|
|
5906
|
+
var AuthProvider = (0, import_react21.memo)(AuthProviderRaw);
|
|
5840
5907
|
var defaultAuthState = {
|
|
5841
5908
|
user: null,
|
|
5842
5909
|
isLoading: false,
|
|
@@ -5893,7 +5960,7 @@ var defaultAuthState = {
|
|
|
5893
5960
|
}, "uploadAvatar")
|
|
5894
5961
|
};
|
|
5895
5962
|
var useAuth = /* @__PURE__ */ __name(() => {
|
|
5896
|
-
const context2 = (0,
|
|
5963
|
+
const context2 = (0, import_react21.useContext)(AuthContext);
|
|
5897
5964
|
if (context2 === void 0) {
|
|
5898
5965
|
if (isBrowser2 && isDev) {
|
|
5899
5966
|
authLogger.debug("useAuth called outside AuthProvider, returning default state");
|