@djangocfg/api 2.1.542 → 2.1.544
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-server.cjs +1 -0
- package/dist/auth-server.cjs.map +1 -1
- package/dist/auth.cjs +57 -59
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +134 -7
- package/dist/auth.d.ts +134 -7
- package/dist/auth.mjs +69 -72
- package/dist/auth.mjs.map +1 -1
- package/dist/clients.cjs +1 -0
- package/dist/clients.cjs.map +1 -1
- package/dist/hooks.cjs +1 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/package.json +3 -2
- package/src/auth/__tests__/useTwoFactorStatus.test.ts +2 -2
- package/src/auth/context/AccountsContext.tsx +15 -11
- package/src/auth/hooks/useAuthForm.ts +0 -1
- package/src/auth/hooks/useCfgRouter.ts +1 -4
- package/src/auth/hooks/useGithubAuth.ts +25 -3
- package/src/auth/hooks/useLocalStorage.ts +7 -30
- package/src/auth/hooks/useSessionStorage.ts +6 -29
- package/src/auth/hooks/useTwoFactorVerify.ts +5 -9
- package/src/auth/utils/analytics.ts +22 -2
- package/src/auth/utils/errors.ts +22 -11
- package/src/auth/utils/storage.ts +64 -0
package/dist/auth.mjs
CHANGED
|
@@ -16,10 +16,10 @@ var AUTH_CONSTANTS = {
|
|
|
16
16
|
import { usePathname as usePathname3 } from "next/navigation";
|
|
17
17
|
import {
|
|
18
18
|
createContext as createContext2,
|
|
19
|
-
memo
|
|
19
|
+
memo,
|
|
20
20
|
useCallback as useCallback11,
|
|
21
21
|
useContext as useContext2,
|
|
22
|
-
useEffect as
|
|
22
|
+
useEffect as useEffect6,
|
|
23
23
|
useMemo as useMemo3,
|
|
24
24
|
useRef as useRef6,
|
|
25
25
|
useState as useState11
|
|
@@ -873,9 +873,6 @@ __name(withBasePath, "withBasePath");
|
|
|
873
873
|
function useCfgRouter() {
|
|
874
874
|
const router = useNextRouter();
|
|
875
875
|
const basePath = useMemo(() => getBasePath(), []);
|
|
876
|
-
const isStaticBuild2 = useMemo(() => {
|
|
877
|
-
return typeof process !== "undefined" && process.env.NEXT_PUBLIC_STATIC_BUILD === "true";
|
|
878
|
-
}, []);
|
|
879
876
|
const push = useCallback((href, options) => {
|
|
880
877
|
if (basePath) {
|
|
881
878
|
window.location.href = withBasePath(href, basePath);
|
|
@@ -2472,6 +2469,33 @@ var Analytics = {
|
|
|
2472
2469
|
|
|
2473
2470
|
// src/auth/hooks/useSessionStorage.ts
|
|
2474
2471
|
import { useState as useState3 } from "react";
|
|
2472
|
+
|
|
2473
|
+
// src/auth/utils/storage.ts
|
|
2474
|
+
var MAX_ITEM_KB = 1024;
|
|
2475
|
+
function isQuotaExceededError(error) {
|
|
2476
|
+
if (typeof error !== "object" || error === null) return false;
|
|
2477
|
+
const { name, code, message } = error;
|
|
2478
|
+
return name === "QuotaExceededError" || code === 22 || typeof message === "string" && message.includes("quota");
|
|
2479
|
+
}
|
|
2480
|
+
__name(isQuotaExceededError, "isQuotaExceededError");
|
|
2481
|
+
function isWithinSizeLimit(data, key) {
|
|
2482
|
+
try {
|
|
2483
|
+
const sizeInKB = new Blob([JSON.stringify(data)]).size / 1024;
|
|
2484
|
+
if (sizeInKB > MAX_ITEM_KB) {
|
|
2485
|
+
authLogger.warn(
|
|
2486
|
+
`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`
|
|
2487
|
+
);
|
|
2488
|
+
return false;
|
|
2489
|
+
}
|
|
2490
|
+
return true;
|
|
2491
|
+
} catch (error) {
|
|
2492
|
+
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
2493
|
+
return false;
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
__name(isWithinSizeLimit, "isWithinSizeLimit");
|
|
2497
|
+
|
|
2498
|
+
// src/auth/hooks/useSessionStorage.ts
|
|
2475
2499
|
function useSessionStorage(key, initialValue) {
|
|
2476
2500
|
const [storedValue, setStoredValue] = useState3(() => {
|
|
2477
2501
|
if (typeof window === "undefined") {
|
|
@@ -2485,21 +2509,6 @@ function useSessionStorage(key, initialValue) {
|
|
|
2485
2509
|
return initialValue;
|
|
2486
2510
|
}
|
|
2487
2511
|
});
|
|
2488
|
-
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
2489
|
-
try {
|
|
2490
|
-
const jsonString = JSON.stringify(data);
|
|
2491
|
-
const sizeInBytes = new Blob([jsonString]).size;
|
|
2492
|
-
const sizeInKB = sizeInBytes / 1024;
|
|
2493
|
-
if (sizeInKB > 1024) {
|
|
2494
|
-
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
2495
|
-
return false;
|
|
2496
|
-
}
|
|
2497
|
-
return true;
|
|
2498
|
-
} catch (error) {
|
|
2499
|
-
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
2500
|
-
return false;
|
|
2501
|
-
}
|
|
2502
|
-
}, "checkDataSize");
|
|
2503
2512
|
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
2504
2513
|
try {
|
|
2505
2514
|
const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
@@ -2536,7 +2545,7 @@ function useSessionStorage(key, initialValue) {
|
|
|
2536
2545
|
const setValue = /* @__PURE__ */ __name((value) => {
|
|
2537
2546
|
try {
|
|
2538
2547
|
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
2539
|
-
if (!
|
|
2548
|
+
if (!isWithinSizeLimit(valueToStore, key)) {
|
|
2540
2549
|
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
2541
2550
|
try {
|
|
2542
2551
|
window.sessionStorage.removeItem(key);
|
|
@@ -2552,7 +2561,7 @@ function useSessionStorage(key, initialValue) {
|
|
|
2552
2561
|
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
2553
2562
|
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
2554
2563
|
} catch (storageError) {
|
|
2555
|
-
if (storageError
|
|
2564
|
+
if (isQuotaExceededError(storageError)) {
|
|
2556
2565
|
authLogger.warn("sessionStorage quota exceeded, clearing old data...");
|
|
2557
2566
|
clearOldData();
|
|
2558
2567
|
try {
|
|
@@ -2588,7 +2597,7 @@ function useSessionStorage(key, initialValue) {
|
|
|
2588
2597
|
window.sessionStorage.removeItem(key);
|
|
2589
2598
|
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
2590
2599
|
} catch (removeError) {
|
|
2591
|
-
if (removeError
|
|
2600
|
+
if (isQuotaExceededError(removeError)) {
|
|
2592
2601
|
authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
|
|
2593
2602
|
clearOldData();
|
|
2594
2603
|
try {
|
|
@@ -2863,7 +2872,6 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
2863
2872
|
const {
|
|
2864
2873
|
identifier,
|
|
2865
2874
|
otp,
|
|
2866
|
-
isLoading,
|
|
2867
2875
|
acceptedTerms,
|
|
2868
2876
|
marketingConsent,
|
|
2869
2877
|
rememberMe,
|
|
@@ -3215,7 +3223,9 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3215
3223
|
if (response.user?.id) {
|
|
3216
3224
|
Analytics.setUser(String(response.user.id));
|
|
3217
3225
|
}
|
|
3218
|
-
|
|
3226
|
+
if (response.user) {
|
|
3227
|
+
onSuccess?.(response.user, response.is_new_user || false);
|
|
3228
|
+
}
|
|
3219
3229
|
if (!skipRedirect) {
|
|
3220
3230
|
const finalRedirectUrl = redirectUrl || "/private";
|
|
3221
3231
|
router.hardPush(finalRedirectUrl);
|
|
@@ -3448,21 +3458,6 @@ function useLocalStorage(key, initialValue) {
|
|
|
3448
3458
|
return initialValue;
|
|
3449
3459
|
}
|
|
3450
3460
|
});
|
|
3451
|
-
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
3452
|
-
try {
|
|
3453
|
-
const jsonString = JSON.stringify(data);
|
|
3454
|
-
const sizeInBytes = new Blob([jsonString]).size;
|
|
3455
|
-
const sizeInKB = sizeInBytes / 1024;
|
|
3456
|
-
if (sizeInKB > 1024) {
|
|
3457
|
-
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
3458
|
-
return false;
|
|
3459
|
-
}
|
|
3460
|
-
return true;
|
|
3461
|
-
} catch (error) {
|
|
3462
|
-
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
3463
|
-
return false;
|
|
3464
|
-
}
|
|
3465
|
-
}, "checkDataSize");
|
|
3466
3461
|
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
3467
3462
|
try {
|
|
3468
3463
|
const keys = Object.keys(localStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
@@ -3499,7 +3494,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
3499
3494
|
const setValue = /* @__PURE__ */ __name((value) => {
|
|
3500
3495
|
try {
|
|
3501
3496
|
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
3502
|
-
if (!
|
|
3497
|
+
if (!isWithinSizeLimit(valueToStore, key)) {
|
|
3503
3498
|
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
3504
3499
|
try {
|
|
3505
3500
|
window.localStorage.removeItem(key);
|
|
@@ -3519,7 +3514,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
3519
3514
|
}
|
|
3520
3515
|
window.localStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3521
3516
|
} catch (storageError) {
|
|
3522
|
-
if (storageError
|
|
3517
|
+
if (isQuotaExceededError(storageError)) {
|
|
3523
3518
|
authLogger.warn("localStorage quota exceeded, clearing old data...");
|
|
3524
3519
|
clearOldData();
|
|
3525
3520
|
try {
|
|
@@ -3563,7 +3558,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
3563
3558
|
window.localStorage.removeItem(key);
|
|
3564
3559
|
window.localStorage.removeItem(`${key}_timestamp`);
|
|
3565
3560
|
} catch (removeError) {
|
|
3566
|
-
if (removeError
|
|
3561
|
+
if (isQuotaExceededError(removeError)) {
|
|
3567
3562
|
authLogger.warn("localStorage quota exceeded during removal, clearing old data...");
|
|
3568
3563
|
clearOldData();
|
|
3569
3564
|
try {
|
|
@@ -3767,7 +3762,7 @@ import {
|
|
|
3767
3762
|
createContext,
|
|
3768
3763
|
useCallback as useCallback10,
|
|
3769
3764
|
useContext,
|
|
3770
|
-
useEffect as
|
|
3765
|
+
useEffect as useEffect5,
|
|
3771
3766
|
useMemo as useMemo2,
|
|
3772
3767
|
useRef as useRef5,
|
|
3773
3768
|
useState as useState10
|
|
@@ -4370,10 +4365,10 @@ function AccountsProvider({ children }) {
|
|
|
4370
4365
|
const [profileError, setProfileError] = useState10(null);
|
|
4371
4366
|
const profileRef = useRef5(profile);
|
|
4372
4367
|
const isLoadingRef = useRef5(false);
|
|
4373
|
-
|
|
4368
|
+
useEffect5(() => {
|
|
4374
4369
|
profileRef.current = profile;
|
|
4375
4370
|
}, [profile]);
|
|
4376
|
-
|
|
4371
|
+
useEffect5(() => {
|
|
4377
4372
|
isLoadingRef.current = isLoadingProfile;
|
|
4378
4373
|
}, [isLoadingProfile]);
|
|
4379
4374
|
const { trigger: triggerProfileUpdate } = useCfgAccountsProfileUpdateUpdate();
|
|
@@ -4411,26 +4406,26 @@ function AccountsProvider({ children }) {
|
|
|
4411
4406
|
isLoadingRef.current = false;
|
|
4412
4407
|
}
|
|
4413
4408
|
}, []);
|
|
4414
|
-
const updateProfile =
|
|
4409
|
+
const updateProfile = useCallback10(async (data) => {
|
|
4415
4410
|
await triggerProfileUpdate({ body: data });
|
|
4416
4411
|
const user = await refreshProfile({ callerId: "updateProfile", force: true });
|
|
4417
4412
|
return user;
|
|
4418
|
-
},
|
|
4419
|
-
const partialUpdateProfile =
|
|
4413
|
+
}, [triggerProfileUpdate, refreshProfile]);
|
|
4414
|
+
const partialUpdateProfile = useCallback10(async (data) => {
|
|
4420
4415
|
await triggerProfilePartialUpdate({ body: data });
|
|
4421
4416
|
const user = await refreshProfile({ callerId: "partialUpdateProfile", force: true });
|
|
4422
4417
|
return user;
|
|
4423
|
-
},
|
|
4424
|
-
const uploadAvatar =
|
|
4418
|
+
}, [triggerProfilePartialUpdate, refreshProfile]);
|
|
4419
|
+
const uploadAvatar = useCallback10(async (avatar) => {
|
|
4425
4420
|
await triggerAvatar({ body: { avatar } });
|
|
4426
4421
|
const user = await refreshProfile({ callerId: "uploadAvatar", force: true });
|
|
4427
4422
|
return user;
|
|
4428
|
-
},
|
|
4429
|
-
const requestOTP =
|
|
4423
|
+
}, [triggerAvatar, refreshProfile]);
|
|
4424
|
+
const requestOTP = useCallback10(async (data) => {
|
|
4430
4425
|
const result = await triggerOtpRequest({ body: data });
|
|
4431
4426
|
return result;
|
|
4432
|
-
},
|
|
4433
|
-
const verifyOTP =
|
|
4427
|
+
}, [triggerOtpRequest]);
|
|
4428
|
+
const verifyOTP = useCallback10(async (data) => {
|
|
4434
4429
|
const result = await triggerOtpVerify({ body: data });
|
|
4435
4430
|
if (result.requires_2fa && result.session_id) {
|
|
4436
4431
|
authLogger.info("2FA required, session:", result.session_id);
|
|
@@ -4445,7 +4440,7 @@ function AccountsProvider({ children }) {
|
|
|
4445
4440
|
}
|
|
4446
4441
|
}
|
|
4447
4442
|
return result;
|
|
4448
|
-
},
|
|
4443
|
+
}, [triggerOtpVerify, refreshProfile]);
|
|
4449
4444
|
const logout = useCallback10(() => {
|
|
4450
4445
|
const refresh = auth.getRefreshToken();
|
|
4451
4446
|
if (refresh) {
|
|
@@ -4524,7 +4519,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4524
4519
|
);
|
|
4525
4520
|
const routes = useMemo3(() => resolveAuthRoutes(config?.routes), [config?.routes]);
|
|
4526
4521
|
const routesRef = useRef6(routes);
|
|
4527
|
-
|
|
4522
|
+
useEffect6(() => {
|
|
4528
4523
|
routesRef.current = routes;
|
|
4529
4524
|
}, [routes]);
|
|
4530
4525
|
const redirectManager = useAuthRedirectManager({
|
|
@@ -4532,18 +4527,18 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4532
4527
|
clearOnUse: true
|
|
4533
4528
|
});
|
|
4534
4529
|
const configRef = useRef6(config);
|
|
4535
|
-
|
|
4530
|
+
useEffect6(() => {
|
|
4536
4531
|
configRef.current = config;
|
|
4537
4532
|
}, [config]);
|
|
4538
4533
|
const accountsRef = useRef6(accounts);
|
|
4539
|
-
|
|
4534
|
+
useEffect6(() => {
|
|
4540
4535
|
accountsRef.current = accounts;
|
|
4541
4536
|
}, [accounts]);
|
|
4542
4537
|
const pendingManualNavRef = useRef6(false);
|
|
4543
4538
|
const [profileSettled, setProfileSettled] = useState11(false);
|
|
4544
4539
|
const hasProfile = Boolean(accounts.profile);
|
|
4545
4540
|
const profileAttemptedRef = useRef6(false);
|
|
4546
|
-
|
|
4541
|
+
useEffect6(() => {
|
|
4547
4542
|
if (!isAuthenticated) {
|
|
4548
4543
|
profileAttemptedRef.current = false;
|
|
4549
4544
|
const hasTokens = Boolean(auth.getToken() || auth.getRefreshToken());
|
|
@@ -4572,7 +4567,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4572
4567
|
}, [isAuthenticated, hasProfile]);
|
|
4573
4568
|
const isLoading = !profileSettled;
|
|
4574
4569
|
const expiredHandledRef = useRef6(false);
|
|
4575
|
-
|
|
4570
|
+
useEffect6(() => {
|
|
4576
4571
|
const unsubscribe = auth.onSessionExpired(() => {
|
|
4577
4572
|
if (expiredHandledRef.current) return;
|
|
4578
4573
|
expiredHandledRef.current = true;
|
|
@@ -4585,7 +4580,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4585
4580
|
});
|
|
4586
4581
|
return unsubscribe;
|
|
4587
4582
|
}, [router]);
|
|
4588
|
-
|
|
4583
|
+
useEffect6(() => {
|
|
4589
4584
|
if (!isAuthenticated || pendingManualNavRef.current) return;
|
|
4590
4585
|
if (pathname === routes.auth && !queryParams.get("flow")) {
|
|
4591
4586
|
const saved = redirectManager.hasRedirect() ? redirectManager.getRedirect() : null;
|
|
@@ -4737,7 +4732,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4737
4732
|
}, [router]);
|
|
4738
4733
|
const user = accounts.profile ?? null;
|
|
4739
4734
|
const isAdminUser = Boolean(user?.is_staff || user?.is_superuser);
|
|
4740
|
-
|
|
4735
|
+
useEffect6(() => {
|
|
4741
4736
|
applyRoleLogPolicy({ isAdmin: isAdminUser });
|
|
4742
4737
|
}, [isAdminUser]);
|
|
4743
4738
|
const updateProfile = useCallback11(
|
|
@@ -4805,7 +4800,7 @@ function AuthProviderRaw({ children, config, enabled = true }) {
|
|
|
4805
4800
|
return /* @__PURE__ */ jsx2(AccountsProvider, { children: /* @__PURE__ */ jsx2(AuthProviderInternal, { config, children }) });
|
|
4806
4801
|
}
|
|
4807
4802
|
__name(AuthProviderRaw, "AuthProviderRaw");
|
|
4808
|
-
var AuthProvider =
|
|
4803
|
+
var AuthProvider = memo(AuthProviderRaw);
|
|
4809
4804
|
var defaultAuthState = {
|
|
4810
4805
|
user: null,
|
|
4811
4806
|
isLoading: false,
|
|
@@ -4875,18 +4870,20 @@ var validateEmail = /* @__PURE__ */ __name((email) => {
|
|
|
4875
4870
|
}, "validateEmail");
|
|
4876
4871
|
|
|
4877
4872
|
// src/auth/utils/errors.ts
|
|
4873
|
+
var prop = /* @__PURE__ */ __name((value, key) => typeof value === "object" && value !== null ? value[key] : void 0, "prop");
|
|
4878
4874
|
var formatAuthError = /* @__PURE__ */ __name((error) => {
|
|
4879
4875
|
if (typeof error === "string") {
|
|
4880
4876
|
return error;
|
|
4881
4877
|
}
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4878
|
+
const candidates = [
|
|
4879
|
+
prop(error, "message"),
|
|
4880
|
+
prop(error, "detail"),
|
|
4881
|
+
prop(prop(prop(error, "response"), "data"), "detail")
|
|
4882
|
+
];
|
|
4883
|
+
for (const candidate of candidates) {
|
|
4884
|
+
if (typeof candidate === "string" && candidate) {
|
|
4885
|
+
return candidate;
|
|
4886
|
+
}
|
|
4890
4887
|
}
|
|
4891
4888
|
return "An unexpected error occurred";
|
|
4892
4889
|
}, "formatAuthError");
|