@djangocfg/api 2.1.46 → 2.1.48
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 +252 -230
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +12 -0
- package/dist/auth.d.ts +12 -0
- package/dist/auth.mjs +237 -215
- package/dist/auth.mjs.map +1 -1
- package/package.json +3 -3
- package/src/auth/context/AuthContext.tsx +17 -2
- package/src/auth/context/types.ts +6 -0
- package/src/auth/hooks/useAuthForm.ts +9 -6
- package/src/auth/hooks/useAuthGuard.ts +16 -6
- package/src/auth/hooks/useAutoAuth.ts +14 -6
package/dist/auth.d.cts
CHANGED
|
@@ -270,6 +270,10 @@ interface AuthContextType {
|
|
|
270
270
|
message: string;
|
|
271
271
|
}>;
|
|
272
272
|
logout: () => Promise<void>;
|
|
273
|
+
saveRedirectUrl: (url: string) => void;
|
|
274
|
+
getRedirectUrl: () => string;
|
|
275
|
+
clearRedirectUrl: () => void;
|
|
276
|
+
hasRedirectUrl: () => boolean;
|
|
273
277
|
}
|
|
274
278
|
interface AuthProviderProps {
|
|
275
279
|
children: React$1.ReactNode;
|
|
@@ -315,10 +319,13 @@ declare const useAuthRedirectManager: (options?: AuthRedirectOptions) => {
|
|
|
315
319
|
interface UseAuthGuardOptions {
|
|
316
320
|
redirectTo?: string;
|
|
317
321
|
requireAuth?: boolean;
|
|
322
|
+
/** Whether to save current URL for redirect after auth (default: true) */
|
|
323
|
+
saveRedirectUrl?: boolean;
|
|
318
324
|
}
|
|
319
325
|
declare const useAuthGuard: (options?: UseAuthGuardOptions) => {
|
|
320
326
|
isAuthenticated: boolean;
|
|
321
327
|
isLoading: boolean;
|
|
328
|
+
isRedirecting: boolean;
|
|
322
329
|
};
|
|
323
330
|
|
|
324
331
|
/**
|
|
@@ -370,12 +377,16 @@ interface UseAuthFormOptions {
|
|
|
370
377
|
redirectUrl?: string;
|
|
371
378
|
/** If true, user must accept terms before submitting. Default: false */
|
|
372
379
|
requireTermsAcceptance?: boolean;
|
|
380
|
+
/** Path to auth page for auto-OTP detection. Default: '/auth' */
|
|
381
|
+
authPath?: string;
|
|
373
382
|
}
|
|
374
383
|
declare const useAuthForm: (options: UseAuthFormOptions) => AuthFormState & AuthFormHandlers;
|
|
375
384
|
|
|
376
385
|
interface UseAutoAuthOptions {
|
|
377
386
|
onOTPDetected?: (otp: string) => void;
|
|
378
387
|
cleanupUrl?: boolean;
|
|
388
|
+
/** Paths where auto-auth should be active. Default: ['/auth'] */
|
|
389
|
+
allowedPaths?: string[];
|
|
379
390
|
}
|
|
380
391
|
/**
|
|
381
392
|
* Hook for automatic authentication from URL query parameters
|
|
@@ -384,6 +395,7 @@ interface UseAutoAuthOptions {
|
|
|
384
395
|
declare const useAutoAuth: (options?: UseAutoAuthOptions) => {
|
|
385
396
|
isReady: boolean;
|
|
386
397
|
hasOTP: boolean;
|
|
398
|
+
isAllowedPath: boolean;
|
|
387
399
|
};
|
|
388
400
|
|
|
389
401
|
interface UseGithubAuthOptions {
|
package/dist/auth.d.ts
CHANGED
|
@@ -270,6 +270,10 @@ interface AuthContextType {
|
|
|
270
270
|
message: string;
|
|
271
271
|
}>;
|
|
272
272
|
logout: () => Promise<void>;
|
|
273
|
+
saveRedirectUrl: (url: string) => void;
|
|
274
|
+
getRedirectUrl: () => string;
|
|
275
|
+
clearRedirectUrl: () => void;
|
|
276
|
+
hasRedirectUrl: () => boolean;
|
|
273
277
|
}
|
|
274
278
|
interface AuthProviderProps {
|
|
275
279
|
children: React$1.ReactNode;
|
|
@@ -315,10 +319,13 @@ declare const useAuthRedirectManager: (options?: AuthRedirectOptions) => {
|
|
|
315
319
|
interface UseAuthGuardOptions {
|
|
316
320
|
redirectTo?: string;
|
|
317
321
|
requireAuth?: boolean;
|
|
322
|
+
/** Whether to save current URL for redirect after auth (default: true) */
|
|
323
|
+
saveRedirectUrl?: boolean;
|
|
318
324
|
}
|
|
319
325
|
declare const useAuthGuard: (options?: UseAuthGuardOptions) => {
|
|
320
326
|
isAuthenticated: boolean;
|
|
321
327
|
isLoading: boolean;
|
|
328
|
+
isRedirecting: boolean;
|
|
322
329
|
};
|
|
323
330
|
|
|
324
331
|
/**
|
|
@@ -370,12 +377,16 @@ interface UseAuthFormOptions {
|
|
|
370
377
|
redirectUrl?: string;
|
|
371
378
|
/** If true, user must accept terms before submitting. Default: false */
|
|
372
379
|
requireTermsAcceptance?: boolean;
|
|
380
|
+
/** Path to auth page for auto-OTP detection. Default: '/auth' */
|
|
381
|
+
authPath?: string;
|
|
373
382
|
}
|
|
374
383
|
declare const useAuthForm: (options: UseAuthFormOptions) => AuthFormState & AuthFormHandlers;
|
|
375
384
|
|
|
376
385
|
interface UseAutoAuthOptions {
|
|
377
386
|
onOTPDetected?: (otp: string) => void;
|
|
378
387
|
cleanupUrl?: boolean;
|
|
388
|
+
/** Paths where auto-auth should be active. Default: ['/auth'] */
|
|
389
|
+
allowedPaths?: string[];
|
|
379
390
|
}
|
|
380
391
|
/**
|
|
381
392
|
* Hook for automatic authentication from URL query parameters
|
|
@@ -384,6 +395,7 @@ interface UseAutoAuthOptions {
|
|
|
384
395
|
declare const useAutoAuth: (options?: UseAutoAuthOptions) => {
|
|
385
396
|
isReady: boolean;
|
|
386
397
|
hasOTP: boolean;
|
|
398
|
+
isAllowedPath: boolean;
|
|
387
399
|
};
|
|
388
400
|
|
|
389
401
|
interface UseGithubAuthOptions {
|
package/dist/auth.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
useEffect as useEffect2,
|
|
15
15
|
useMemo,
|
|
16
16
|
useRef as useRef2,
|
|
17
|
-
useState as
|
|
17
|
+
useState as useState3
|
|
18
18
|
} from "react";
|
|
19
19
|
import { useCfgRouter, useLocalStorage, useQueryParams } from "@djangocfg/ui-nextjs/hooks";
|
|
20
20
|
|
|
@@ -3670,6 +3670,185 @@ function getCacheMetadata() {
|
|
|
3670
3670
|
}
|
|
3671
3671
|
__name(getCacheMetadata, "getCacheMetadata");
|
|
3672
3672
|
|
|
3673
|
+
// src/auth/hooks/useSessionStorage.ts
|
|
3674
|
+
import { useState } from "react";
|
|
3675
|
+
function useSessionStorage(key, initialValue) {
|
|
3676
|
+
const [storedValue, setStoredValue] = useState(() => {
|
|
3677
|
+
if (typeof window === "undefined") {
|
|
3678
|
+
return initialValue;
|
|
3679
|
+
}
|
|
3680
|
+
try {
|
|
3681
|
+
const item = window.sessionStorage.getItem(key);
|
|
3682
|
+
return item ? JSON.parse(item) : initialValue;
|
|
3683
|
+
} catch (error) {
|
|
3684
|
+
authLogger.error(`Error reading sessionStorage key "${key}":`, error);
|
|
3685
|
+
return initialValue;
|
|
3686
|
+
}
|
|
3687
|
+
});
|
|
3688
|
+
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
3689
|
+
try {
|
|
3690
|
+
const jsonString = JSON.stringify(data);
|
|
3691
|
+
const sizeInBytes = new Blob([jsonString]).size;
|
|
3692
|
+
const sizeInKB = sizeInBytes / 1024;
|
|
3693
|
+
if (sizeInKB > 1024) {
|
|
3694
|
+
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
3695
|
+
return false;
|
|
3696
|
+
}
|
|
3697
|
+
return true;
|
|
3698
|
+
} catch (error) {
|
|
3699
|
+
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
3700
|
+
return false;
|
|
3701
|
+
}
|
|
3702
|
+
}, "checkDataSize");
|
|
3703
|
+
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
3704
|
+
try {
|
|
3705
|
+
const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
3706
|
+
if (keys.length > 50) {
|
|
3707
|
+
const itemsToRemove = Math.ceil(keys.length * 0.2);
|
|
3708
|
+
for (let i = 0; i < itemsToRemove; i++) {
|
|
3709
|
+
try {
|
|
3710
|
+
const key2 = keys[i];
|
|
3711
|
+
if (key2) {
|
|
3712
|
+
sessionStorage.removeItem(key2);
|
|
3713
|
+
sessionStorage.removeItem(`${key2}_timestamp`);
|
|
3714
|
+
}
|
|
3715
|
+
} catch {
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
} catch (error) {
|
|
3720
|
+
authLogger.error("Error clearing old sessionStorage data:", error);
|
|
3721
|
+
}
|
|
3722
|
+
}, "clearOldData");
|
|
3723
|
+
const forceClearAll = /* @__PURE__ */ __name(() => {
|
|
3724
|
+
try {
|
|
3725
|
+
const keys = Object.keys(sessionStorage);
|
|
3726
|
+
for (const key2 of keys) {
|
|
3727
|
+
try {
|
|
3728
|
+
sessionStorage.removeItem(key2);
|
|
3729
|
+
} catch {
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
} catch (error) {
|
|
3733
|
+
authLogger.error("Error force clearing sessionStorage:", error);
|
|
3734
|
+
}
|
|
3735
|
+
}, "forceClearAll");
|
|
3736
|
+
const setValue = /* @__PURE__ */ __name((value) => {
|
|
3737
|
+
try {
|
|
3738
|
+
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
3739
|
+
if (!checkDataSize(valueToStore)) {
|
|
3740
|
+
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
3741
|
+
try {
|
|
3742
|
+
window.sessionStorage.removeItem(key);
|
|
3743
|
+
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
3744
|
+
} catch {
|
|
3745
|
+
}
|
|
3746
|
+
setStoredValue(valueToStore);
|
|
3747
|
+
return;
|
|
3748
|
+
}
|
|
3749
|
+
setStoredValue(valueToStore);
|
|
3750
|
+
if (typeof window !== "undefined") {
|
|
3751
|
+
try {
|
|
3752
|
+
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
3753
|
+
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3754
|
+
} catch (storageError) {
|
|
3755
|
+
if (storageError.name === "QuotaExceededError" || storageError.code === 22 || storageError.message?.includes("quota")) {
|
|
3756
|
+
authLogger.warn("sessionStorage quota exceeded, clearing old data...");
|
|
3757
|
+
clearOldData();
|
|
3758
|
+
try {
|
|
3759
|
+
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
3760
|
+
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3761
|
+
} catch (retryError) {
|
|
3762
|
+
authLogger.error(`Failed to set sessionStorage key "${key}" after clearing old data:`, retryError);
|
|
3763
|
+
try {
|
|
3764
|
+
forceClearAll();
|
|
3765
|
+
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
3766
|
+
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3767
|
+
} catch (finalError) {
|
|
3768
|
+
authLogger.error(`Failed to set sessionStorage key "${key}" after force clearing:`, finalError);
|
|
3769
|
+
setStoredValue(valueToStore);
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
} else {
|
|
3773
|
+
throw storageError;
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
} catch (error) {
|
|
3778
|
+
authLogger.error(`Error setting sessionStorage key "${key}":`, error);
|
|
3779
|
+
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
3780
|
+
setStoredValue(valueToStore);
|
|
3781
|
+
}
|
|
3782
|
+
}, "setValue");
|
|
3783
|
+
const removeValue = /* @__PURE__ */ __name(() => {
|
|
3784
|
+
try {
|
|
3785
|
+
setStoredValue(initialValue);
|
|
3786
|
+
if (typeof window !== "undefined") {
|
|
3787
|
+
try {
|
|
3788
|
+
window.sessionStorage.removeItem(key);
|
|
3789
|
+
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
3790
|
+
} catch (removeError) {
|
|
3791
|
+
if (removeError.name === "QuotaExceededError" || removeError.code === 22 || removeError.message?.includes("quota")) {
|
|
3792
|
+
authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
|
|
3793
|
+
clearOldData();
|
|
3794
|
+
try {
|
|
3795
|
+
window.sessionStorage.removeItem(key);
|
|
3796
|
+
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
3797
|
+
} catch (retryError) {
|
|
3798
|
+
authLogger.error(`Failed to remove sessionStorage key "${key}" after clearing:`, retryError);
|
|
3799
|
+
forceClearAll();
|
|
3800
|
+
}
|
|
3801
|
+
} else {
|
|
3802
|
+
throw removeError;
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
} catch (error) {
|
|
3807
|
+
authLogger.error(`Error removing sessionStorage key "${key}":`, error);
|
|
3808
|
+
}
|
|
3809
|
+
}, "removeValue");
|
|
3810
|
+
return [storedValue, setValue, removeValue];
|
|
3811
|
+
}
|
|
3812
|
+
__name(useSessionStorage, "useSessionStorage");
|
|
3813
|
+
|
|
3814
|
+
// src/auth/hooks/useAuthRedirect.ts
|
|
3815
|
+
var AUTH_REDIRECT_KEY = "auth_redirect_url";
|
|
3816
|
+
var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
|
|
3817
|
+
const { fallbackUrl = "/dashboard", clearOnUse = true } = options;
|
|
3818
|
+
const [redirectUrl, setRedirectUrl, removeRedirectUrl] = useSessionStorage(AUTH_REDIRECT_KEY, "");
|
|
3819
|
+
const setRedirect = /* @__PURE__ */ __name((url) => {
|
|
3820
|
+
setRedirectUrl(url);
|
|
3821
|
+
}, "setRedirect");
|
|
3822
|
+
const getRedirect = /* @__PURE__ */ __name(() => {
|
|
3823
|
+
return redirectUrl;
|
|
3824
|
+
}, "getRedirect");
|
|
3825
|
+
const clearRedirect = /* @__PURE__ */ __name(() => {
|
|
3826
|
+
removeRedirectUrl();
|
|
3827
|
+
}, "clearRedirect");
|
|
3828
|
+
const hasRedirect = /* @__PURE__ */ __name(() => {
|
|
3829
|
+
return redirectUrl.length > 0;
|
|
3830
|
+
}, "hasRedirect");
|
|
3831
|
+
const getFinalRedirectUrl = /* @__PURE__ */ __name(() => {
|
|
3832
|
+
return redirectUrl || fallbackUrl;
|
|
3833
|
+
}, "getFinalRedirectUrl");
|
|
3834
|
+
const useAndClearRedirect = /* @__PURE__ */ __name(() => {
|
|
3835
|
+
const finalUrl = getFinalRedirectUrl();
|
|
3836
|
+
if (clearOnUse) {
|
|
3837
|
+
clearRedirect();
|
|
3838
|
+
}
|
|
3839
|
+
return finalUrl;
|
|
3840
|
+
}, "useAndClearRedirect");
|
|
3841
|
+
return {
|
|
3842
|
+
redirectUrl,
|
|
3843
|
+
setRedirect,
|
|
3844
|
+
getRedirect,
|
|
3845
|
+
clearRedirect,
|
|
3846
|
+
hasRedirect,
|
|
3847
|
+
getFinalRedirectUrl,
|
|
3848
|
+
useAndClearRedirect
|
|
3849
|
+
};
|
|
3850
|
+
}, "useAuthRedirectManager");
|
|
3851
|
+
|
|
3673
3852
|
// src/auth/utils/analytics.ts
|
|
3674
3853
|
var AnalyticsEvent = /* @__PURE__ */ ((AnalyticsEvent2) => {
|
|
3675
3854
|
AnalyticsEvent2["AUTH_OTP_REQUEST"] = "auth_otp_request";
|
|
@@ -3713,7 +3892,7 @@ import {
|
|
|
3713
3892
|
useContext,
|
|
3714
3893
|
useEffect,
|
|
3715
3894
|
useRef,
|
|
3716
|
-
useState
|
|
3895
|
+
useState as useState2
|
|
3717
3896
|
} from "react";
|
|
3718
3897
|
|
|
3719
3898
|
// src/generated/cfg_accounts/_utils/hooks/accounts__auth.ts
|
|
@@ -3788,12 +3967,12 @@ __name(useCreateAccountsOtpVerifyCreate, "useCreateAccountsOtpVerifyCreate");
|
|
|
3788
3967
|
import { jsx } from "react/jsx-runtime";
|
|
3789
3968
|
var AccountsContext = createContext(void 0);
|
|
3790
3969
|
function AccountsProvider({ children }) {
|
|
3791
|
-
const [profile, setProfile] =
|
|
3970
|
+
const [profile, setProfile] = useState2(() => {
|
|
3792
3971
|
const cached = getCachedProfile();
|
|
3793
3972
|
return cached || void 0;
|
|
3794
3973
|
});
|
|
3795
|
-
const [isLoadingProfile, setIsLoadingProfile] =
|
|
3796
|
-
const [profileError, setProfileError] =
|
|
3974
|
+
const [isLoadingProfile, setIsLoadingProfile] = useState2(false);
|
|
3975
|
+
const [profileError, setProfileError] = useState2(null);
|
|
3797
3976
|
const profileRef = useRef(profile);
|
|
3798
3977
|
const isLoadingRef = useRef(false);
|
|
3799
3978
|
useEffect(() => {
|
|
@@ -3917,14 +4096,18 @@ var hasValidTokens = /* @__PURE__ */ __name(() => {
|
|
|
3917
4096
|
}, "hasValidTokens");
|
|
3918
4097
|
var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
3919
4098
|
const accounts = useAccountsContext();
|
|
3920
|
-
const
|
|
4099
|
+
const redirectManager = useAuthRedirectManager({
|
|
4100
|
+
fallbackUrl: config?.routes?.defaultCallback || defaultRoutes.defaultCallback,
|
|
4101
|
+
clearOnUse: true
|
|
4102
|
+
});
|
|
4103
|
+
const [isLoading, setIsLoading] = useState3(() => {
|
|
3921
4104
|
if (typeof window !== "undefined") {
|
|
3922
4105
|
const hasTokens = hasValidTokens();
|
|
3923
4106
|
return !hasTokens;
|
|
3924
4107
|
}
|
|
3925
4108
|
return true;
|
|
3926
4109
|
});
|
|
3927
|
-
const [initialized, setInitialized] =
|
|
4110
|
+
const [initialized, setInitialized] = useState3(false);
|
|
3928
4111
|
const router = useCfgRouter();
|
|
3929
4112
|
const pathname = usePathname();
|
|
3930
4113
|
const queryParams = useQueryParams();
|
|
@@ -4141,7 +4324,9 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4141
4324
|
if (result.user?.id) {
|
|
4142
4325
|
Analytics.setUser(String(result.user.id));
|
|
4143
4326
|
}
|
|
4144
|
-
const
|
|
4327
|
+
const savedRedirect = redirectManager.useAndClearRedirect();
|
|
4328
|
+
const finalRedirectUrl = redirectUrl || savedRedirect || config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
|
|
4329
|
+
authLogger.info("Redirecting after auth to:", finalRedirectUrl);
|
|
4145
4330
|
router.hardPush(finalRedirectUrl);
|
|
4146
4331
|
return {
|
|
4147
4332
|
success: true,
|
|
@@ -4247,7 +4432,12 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4247
4432
|
requestOTP,
|
|
4248
4433
|
verifyOTP,
|
|
4249
4434
|
refreshToken,
|
|
4250
|
-
logout
|
|
4435
|
+
logout,
|
|
4436
|
+
// Redirect URL methods
|
|
4437
|
+
saveRedirectUrl: redirectManager.setRedirect,
|
|
4438
|
+
getRedirectUrl: redirectManager.getFinalRedirectUrl,
|
|
4439
|
+
clearRedirectUrl: redirectManager.clearRedirect,
|
|
4440
|
+
hasRedirectUrl: redirectManager.hasRedirect
|
|
4251
4441
|
}),
|
|
4252
4442
|
[
|
|
4253
4443
|
user,
|
|
@@ -4264,7 +4454,8 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4264
4454
|
requestOTP,
|
|
4265
4455
|
verifyOTP,
|
|
4266
4456
|
refreshToken,
|
|
4267
|
-
logout
|
|
4457
|
+
logout,
|
|
4458
|
+
redirectManager
|
|
4268
4459
|
]
|
|
4269
4460
|
);
|
|
4270
4461
|
return /* @__PURE__ */ jsx2(AuthContext.Provider, { value, children });
|
|
@@ -4280,204 +4471,31 @@ var useAuth = /* @__PURE__ */ __name(() => {
|
|
|
4280
4471
|
return context;
|
|
4281
4472
|
}, "useAuth");
|
|
4282
4473
|
|
|
4283
|
-
// src/auth/hooks/useSessionStorage.ts
|
|
4284
|
-
import { useState as useState3 } from "react";
|
|
4285
|
-
function useSessionStorage(key, initialValue) {
|
|
4286
|
-
const [storedValue, setStoredValue] = useState3(() => {
|
|
4287
|
-
if (typeof window === "undefined") {
|
|
4288
|
-
return initialValue;
|
|
4289
|
-
}
|
|
4290
|
-
try {
|
|
4291
|
-
const item = window.sessionStorage.getItem(key);
|
|
4292
|
-
return item ? JSON.parse(item) : initialValue;
|
|
4293
|
-
} catch (error) {
|
|
4294
|
-
authLogger.error(`Error reading sessionStorage key "${key}":`, error);
|
|
4295
|
-
return initialValue;
|
|
4296
|
-
}
|
|
4297
|
-
});
|
|
4298
|
-
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
4299
|
-
try {
|
|
4300
|
-
const jsonString = JSON.stringify(data);
|
|
4301
|
-
const sizeInBytes = new Blob([jsonString]).size;
|
|
4302
|
-
const sizeInKB = sizeInBytes / 1024;
|
|
4303
|
-
if (sizeInKB > 1024) {
|
|
4304
|
-
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
4305
|
-
return false;
|
|
4306
|
-
}
|
|
4307
|
-
return true;
|
|
4308
|
-
} catch (error) {
|
|
4309
|
-
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
4310
|
-
return false;
|
|
4311
|
-
}
|
|
4312
|
-
}, "checkDataSize");
|
|
4313
|
-
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
4314
|
-
try {
|
|
4315
|
-
const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
4316
|
-
if (keys.length > 50) {
|
|
4317
|
-
const itemsToRemove = Math.ceil(keys.length * 0.2);
|
|
4318
|
-
for (let i = 0; i < itemsToRemove; i++) {
|
|
4319
|
-
try {
|
|
4320
|
-
const key2 = keys[i];
|
|
4321
|
-
if (key2) {
|
|
4322
|
-
sessionStorage.removeItem(key2);
|
|
4323
|
-
sessionStorage.removeItem(`${key2}_timestamp`);
|
|
4324
|
-
}
|
|
4325
|
-
} catch {
|
|
4326
|
-
}
|
|
4327
|
-
}
|
|
4328
|
-
}
|
|
4329
|
-
} catch (error) {
|
|
4330
|
-
authLogger.error("Error clearing old sessionStorage data:", error);
|
|
4331
|
-
}
|
|
4332
|
-
}, "clearOldData");
|
|
4333
|
-
const forceClearAll = /* @__PURE__ */ __name(() => {
|
|
4334
|
-
try {
|
|
4335
|
-
const keys = Object.keys(sessionStorage);
|
|
4336
|
-
for (const key2 of keys) {
|
|
4337
|
-
try {
|
|
4338
|
-
sessionStorage.removeItem(key2);
|
|
4339
|
-
} catch {
|
|
4340
|
-
}
|
|
4341
|
-
}
|
|
4342
|
-
} catch (error) {
|
|
4343
|
-
authLogger.error("Error force clearing sessionStorage:", error);
|
|
4344
|
-
}
|
|
4345
|
-
}, "forceClearAll");
|
|
4346
|
-
const setValue = /* @__PURE__ */ __name((value) => {
|
|
4347
|
-
try {
|
|
4348
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
4349
|
-
if (!checkDataSize(valueToStore)) {
|
|
4350
|
-
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
4351
|
-
try {
|
|
4352
|
-
window.sessionStorage.removeItem(key);
|
|
4353
|
-
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
4354
|
-
} catch {
|
|
4355
|
-
}
|
|
4356
|
-
setStoredValue(valueToStore);
|
|
4357
|
-
return;
|
|
4358
|
-
}
|
|
4359
|
-
setStoredValue(valueToStore);
|
|
4360
|
-
if (typeof window !== "undefined") {
|
|
4361
|
-
try {
|
|
4362
|
-
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
4363
|
-
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
4364
|
-
} catch (storageError) {
|
|
4365
|
-
if (storageError.name === "QuotaExceededError" || storageError.code === 22 || storageError.message?.includes("quota")) {
|
|
4366
|
-
authLogger.warn("sessionStorage quota exceeded, clearing old data...");
|
|
4367
|
-
clearOldData();
|
|
4368
|
-
try {
|
|
4369
|
-
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
4370
|
-
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
4371
|
-
} catch (retryError) {
|
|
4372
|
-
authLogger.error(`Failed to set sessionStorage key "${key}" after clearing old data:`, retryError);
|
|
4373
|
-
try {
|
|
4374
|
-
forceClearAll();
|
|
4375
|
-
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
4376
|
-
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
4377
|
-
} catch (finalError) {
|
|
4378
|
-
authLogger.error(`Failed to set sessionStorage key "${key}" after force clearing:`, finalError);
|
|
4379
|
-
setStoredValue(valueToStore);
|
|
4380
|
-
}
|
|
4381
|
-
}
|
|
4382
|
-
} else {
|
|
4383
|
-
throw storageError;
|
|
4384
|
-
}
|
|
4385
|
-
}
|
|
4386
|
-
}
|
|
4387
|
-
} catch (error) {
|
|
4388
|
-
authLogger.error(`Error setting sessionStorage key "${key}":`, error);
|
|
4389
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
4390
|
-
setStoredValue(valueToStore);
|
|
4391
|
-
}
|
|
4392
|
-
}, "setValue");
|
|
4393
|
-
const removeValue = /* @__PURE__ */ __name(() => {
|
|
4394
|
-
try {
|
|
4395
|
-
setStoredValue(initialValue);
|
|
4396
|
-
if (typeof window !== "undefined") {
|
|
4397
|
-
try {
|
|
4398
|
-
window.sessionStorage.removeItem(key);
|
|
4399
|
-
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
4400
|
-
} catch (removeError) {
|
|
4401
|
-
if (removeError.name === "QuotaExceededError" || removeError.code === 22 || removeError.message?.includes("quota")) {
|
|
4402
|
-
authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
|
|
4403
|
-
clearOldData();
|
|
4404
|
-
try {
|
|
4405
|
-
window.sessionStorage.removeItem(key);
|
|
4406
|
-
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
4407
|
-
} catch (retryError) {
|
|
4408
|
-
authLogger.error(`Failed to remove sessionStorage key "${key}" after clearing:`, retryError);
|
|
4409
|
-
forceClearAll();
|
|
4410
|
-
}
|
|
4411
|
-
} else {
|
|
4412
|
-
throw removeError;
|
|
4413
|
-
}
|
|
4414
|
-
}
|
|
4415
|
-
}
|
|
4416
|
-
} catch (error) {
|
|
4417
|
-
authLogger.error(`Error removing sessionStorage key "${key}":`, error);
|
|
4418
|
-
}
|
|
4419
|
-
}, "removeValue");
|
|
4420
|
-
return [storedValue, setValue, removeValue];
|
|
4421
|
-
}
|
|
4422
|
-
__name(useSessionStorage, "useSessionStorage");
|
|
4423
|
-
|
|
4424
|
-
// src/auth/hooks/useAuthRedirect.ts
|
|
4425
|
-
var AUTH_REDIRECT_KEY = "auth_redirect_url";
|
|
4426
|
-
var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
|
|
4427
|
-
const { fallbackUrl = "/dashboard", clearOnUse = true } = options;
|
|
4428
|
-
const [redirectUrl, setRedirectUrl, removeRedirectUrl] = useSessionStorage(AUTH_REDIRECT_KEY, "");
|
|
4429
|
-
const setRedirect = /* @__PURE__ */ __name((url) => {
|
|
4430
|
-
setRedirectUrl(url);
|
|
4431
|
-
}, "setRedirect");
|
|
4432
|
-
const getRedirect = /* @__PURE__ */ __name(() => {
|
|
4433
|
-
return redirectUrl;
|
|
4434
|
-
}, "getRedirect");
|
|
4435
|
-
const clearRedirect = /* @__PURE__ */ __name(() => {
|
|
4436
|
-
removeRedirectUrl();
|
|
4437
|
-
}, "clearRedirect");
|
|
4438
|
-
const hasRedirect = /* @__PURE__ */ __name(() => {
|
|
4439
|
-
return redirectUrl.length > 0;
|
|
4440
|
-
}, "hasRedirect");
|
|
4441
|
-
const getFinalRedirectUrl = /* @__PURE__ */ __name(() => {
|
|
4442
|
-
return redirectUrl || fallbackUrl;
|
|
4443
|
-
}, "getFinalRedirectUrl");
|
|
4444
|
-
const useAndClearRedirect = /* @__PURE__ */ __name(() => {
|
|
4445
|
-
const finalUrl = getFinalRedirectUrl();
|
|
4446
|
-
if (clearOnUse) {
|
|
4447
|
-
clearRedirect();
|
|
4448
|
-
}
|
|
4449
|
-
return finalUrl;
|
|
4450
|
-
}, "useAndClearRedirect");
|
|
4451
|
-
return {
|
|
4452
|
-
redirectUrl,
|
|
4453
|
-
setRedirect,
|
|
4454
|
-
getRedirect,
|
|
4455
|
-
clearRedirect,
|
|
4456
|
-
hasRedirect,
|
|
4457
|
-
getFinalRedirectUrl,
|
|
4458
|
-
useAndClearRedirect
|
|
4459
|
-
};
|
|
4460
|
-
}, "useAuthRedirectManager");
|
|
4461
|
-
|
|
4462
4474
|
// src/auth/hooks/useAuthGuard.ts
|
|
4463
|
-
import { useEffect as useEffect3 } from "react";
|
|
4475
|
+
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
4464
4476
|
import { useCfgRouter as useCfgRouter2 } from "@djangocfg/ui-nextjs/hooks";
|
|
4465
4477
|
var useAuthGuard = /* @__PURE__ */ __name((options = {}) => {
|
|
4466
|
-
const { redirectTo = "/auth", requireAuth = true } = options;
|
|
4467
|
-
const { isAuthenticated, isLoading } = useAuth();
|
|
4478
|
+
const { redirectTo = "/auth", requireAuth = true, saveRedirectUrl: shouldSaveUrl = true } = options;
|
|
4479
|
+
const { isAuthenticated, isLoading, saveRedirectUrl } = useAuth();
|
|
4468
4480
|
const router = useCfgRouter2();
|
|
4481
|
+
const [isRedirecting, setIsRedirecting] = useState4(false);
|
|
4469
4482
|
useEffect3(() => {
|
|
4470
|
-
if (!isLoading && requireAuth && !isAuthenticated) {
|
|
4483
|
+
if (!isLoading && requireAuth && !isAuthenticated && !isRedirecting) {
|
|
4484
|
+
if (shouldSaveUrl && typeof window !== "undefined") {
|
|
4485
|
+
const currentUrl = window.location.pathname + window.location.search;
|
|
4486
|
+
saveRedirectUrl(currentUrl);
|
|
4487
|
+
}
|
|
4488
|
+
setIsRedirecting(true);
|
|
4471
4489
|
router.push(redirectTo);
|
|
4472
4490
|
}
|
|
4473
|
-
}, [isAuthenticated, isLoading, router, redirectTo, requireAuth]);
|
|
4474
|
-
return { isAuthenticated, isLoading };
|
|
4491
|
+
}, [isAuthenticated, isLoading, router, redirectTo, requireAuth, isRedirecting, shouldSaveUrl, saveRedirectUrl]);
|
|
4492
|
+
return { isAuthenticated, isLoading, isRedirecting };
|
|
4475
4493
|
}, "useAuthGuard");
|
|
4476
4494
|
|
|
4477
4495
|
// src/auth/hooks/useLocalStorage.ts
|
|
4478
|
-
import { useState as
|
|
4496
|
+
import { useState as useState5 } from "react";
|
|
4479
4497
|
function useLocalStorage2(key, initialValue) {
|
|
4480
|
-
const [storedValue, setStoredValue] =
|
|
4498
|
+
const [storedValue, setStoredValue] = useState5(() => {
|
|
4481
4499
|
if (typeof window === "undefined") {
|
|
4482
4500
|
return initialValue;
|
|
4483
4501
|
}
|
|
@@ -4635,48 +4653,51 @@ function useLocalStorage2(key, initialValue) {
|
|
|
4635
4653
|
__name(useLocalStorage2, "useLocalStorage");
|
|
4636
4654
|
|
|
4637
4655
|
// src/auth/hooks/useAuthForm.ts
|
|
4638
|
-
import { useCallback as useCallback3, useEffect as useEffect6, useState as
|
|
4656
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useState as useState6 } from "react";
|
|
4639
4657
|
|
|
4640
4658
|
// src/auth/hooks/useAutoAuth.ts
|
|
4641
4659
|
import { usePathname as usePathname2 } from "next/navigation";
|
|
4642
4660
|
import { useEffect as useEffect5 } from "react";
|
|
4643
4661
|
import { useCfgRouter as useCfgRouter3, useQueryParams as useQueryParams2 } from "@djangocfg/ui-nextjs/hooks";
|
|
4644
4662
|
var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
4645
|
-
const { onOTPDetected, cleanupUrl = true } = options;
|
|
4663
|
+
const { onOTPDetected, cleanupUrl = true, allowedPaths = ["/auth"] } = options;
|
|
4646
4664
|
const queryParams = useQueryParams2();
|
|
4647
4665
|
const pathname = usePathname2();
|
|
4648
4666
|
const router = useCfgRouter3();
|
|
4649
|
-
const
|
|
4667
|
+
const isAllowedPath = allowedPaths.some((path) => pathname === path || pathname?.startsWith(path + "/"));
|
|
4650
4668
|
const hasOTP = !!queryParams.get("otp");
|
|
4669
|
+
const isReady = !!pathname && hasOTP && isAllowedPath;
|
|
4651
4670
|
useEffect5(() => {
|
|
4652
4671
|
if (!isReady) return;
|
|
4653
4672
|
const queryOtp = queryParams.get("otp");
|
|
4654
4673
|
if (queryOtp && typeof queryOtp === "string" && queryOtp.length === 6) {
|
|
4655
|
-
authLogger.info("OTP detected in URL:", queryOtp);
|
|
4674
|
+
authLogger.info("OTP detected in URL on auth page:", queryOtp);
|
|
4656
4675
|
onOTPDetected?.(queryOtp);
|
|
4657
4676
|
}
|
|
4658
4677
|
if (cleanupUrl && queryOtp) {
|
|
4659
4678
|
const cleanQuery = Object.fromEntries(queryParams.entries());
|
|
4660
4679
|
delete cleanQuery.otp;
|
|
4661
|
-
|
|
4680
|
+
const queryString = new URLSearchParams(cleanQuery).toString();
|
|
4681
|
+
router.push(queryString ? `${pathname}?${queryString}` : pathname);
|
|
4662
4682
|
}
|
|
4663
|
-
}, [pathname, queryParams, onOTPDetected, cleanupUrl, router]);
|
|
4683
|
+
}, [pathname, queryParams, onOTPDetected, cleanupUrl, router, isReady]);
|
|
4664
4684
|
return {
|
|
4665
4685
|
isReady,
|
|
4666
|
-
hasOTP
|
|
4686
|
+
hasOTP,
|
|
4687
|
+
isAllowedPath
|
|
4667
4688
|
};
|
|
4668
4689
|
}, "useAutoAuth");
|
|
4669
4690
|
|
|
4670
4691
|
// src/auth/hooks/useAuthForm.ts
|
|
4671
4692
|
var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
4672
|
-
const { onIdentifierSuccess, onOTPSuccess, onError, sourceUrl, redirectUrl, requireTermsAcceptance = false } = options;
|
|
4673
|
-
const [identifier, setIdentifier] =
|
|
4674
|
-
const [channel, setChannel] =
|
|
4675
|
-
const [otp, setOtp] =
|
|
4676
|
-
const [isLoading, setIsLoading] =
|
|
4677
|
-
const [acceptedTerms, setAcceptedTerms] =
|
|
4678
|
-
const [step, setStep] =
|
|
4679
|
-
const [error, setError] =
|
|
4693
|
+
const { onIdentifierSuccess, onOTPSuccess, onError, sourceUrl, redirectUrl, requireTermsAcceptance = false, authPath = "/auth" } = options;
|
|
4694
|
+
const [identifier, setIdentifier] = useState6("");
|
|
4695
|
+
const [channel, setChannel] = useState6("email");
|
|
4696
|
+
const [otp, setOtp] = useState6("");
|
|
4697
|
+
const [isLoading, setIsLoading] = useState6(false);
|
|
4698
|
+
const [acceptedTerms, setAcceptedTerms] = useState6(false);
|
|
4699
|
+
const [step, setStep] = useState6("identifier");
|
|
4700
|
+
const [error, setError] = useState6("");
|
|
4680
4701
|
const { requestOTP, verifyOTP, getSavedEmail, saveEmail, getSavedPhone, savePhone } = useAuth();
|
|
4681
4702
|
const [savedTermsAccepted, setSavedTermsAccepted] = useLocalStorage2("auth_terms_accepted", false);
|
|
4682
4703
|
const [savedEmail, setSavedEmail] = useLocalStorage2("auth_email", "");
|
|
@@ -4843,6 +4864,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
4843
4864
|
setSavedTermsAccepted(checked);
|
|
4844
4865
|
}, [setSavedTermsAccepted]);
|
|
4845
4866
|
useAutoAuth({
|
|
4867
|
+
allowedPaths: [authPath],
|
|
4846
4868
|
onOTPDetected: /* @__PURE__ */ __name((otp2) => {
|
|
4847
4869
|
authLogger.info("OTP detected, auto-submitting");
|
|
4848
4870
|
const savedEmail2 = getSavedEmail();
|
|
@@ -4893,7 +4915,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
4893
4915
|
}, "useAuthForm");
|
|
4894
4916
|
|
|
4895
4917
|
// src/auth/hooks/useGithubAuth.ts
|
|
4896
|
-
import { useCallback as useCallback4, useState as
|
|
4918
|
+
import { useCallback as useCallback4, useState as useState7 } from "react";
|
|
4897
4919
|
import { useCfgRouter as useCfgRouter4 } from "@djangocfg/ui-nextjs/hooks";
|
|
4898
4920
|
|
|
4899
4921
|
// src/generated/cfg_webpush/_utils/hooks/webpush__web_push.ts
|
|
@@ -4924,8 +4946,8 @@ var apiCentrifugo = new API2(apiUrl2, { storage });
|
|
|
4924
4946
|
var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
4925
4947
|
const { sourceUrl, onSuccess, onError, redirectUrl } = options;
|
|
4926
4948
|
const router = useCfgRouter4();
|
|
4927
|
-
const [isLoading, setIsLoading] =
|
|
4928
|
-
const [error, setError] =
|
|
4949
|
+
const [isLoading, setIsLoading] = useState7(false);
|
|
4950
|
+
const [error, setError] = useState7(null);
|
|
4929
4951
|
const startGithubAuth = useCallback4(async () => {
|
|
4930
4952
|
setIsLoading(true);
|
|
4931
4953
|
setError(null);
|