@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.cjs
CHANGED
|
@@ -62,7 +62,7 @@ module.exports = __toCommonJS(auth_exports);
|
|
|
62
62
|
|
|
63
63
|
// src/auth/context/AuthContext.tsx
|
|
64
64
|
var import_navigation = require("next/navigation");
|
|
65
|
-
var
|
|
65
|
+
var import_react3 = require("react");
|
|
66
66
|
var import_hooks2 = require("@djangocfg/ui-nextjs/hooks");
|
|
67
67
|
|
|
68
68
|
// src/generated/cfg_accounts/accounts__auth/client.ts
|
|
@@ -3717,6 +3717,185 @@ function getCacheMetadata() {
|
|
|
3717
3717
|
}
|
|
3718
3718
|
__name(getCacheMetadata, "getCacheMetadata");
|
|
3719
3719
|
|
|
3720
|
+
// src/auth/hooks/useSessionStorage.ts
|
|
3721
|
+
var import_react = require("react");
|
|
3722
|
+
function useSessionStorage(key, initialValue) {
|
|
3723
|
+
const [storedValue, setStoredValue] = (0, import_react.useState)(() => {
|
|
3724
|
+
if (typeof window === "undefined") {
|
|
3725
|
+
return initialValue;
|
|
3726
|
+
}
|
|
3727
|
+
try {
|
|
3728
|
+
const item = window.sessionStorage.getItem(key);
|
|
3729
|
+
return item ? JSON.parse(item) : initialValue;
|
|
3730
|
+
} catch (error) {
|
|
3731
|
+
authLogger.error(`Error reading sessionStorage key "${key}":`, error);
|
|
3732
|
+
return initialValue;
|
|
3733
|
+
}
|
|
3734
|
+
});
|
|
3735
|
+
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
3736
|
+
try {
|
|
3737
|
+
const jsonString = JSON.stringify(data);
|
|
3738
|
+
const sizeInBytes = new Blob([jsonString]).size;
|
|
3739
|
+
const sizeInKB = sizeInBytes / 1024;
|
|
3740
|
+
if (sizeInKB > 1024) {
|
|
3741
|
+
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
3742
|
+
return false;
|
|
3743
|
+
}
|
|
3744
|
+
return true;
|
|
3745
|
+
} catch (error) {
|
|
3746
|
+
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
3747
|
+
return false;
|
|
3748
|
+
}
|
|
3749
|
+
}, "checkDataSize");
|
|
3750
|
+
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
3751
|
+
try {
|
|
3752
|
+
const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
3753
|
+
if (keys.length > 50) {
|
|
3754
|
+
const itemsToRemove = Math.ceil(keys.length * 0.2);
|
|
3755
|
+
for (let i = 0; i < itemsToRemove; i++) {
|
|
3756
|
+
try {
|
|
3757
|
+
const key2 = keys[i];
|
|
3758
|
+
if (key2) {
|
|
3759
|
+
sessionStorage.removeItem(key2);
|
|
3760
|
+
sessionStorage.removeItem(`${key2}_timestamp`);
|
|
3761
|
+
}
|
|
3762
|
+
} catch {
|
|
3763
|
+
}
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
} catch (error) {
|
|
3767
|
+
authLogger.error("Error clearing old sessionStorage data:", error);
|
|
3768
|
+
}
|
|
3769
|
+
}, "clearOldData");
|
|
3770
|
+
const forceClearAll = /* @__PURE__ */ __name(() => {
|
|
3771
|
+
try {
|
|
3772
|
+
const keys = Object.keys(sessionStorage);
|
|
3773
|
+
for (const key2 of keys) {
|
|
3774
|
+
try {
|
|
3775
|
+
sessionStorage.removeItem(key2);
|
|
3776
|
+
} catch {
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
} catch (error) {
|
|
3780
|
+
authLogger.error("Error force clearing sessionStorage:", error);
|
|
3781
|
+
}
|
|
3782
|
+
}, "forceClearAll");
|
|
3783
|
+
const setValue = /* @__PURE__ */ __name((value) => {
|
|
3784
|
+
try {
|
|
3785
|
+
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
3786
|
+
if (!checkDataSize(valueToStore)) {
|
|
3787
|
+
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
3788
|
+
try {
|
|
3789
|
+
window.sessionStorage.removeItem(key);
|
|
3790
|
+
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
3791
|
+
} catch {
|
|
3792
|
+
}
|
|
3793
|
+
setStoredValue(valueToStore);
|
|
3794
|
+
return;
|
|
3795
|
+
}
|
|
3796
|
+
setStoredValue(valueToStore);
|
|
3797
|
+
if (typeof window !== "undefined") {
|
|
3798
|
+
try {
|
|
3799
|
+
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
3800
|
+
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3801
|
+
} catch (storageError) {
|
|
3802
|
+
if (storageError.name === "QuotaExceededError" || storageError.code === 22 || storageError.message?.includes("quota")) {
|
|
3803
|
+
authLogger.warn("sessionStorage quota exceeded, clearing old data...");
|
|
3804
|
+
clearOldData();
|
|
3805
|
+
try {
|
|
3806
|
+
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
3807
|
+
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3808
|
+
} catch (retryError) {
|
|
3809
|
+
authLogger.error(`Failed to set sessionStorage key "${key}" after clearing old data:`, retryError);
|
|
3810
|
+
try {
|
|
3811
|
+
forceClearAll();
|
|
3812
|
+
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
3813
|
+
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3814
|
+
} catch (finalError) {
|
|
3815
|
+
authLogger.error(`Failed to set sessionStorage key "${key}" after force clearing:`, finalError);
|
|
3816
|
+
setStoredValue(valueToStore);
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
} else {
|
|
3820
|
+
throw storageError;
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
} catch (error) {
|
|
3825
|
+
authLogger.error(`Error setting sessionStorage key "${key}":`, error);
|
|
3826
|
+
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
3827
|
+
setStoredValue(valueToStore);
|
|
3828
|
+
}
|
|
3829
|
+
}, "setValue");
|
|
3830
|
+
const removeValue = /* @__PURE__ */ __name(() => {
|
|
3831
|
+
try {
|
|
3832
|
+
setStoredValue(initialValue);
|
|
3833
|
+
if (typeof window !== "undefined") {
|
|
3834
|
+
try {
|
|
3835
|
+
window.sessionStorage.removeItem(key);
|
|
3836
|
+
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
3837
|
+
} catch (removeError) {
|
|
3838
|
+
if (removeError.name === "QuotaExceededError" || removeError.code === 22 || removeError.message?.includes("quota")) {
|
|
3839
|
+
authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
|
|
3840
|
+
clearOldData();
|
|
3841
|
+
try {
|
|
3842
|
+
window.sessionStorage.removeItem(key);
|
|
3843
|
+
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
3844
|
+
} catch (retryError) {
|
|
3845
|
+
authLogger.error(`Failed to remove sessionStorage key "${key}" after clearing:`, retryError);
|
|
3846
|
+
forceClearAll();
|
|
3847
|
+
}
|
|
3848
|
+
} else {
|
|
3849
|
+
throw removeError;
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
} catch (error) {
|
|
3854
|
+
authLogger.error(`Error removing sessionStorage key "${key}":`, error);
|
|
3855
|
+
}
|
|
3856
|
+
}, "removeValue");
|
|
3857
|
+
return [storedValue, setValue, removeValue];
|
|
3858
|
+
}
|
|
3859
|
+
__name(useSessionStorage, "useSessionStorage");
|
|
3860
|
+
|
|
3861
|
+
// src/auth/hooks/useAuthRedirect.ts
|
|
3862
|
+
var AUTH_REDIRECT_KEY = "auth_redirect_url";
|
|
3863
|
+
var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
|
|
3864
|
+
const { fallbackUrl = "/dashboard", clearOnUse = true } = options;
|
|
3865
|
+
const [redirectUrl, setRedirectUrl, removeRedirectUrl] = useSessionStorage(AUTH_REDIRECT_KEY, "");
|
|
3866
|
+
const setRedirect = /* @__PURE__ */ __name((url) => {
|
|
3867
|
+
setRedirectUrl(url);
|
|
3868
|
+
}, "setRedirect");
|
|
3869
|
+
const getRedirect = /* @__PURE__ */ __name(() => {
|
|
3870
|
+
return redirectUrl;
|
|
3871
|
+
}, "getRedirect");
|
|
3872
|
+
const clearRedirect = /* @__PURE__ */ __name(() => {
|
|
3873
|
+
removeRedirectUrl();
|
|
3874
|
+
}, "clearRedirect");
|
|
3875
|
+
const hasRedirect = /* @__PURE__ */ __name(() => {
|
|
3876
|
+
return redirectUrl.length > 0;
|
|
3877
|
+
}, "hasRedirect");
|
|
3878
|
+
const getFinalRedirectUrl = /* @__PURE__ */ __name(() => {
|
|
3879
|
+
return redirectUrl || fallbackUrl;
|
|
3880
|
+
}, "getFinalRedirectUrl");
|
|
3881
|
+
const useAndClearRedirect = /* @__PURE__ */ __name(() => {
|
|
3882
|
+
const finalUrl = getFinalRedirectUrl();
|
|
3883
|
+
if (clearOnUse) {
|
|
3884
|
+
clearRedirect();
|
|
3885
|
+
}
|
|
3886
|
+
return finalUrl;
|
|
3887
|
+
}, "useAndClearRedirect");
|
|
3888
|
+
return {
|
|
3889
|
+
redirectUrl,
|
|
3890
|
+
setRedirect,
|
|
3891
|
+
getRedirect,
|
|
3892
|
+
clearRedirect,
|
|
3893
|
+
hasRedirect,
|
|
3894
|
+
getFinalRedirectUrl,
|
|
3895
|
+
useAndClearRedirect
|
|
3896
|
+
};
|
|
3897
|
+
}, "useAuthRedirectManager");
|
|
3898
|
+
|
|
3720
3899
|
// src/auth/utils/analytics.ts
|
|
3721
3900
|
var AnalyticsEvent = /* @__PURE__ */ ((AnalyticsEvent2) => {
|
|
3722
3901
|
AnalyticsEvent2["AUTH_OTP_REQUEST"] = "auth_otp_request";
|
|
@@ -3754,7 +3933,7 @@ var Analytics = {
|
|
|
3754
3933
|
};
|
|
3755
3934
|
|
|
3756
3935
|
// src/auth/context/AccountsContext.tsx
|
|
3757
|
-
var
|
|
3936
|
+
var import_react2 = require("react");
|
|
3758
3937
|
|
|
3759
3938
|
// src/generated/cfg_accounts/_utils/hooks/accounts__auth.ts
|
|
3760
3939
|
var import_swr = require("swr");
|
|
@@ -3826,20 +4005,20 @@ __name(useCreateAccountsOtpVerifyCreate, "useCreateAccountsOtpVerifyCreate");
|
|
|
3826
4005
|
|
|
3827
4006
|
// src/auth/context/AccountsContext.tsx
|
|
3828
4007
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
3829
|
-
var AccountsContext = (0,
|
|
4008
|
+
var AccountsContext = (0, import_react2.createContext)(void 0);
|
|
3830
4009
|
function AccountsProvider({ children }) {
|
|
3831
|
-
const [profile, setProfile] = (0,
|
|
4010
|
+
const [profile, setProfile] = (0, import_react2.useState)(() => {
|
|
3832
4011
|
const cached = getCachedProfile();
|
|
3833
4012
|
return cached || void 0;
|
|
3834
4013
|
});
|
|
3835
|
-
const [isLoadingProfile, setIsLoadingProfile] = (0,
|
|
3836
|
-
const [profileError, setProfileError] = (0,
|
|
3837
|
-
const profileRef = (0,
|
|
3838
|
-
const isLoadingRef = (0,
|
|
3839
|
-
(0,
|
|
4014
|
+
const [isLoadingProfile, setIsLoadingProfile] = (0, import_react2.useState)(false);
|
|
4015
|
+
const [profileError, setProfileError] = (0, import_react2.useState)(null);
|
|
4016
|
+
const profileRef = (0, import_react2.useRef)(profile);
|
|
4017
|
+
const isLoadingRef = (0, import_react2.useRef)(false);
|
|
4018
|
+
(0, import_react2.useEffect)(() => {
|
|
3840
4019
|
profileRef.current = profile;
|
|
3841
4020
|
}, [profile]);
|
|
3842
|
-
(0,
|
|
4021
|
+
(0, import_react2.useEffect)(() => {
|
|
3843
4022
|
isLoadingRef.current = isLoadingProfile;
|
|
3844
4023
|
}, [isLoadingProfile]);
|
|
3845
4024
|
const updateMutation = useUpdateAccountsProfileUpdateUpdate();
|
|
@@ -3848,7 +4027,7 @@ function AccountsProvider({ children }) {
|
|
|
3848
4027
|
const otpRequestMutation = useCreateAccountsOtpRequestCreate();
|
|
3849
4028
|
const otpVerifyMutation = useCreateAccountsOtpVerifyCreate();
|
|
3850
4029
|
const tokenRefreshMutation = useCreateAccountsTokenRefreshCreate();
|
|
3851
|
-
const refreshProfile = (0,
|
|
4030
|
+
const refreshProfile = (0, import_react2.useCallback)(async (callerId) => {
|
|
3852
4031
|
const currentProfile = profileRef.current;
|
|
3853
4032
|
const currentLoading = isLoadingRef.current;
|
|
3854
4033
|
if (currentProfile && !currentLoading) {
|
|
@@ -3910,7 +4089,7 @@ function AccountsProvider({ children }) {
|
|
|
3910
4089
|
}
|
|
3911
4090
|
return result;
|
|
3912
4091
|
}, "refreshToken");
|
|
3913
|
-
const logout = (0,
|
|
4092
|
+
const logout = (0, import_react2.useCallback)(() => {
|
|
3914
4093
|
api.clearTokens();
|
|
3915
4094
|
setProfile(void 0);
|
|
3916
4095
|
setProfileError(null);
|
|
@@ -3933,7 +4112,7 @@ function AccountsProvider({ children }) {
|
|
|
3933
4112
|
}
|
|
3934
4113
|
__name(AccountsProvider, "AccountsProvider");
|
|
3935
4114
|
function useAccountsContext() {
|
|
3936
|
-
const context = (0,
|
|
4115
|
+
const context = (0, import_react2.useContext)(AccountsContext);
|
|
3937
4116
|
if (!context) {
|
|
3938
4117
|
throw new Error("useAccountsContext must be used within AccountsProvider");
|
|
3939
4118
|
}
|
|
@@ -3948,7 +4127,7 @@ var defaultRoutes = {
|
|
|
3948
4127
|
defaultCallback: "/dashboard",
|
|
3949
4128
|
defaultAuthCallback: "/auth"
|
|
3950
4129
|
};
|
|
3951
|
-
var AuthContext = (0,
|
|
4130
|
+
var AuthContext = (0, import_react3.createContext)(void 0);
|
|
3952
4131
|
var EMAIL_STORAGE_KEY = "auth_email";
|
|
3953
4132
|
var PHONE_STORAGE_KEY = "auth_phone";
|
|
3954
4133
|
var hasValidTokens = /* @__PURE__ */ __name(() => {
|
|
@@ -3957,37 +4136,41 @@ var hasValidTokens = /* @__PURE__ */ __name(() => {
|
|
|
3957
4136
|
}, "hasValidTokens");
|
|
3958
4137
|
var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
3959
4138
|
const accounts = useAccountsContext();
|
|
3960
|
-
const
|
|
4139
|
+
const redirectManager = useAuthRedirectManager({
|
|
4140
|
+
fallbackUrl: config?.routes?.defaultCallback || defaultRoutes.defaultCallback,
|
|
4141
|
+
clearOnUse: true
|
|
4142
|
+
});
|
|
4143
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(() => {
|
|
3961
4144
|
if (typeof window !== "undefined") {
|
|
3962
4145
|
const hasTokens = hasValidTokens();
|
|
3963
4146
|
return !hasTokens;
|
|
3964
4147
|
}
|
|
3965
4148
|
return true;
|
|
3966
4149
|
});
|
|
3967
|
-
const [initialized, setInitialized] = (0,
|
|
4150
|
+
const [initialized, setInitialized] = (0, import_react3.useState)(false);
|
|
3968
4151
|
const router = (0, import_hooks2.useCfgRouter)();
|
|
3969
4152
|
const pathname = (0, import_navigation.usePathname)();
|
|
3970
4153
|
const queryParams = (0, import_hooks2.useQueryParams)();
|
|
3971
4154
|
const [storedEmail, setStoredEmail, clearStoredEmail] = (0, import_hooks2.useLocalStorage)(EMAIL_STORAGE_KEY, null);
|
|
3972
4155
|
const [storedPhone, setStoredPhone, clearStoredPhone] = (0, import_hooks2.useLocalStorage)(PHONE_STORAGE_KEY, null);
|
|
3973
4156
|
const user = accounts.profile;
|
|
3974
|
-
const userRef = (0,
|
|
3975
|
-
const configRef = (0,
|
|
3976
|
-
const isLoadingProfileRef = (0,
|
|
3977
|
-
(0,
|
|
4157
|
+
const userRef = (0, import_react3.useRef)(user);
|
|
4158
|
+
const configRef = (0, import_react3.useRef)(config);
|
|
4159
|
+
const isLoadingProfileRef = (0, import_react3.useRef)(false);
|
|
4160
|
+
(0, import_react3.useEffect)(() => {
|
|
3978
4161
|
userRef.current = user;
|
|
3979
4162
|
}, [user]);
|
|
3980
|
-
(0,
|
|
4163
|
+
(0, import_react3.useEffect)(() => {
|
|
3981
4164
|
configRef.current = config;
|
|
3982
4165
|
}, [config]);
|
|
3983
|
-
const clearAuthState = (0,
|
|
4166
|
+
const clearAuthState = (0, import_react3.useCallback)((caller) => {
|
|
3984
4167
|
authLogger.info("clearAuthState >> caller", caller);
|
|
3985
4168
|
api.clearTokens();
|
|
3986
4169
|
clearProfileCache();
|
|
3987
4170
|
setInitialized(true);
|
|
3988
4171
|
setIsLoading(false);
|
|
3989
4172
|
}, []);
|
|
3990
|
-
const handleGlobalAuthError = (0,
|
|
4173
|
+
const handleGlobalAuthError = (0, import_react3.useCallback)((error, context = "API Request") => {
|
|
3991
4174
|
if (error?.success === false) {
|
|
3992
4175
|
authLogger.warn(`Error detected in ${context}, clearing tokens`);
|
|
3993
4176
|
clearAuthState(`globalAuthError:${context}`);
|
|
@@ -3995,7 +4178,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
3995
4178
|
}
|
|
3996
4179
|
return false;
|
|
3997
4180
|
}, [clearAuthState]);
|
|
3998
|
-
const loadCurrentProfile = (0,
|
|
4181
|
+
const loadCurrentProfile = (0, import_react3.useCallback)(async (callerId) => {
|
|
3999
4182
|
const finalCallerId = callerId || "AuthContext.loadCurrentProfile";
|
|
4000
4183
|
if (isLoadingProfileRef.current) {
|
|
4001
4184
|
authLogger.debug(`Profile loading already in progress, skipping duplicate call from: ${finalCallerId}`);
|
|
@@ -4031,7 +4214,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4031
4214
|
isLoadingProfileRef.current = false;
|
|
4032
4215
|
}
|
|
4033
4216
|
}, [clearAuthState, handleGlobalAuthError, accounts]);
|
|
4034
|
-
(0,
|
|
4217
|
+
(0, import_react3.useEffect)(() => {
|
|
4035
4218
|
if (initialized) return;
|
|
4036
4219
|
const initializeAuth = /* @__PURE__ */ __name(async () => {
|
|
4037
4220
|
authLogger.info("Initializing auth...");
|
|
@@ -4081,7 +4264,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4081
4264
|
}, "initializeAuth");
|
|
4082
4265
|
initializeAuth();
|
|
4083
4266
|
}, [initialized]);
|
|
4084
|
-
(0,
|
|
4267
|
+
(0, import_react3.useEffect)(() => {
|
|
4085
4268
|
if (!initialized) return;
|
|
4086
4269
|
const isAuthenticated = api.isAuthenticated();
|
|
4087
4270
|
const authRoute = config?.routes?.auth || defaultRoutes.auth;
|
|
@@ -4092,15 +4275,15 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4092
4275
|
router.push(callbackUrl);
|
|
4093
4276
|
}
|
|
4094
4277
|
}, [initialized, pathname, queryParams, config?.routes]);
|
|
4095
|
-
const pushToDefaultCallbackUrl = (0,
|
|
4278
|
+
const pushToDefaultCallbackUrl = (0, import_react3.useCallback)(() => {
|
|
4096
4279
|
const callbackUrl = config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
|
|
4097
4280
|
router.push(callbackUrl);
|
|
4098
4281
|
}, [config?.routes, router]);
|
|
4099
|
-
const pushToDefaultAuthCallbackUrl = (0,
|
|
4282
|
+
const pushToDefaultAuthCallbackUrl = (0, import_react3.useCallback)(() => {
|
|
4100
4283
|
const authCallbackUrl = config?.routes?.defaultAuthCallback || defaultRoutes.defaultAuthCallback;
|
|
4101
4284
|
router.push(authCallbackUrl);
|
|
4102
4285
|
}, [config?.routes, router]);
|
|
4103
|
-
const checkAuthAndRedirect = (0,
|
|
4286
|
+
const checkAuthAndRedirect = (0, import_react3.useCallback)(async () => {
|
|
4104
4287
|
try {
|
|
4105
4288
|
setIsLoading(true);
|
|
4106
4289
|
const isAuthenticated = api.isAuthenticated();
|
|
@@ -4122,7 +4305,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4122
4305
|
setIsLoading(false);
|
|
4123
4306
|
}
|
|
4124
4307
|
}, [loadCurrentProfile, clearAuthState, pushToDefaultCallbackUrl, pushToDefaultAuthCallbackUrl, handleGlobalAuthError]);
|
|
4125
|
-
const requestOTP = (0,
|
|
4308
|
+
const requestOTP = (0, import_react3.useCallback)(
|
|
4126
4309
|
async (identifier, channel, sourceUrl) => {
|
|
4127
4310
|
api.clearTokens();
|
|
4128
4311
|
try {
|
|
@@ -4150,7 +4333,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4150
4333
|
},
|
|
4151
4334
|
[accounts]
|
|
4152
4335
|
);
|
|
4153
|
-
const verifyOTP = (0,
|
|
4336
|
+
const verifyOTP = (0, import_react3.useCallback)(
|
|
4154
4337
|
async (identifier, otpCode, channel, sourceUrl, redirectUrl) => {
|
|
4155
4338
|
try {
|
|
4156
4339
|
const channelValue = channel === "phone" ? enums_exports.OTPVerifyRequestChannel.PHONE : enums_exports.OTPVerifyRequestChannel.EMAIL;
|
|
@@ -4181,7 +4364,9 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4181
4364
|
if (result.user?.id) {
|
|
4182
4365
|
Analytics.setUser(String(result.user.id));
|
|
4183
4366
|
}
|
|
4184
|
-
const
|
|
4367
|
+
const savedRedirect = redirectManager.useAndClearRedirect();
|
|
4368
|
+
const finalRedirectUrl = redirectUrl || savedRedirect || config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
|
|
4369
|
+
authLogger.info("Redirecting after auth to:", finalRedirectUrl);
|
|
4185
4370
|
router.hardPush(finalRedirectUrl);
|
|
4186
4371
|
return {
|
|
4187
4372
|
success: true,
|
|
@@ -4202,7 +4387,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4202
4387
|
},
|
|
4203
4388
|
[setStoredEmail, setStoredPhone, clearStoredEmail, clearStoredPhone, config?.routes?.defaultCallback, accounts, router]
|
|
4204
4389
|
);
|
|
4205
|
-
const refreshToken = (0,
|
|
4390
|
+
const refreshToken = (0, import_react3.useCallback)(async () => {
|
|
4206
4391
|
try {
|
|
4207
4392
|
const refreshTokenValue = api.getRefreshToken();
|
|
4208
4393
|
if (!refreshTokenValue) {
|
|
@@ -4235,7 +4420,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4235
4420
|
};
|
|
4236
4421
|
}
|
|
4237
4422
|
}, [clearAuthState, accounts]);
|
|
4238
|
-
const logout = (0,
|
|
4423
|
+
const logout = (0, import_react3.useCallback)(async () => {
|
|
4239
4424
|
const performLogout = /* @__PURE__ */ __name(() => {
|
|
4240
4425
|
Analytics.event("auth_logout" /* AUTH_LOGOUT */, {
|
|
4241
4426
|
category: "auth" /* AUTH */
|
|
@@ -4264,10 +4449,10 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4264
4449
|
}
|
|
4265
4450
|
}
|
|
4266
4451
|
}, [accounts, config?.routes?.defaultAuthCallback, router]);
|
|
4267
|
-
const isAdminUser = (0,
|
|
4452
|
+
const isAdminUser = (0, import_react3.useMemo)(() => {
|
|
4268
4453
|
return Boolean(user?.is_staff || user?.is_superuser);
|
|
4269
4454
|
}, [user]);
|
|
4270
|
-
const value = (0,
|
|
4455
|
+
const value = (0, import_react3.useMemo)(
|
|
4271
4456
|
() => ({
|
|
4272
4457
|
user,
|
|
4273
4458
|
isLoading,
|
|
@@ -4287,7 +4472,12 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4287
4472
|
requestOTP,
|
|
4288
4473
|
verifyOTP,
|
|
4289
4474
|
refreshToken,
|
|
4290
|
-
logout
|
|
4475
|
+
logout,
|
|
4476
|
+
// Redirect URL methods
|
|
4477
|
+
saveRedirectUrl: redirectManager.setRedirect,
|
|
4478
|
+
getRedirectUrl: redirectManager.getFinalRedirectUrl,
|
|
4479
|
+
clearRedirectUrl: redirectManager.clearRedirect,
|
|
4480
|
+
hasRedirectUrl: redirectManager.hasRedirect
|
|
4291
4481
|
}),
|
|
4292
4482
|
[
|
|
4293
4483
|
user,
|
|
@@ -4304,7 +4494,8 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4304
4494
|
requestOTP,
|
|
4305
4495
|
verifyOTP,
|
|
4306
4496
|
refreshToken,
|
|
4307
|
-
logout
|
|
4497
|
+
logout,
|
|
4498
|
+
redirectManager
|
|
4308
4499
|
]
|
|
4309
4500
|
);
|
|
4310
4501
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthContext.Provider, { value, children });
|
|
@@ -4313,205 +4504,32 @@ var AuthProvider = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4313
4504
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AccountsProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthProviderInternal, { config, children }) });
|
|
4314
4505
|
}, "AuthProvider");
|
|
4315
4506
|
var useAuth = /* @__PURE__ */ __name(() => {
|
|
4316
|
-
const context = (0,
|
|
4507
|
+
const context = (0, import_react3.useContext)(AuthContext);
|
|
4317
4508
|
if (context === void 0) {
|
|
4318
4509
|
throw new Error("useAuth must be used within an AuthProvider");
|
|
4319
4510
|
}
|
|
4320
4511
|
return context;
|
|
4321
4512
|
}, "useAuth");
|
|
4322
4513
|
|
|
4323
|
-
// src/auth/hooks/useSessionStorage.ts
|
|
4324
|
-
var import_react3 = require("react");
|
|
4325
|
-
function useSessionStorage(key, initialValue) {
|
|
4326
|
-
const [storedValue, setStoredValue] = (0, import_react3.useState)(() => {
|
|
4327
|
-
if (typeof window === "undefined") {
|
|
4328
|
-
return initialValue;
|
|
4329
|
-
}
|
|
4330
|
-
try {
|
|
4331
|
-
const item = window.sessionStorage.getItem(key);
|
|
4332
|
-
return item ? JSON.parse(item) : initialValue;
|
|
4333
|
-
} catch (error) {
|
|
4334
|
-
authLogger.error(`Error reading sessionStorage key "${key}":`, error);
|
|
4335
|
-
return initialValue;
|
|
4336
|
-
}
|
|
4337
|
-
});
|
|
4338
|
-
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
4339
|
-
try {
|
|
4340
|
-
const jsonString = JSON.stringify(data);
|
|
4341
|
-
const sizeInBytes = new Blob([jsonString]).size;
|
|
4342
|
-
const sizeInKB = sizeInBytes / 1024;
|
|
4343
|
-
if (sizeInKB > 1024) {
|
|
4344
|
-
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
4345
|
-
return false;
|
|
4346
|
-
}
|
|
4347
|
-
return true;
|
|
4348
|
-
} catch (error) {
|
|
4349
|
-
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
4350
|
-
return false;
|
|
4351
|
-
}
|
|
4352
|
-
}, "checkDataSize");
|
|
4353
|
-
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
4354
|
-
try {
|
|
4355
|
-
const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
4356
|
-
if (keys.length > 50) {
|
|
4357
|
-
const itemsToRemove = Math.ceil(keys.length * 0.2);
|
|
4358
|
-
for (let i = 0; i < itemsToRemove; i++) {
|
|
4359
|
-
try {
|
|
4360
|
-
const key2 = keys[i];
|
|
4361
|
-
if (key2) {
|
|
4362
|
-
sessionStorage.removeItem(key2);
|
|
4363
|
-
sessionStorage.removeItem(`${key2}_timestamp`);
|
|
4364
|
-
}
|
|
4365
|
-
} catch {
|
|
4366
|
-
}
|
|
4367
|
-
}
|
|
4368
|
-
}
|
|
4369
|
-
} catch (error) {
|
|
4370
|
-
authLogger.error("Error clearing old sessionStorage data:", error);
|
|
4371
|
-
}
|
|
4372
|
-
}, "clearOldData");
|
|
4373
|
-
const forceClearAll = /* @__PURE__ */ __name(() => {
|
|
4374
|
-
try {
|
|
4375
|
-
const keys = Object.keys(sessionStorage);
|
|
4376
|
-
for (const key2 of keys) {
|
|
4377
|
-
try {
|
|
4378
|
-
sessionStorage.removeItem(key2);
|
|
4379
|
-
} catch {
|
|
4380
|
-
}
|
|
4381
|
-
}
|
|
4382
|
-
} catch (error) {
|
|
4383
|
-
authLogger.error("Error force clearing sessionStorage:", error);
|
|
4384
|
-
}
|
|
4385
|
-
}, "forceClearAll");
|
|
4386
|
-
const setValue = /* @__PURE__ */ __name((value) => {
|
|
4387
|
-
try {
|
|
4388
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
4389
|
-
if (!checkDataSize(valueToStore)) {
|
|
4390
|
-
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
4391
|
-
try {
|
|
4392
|
-
window.sessionStorage.removeItem(key);
|
|
4393
|
-
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
4394
|
-
} catch {
|
|
4395
|
-
}
|
|
4396
|
-
setStoredValue(valueToStore);
|
|
4397
|
-
return;
|
|
4398
|
-
}
|
|
4399
|
-
setStoredValue(valueToStore);
|
|
4400
|
-
if (typeof window !== "undefined") {
|
|
4401
|
-
try {
|
|
4402
|
-
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
4403
|
-
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
4404
|
-
} catch (storageError) {
|
|
4405
|
-
if (storageError.name === "QuotaExceededError" || storageError.code === 22 || storageError.message?.includes("quota")) {
|
|
4406
|
-
authLogger.warn("sessionStorage quota exceeded, clearing old data...");
|
|
4407
|
-
clearOldData();
|
|
4408
|
-
try {
|
|
4409
|
-
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
4410
|
-
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
4411
|
-
} catch (retryError) {
|
|
4412
|
-
authLogger.error(`Failed to set sessionStorage key "${key}" after clearing old data:`, retryError);
|
|
4413
|
-
try {
|
|
4414
|
-
forceClearAll();
|
|
4415
|
-
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
4416
|
-
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
4417
|
-
} catch (finalError) {
|
|
4418
|
-
authLogger.error(`Failed to set sessionStorage key "${key}" after force clearing:`, finalError);
|
|
4419
|
-
setStoredValue(valueToStore);
|
|
4420
|
-
}
|
|
4421
|
-
}
|
|
4422
|
-
} else {
|
|
4423
|
-
throw storageError;
|
|
4424
|
-
}
|
|
4425
|
-
}
|
|
4426
|
-
}
|
|
4427
|
-
} catch (error) {
|
|
4428
|
-
authLogger.error(`Error setting sessionStorage key "${key}":`, error);
|
|
4429
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
4430
|
-
setStoredValue(valueToStore);
|
|
4431
|
-
}
|
|
4432
|
-
}, "setValue");
|
|
4433
|
-
const removeValue = /* @__PURE__ */ __name(() => {
|
|
4434
|
-
try {
|
|
4435
|
-
setStoredValue(initialValue);
|
|
4436
|
-
if (typeof window !== "undefined") {
|
|
4437
|
-
try {
|
|
4438
|
-
window.sessionStorage.removeItem(key);
|
|
4439
|
-
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
4440
|
-
} catch (removeError) {
|
|
4441
|
-
if (removeError.name === "QuotaExceededError" || removeError.code === 22 || removeError.message?.includes("quota")) {
|
|
4442
|
-
authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
|
|
4443
|
-
clearOldData();
|
|
4444
|
-
try {
|
|
4445
|
-
window.sessionStorage.removeItem(key);
|
|
4446
|
-
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
4447
|
-
} catch (retryError) {
|
|
4448
|
-
authLogger.error(`Failed to remove sessionStorage key "${key}" after clearing:`, retryError);
|
|
4449
|
-
forceClearAll();
|
|
4450
|
-
}
|
|
4451
|
-
} else {
|
|
4452
|
-
throw removeError;
|
|
4453
|
-
}
|
|
4454
|
-
}
|
|
4455
|
-
}
|
|
4456
|
-
} catch (error) {
|
|
4457
|
-
authLogger.error(`Error removing sessionStorage key "${key}":`, error);
|
|
4458
|
-
}
|
|
4459
|
-
}, "removeValue");
|
|
4460
|
-
return [storedValue, setValue, removeValue];
|
|
4461
|
-
}
|
|
4462
|
-
__name(useSessionStorage, "useSessionStorage");
|
|
4463
|
-
|
|
4464
|
-
// src/auth/hooks/useAuthRedirect.ts
|
|
4465
|
-
var AUTH_REDIRECT_KEY = "auth_redirect_url";
|
|
4466
|
-
var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
|
|
4467
|
-
const { fallbackUrl = "/dashboard", clearOnUse = true } = options;
|
|
4468
|
-
const [redirectUrl, setRedirectUrl, removeRedirectUrl] = useSessionStorage(AUTH_REDIRECT_KEY, "");
|
|
4469
|
-
const setRedirect = /* @__PURE__ */ __name((url) => {
|
|
4470
|
-
setRedirectUrl(url);
|
|
4471
|
-
}, "setRedirect");
|
|
4472
|
-
const getRedirect = /* @__PURE__ */ __name(() => {
|
|
4473
|
-
return redirectUrl;
|
|
4474
|
-
}, "getRedirect");
|
|
4475
|
-
const clearRedirect = /* @__PURE__ */ __name(() => {
|
|
4476
|
-
removeRedirectUrl();
|
|
4477
|
-
}, "clearRedirect");
|
|
4478
|
-
const hasRedirect = /* @__PURE__ */ __name(() => {
|
|
4479
|
-
return redirectUrl.length > 0;
|
|
4480
|
-
}, "hasRedirect");
|
|
4481
|
-
const getFinalRedirectUrl = /* @__PURE__ */ __name(() => {
|
|
4482
|
-
return redirectUrl || fallbackUrl;
|
|
4483
|
-
}, "getFinalRedirectUrl");
|
|
4484
|
-
const useAndClearRedirect = /* @__PURE__ */ __name(() => {
|
|
4485
|
-
const finalUrl = getFinalRedirectUrl();
|
|
4486
|
-
if (clearOnUse) {
|
|
4487
|
-
clearRedirect();
|
|
4488
|
-
}
|
|
4489
|
-
return finalUrl;
|
|
4490
|
-
}, "useAndClearRedirect");
|
|
4491
|
-
return {
|
|
4492
|
-
redirectUrl,
|
|
4493
|
-
setRedirect,
|
|
4494
|
-
getRedirect,
|
|
4495
|
-
clearRedirect,
|
|
4496
|
-
hasRedirect,
|
|
4497
|
-
getFinalRedirectUrl,
|
|
4498
|
-
useAndClearRedirect
|
|
4499
|
-
};
|
|
4500
|
-
}, "useAuthRedirectManager");
|
|
4501
|
-
|
|
4502
4514
|
// src/auth/hooks/useAuthGuard.ts
|
|
4503
4515
|
var import_react4 = require("react");
|
|
4504
4516
|
var import_hooks3 = require("@djangocfg/ui-nextjs/hooks");
|
|
4505
4517
|
var useAuthGuard = /* @__PURE__ */ __name((options = {}) => {
|
|
4506
|
-
const { redirectTo = "/auth", requireAuth = true } = options;
|
|
4507
|
-
const { isAuthenticated, isLoading } = useAuth();
|
|
4518
|
+
const { redirectTo = "/auth", requireAuth = true, saveRedirectUrl: shouldSaveUrl = true } = options;
|
|
4519
|
+
const { isAuthenticated, isLoading, saveRedirectUrl } = useAuth();
|
|
4508
4520
|
const router = (0, import_hooks3.useCfgRouter)();
|
|
4521
|
+
const [isRedirecting, setIsRedirecting] = (0, import_react4.useState)(false);
|
|
4509
4522
|
(0, import_react4.useEffect)(() => {
|
|
4510
|
-
if (!isLoading && requireAuth && !isAuthenticated) {
|
|
4523
|
+
if (!isLoading && requireAuth && !isAuthenticated && !isRedirecting) {
|
|
4524
|
+
if (shouldSaveUrl && typeof window !== "undefined") {
|
|
4525
|
+
const currentUrl = window.location.pathname + window.location.search;
|
|
4526
|
+
saveRedirectUrl(currentUrl);
|
|
4527
|
+
}
|
|
4528
|
+
setIsRedirecting(true);
|
|
4511
4529
|
router.push(redirectTo);
|
|
4512
4530
|
}
|
|
4513
|
-
}, [isAuthenticated, isLoading, router, redirectTo, requireAuth]);
|
|
4514
|
-
return { isAuthenticated, isLoading };
|
|
4531
|
+
}, [isAuthenticated, isLoading, router, redirectTo, requireAuth, isRedirecting, shouldSaveUrl, saveRedirectUrl]);
|
|
4532
|
+
return { isAuthenticated, isLoading, isRedirecting };
|
|
4515
4533
|
}, "useAuthGuard");
|
|
4516
4534
|
|
|
4517
4535
|
// src/auth/hooks/useLocalStorage.ts
|
|
@@ -4682,34 +4700,37 @@ var import_navigation2 = require("next/navigation");
|
|
|
4682
4700
|
var import_react6 = require("react");
|
|
4683
4701
|
var import_hooks4 = require("@djangocfg/ui-nextjs/hooks");
|
|
4684
4702
|
var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
4685
|
-
const { onOTPDetected, cleanupUrl = true } = options;
|
|
4703
|
+
const { onOTPDetected, cleanupUrl = true, allowedPaths = ["/auth"] } = options;
|
|
4686
4704
|
const queryParams = (0, import_hooks4.useQueryParams)();
|
|
4687
4705
|
const pathname = (0, import_navigation2.usePathname)();
|
|
4688
4706
|
const router = (0, import_hooks4.useCfgRouter)();
|
|
4689
|
-
const
|
|
4707
|
+
const isAllowedPath = allowedPaths.some((path) => pathname === path || pathname?.startsWith(path + "/"));
|
|
4690
4708
|
const hasOTP = !!queryParams.get("otp");
|
|
4709
|
+
const isReady = !!pathname && hasOTP && isAllowedPath;
|
|
4691
4710
|
(0, import_react6.useEffect)(() => {
|
|
4692
4711
|
if (!isReady) return;
|
|
4693
4712
|
const queryOtp = queryParams.get("otp");
|
|
4694
4713
|
if (queryOtp && typeof queryOtp === "string" && queryOtp.length === 6) {
|
|
4695
|
-
authLogger.info("OTP detected in URL:", queryOtp);
|
|
4714
|
+
authLogger.info("OTP detected in URL on auth page:", queryOtp);
|
|
4696
4715
|
onOTPDetected?.(queryOtp);
|
|
4697
4716
|
}
|
|
4698
4717
|
if (cleanupUrl && queryOtp) {
|
|
4699
4718
|
const cleanQuery = Object.fromEntries(queryParams.entries());
|
|
4700
4719
|
delete cleanQuery.otp;
|
|
4701
|
-
|
|
4720
|
+
const queryString = new URLSearchParams(cleanQuery).toString();
|
|
4721
|
+
router.push(queryString ? `${pathname}?${queryString}` : pathname);
|
|
4702
4722
|
}
|
|
4703
|
-
}, [pathname, queryParams, onOTPDetected, cleanupUrl, router]);
|
|
4723
|
+
}, [pathname, queryParams, onOTPDetected, cleanupUrl, router, isReady]);
|
|
4704
4724
|
return {
|
|
4705
4725
|
isReady,
|
|
4706
|
-
hasOTP
|
|
4726
|
+
hasOTP,
|
|
4727
|
+
isAllowedPath
|
|
4707
4728
|
};
|
|
4708
4729
|
}, "useAutoAuth");
|
|
4709
4730
|
|
|
4710
4731
|
// src/auth/hooks/useAuthForm.ts
|
|
4711
4732
|
var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
4712
|
-
const { onIdentifierSuccess, onOTPSuccess, onError, sourceUrl, redirectUrl, requireTermsAcceptance = false } = options;
|
|
4733
|
+
const { onIdentifierSuccess, onOTPSuccess, onError, sourceUrl, redirectUrl, requireTermsAcceptance = false, authPath = "/auth" } = options;
|
|
4713
4734
|
const [identifier, setIdentifier] = (0, import_react7.useState)("");
|
|
4714
4735
|
const [channel, setChannel] = (0, import_react7.useState)("email");
|
|
4715
4736
|
const [otp, setOtp] = (0, import_react7.useState)("");
|
|
@@ -4883,6 +4904,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
4883
4904
|
setSavedTermsAccepted(checked);
|
|
4884
4905
|
}, [setSavedTermsAccepted]);
|
|
4885
4906
|
useAutoAuth({
|
|
4907
|
+
allowedPaths: [authPath],
|
|
4886
4908
|
onOTPDetected: /* @__PURE__ */ __name((otp2) => {
|
|
4887
4909
|
authLogger.info("OTP detected, auto-submitting");
|
|
4888
4910
|
const savedEmail2 = getSavedEmail();
|