@djangocfg/api 2.1.86 → 2.1.88
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 +1948 -4
- package/dist/auth-server.cjs.map +1 -1
- package/dist/auth-server.d.cts +35 -1
- package/dist/auth-server.d.ts +35 -1
- package/dist/auth-server.mjs +1938 -4
- package/dist/auth-server.mjs.map +1 -1
- package/dist/auth.cjs +237 -112
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +17 -1
- package/dist/auth.d.ts +17 -1
- package/dist/auth.mjs +200 -75
- package/dist/auth.mjs.map +1 -1
- package/package.json +3 -3
- package/src/auth/context/AuthContext.tsx +56 -10
- package/src/auth/hooks/index.ts +3 -0
- package/src/auth/hooks/useProfileCache.ts +1 -1
- package/src/auth/hooks/useTokenRefresh.ts +167 -0
- package/src/auth/middlewares/index.ts +8 -1
- package/src/auth/middlewares/tokenRefresh.ts +169 -0
package/dist/auth.mjs
CHANGED
|
@@ -9,11 +9,11 @@ var __export = (target, all) => {
|
|
|
9
9
|
import { usePathname } from "next/navigation";
|
|
10
10
|
import {
|
|
11
11
|
createContext as createContext2,
|
|
12
|
-
useCallback as
|
|
12
|
+
useCallback as useCallback3,
|
|
13
13
|
useContext as useContext2,
|
|
14
|
-
useEffect as
|
|
14
|
+
useEffect as useEffect3,
|
|
15
15
|
useMemo,
|
|
16
|
-
useRef as
|
|
16
|
+
useRef as useRef3,
|
|
17
17
|
useState as useState3
|
|
18
18
|
} from "react";
|
|
19
19
|
import { useCfgRouter, useLocalStorage, useQueryParams } from "@djangocfg/ui-nextjs/hooks";
|
|
@@ -3618,7 +3618,7 @@ __name(useBase64, "useBase64");
|
|
|
3618
3618
|
// src/auth/hooks/useProfileCache.ts
|
|
3619
3619
|
var CACHE_KEY = "user_profile_cache";
|
|
3620
3620
|
var CACHE_VERSION = 1;
|
|
3621
|
-
var DEFAULT_TTL =
|
|
3621
|
+
var DEFAULT_TTL = 144e5;
|
|
3622
3622
|
function getCachedProfile() {
|
|
3623
3623
|
try {
|
|
3624
3624
|
if (typeof window === "undefined") return null;
|
|
@@ -3904,6 +3904,106 @@ var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3904
3904
|
};
|
|
3905
3905
|
}, "useAuthRedirectManager");
|
|
3906
3906
|
|
|
3907
|
+
// src/auth/hooks/useTokenRefresh.ts
|
|
3908
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
3909
|
+
var TOKEN_REFRESH_THRESHOLD_MS = 10 * 60 * 1e3;
|
|
3910
|
+
var CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
3911
|
+
function getTokenExpiry(token) {
|
|
3912
|
+
try {
|
|
3913
|
+
const payload = JSON.parse(atob(token.split(".")[1]));
|
|
3914
|
+
return payload.exp * 1e3;
|
|
3915
|
+
} catch {
|
|
3916
|
+
return null;
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
__name(getTokenExpiry, "getTokenExpiry");
|
|
3920
|
+
function isTokenExpiringSoon(token, thresholdMs) {
|
|
3921
|
+
const expiry = getTokenExpiry(token);
|
|
3922
|
+
if (!expiry) return false;
|
|
3923
|
+
const timeUntilExpiry = expiry - Date.now();
|
|
3924
|
+
return timeUntilExpiry < thresholdMs;
|
|
3925
|
+
}
|
|
3926
|
+
__name(isTokenExpiringSoon, "isTokenExpiringSoon");
|
|
3927
|
+
function useTokenRefresh(options = {}) {
|
|
3928
|
+
const { enabled = true, onRefresh, onRefreshError } = options;
|
|
3929
|
+
const isRefreshingRef = useRef(false);
|
|
3930
|
+
const refreshToken = useCallback(async () => {
|
|
3931
|
+
if (isRefreshingRef.current) {
|
|
3932
|
+
authLogger.debug("Token refresh already in progress");
|
|
3933
|
+
return false;
|
|
3934
|
+
}
|
|
3935
|
+
const refreshTokenValue = api.getRefreshToken();
|
|
3936
|
+
if (!refreshTokenValue) {
|
|
3937
|
+
authLogger.warn("No refresh token available");
|
|
3938
|
+
return false;
|
|
3939
|
+
}
|
|
3940
|
+
isRefreshingRef.current = true;
|
|
3941
|
+
authLogger.info("Refreshing token...");
|
|
3942
|
+
try {
|
|
3943
|
+
const response = await fetch("/api/accounts/token/refresh/", {
|
|
3944
|
+
method: "POST",
|
|
3945
|
+
headers: { "Content-Type": "application/json" },
|
|
3946
|
+
body: JSON.stringify({ refresh: refreshTokenValue })
|
|
3947
|
+
});
|
|
3948
|
+
if (!response.ok) {
|
|
3949
|
+
throw new Error(`Token refresh failed: ${response.status}`);
|
|
3950
|
+
}
|
|
3951
|
+
const data = await response.json();
|
|
3952
|
+
const newAccessToken = data.access;
|
|
3953
|
+
if (!newAccessToken) {
|
|
3954
|
+
throw new Error("No access token in refresh response");
|
|
3955
|
+
}
|
|
3956
|
+
api.setToken(newAccessToken, refreshTokenValue);
|
|
3957
|
+
authLogger.info("Token refreshed successfully");
|
|
3958
|
+
onRefresh?.(newAccessToken);
|
|
3959
|
+
return true;
|
|
3960
|
+
} catch (error) {
|
|
3961
|
+
authLogger.error("Token refresh error:", error);
|
|
3962
|
+
onRefreshError?.(error instanceof Error ? error : new Error(String(error)));
|
|
3963
|
+
return false;
|
|
3964
|
+
} finally {
|
|
3965
|
+
isRefreshingRef.current = false;
|
|
3966
|
+
}
|
|
3967
|
+
}, [onRefresh, onRefreshError]);
|
|
3968
|
+
const checkAndRefresh = useCallback(async () => {
|
|
3969
|
+
const token = api.getToken();
|
|
3970
|
+
if (!token) return;
|
|
3971
|
+
if (isTokenExpiringSoon(token, TOKEN_REFRESH_THRESHOLD_MS)) {
|
|
3972
|
+
authLogger.info("Token expiring soon, refreshing proactively");
|
|
3973
|
+
await refreshToken();
|
|
3974
|
+
}
|
|
3975
|
+
}, [refreshToken]);
|
|
3976
|
+
useEffect(() => {
|
|
3977
|
+
if (!enabled) return;
|
|
3978
|
+
checkAndRefresh();
|
|
3979
|
+
const intervalId = setInterval(checkAndRefresh, CHECK_INTERVAL_MS);
|
|
3980
|
+
return () => clearInterval(intervalId);
|
|
3981
|
+
}, [enabled, checkAndRefresh]);
|
|
3982
|
+
useEffect(() => {
|
|
3983
|
+
if (!enabled) return;
|
|
3984
|
+
const handleFocus = /* @__PURE__ */ __name(() => {
|
|
3985
|
+
authLogger.debug("Window focused, checking token...");
|
|
3986
|
+
checkAndRefresh();
|
|
3987
|
+
}, "handleFocus");
|
|
3988
|
+
window.addEventListener("focus", handleFocus);
|
|
3989
|
+
return () => window.removeEventListener("focus", handleFocus);
|
|
3990
|
+
}, [enabled, checkAndRefresh]);
|
|
3991
|
+
useEffect(() => {
|
|
3992
|
+
if (!enabled) return;
|
|
3993
|
+
const handleOnline = /* @__PURE__ */ __name(() => {
|
|
3994
|
+
authLogger.info("Network reconnected, checking token...");
|
|
3995
|
+
checkAndRefresh();
|
|
3996
|
+
}, "handleOnline");
|
|
3997
|
+
window.addEventListener("online", handleOnline);
|
|
3998
|
+
return () => window.removeEventListener("online", handleOnline);
|
|
3999
|
+
}, [enabled, checkAndRefresh]);
|
|
4000
|
+
return {
|
|
4001
|
+
refreshToken,
|
|
4002
|
+
checkAndRefresh
|
|
4003
|
+
};
|
|
4004
|
+
}
|
|
4005
|
+
__name(useTokenRefresh, "useTokenRefresh");
|
|
4006
|
+
|
|
3907
4007
|
// src/auth/utils/analytics.ts
|
|
3908
4008
|
var AnalyticsEvent = /* @__PURE__ */ ((AnalyticsEvent2) => {
|
|
3909
4009
|
AnalyticsEvent2["AUTH_OTP_REQUEST"] = "auth_otp_request";
|
|
@@ -3943,10 +4043,10 @@ var Analytics = {
|
|
|
3943
4043
|
// src/auth/context/AccountsContext.tsx
|
|
3944
4044
|
import {
|
|
3945
4045
|
createContext,
|
|
3946
|
-
useCallback,
|
|
4046
|
+
useCallback as useCallback2,
|
|
3947
4047
|
useContext,
|
|
3948
|
-
useEffect,
|
|
3949
|
-
useRef,
|
|
4048
|
+
useEffect as useEffect2,
|
|
4049
|
+
useRef as useRef2,
|
|
3950
4050
|
useState as useState2
|
|
3951
4051
|
} from "react";
|
|
3952
4052
|
|
|
@@ -4028,12 +4128,12 @@ function AccountsProvider({ children }) {
|
|
|
4028
4128
|
});
|
|
4029
4129
|
const [isLoadingProfile, setIsLoadingProfile] = useState2(false);
|
|
4030
4130
|
const [profileError, setProfileError] = useState2(null);
|
|
4031
|
-
const profileRef =
|
|
4032
|
-
const isLoadingRef =
|
|
4033
|
-
|
|
4131
|
+
const profileRef = useRef2(profile);
|
|
4132
|
+
const isLoadingRef = useRef2(false);
|
|
4133
|
+
useEffect2(() => {
|
|
4034
4134
|
profileRef.current = profile;
|
|
4035
4135
|
}, [profile]);
|
|
4036
|
-
|
|
4136
|
+
useEffect2(() => {
|
|
4037
4137
|
isLoadingRef.current = isLoadingProfile;
|
|
4038
4138
|
}, [isLoadingProfile]);
|
|
4039
4139
|
const updateMutation = useUpdateAccountsProfileUpdateUpdate();
|
|
@@ -4042,7 +4142,7 @@ function AccountsProvider({ children }) {
|
|
|
4042
4142
|
const otpRequestMutation = useCreateAccountsOtpRequestCreate();
|
|
4043
4143
|
const otpVerifyMutation = useCreateAccountsOtpVerifyCreate();
|
|
4044
4144
|
const tokenRefreshMutation = useCreateAccountsTokenRefreshCreate();
|
|
4045
|
-
const refreshProfile =
|
|
4145
|
+
const refreshProfile = useCallback2(async (callerId) => {
|
|
4046
4146
|
const currentProfile = profileRef.current;
|
|
4047
4147
|
const currentLoading = isLoadingRef.current;
|
|
4048
4148
|
if (currentProfile && !currentLoading) {
|
|
@@ -4108,7 +4208,7 @@ function AccountsProvider({ children }) {
|
|
|
4108
4208
|
}
|
|
4109
4209
|
return result;
|
|
4110
4210
|
}, "refreshToken");
|
|
4111
|
-
const logout =
|
|
4211
|
+
const logout = useCallback2(() => {
|
|
4112
4212
|
api.clearTokens();
|
|
4113
4213
|
setProfile(void 0);
|
|
4114
4214
|
setProfileError(null);
|
|
@@ -4172,32 +4272,45 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4172
4272
|
const queryParams = useQueryParams();
|
|
4173
4273
|
const [storedEmail, setStoredEmail, clearStoredEmail] = useLocalStorage(EMAIL_STORAGE_KEY, null);
|
|
4174
4274
|
const [storedPhone, setStoredPhone, clearStoredPhone] = useLocalStorage(PHONE_STORAGE_KEY, null);
|
|
4275
|
+
useTokenRefresh({
|
|
4276
|
+
enabled: true,
|
|
4277
|
+
onRefresh: /* @__PURE__ */ __name((newToken) => {
|
|
4278
|
+
authLogger.info("Token auto-refreshed successfully");
|
|
4279
|
+
}, "onRefresh"),
|
|
4280
|
+
onRefreshError: /* @__PURE__ */ __name((error) => {
|
|
4281
|
+
authLogger.warn("Token auto-refresh failed:", error.message);
|
|
4282
|
+
}, "onRefreshError")
|
|
4283
|
+
});
|
|
4175
4284
|
const user = accounts.profile;
|
|
4176
|
-
const userRef =
|
|
4177
|
-
const configRef =
|
|
4178
|
-
const isLoadingProfileRef =
|
|
4179
|
-
|
|
4285
|
+
const userRef = useRef3(user);
|
|
4286
|
+
const configRef = useRef3(config);
|
|
4287
|
+
const isLoadingProfileRef = useRef3(false);
|
|
4288
|
+
useEffect3(() => {
|
|
4180
4289
|
userRef.current = user;
|
|
4181
4290
|
}, [user]);
|
|
4182
|
-
|
|
4291
|
+
useEffect3(() => {
|
|
4183
4292
|
configRef.current = config;
|
|
4184
4293
|
}, [config]);
|
|
4185
|
-
const clearAuthState =
|
|
4294
|
+
const clearAuthState = useCallback3((caller) => {
|
|
4186
4295
|
authLogger.info("clearAuthState >> caller", caller);
|
|
4187
4296
|
api.clearTokens();
|
|
4188
4297
|
clearProfileCache();
|
|
4189
4298
|
setInitialized(true);
|
|
4190
4299
|
setIsLoading(false);
|
|
4191
4300
|
}, []);
|
|
4192
|
-
const handleGlobalAuthError =
|
|
4193
|
-
|
|
4194
|
-
|
|
4301
|
+
const handleGlobalAuthError = useCallback3((error, context = "API Request") => {
|
|
4302
|
+
const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
|
|
4303
|
+
if (isAuthError) {
|
|
4304
|
+
authLogger.warn(`Authentication error in ${context}, clearing tokens`);
|
|
4195
4305
|
clearAuthState(`globalAuthError:${context}`);
|
|
4196
4306
|
return true;
|
|
4197
4307
|
}
|
|
4308
|
+
if (error?.success === false) {
|
|
4309
|
+
authLogger.warn(`Non-auth error in ${context} (not clearing session):`, error?.message || error);
|
|
4310
|
+
}
|
|
4198
4311
|
return false;
|
|
4199
4312
|
}, [clearAuthState]);
|
|
4200
|
-
const loadCurrentProfile =
|
|
4313
|
+
const loadCurrentProfile = useCallback3(async (callerId) => {
|
|
4201
4314
|
const finalCallerId = callerId || "AuthContext.loadCurrentProfile";
|
|
4202
4315
|
if (isLoadingProfileRef.current) {
|
|
4203
4316
|
authLogger.debug(`Profile loading already in progress, skipping duplicate call from: ${finalCallerId}`);
|
|
@@ -4226,14 +4339,19 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4226
4339
|
setInitialized(true);
|
|
4227
4340
|
} catch (error) {
|
|
4228
4341
|
authLogger.error("Failed to load profile:", error);
|
|
4229
|
-
|
|
4230
|
-
|
|
4342
|
+
const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
|
|
4343
|
+
if (isAuthError) {
|
|
4344
|
+
authLogger.warn("Authentication error, clearing session");
|
|
4345
|
+
clearAuthState("loadCurrentProfile:authError");
|
|
4346
|
+
} else {
|
|
4347
|
+
authLogger.warn("Profile load failed but keeping session (non-auth error)");
|
|
4348
|
+
setInitialized(true);
|
|
4231
4349
|
}
|
|
4232
4350
|
} finally {
|
|
4233
4351
|
isLoadingProfileRef.current = false;
|
|
4234
4352
|
}
|
|
4235
4353
|
}, [clearAuthState, handleGlobalAuthError, accounts]);
|
|
4236
|
-
|
|
4354
|
+
useEffect3(() => {
|
|
4237
4355
|
if (initialized) return;
|
|
4238
4356
|
const initializeAuth = /* @__PURE__ */ __name(async () => {
|
|
4239
4357
|
authLogger.info("Initializing auth...");
|
|
@@ -4273,7 +4391,13 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4273
4391
|
await loadCurrentProfile("AuthContext.initializeAuth");
|
|
4274
4392
|
} catch (error) {
|
|
4275
4393
|
authLogger.error("Failed to load profile during initialization:", error);
|
|
4276
|
-
|
|
4394
|
+
const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
|
|
4395
|
+
if (isAuthError) {
|
|
4396
|
+
clearAuthState("initializeAuth:authError");
|
|
4397
|
+
} else {
|
|
4398
|
+
authLogger.warn("Init profile load failed but keeping session");
|
|
4399
|
+
setInitialized(true);
|
|
4400
|
+
}
|
|
4277
4401
|
}
|
|
4278
4402
|
setIsLoading(false);
|
|
4279
4403
|
} else {
|
|
@@ -4283,7 +4407,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4283
4407
|
}, "initializeAuth");
|
|
4284
4408
|
initializeAuth();
|
|
4285
4409
|
}, [initialized]);
|
|
4286
|
-
|
|
4410
|
+
useEffect3(() => {
|
|
4287
4411
|
if (!initialized) return;
|
|
4288
4412
|
const isAuthenticated = api.isAuthenticated();
|
|
4289
4413
|
const authRoute = config?.routes?.auth || defaultRoutes.auth;
|
|
@@ -4294,15 +4418,15 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4294
4418
|
router.push(callbackUrl);
|
|
4295
4419
|
}
|
|
4296
4420
|
}, [initialized, pathname, queryParams, config?.routes]);
|
|
4297
|
-
const pushToDefaultCallbackUrl =
|
|
4421
|
+
const pushToDefaultCallbackUrl = useCallback3(() => {
|
|
4298
4422
|
const callbackUrl = config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
|
|
4299
4423
|
router.push(callbackUrl);
|
|
4300
4424
|
}, [config?.routes, router]);
|
|
4301
|
-
const pushToDefaultAuthCallbackUrl =
|
|
4425
|
+
const pushToDefaultAuthCallbackUrl = useCallback3(() => {
|
|
4302
4426
|
const authCallbackUrl = config?.routes?.defaultAuthCallback || defaultRoutes.defaultAuthCallback;
|
|
4303
4427
|
router.push(authCallbackUrl);
|
|
4304
4428
|
}, [config?.routes, router]);
|
|
4305
|
-
const checkAuthAndRedirect =
|
|
4429
|
+
const checkAuthAndRedirect = useCallback3(async () => {
|
|
4306
4430
|
try {
|
|
4307
4431
|
setIsLoading(true);
|
|
4308
4432
|
const isAuthenticated = api.isAuthenticated();
|
|
@@ -4324,7 +4448,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4324
4448
|
setIsLoading(false);
|
|
4325
4449
|
}
|
|
4326
4450
|
}, [loadCurrentProfile, clearAuthState, pushToDefaultCallbackUrl, pushToDefaultAuthCallbackUrl, handleGlobalAuthError]);
|
|
4327
|
-
const requestOTP =
|
|
4451
|
+
const requestOTP = useCallback3(
|
|
4328
4452
|
async (identifier, channel, sourceUrl) => {
|
|
4329
4453
|
api.clearTokens();
|
|
4330
4454
|
try {
|
|
@@ -4352,7 +4476,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4352
4476
|
},
|
|
4353
4477
|
[accounts]
|
|
4354
4478
|
);
|
|
4355
|
-
const verifyOTP =
|
|
4479
|
+
const verifyOTP = useCallback3(
|
|
4356
4480
|
async (identifier, otpCode, channel, sourceUrl, redirectUrl, skipRedirect) => {
|
|
4357
4481
|
try {
|
|
4358
4482
|
const channelValue = channel === "phone" ? enums_exports.OTPVerifyRequestChannel.PHONE : enums_exports.OTPVerifyRequestChannel.EMAIL;
|
|
@@ -4419,7 +4543,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4419
4543
|
},
|
|
4420
4544
|
[setStoredEmail, setStoredPhone, clearStoredEmail, clearStoredPhone, config?.routes?.defaultCallback, accounts, router]
|
|
4421
4545
|
);
|
|
4422
|
-
const refreshToken =
|
|
4546
|
+
const refreshToken = useCallback3(async () => {
|
|
4423
4547
|
try {
|
|
4424
4548
|
const refreshTokenValue = api.getRefreshToken();
|
|
4425
4549
|
if (!refreshTokenValue) {
|
|
@@ -4452,7 +4576,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4452
4576
|
};
|
|
4453
4577
|
}
|
|
4454
4578
|
}, [clearAuthState, accounts]);
|
|
4455
|
-
const logout =
|
|
4579
|
+
const logout = useCallback3(async () => {
|
|
4456
4580
|
const performLogout = /* @__PURE__ */ __name(() => {
|
|
4457
4581
|
Analytics.event("auth_logout" /* AUTH_LOGOUT */, {
|
|
4458
4582
|
category: "auth" /* AUTH */
|
|
@@ -4544,7 +4668,7 @@ var useAuth = /* @__PURE__ */ __name(() => {
|
|
|
4544
4668
|
}, "useAuth");
|
|
4545
4669
|
|
|
4546
4670
|
// src/auth/hooks/useAuthFormState.ts
|
|
4547
|
-
import { useCallback as
|
|
4671
|
+
import { useCallback as useCallback4, useState as useState4 } from "react";
|
|
4548
4672
|
var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialChannel = "email") => {
|
|
4549
4673
|
const [identifier, setIdentifier] = useState4(initialIdentifier);
|
|
4550
4674
|
const [channel, setChannel] = useState4(initialChannel);
|
|
@@ -4557,7 +4681,7 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialCh
|
|
|
4557
4681
|
const [shouldPrompt2FA, setShouldPrompt2FA] = useState4(false);
|
|
4558
4682
|
const [twoFactorCode, setTwoFactorCode] = useState4("");
|
|
4559
4683
|
const [useBackupCode, setUseBackupCode] = useState4(false);
|
|
4560
|
-
const clearError =
|
|
4684
|
+
const clearError = useCallback4(() => setError(""), []);
|
|
4561
4685
|
return {
|
|
4562
4686
|
// State
|
|
4563
4687
|
identifier,
|
|
@@ -4588,11 +4712,11 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialCh
|
|
|
4588
4712
|
}, "useAuthFormState");
|
|
4589
4713
|
|
|
4590
4714
|
// src/auth/hooks/useAuthValidation.ts
|
|
4591
|
-
import { useCallback as
|
|
4715
|
+
import { useCallback as useCallback5 } from "react";
|
|
4592
4716
|
var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
4593
4717
|
var PHONE_REGEX = /^\+[1-9]\d{6,14}$/;
|
|
4594
4718
|
var useAuthValidation = /* @__PURE__ */ __name(() => {
|
|
4595
|
-
const detectChannelFromIdentifier2 =
|
|
4719
|
+
const detectChannelFromIdentifier2 = useCallback5((id) => {
|
|
4596
4720
|
if (!id) return null;
|
|
4597
4721
|
if (id.includes("@")) {
|
|
4598
4722
|
return "email";
|
|
@@ -4602,7 +4726,7 @@ var useAuthValidation = /* @__PURE__ */ __name(() => {
|
|
|
4602
4726
|
}
|
|
4603
4727
|
return null;
|
|
4604
4728
|
}, []);
|
|
4605
|
-
const validateIdentifier2 =
|
|
4729
|
+
const validateIdentifier2 = useCallback5((id, channelType) => {
|
|
4606
4730
|
if (!id) return false;
|
|
4607
4731
|
const channel = channelType || detectChannelFromIdentifier2(id);
|
|
4608
4732
|
if (channel === "email") {
|
|
@@ -4633,11 +4757,11 @@ var validateIdentifier = /* @__PURE__ */ __name((id, channelType) => {
|
|
|
4633
4757
|
}, "validateIdentifier");
|
|
4634
4758
|
|
|
4635
4759
|
// src/auth/hooks/useAuthForm.ts
|
|
4636
|
-
import { useCallback as
|
|
4760
|
+
import { useCallback as useCallback7, useEffect as useEffect5, useRef as useRef4 } from "react";
|
|
4637
4761
|
|
|
4638
4762
|
// src/auth/hooks/useAutoAuth.ts
|
|
4639
4763
|
import { usePathname as usePathname2 } from "next/navigation";
|
|
4640
|
-
import { useEffect as
|
|
4764
|
+
import { useEffect as useEffect4 } from "react";
|
|
4641
4765
|
import { useCfgRouter as useCfgRouter2, useQueryParams as useQueryParams2 } from "@djangocfg/ui-nextjs/hooks";
|
|
4642
4766
|
var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
4643
4767
|
const { onOTPDetected, cleanupUrl = true, allowedPaths = ["/auth"] } = options;
|
|
@@ -4647,7 +4771,7 @@ var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
4647
4771
|
const isAllowedPath = allowedPaths.some((path) => pathname === path || pathname?.startsWith(path + "/"));
|
|
4648
4772
|
const hasOTP = !!queryParams.get("otp");
|
|
4649
4773
|
const isReady = !!pathname && hasOTP && isAllowedPath;
|
|
4650
|
-
|
|
4774
|
+
useEffect4(() => {
|
|
4651
4775
|
if (!isReady) return;
|
|
4652
4776
|
const queryOtp = queryParams.get("otp");
|
|
4653
4777
|
if (queryOtp && typeof queryOtp === "string" && queryOtp.length === 6) {
|
|
@@ -4669,7 +4793,7 @@ var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
4669
4793
|
}, "useAutoAuth");
|
|
4670
4794
|
|
|
4671
4795
|
// src/auth/hooks/useTwoFactor.ts
|
|
4672
|
-
import { useCallback as
|
|
4796
|
+
import { useCallback as useCallback6, useState as useState5 } from "react";
|
|
4673
4797
|
import { useCfgRouter as useCfgRouter3 } from "@djangocfg/ui-nextjs/hooks";
|
|
4674
4798
|
|
|
4675
4799
|
// src/generated/cfg_totp/totp__backup_codes/client.ts
|
|
@@ -5714,10 +5838,10 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
|
|
|
5714
5838
|
const [error, setError] = useState5(null);
|
|
5715
5839
|
const [warning, setWarning] = useState5(null);
|
|
5716
5840
|
const [remainingBackupCodes, setRemainingBackupCodes] = useState5(null);
|
|
5717
|
-
const clearError =
|
|
5841
|
+
const clearError = useCallback6(() => {
|
|
5718
5842
|
setError(null);
|
|
5719
5843
|
}, []);
|
|
5720
|
-
const handleSuccess =
|
|
5844
|
+
const handleSuccess = useCallback6((response) => {
|
|
5721
5845
|
apiAccounts.setToken(response.access_token, response.refresh_token);
|
|
5722
5846
|
if (response.warning) {
|
|
5723
5847
|
setWarning(response.warning);
|
|
@@ -5739,7 +5863,7 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
|
|
|
5739
5863
|
router.hardPush(finalRedirectUrl);
|
|
5740
5864
|
}
|
|
5741
5865
|
}, [onSuccess, redirectUrl, router, skipRedirect]);
|
|
5742
|
-
const verifyTOTP =
|
|
5866
|
+
const verifyTOTP = useCallback6(async (sessionId, code) => {
|
|
5743
5867
|
if (!sessionId) {
|
|
5744
5868
|
const msg = "Missing 2FA session ID";
|
|
5745
5869
|
setError(msg);
|
|
@@ -5779,7 +5903,7 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
|
|
|
5779
5903
|
setIsLoading(false);
|
|
5780
5904
|
}
|
|
5781
5905
|
}, [handleSuccess, onError]);
|
|
5782
|
-
const verifyBackupCode =
|
|
5906
|
+
const verifyBackupCode = useCallback6(async (sessionId, backupCode) => {
|
|
5783
5907
|
if (!sessionId) {
|
|
5784
5908
|
const msg = "Missing 2FA session ID";
|
|
5785
5909
|
setError(msg);
|
|
@@ -5845,7 +5969,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
5845
5969
|
} = options;
|
|
5846
5970
|
const formState = useAuthFormState();
|
|
5847
5971
|
const validation = useAuthValidation();
|
|
5848
|
-
const isAutoSubmitFromUrlRef =
|
|
5972
|
+
const isAutoSubmitFromUrlRef = useRef4(false);
|
|
5849
5973
|
const {
|
|
5850
5974
|
requestOTP,
|
|
5851
5975
|
verifyOTP,
|
|
@@ -5892,7 +6016,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
5892
6016
|
// We handle navigation via success step
|
|
5893
6017
|
});
|
|
5894
6018
|
const { detectChannelFromIdentifier: detectChannelFromIdentifier2, validateIdentifier: validateIdentifier2 } = validation;
|
|
5895
|
-
const saveIdentifierToStorage =
|
|
6019
|
+
const saveIdentifierToStorage = useCallback7((id, ch) => {
|
|
5896
6020
|
if (ch === "email") {
|
|
5897
6021
|
saveEmail(id);
|
|
5898
6022
|
clearSavedPhone();
|
|
@@ -5901,7 +6025,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
5901
6025
|
clearSavedEmail();
|
|
5902
6026
|
}
|
|
5903
6027
|
}, [saveEmail, savePhone, clearSavedEmail, clearSavedPhone]);
|
|
5904
|
-
|
|
6028
|
+
useEffect5(() => {
|
|
5905
6029
|
const savedPhone = getSavedPhone();
|
|
5906
6030
|
const savedEmail = getSavedEmail();
|
|
5907
6031
|
if (savedPhone) {
|
|
@@ -5912,7 +6036,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
5912
6036
|
setChannel("email");
|
|
5913
6037
|
}
|
|
5914
6038
|
}, [getSavedEmail, getSavedPhone, setIdentifier, setChannel]);
|
|
5915
|
-
|
|
6039
|
+
useEffect5(() => {
|
|
5916
6040
|
if (identifier) {
|
|
5917
6041
|
const detected = detectChannelFromIdentifier2(identifier);
|
|
5918
6042
|
if (detected && detected !== channel) {
|
|
@@ -5920,7 +6044,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
5920
6044
|
}
|
|
5921
6045
|
}
|
|
5922
6046
|
}, [identifier, channel, detectChannelFromIdentifier2, setChannel]);
|
|
5923
|
-
const handleIdentifierSubmit =
|
|
6047
|
+
const handleIdentifierSubmit = useCallback7(async (e) => {
|
|
5924
6048
|
e.preventDefault();
|
|
5925
6049
|
if (!identifier) {
|
|
5926
6050
|
const msg = channel === "phone" ? "Please enter your phone number" : "Please enter your email address";
|
|
@@ -5975,7 +6099,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
5975
6099
|
onError,
|
|
5976
6100
|
sourceUrl
|
|
5977
6101
|
]);
|
|
5978
|
-
const submitOTP =
|
|
6102
|
+
const submitOTP = useCallback7(async (submitIdentifier, submitOtp, submitChannel) => {
|
|
5979
6103
|
if (!submitOtp || submitOtp.length < 6) {
|
|
5980
6104
|
const msg = "Please enter the 6-digit verification code";
|
|
5981
6105
|
setError(msg);
|
|
@@ -6025,11 +6149,11 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
6025
6149
|
setIsLoading(false);
|
|
6026
6150
|
}
|
|
6027
6151
|
}, [verifyOTP, saveIdentifierToStorage, setError, setIsLoading, clearError, onOTPSuccess, onError, sourceUrl, redirectUrl, setTwoFactorSessionId, setShouldPrompt2FA, setStep, enable2FASetup]);
|
|
6028
|
-
const handleOTPSubmit =
|
|
6152
|
+
const handleOTPSubmit = useCallback7(async (e) => {
|
|
6029
6153
|
e.preventDefault();
|
|
6030
6154
|
await submitOTP(identifier, otp, channel);
|
|
6031
6155
|
}, [identifier, otp, channel, submitOTP]);
|
|
6032
|
-
const handleResendOTP =
|
|
6156
|
+
const handleResendOTP = useCallback7(async () => {
|
|
6033
6157
|
setIsLoading(true);
|
|
6034
6158
|
clearError();
|
|
6035
6159
|
try {
|
|
@@ -6049,15 +6173,15 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
6049
6173
|
setIsLoading(false);
|
|
6050
6174
|
}
|
|
6051
6175
|
}, [identifier, channel, requestOTP, saveIdentifierToStorage, setOtp, setError, setIsLoading, clearError, onError, sourceUrl]);
|
|
6052
|
-
const handleBackToIdentifier =
|
|
6176
|
+
const handleBackToIdentifier = useCallback7(() => {
|
|
6053
6177
|
setStep("identifier");
|
|
6054
6178
|
clearError();
|
|
6055
6179
|
}, [setStep, clearError]);
|
|
6056
|
-
const forceOTPStep =
|
|
6180
|
+
const forceOTPStep = useCallback7(() => {
|
|
6057
6181
|
setStep("otp");
|
|
6058
6182
|
clearError();
|
|
6059
6183
|
}, [setStep, clearError]);
|
|
6060
|
-
const handle2FASubmit =
|
|
6184
|
+
const handle2FASubmit = useCallback7(async (e) => {
|
|
6061
6185
|
e.preventDefault();
|
|
6062
6186
|
if (!twoFactorSessionId) {
|
|
6063
6187
|
const msg = "Missing 2FA session";
|
|
@@ -6071,12 +6195,12 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
6071
6195
|
await twoFactor.verifyTOTP(twoFactorSessionId, twoFactorCode);
|
|
6072
6196
|
}
|
|
6073
6197
|
}, [twoFactorSessionId, twoFactorCode, useBackupCode, twoFactor, setError, onError]);
|
|
6074
|
-
const handleUseBackupCode =
|
|
6198
|
+
const handleUseBackupCode = useCallback7(() => {
|
|
6075
6199
|
setUseBackupCode(true);
|
|
6076
6200
|
setTwoFactorCode("");
|
|
6077
6201
|
clearError();
|
|
6078
6202
|
}, [setUseBackupCode, setTwoFactorCode, clearError]);
|
|
6079
|
-
const handleUseTOTP =
|
|
6203
|
+
const handleUseTOTP = useCallback7(() => {
|
|
6080
6204
|
setUseBackupCode(false);
|
|
6081
6205
|
setTwoFactorCode("");
|
|
6082
6206
|
clearError();
|
|
@@ -6141,14 +6265,14 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
6141
6265
|
}, "useAuthForm");
|
|
6142
6266
|
|
|
6143
6267
|
// src/auth/hooks/useGithubAuth.ts
|
|
6144
|
-
import { useCallback as
|
|
6268
|
+
import { useCallback as useCallback8, useState as useState6 } from "react";
|
|
6145
6269
|
import { useCfgRouter as useCfgRouter4 } from "@djangocfg/ui-nextjs/hooks";
|
|
6146
6270
|
var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
6147
6271
|
const { sourceUrl, onSuccess, onError, onRequires2FA, redirectUrl, skipRedirect = false } = options;
|
|
6148
6272
|
const router = useCfgRouter4();
|
|
6149
6273
|
const [isLoading, setIsLoading] = useState6(false);
|
|
6150
6274
|
const [error, setError] = useState6(null);
|
|
6151
|
-
const startGithubAuth =
|
|
6275
|
+
const startGithubAuth = useCallback8(async () => {
|
|
6152
6276
|
setIsLoading(true);
|
|
6153
6277
|
setError(null);
|
|
6154
6278
|
try {
|
|
@@ -6182,7 +6306,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
6182
6306
|
setIsLoading(false);
|
|
6183
6307
|
}
|
|
6184
6308
|
}, [sourceUrl, onError]);
|
|
6185
|
-
const handleGithubCallback =
|
|
6309
|
+
const handleGithubCallback = useCallback8(async (code, state) => {
|
|
6186
6310
|
setIsLoading(true);
|
|
6187
6311
|
setError(null);
|
|
6188
6312
|
try {
|
|
@@ -6247,7 +6371,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
6247
6371
|
}, "useGithubAuth");
|
|
6248
6372
|
|
|
6249
6373
|
// src/auth/hooks/useTwoFactorSetup.ts
|
|
6250
|
-
import { useCallback as
|
|
6374
|
+
import { useCallback as useCallback9, useState as useState7 } from "react";
|
|
6251
6375
|
var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
|
|
6252
6376
|
const { onComplete, onError } = options;
|
|
6253
6377
|
const [isLoading, setIsLoading] = useState7(false);
|
|
@@ -6256,17 +6380,17 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
|
|
|
6256
6380
|
const [backupCodes, setBackupCodes] = useState7(null);
|
|
6257
6381
|
const [backupCodesWarning, setBackupCodesWarning] = useState7(null);
|
|
6258
6382
|
const [setupStep, setSetupStep] = useState7("idle");
|
|
6259
|
-
const clearError =
|
|
6383
|
+
const clearError = useCallback9(() => {
|
|
6260
6384
|
setError(null);
|
|
6261
6385
|
}, []);
|
|
6262
|
-
const resetSetup =
|
|
6386
|
+
const resetSetup = useCallback9(() => {
|
|
6263
6387
|
setSetupData(null);
|
|
6264
6388
|
setBackupCodes(null);
|
|
6265
6389
|
setBackupCodesWarning(null);
|
|
6266
6390
|
setSetupStep("idle");
|
|
6267
6391
|
setError(null);
|
|
6268
6392
|
}, []);
|
|
6269
|
-
const startSetup =
|
|
6393
|
+
const startSetup = useCallback9(async (deviceName) => {
|
|
6270
6394
|
setIsLoading(true);
|
|
6271
6395
|
setError(null);
|
|
6272
6396
|
setSetupStep("scanning");
|
|
@@ -6296,7 +6420,7 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
|
|
|
6296
6420
|
setIsLoading(false);
|
|
6297
6421
|
}
|
|
6298
6422
|
}, [onError]);
|
|
6299
|
-
const confirmSetup =
|
|
6423
|
+
const confirmSetup = useCallback9(async (code) => {
|
|
6300
6424
|
if (!setupData) {
|
|
6301
6425
|
const msg = "Setup not started. Call startSetup() first.";
|
|
6302
6426
|
setError(msg);
|
|
@@ -6351,16 +6475,16 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
|
|
|
6351
6475
|
}, "useTwoFactorSetup");
|
|
6352
6476
|
|
|
6353
6477
|
// src/auth/hooks/useTwoFactorStatus.ts
|
|
6354
|
-
import { useCallback as
|
|
6478
|
+
import { useCallback as useCallback10, useState as useState8 } from "react";
|
|
6355
6479
|
var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
|
|
6356
6480
|
const [isLoading, setIsLoading] = useState8(false);
|
|
6357
6481
|
const [error, setError] = useState8(null);
|
|
6358
6482
|
const [has2FAEnabled, setHas2FAEnabled] = useState8(null);
|
|
6359
6483
|
const [devices, setDevices] = useState8([]);
|
|
6360
|
-
const clearError =
|
|
6484
|
+
const clearError = useCallback10(() => {
|
|
6361
6485
|
setError(null);
|
|
6362
6486
|
}, []);
|
|
6363
|
-
const fetchStatus =
|
|
6487
|
+
const fetchStatus = useCallback10(async () => {
|
|
6364
6488
|
setIsLoading(true);
|
|
6365
6489
|
setError(null);
|
|
6366
6490
|
try {
|
|
@@ -6385,7 +6509,7 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
|
|
|
6385
6509
|
setIsLoading(false);
|
|
6386
6510
|
}
|
|
6387
6511
|
}, []);
|
|
6388
|
-
const disable2FA =
|
|
6512
|
+
const disable2FA = useCallback10(async (code) => {
|
|
6389
6513
|
if (!code || code.length !== 6) {
|
|
6390
6514
|
setError("Please enter a 6-digit code");
|
|
6391
6515
|
return false;
|
|
@@ -6420,14 +6544,14 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
|
|
|
6420
6544
|
}, "useTwoFactorStatus");
|
|
6421
6545
|
|
|
6422
6546
|
// src/auth/hooks/useAuthGuard.ts
|
|
6423
|
-
import { useEffect as
|
|
6547
|
+
import { useEffect as useEffect6, useState as useState9 } from "react";
|
|
6424
6548
|
import { useCfgRouter as useCfgRouter5 } from "@djangocfg/ui-nextjs/hooks";
|
|
6425
6549
|
var useAuthGuard = /* @__PURE__ */ __name((options = {}) => {
|
|
6426
6550
|
const { redirectTo = "/auth", requireAuth = true, saveRedirectUrl: shouldSaveUrl = true } = options;
|
|
6427
6551
|
const { isAuthenticated, isLoading, saveRedirectUrl } = useAuth();
|
|
6428
6552
|
const router = useCfgRouter5();
|
|
6429
6553
|
const [isRedirecting, setIsRedirecting] = useState9(false);
|
|
6430
|
-
|
|
6554
|
+
useEffect6(() => {
|
|
6431
6555
|
if (!isLoading && requireAuth && !isAuthenticated && !isRedirecting) {
|
|
6432
6556
|
if (shouldSaveUrl && typeof window !== "undefined") {
|
|
6433
6557
|
const currentUrl = window.location.pathname + window.location.search;
|
|
@@ -6652,6 +6776,7 @@ export {
|
|
|
6652
6776
|
useGithubAuth,
|
|
6653
6777
|
useLocalStorage2 as useLocalStorage,
|
|
6654
6778
|
useSessionStorage,
|
|
6779
|
+
useTokenRefresh,
|
|
6655
6780
|
useTwoFactor,
|
|
6656
6781
|
useTwoFactorSetup,
|
|
6657
6782
|
useTwoFactorStatus,
|