@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.cjs CHANGED
@@ -59,6 +59,7 @@ __export(auth_exports, {
59
59
  useGithubAuth: () => useGithubAuth,
60
60
  useLocalStorage: () => useLocalStorage2,
61
61
  useSessionStorage: () => useSessionStorage,
62
+ useTokenRefresh: () => useTokenRefresh,
62
63
  useTwoFactor: () => useTwoFactor,
63
64
  useTwoFactorSetup: () => useTwoFactorSetup,
64
65
  useTwoFactorStatus: () => useTwoFactorStatus,
@@ -69,7 +70,7 @@ module.exports = __toCommonJS(auth_exports);
69
70
 
70
71
  // src/auth/context/AuthContext.tsx
71
72
  var import_navigation = require("next/navigation");
72
- var import_react3 = require("react");
73
+ var import_react4 = require("react");
73
74
  var import_hooks2 = require("@djangocfg/ui-nextjs/hooks");
74
75
 
75
76
  // src/generated/cfg_accounts/accounts__auth/client.ts
@@ -3672,7 +3673,7 @@ __name(useBase64, "useBase64");
3672
3673
  // src/auth/hooks/useProfileCache.ts
3673
3674
  var CACHE_KEY = "user_profile_cache";
3674
3675
  var CACHE_VERSION = 1;
3675
- var DEFAULT_TTL = 36e5;
3676
+ var DEFAULT_TTL = 144e5;
3676
3677
  function getCachedProfile() {
3677
3678
  try {
3678
3679
  if (typeof window === "undefined") return null;
@@ -3958,6 +3959,106 @@ var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
3958
3959
  };
3959
3960
  }, "useAuthRedirectManager");
3960
3961
 
3962
+ // src/auth/hooks/useTokenRefresh.ts
3963
+ var import_react2 = require("react");
3964
+ var TOKEN_REFRESH_THRESHOLD_MS = 10 * 60 * 1e3;
3965
+ var CHECK_INTERVAL_MS = 5 * 60 * 1e3;
3966
+ function getTokenExpiry(token) {
3967
+ try {
3968
+ const payload = JSON.parse(atob(token.split(".")[1]));
3969
+ return payload.exp * 1e3;
3970
+ } catch {
3971
+ return null;
3972
+ }
3973
+ }
3974
+ __name(getTokenExpiry, "getTokenExpiry");
3975
+ function isTokenExpiringSoon(token, thresholdMs) {
3976
+ const expiry = getTokenExpiry(token);
3977
+ if (!expiry) return false;
3978
+ const timeUntilExpiry = expiry - Date.now();
3979
+ return timeUntilExpiry < thresholdMs;
3980
+ }
3981
+ __name(isTokenExpiringSoon, "isTokenExpiringSoon");
3982
+ function useTokenRefresh(options = {}) {
3983
+ const { enabled = true, onRefresh, onRefreshError } = options;
3984
+ const isRefreshingRef = (0, import_react2.useRef)(false);
3985
+ const refreshToken = (0, import_react2.useCallback)(async () => {
3986
+ if (isRefreshingRef.current) {
3987
+ authLogger.debug("Token refresh already in progress");
3988
+ return false;
3989
+ }
3990
+ const refreshTokenValue = api.getRefreshToken();
3991
+ if (!refreshTokenValue) {
3992
+ authLogger.warn("No refresh token available");
3993
+ return false;
3994
+ }
3995
+ isRefreshingRef.current = true;
3996
+ authLogger.info("Refreshing token...");
3997
+ try {
3998
+ const response = await fetch("/api/accounts/token/refresh/", {
3999
+ method: "POST",
4000
+ headers: { "Content-Type": "application/json" },
4001
+ body: JSON.stringify({ refresh: refreshTokenValue })
4002
+ });
4003
+ if (!response.ok) {
4004
+ throw new Error(`Token refresh failed: ${response.status}`);
4005
+ }
4006
+ const data = await response.json();
4007
+ const newAccessToken = data.access;
4008
+ if (!newAccessToken) {
4009
+ throw new Error("No access token in refresh response");
4010
+ }
4011
+ api.setToken(newAccessToken, refreshTokenValue);
4012
+ authLogger.info("Token refreshed successfully");
4013
+ onRefresh?.(newAccessToken);
4014
+ return true;
4015
+ } catch (error) {
4016
+ authLogger.error("Token refresh error:", error);
4017
+ onRefreshError?.(error instanceof Error ? error : new Error(String(error)));
4018
+ return false;
4019
+ } finally {
4020
+ isRefreshingRef.current = false;
4021
+ }
4022
+ }, [onRefresh, onRefreshError]);
4023
+ const checkAndRefresh = (0, import_react2.useCallback)(async () => {
4024
+ const token = api.getToken();
4025
+ if (!token) return;
4026
+ if (isTokenExpiringSoon(token, TOKEN_REFRESH_THRESHOLD_MS)) {
4027
+ authLogger.info("Token expiring soon, refreshing proactively");
4028
+ await refreshToken();
4029
+ }
4030
+ }, [refreshToken]);
4031
+ (0, import_react2.useEffect)(() => {
4032
+ if (!enabled) return;
4033
+ checkAndRefresh();
4034
+ const intervalId = setInterval(checkAndRefresh, CHECK_INTERVAL_MS);
4035
+ return () => clearInterval(intervalId);
4036
+ }, [enabled, checkAndRefresh]);
4037
+ (0, import_react2.useEffect)(() => {
4038
+ if (!enabled) return;
4039
+ const handleFocus = /* @__PURE__ */ __name(() => {
4040
+ authLogger.debug("Window focused, checking token...");
4041
+ checkAndRefresh();
4042
+ }, "handleFocus");
4043
+ window.addEventListener("focus", handleFocus);
4044
+ return () => window.removeEventListener("focus", handleFocus);
4045
+ }, [enabled, checkAndRefresh]);
4046
+ (0, import_react2.useEffect)(() => {
4047
+ if (!enabled) return;
4048
+ const handleOnline = /* @__PURE__ */ __name(() => {
4049
+ authLogger.info("Network reconnected, checking token...");
4050
+ checkAndRefresh();
4051
+ }, "handleOnline");
4052
+ window.addEventListener("online", handleOnline);
4053
+ return () => window.removeEventListener("online", handleOnline);
4054
+ }, [enabled, checkAndRefresh]);
4055
+ return {
4056
+ refreshToken,
4057
+ checkAndRefresh
4058
+ };
4059
+ }
4060
+ __name(useTokenRefresh, "useTokenRefresh");
4061
+
3961
4062
  // src/auth/utils/analytics.ts
3962
4063
  var AnalyticsEvent = /* @__PURE__ */ ((AnalyticsEvent2) => {
3963
4064
  AnalyticsEvent2["AUTH_OTP_REQUEST"] = "auth_otp_request";
@@ -3995,7 +4096,7 @@ var Analytics = {
3995
4096
  };
3996
4097
 
3997
4098
  // src/auth/context/AccountsContext.tsx
3998
- var import_react2 = require("react");
4099
+ var import_react3 = require("react");
3999
4100
 
4000
4101
  // src/generated/cfg_accounts/_utils/hooks/accounts__auth.ts
4001
4102
  var import_swr = require("swr");
@@ -4067,20 +4168,20 @@ __name(useCreateAccountsOtpVerifyCreate, "useCreateAccountsOtpVerifyCreate");
4067
4168
 
4068
4169
  // src/auth/context/AccountsContext.tsx
4069
4170
  var import_jsx_runtime = require("react/jsx-runtime");
4070
- var AccountsContext = (0, import_react2.createContext)(void 0);
4171
+ var AccountsContext = (0, import_react3.createContext)(void 0);
4071
4172
  function AccountsProvider({ children }) {
4072
- const [profile, setProfile] = (0, import_react2.useState)(() => {
4173
+ const [profile, setProfile] = (0, import_react3.useState)(() => {
4073
4174
  const cached = getCachedProfile();
4074
4175
  return cached || void 0;
4075
4176
  });
4076
- const [isLoadingProfile, setIsLoadingProfile] = (0, import_react2.useState)(false);
4077
- const [profileError, setProfileError] = (0, import_react2.useState)(null);
4078
- const profileRef = (0, import_react2.useRef)(profile);
4079
- const isLoadingRef = (0, import_react2.useRef)(false);
4080
- (0, import_react2.useEffect)(() => {
4177
+ const [isLoadingProfile, setIsLoadingProfile] = (0, import_react3.useState)(false);
4178
+ const [profileError, setProfileError] = (0, import_react3.useState)(null);
4179
+ const profileRef = (0, import_react3.useRef)(profile);
4180
+ const isLoadingRef = (0, import_react3.useRef)(false);
4181
+ (0, import_react3.useEffect)(() => {
4081
4182
  profileRef.current = profile;
4082
4183
  }, [profile]);
4083
- (0, import_react2.useEffect)(() => {
4184
+ (0, import_react3.useEffect)(() => {
4084
4185
  isLoadingRef.current = isLoadingProfile;
4085
4186
  }, [isLoadingProfile]);
4086
4187
  const updateMutation = useUpdateAccountsProfileUpdateUpdate();
@@ -4089,7 +4190,7 @@ function AccountsProvider({ children }) {
4089
4190
  const otpRequestMutation = useCreateAccountsOtpRequestCreate();
4090
4191
  const otpVerifyMutation = useCreateAccountsOtpVerifyCreate();
4091
4192
  const tokenRefreshMutation = useCreateAccountsTokenRefreshCreate();
4092
- const refreshProfile = (0, import_react2.useCallback)(async (callerId) => {
4193
+ const refreshProfile = (0, import_react3.useCallback)(async (callerId) => {
4093
4194
  const currentProfile = profileRef.current;
4094
4195
  const currentLoading = isLoadingRef.current;
4095
4196
  if (currentProfile && !currentLoading) {
@@ -4155,7 +4256,7 @@ function AccountsProvider({ children }) {
4155
4256
  }
4156
4257
  return result;
4157
4258
  }, "refreshToken");
4158
- const logout = (0, import_react2.useCallback)(() => {
4259
+ const logout = (0, import_react3.useCallback)(() => {
4159
4260
  api.clearTokens();
4160
4261
  setProfile(void 0);
4161
4262
  setProfileError(null);
@@ -4178,7 +4279,7 @@ function AccountsProvider({ children }) {
4178
4279
  }
4179
4280
  __name(AccountsProvider, "AccountsProvider");
4180
4281
  function useAccountsContext() {
4181
- const context = (0, import_react2.useContext)(AccountsContext);
4282
+ const context = (0, import_react3.useContext)(AccountsContext);
4182
4283
  if (!context) {
4183
4284
  throw new Error("useAccountsContext must be used within AccountsProvider");
4184
4285
  }
@@ -4193,7 +4294,7 @@ var defaultRoutes = {
4193
4294
  defaultCallback: "/dashboard",
4194
4295
  defaultAuthCallback: "/auth"
4195
4296
  };
4196
- var AuthContext = (0, import_react3.createContext)(void 0);
4297
+ var AuthContext = (0, import_react4.createContext)(void 0);
4197
4298
  var EMAIL_STORAGE_KEY = "auth_email";
4198
4299
  var PHONE_STORAGE_KEY = "auth_phone";
4199
4300
  var hasValidTokens = /* @__PURE__ */ __name(() => {
@@ -4206,45 +4307,58 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4206
4307
  fallbackUrl: config?.routes?.defaultCallback || defaultRoutes.defaultCallback,
4207
4308
  clearOnUse: true
4208
4309
  });
4209
- const [isLoading, setIsLoading] = (0, import_react3.useState)(() => {
4310
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(() => {
4210
4311
  if (typeof window !== "undefined") {
4211
4312
  const hasTokens = hasValidTokens();
4212
4313
  return !hasTokens;
4213
4314
  }
4214
4315
  return true;
4215
4316
  });
4216
- const [initialized, setInitialized] = (0, import_react3.useState)(false);
4317
+ const [initialized, setInitialized] = (0, import_react4.useState)(false);
4217
4318
  const router = (0, import_hooks2.useCfgRouter)();
4218
4319
  const pathname = (0, import_navigation.usePathname)();
4219
4320
  const queryParams = (0, import_hooks2.useQueryParams)();
4220
4321
  const [storedEmail, setStoredEmail, clearStoredEmail] = (0, import_hooks2.useLocalStorage)(EMAIL_STORAGE_KEY, null);
4221
4322
  const [storedPhone, setStoredPhone, clearStoredPhone] = (0, import_hooks2.useLocalStorage)(PHONE_STORAGE_KEY, null);
4323
+ useTokenRefresh({
4324
+ enabled: true,
4325
+ onRefresh: /* @__PURE__ */ __name((newToken) => {
4326
+ authLogger.info("Token auto-refreshed successfully");
4327
+ }, "onRefresh"),
4328
+ onRefreshError: /* @__PURE__ */ __name((error) => {
4329
+ authLogger.warn("Token auto-refresh failed:", error.message);
4330
+ }, "onRefreshError")
4331
+ });
4222
4332
  const user = accounts.profile;
4223
- const userRef = (0, import_react3.useRef)(user);
4224
- const configRef = (0, import_react3.useRef)(config);
4225
- const isLoadingProfileRef = (0, import_react3.useRef)(false);
4226
- (0, import_react3.useEffect)(() => {
4333
+ const userRef = (0, import_react4.useRef)(user);
4334
+ const configRef = (0, import_react4.useRef)(config);
4335
+ const isLoadingProfileRef = (0, import_react4.useRef)(false);
4336
+ (0, import_react4.useEffect)(() => {
4227
4337
  userRef.current = user;
4228
4338
  }, [user]);
4229
- (0, import_react3.useEffect)(() => {
4339
+ (0, import_react4.useEffect)(() => {
4230
4340
  configRef.current = config;
4231
4341
  }, [config]);
4232
- const clearAuthState = (0, import_react3.useCallback)((caller) => {
4342
+ const clearAuthState = (0, import_react4.useCallback)((caller) => {
4233
4343
  authLogger.info("clearAuthState >> caller", caller);
4234
4344
  api.clearTokens();
4235
4345
  clearProfileCache();
4236
4346
  setInitialized(true);
4237
4347
  setIsLoading(false);
4238
4348
  }, []);
4239
- const handleGlobalAuthError = (0, import_react3.useCallback)((error, context = "API Request") => {
4240
- if (error?.success === false) {
4241
- authLogger.warn(`Error detected in ${context}, clearing tokens`);
4349
+ const handleGlobalAuthError = (0, import_react4.useCallback)((error, context = "API Request") => {
4350
+ const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
4351
+ if (isAuthError) {
4352
+ authLogger.warn(`Authentication error in ${context}, clearing tokens`);
4242
4353
  clearAuthState(`globalAuthError:${context}`);
4243
4354
  return true;
4244
4355
  }
4356
+ if (error?.success === false) {
4357
+ authLogger.warn(`Non-auth error in ${context} (not clearing session):`, error?.message || error);
4358
+ }
4245
4359
  return false;
4246
4360
  }, [clearAuthState]);
4247
- const loadCurrentProfile = (0, import_react3.useCallback)(async (callerId) => {
4361
+ const loadCurrentProfile = (0, import_react4.useCallback)(async (callerId) => {
4248
4362
  const finalCallerId = callerId || "AuthContext.loadCurrentProfile";
4249
4363
  if (isLoadingProfileRef.current) {
4250
4364
  authLogger.debug(`Profile loading already in progress, skipping duplicate call from: ${finalCallerId}`);
@@ -4273,14 +4387,19 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4273
4387
  setInitialized(true);
4274
4388
  } catch (error) {
4275
4389
  authLogger.error("Failed to load profile:", error);
4276
- if (!handleGlobalAuthError(error, "loadCurrentProfile")) {
4277
- clearAuthState("loadCurrentProfile:error");
4390
+ const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
4391
+ if (isAuthError) {
4392
+ authLogger.warn("Authentication error, clearing session");
4393
+ clearAuthState("loadCurrentProfile:authError");
4394
+ } else {
4395
+ authLogger.warn("Profile load failed but keeping session (non-auth error)");
4396
+ setInitialized(true);
4278
4397
  }
4279
4398
  } finally {
4280
4399
  isLoadingProfileRef.current = false;
4281
4400
  }
4282
4401
  }, [clearAuthState, handleGlobalAuthError, accounts]);
4283
- (0, import_react3.useEffect)(() => {
4402
+ (0, import_react4.useEffect)(() => {
4284
4403
  if (initialized) return;
4285
4404
  const initializeAuth = /* @__PURE__ */ __name(async () => {
4286
4405
  authLogger.info("Initializing auth...");
@@ -4320,7 +4439,13 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4320
4439
  await loadCurrentProfile("AuthContext.initializeAuth");
4321
4440
  } catch (error) {
4322
4441
  authLogger.error("Failed to load profile during initialization:", error);
4323
- clearAuthState("initializeAuth:loadProfileFailed");
4442
+ const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
4443
+ if (isAuthError) {
4444
+ clearAuthState("initializeAuth:authError");
4445
+ } else {
4446
+ authLogger.warn("Init profile load failed but keeping session");
4447
+ setInitialized(true);
4448
+ }
4324
4449
  }
4325
4450
  setIsLoading(false);
4326
4451
  } else {
@@ -4330,7 +4455,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4330
4455
  }, "initializeAuth");
4331
4456
  initializeAuth();
4332
4457
  }, [initialized]);
4333
- (0, import_react3.useEffect)(() => {
4458
+ (0, import_react4.useEffect)(() => {
4334
4459
  if (!initialized) return;
4335
4460
  const isAuthenticated = api.isAuthenticated();
4336
4461
  const authRoute = config?.routes?.auth || defaultRoutes.auth;
@@ -4341,15 +4466,15 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4341
4466
  router.push(callbackUrl);
4342
4467
  }
4343
4468
  }, [initialized, pathname, queryParams, config?.routes]);
4344
- const pushToDefaultCallbackUrl = (0, import_react3.useCallback)(() => {
4469
+ const pushToDefaultCallbackUrl = (0, import_react4.useCallback)(() => {
4345
4470
  const callbackUrl = config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
4346
4471
  router.push(callbackUrl);
4347
4472
  }, [config?.routes, router]);
4348
- const pushToDefaultAuthCallbackUrl = (0, import_react3.useCallback)(() => {
4473
+ const pushToDefaultAuthCallbackUrl = (0, import_react4.useCallback)(() => {
4349
4474
  const authCallbackUrl = config?.routes?.defaultAuthCallback || defaultRoutes.defaultAuthCallback;
4350
4475
  router.push(authCallbackUrl);
4351
4476
  }, [config?.routes, router]);
4352
- const checkAuthAndRedirect = (0, import_react3.useCallback)(async () => {
4477
+ const checkAuthAndRedirect = (0, import_react4.useCallback)(async () => {
4353
4478
  try {
4354
4479
  setIsLoading(true);
4355
4480
  const isAuthenticated = api.isAuthenticated();
@@ -4371,7 +4496,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4371
4496
  setIsLoading(false);
4372
4497
  }
4373
4498
  }, [loadCurrentProfile, clearAuthState, pushToDefaultCallbackUrl, pushToDefaultAuthCallbackUrl, handleGlobalAuthError]);
4374
- const requestOTP = (0, import_react3.useCallback)(
4499
+ const requestOTP = (0, import_react4.useCallback)(
4375
4500
  async (identifier, channel, sourceUrl) => {
4376
4501
  api.clearTokens();
4377
4502
  try {
@@ -4399,7 +4524,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4399
4524
  },
4400
4525
  [accounts]
4401
4526
  );
4402
- const verifyOTP = (0, import_react3.useCallback)(
4527
+ const verifyOTP = (0, import_react4.useCallback)(
4403
4528
  async (identifier, otpCode, channel, sourceUrl, redirectUrl, skipRedirect) => {
4404
4529
  try {
4405
4530
  const channelValue = channel === "phone" ? enums_exports.OTPVerifyRequestChannel.PHONE : enums_exports.OTPVerifyRequestChannel.EMAIL;
@@ -4466,7 +4591,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4466
4591
  },
4467
4592
  [setStoredEmail, setStoredPhone, clearStoredEmail, clearStoredPhone, config?.routes?.defaultCallback, accounts, router]
4468
4593
  );
4469
- const refreshToken = (0, import_react3.useCallback)(async () => {
4594
+ const refreshToken = (0, import_react4.useCallback)(async () => {
4470
4595
  try {
4471
4596
  const refreshTokenValue = api.getRefreshToken();
4472
4597
  if (!refreshTokenValue) {
@@ -4499,7 +4624,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4499
4624
  };
4500
4625
  }
4501
4626
  }, [clearAuthState, accounts]);
4502
- const logout = (0, import_react3.useCallback)(async () => {
4627
+ const logout = (0, import_react4.useCallback)(async () => {
4503
4628
  const performLogout = /* @__PURE__ */ __name(() => {
4504
4629
  Analytics.event("auth_logout" /* AUTH_LOGOUT */, {
4505
4630
  category: "auth" /* AUTH */
@@ -4528,10 +4653,10 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4528
4653
  }
4529
4654
  }
4530
4655
  }, [accounts, config?.routes?.defaultAuthCallback, router]);
4531
- const isAdminUser = (0, import_react3.useMemo)(() => {
4656
+ const isAdminUser = (0, import_react4.useMemo)(() => {
4532
4657
  return Boolean(user?.is_staff || user?.is_superuser);
4533
4658
  }, [user]);
4534
- const value = (0, import_react3.useMemo)(
4659
+ const value = (0, import_react4.useMemo)(
4535
4660
  () => ({
4536
4661
  user,
4537
4662
  isLoading,
@@ -4583,7 +4708,7 @@ var AuthProvider = /* @__PURE__ */ __name(({ children, config }) => {
4583
4708
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AccountsProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthProviderInternal, { config, children }) });
4584
4709
  }, "AuthProvider");
4585
4710
  var useAuth = /* @__PURE__ */ __name(() => {
4586
- const context = (0, import_react3.useContext)(AuthContext);
4711
+ const context = (0, import_react4.useContext)(AuthContext);
4587
4712
  if (context === void 0) {
4588
4713
  throw new Error("useAuth must be used within an AuthProvider");
4589
4714
  }
@@ -4591,20 +4716,20 @@ var useAuth = /* @__PURE__ */ __name(() => {
4591
4716
  }, "useAuth");
4592
4717
 
4593
4718
  // src/auth/hooks/useAuthFormState.ts
4594
- var import_react4 = require("react");
4719
+ var import_react5 = require("react");
4595
4720
  var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialChannel = "email") => {
4596
- const [identifier, setIdentifier] = (0, import_react4.useState)(initialIdentifier);
4597
- const [channel, setChannel] = (0, import_react4.useState)(initialChannel);
4598
- const [otp, setOtp] = (0, import_react4.useState)("");
4599
- const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
4600
- const [acceptedTerms, setAcceptedTerms] = (0, import_react4.useState)(false);
4601
- const [step, setStep] = (0, import_react4.useState)("identifier");
4602
- const [error, setError] = (0, import_react4.useState)("");
4603
- const [twoFactorSessionId, setTwoFactorSessionId] = (0, import_react4.useState)(null);
4604
- const [shouldPrompt2FA, setShouldPrompt2FA] = (0, import_react4.useState)(false);
4605
- const [twoFactorCode, setTwoFactorCode] = (0, import_react4.useState)("");
4606
- const [useBackupCode, setUseBackupCode] = (0, import_react4.useState)(false);
4607
- const clearError = (0, import_react4.useCallback)(() => setError(""), []);
4721
+ const [identifier, setIdentifier] = (0, import_react5.useState)(initialIdentifier);
4722
+ const [channel, setChannel] = (0, import_react5.useState)(initialChannel);
4723
+ const [otp, setOtp] = (0, import_react5.useState)("");
4724
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
4725
+ const [acceptedTerms, setAcceptedTerms] = (0, import_react5.useState)(false);
4726
+ const [step, setStep] = (0, import_react5.useState)("identifier");
4727
+ const [error, setError] = (0, import_react5.useState)("");
4728
+ const [twoFactorSessionId, setTwoFactorSessionId] = (0, import_react5.useState)(null);
4729
+ const [shouldPrompt2FA, setShouldPrompt2FA] = (0, import_react5.useState)(false);
4730
+ const [twoFactorCode, setTwoFactorCode] = (0, import_react5.useState)("");
4731
+ const [useBackupCode, setUseBackupCode] = (0, import_react5.useState)(false);
4732
+ const clearError = (0, import_react5.useCallback)(() => setError(""), []);
4608
4733
  return {
4609
4734
  // State
4610
4735
  identifier,
@@ -4635,11 +4760,11 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialCh
4635
4760
  }, "useAuthFormState");
4636
4761
 
4637
4762
  // src/auth/hooks/useAuthValidation.ts
4638
- var import_react5 = require("react");
4763
+ var import_react6 = require("react");
4639
4764
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4640
4765
  var PHONE_REGEX = /^\+[1-9]\d{6,14}$/;
4641
4766
  var useAuthValidation = /* @__PURE__ */ __name(() => {
4642
- const detectChannelFromIdentifier2 = (0, import_react5.useCallback)((id) => {
4767
+ const detectChannelFromIdentifier2 = (0, import_react6.useCallback)((id) => {
4643
4768
  if (!id) return null;
4644
4769
  if (id.includes("@")) {
4645
4770
  return "email";
@@ -4649,7 +4774,7 @@ var useAuthValidation = /* @__PURE__ */ __name(() => {
4649
4774
  }
4650
4775
  return null;
4651
4776
  }, []);
4652
- const validateIdentifier2 = (0, import_react5.useCallback)((id, channelType) => {
4777
+ const validateIdentifier2 = (0, import_react6.useCallback)((id, channelType) => {
4653
4778
  if (!id) return false;
4654
4779
  const channel = channelType || detectChannelFromIdentifier2(id);
4655
4780
  if (channel === "email") {
@@ -4680,11 +4805,11 @@ var validateIdentifier = /* @__PURE__ */ __name((id, channelType) => {
4680
4805
  }, "validateIdentifier");
4681
4806
 
4682
4807
  // src/auth/hooks/useAuthForm.ts
4683
- var import_react8 = require("react");
4808
+ var import_react9 = require("react");
4684
4809
 
4685
4810
  // src/auth/hooks/useAutoAuth.ts
4686
4811
  var import_navigation2 = require("next/navigation");
4687
- var import_react6 = require("react");
4812
+ var import_react7 = require("react");
4688
4813
  var import_hooks3 = require("@djangocfg/ui-nextjs/hooks");
4689
4814
  var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
4690
4815
  const { onOTPDetected, cleanupUrl = true, allowedPaths = ["/auth"] } = options;
@@ -4694,7 +4819,7 @@ var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
4694
4819
  const isAllowedPath = allowedPaths.some((path) => pathname === path || pathname?.startsWith(path + "/"));
4695
4820
  const hasOTP = !!queryParams.get("otp");
4696
4821
  const isReady = !!pathname && hasOTP && isAllowedPath;
4697
- (0, import_react6.useEffect)(() => {
4822
+ (0, import_react7.useEffect)(() => {
4698
4823
  if (!isReady) return;
4699
4824
  const queryOtp = queryParams.get("otp");
4700
4825
  if (queryOtp && typeof queryOtp === "string" && queryOtp.length === 6) {
@@ -4716,7 +4841,7 @@ var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
4716
4841
  }, "useAutoAuth");
4717
4842
 
4718
4843
  // src/auth/hooks/useTwoFactor.ts
4719
- var import_react7 = require("react");
4844
+ var import_react8 = require("react");
4720
4845
  var import_hooks4 = require("@djangocfg/ui-nextjs/hooks");
4721
4846
 
4722
4847
  // src/generated/cfg_totp/totp__backup_codes/client.ts
@@ -5757,14 +5882,14 @@ var apiCentrifugo = new API2(apiUrl2, { storage });
5757
5882
  var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
5758
5883
  const { onSuccess, onError, redirectUrl, skipRedirect = false } = options;
5759
5884
  const router = (0, import_hooks4.useCfgRouter)();
5760
- const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
5761
- const [error, setError] = (0, import_react7.useState)(null);
5762
- const [warning, setWarning] = (0, import_react7.useState)(null);
5763
- const [remainingBackupCodes, setRemainingBackupCodes] = (0, import_react7.useState)(null);
5764
- const clearError = (0, import_react7.useCallback)(() => {
5885
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
5886
+ const [error, setError] = (0, import_react8.useState)(null);
5887
+ const [warning, setWarning] = (0, import_react8.useState)(null);
5888
+ const [remainingBackupCodes, setRemainingBackupCodes] = (0, import_react8.useState)(null);
5889
+ const clearError = (0, import_react8.useCallback)(() => {
5765
5890
  setError(null);
5766
5891
  }, []);
5767
- const handleSuccess = (0, import_react7.useCallback)((response) => {
5892
+ const handleSuccess = (0, import_react8.useCallback)((response) => {
5768
5893
  apiAccounts.setToken(response.access_token, response.refresh_token);
5769
5894
  if (response.warning) {
5770
5895
  setWarning(response.warning);
@@ -5786,7 +5911,7 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
5786
5911
  router.hardPush(finalRedirectUrl);
5787
5912
  }
5788
5913
  }, [onSuccess, redirectUrl, router, skipRedirect]);
5789
- const verifyTOTP = (0, import_react7.useCallback)(async (sessionId, code) => {
5914
+ const verifyTOTP = (0, import_react8.useCallback)(async (sessionId, code) => {
5790
5915
  if (!sessionId) {
5791
5916
  const msg = "Missing 2FA session ID";
5792
5917
  setError(msg);
@@ -5826,7 +5951,7 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
5826
5951
  setIsLoading(false);
5827
5952
  }
5828
5953
  }, [handleSuccess, onError]);
5829
- const verifyBackupCode = (0, import_react7.useCallback)(async (sessionId, backupCode) => {
5954
+ const verifyBackupCode = (0, import_react8.useCallback)(async (sessionId, backupCode) => {
5830
5955
  if (!sessionId) {
5831
5956
  const msg = "Missing 2FA session ID";
5832
5957
  setError(msg);
@@ -5892,7 +6017,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5892
6017
  } = options;
5893
6018
  const formState = useAuthFormState();
5894
6019
  const validation = useAuthValidation();
5895
- const isAutoSubmitFromUrlRef = (0, import_react8.useRef)(false);
6020
+ const isAutoSubmitFromUrlRef = (0, import_react9.useRef)(false);
5896
6021
  const {
5897
6022
  requestOTP,
5898
6023
  verifyOTP,
@@ -5939,7 +6064,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5939
6064
  // We handle navigation via success step
5940
6065
  });
5941
6066
  const { detectChannelFromIdentifier: detectChannelFromIdentifier2, validateIdentifier: validateIdentifier2 } = validation;
5942
- const saveIdentifierToStorage = (0, import_react8.useCallback)((id, ch) => {
6067
+ const saveIdentifierToStorage = (0, import_react9.useCallback)((id, ch) => {
5943
6068
  if (ch === "email") {
5944
6069
  saveEmail(id);
5945
6070
  clearSavedPhone();
@@ -5948,7 +6073,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5948
6073
  clearSavedEmail();
5949
6074
  }
5950
6075
  }, [saveEmail, savePhone, clearSavedEmail, clearSavedPhone]);
5951
- (0, import_react8.useEffect)(() => {
6076
+ (0, import_react9.useEffect)(() => {
5952
6077
  const savedPhone = getSavedPhone();
5953
6078
  const savedEmail = getSavedEmail();
5954
6079
  if (savedPhone) {
@@ -5959,7 +6084,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5959
6084
  setChannel("email");
5960
6085
  }
5961
6086
  }, [getSavedEmail, getSavedPhone, setIdentifier, setChannel]);
5962
- (0, import_react8.useEffect)(() => {
6087
+ (0, import_react9.useEffect)(() => {
5963
6088
  if (identifier) {
5964
6089
  const detected = detectChannelFromIdentifier2(identifier);
5965
6090
  if (detected && detected !== channel) {
@@ -5967,7 +6092,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5967
6092
  }
5968
6093
  }
5969
6094
  }, [identifier, channel, detectChannelFromIdentifier2, setChannel]);
5970
- const handleIdentifierSubmit = (0, import_react8.useCallback)(async (e) => {
6095
+ const handleIdentifierSubmit = (0, import_react9.useCallback)(async (e) => {
5971
6096
  e.preventDefault();
5972
6097
  if (!identifier) {
5973
6098
  const msg = channel === "phone" ? "Please enter your phone number" : "Please enter your email address";
@@ -6022,7 +6147,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6022
6147
  onError,
6023
6148
  sourceUrl
6024
6149
  ]);
6025
- const submitOTP = (0, import_react8.useCallback)(async (submitIdentifier, submitOtp, submitChannel) => {
6150
+ const submitOTP = (0, import_react9.useCallback)(async (submitIdentifier, submitOtp, submitChannel) => {
6026
6151
  if (!submitOtp || submitOtp.length < 6) {
6027
6152
  const msg = "Please enter the 6-digit verification code";
6028
6153
  setError(msg);
@@ -6072,11 +6197,11 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6072
6197
  setIsLoading(false);
6073
6198
  }
6074
6199
  }, [verifyOTP, saveIdentifierToStorage, setError, setIsLoading, clearError, onOTPSuccess, onError, sourceUrl, redirectUrl, setTwoFactorSessionId, setShouldPrompt2FA, setStep, enable2FASetup]);
6075
- const handleOTPSubmit = (0, import_react8.useCallback)(async (e) => {
6200
+ const handleOTPSubmit = (0, import_react9.useCallback)(async (e) => {
6076
6201
  e.preventDefault();
6077
6202
  await submitOTP(identifier, otp, channel);
6078
6203
  }, [identifier, otp, channel, submitOTP]);
6079
- const handleResendOTP = (0, import_react8.useCallback)(async () => {
6204
+ const handleResendOTP = (0, import_react9.useCallback)(async () => {
6080
6205
  setIsLoading(true);
6081
6206
  clearError();
6082
6207
  try {
@@ -6096,15 +6221,15 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6096
6221
  setIsLoading(false);
6097
6222
  }
6098
6223
  }, [identifier, channel, requestOTP, saveIdentifierToStorage, setOtp, setError, setIsLoading, clearError, onError, sourceUrl]);
6099
- const handleBackToIdentifier = (0, import_react8.useCallback)(() => {
6224
+ const handleBackToIdentifier = (0, import_react9.useCallback)(() => {
6100
6225
  setStep("identifier");
6101
6226
  clearError();
6102
6227
  }, [setStep, clearError]);
6103
- const forceOTPStep = (0, import_react8.useCallback)(() => {
6228
+ const forceOTPStep = (0, import_react9.useCallback)(() => {
6104
6229
  setStep("otp");
6105
6230
  clearError();
6106
6231
  }, [setStep, clearError]);
6107
- const handle2FASubmit = (0, import_react8.useCallback)(async (e) => {
6232
+ const handle2FASubmit = (0, import_react9.useCallback)(async (e) => {
6108
6233
  e.preventDefault();
6109
6234
  if (!twoFactorSessionId) {
6110
6235
  const msg = "Missing 2FA session";
@@ -6118,12 +6243,12 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6118
6243
  await twoFactor.verifyTOTP(twoFactorSessionId, twoFactorCode);
6119
6244
  }
6120
6245
  }, [twoFactorSessionId, twoFactorCode, useBackupCode, twoFactor, setError, onError]);
6121
- const handleUseBackupCode = (0, import_react8.useCallback)(() => {
6246
+ const handleUseBackupCode = (0, import_react9.useCallback)(() => {
6122
6247
  setUseBackupCode(true);
6123
6248
  setTwoFactorCode("");
6124
6249
  clearError();
6125
6250
  }, [setUseBackupCode, setTwoFactorCode, clearError]);
6126
- const handleUseTOTP = (0, import_react8.useCallback)(() => {
6251
+ const handleUseTOTP = (0, import_react9.useCallback)(() => {
6127
6252
  setUseBackupCode(false);
6128
6253
  setTwoFactorCode("");
6129
6254
  clearError();
@@ -6188,14 +6313,14 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6188
6313
  }, "useAuthForm");
6189
6314
 
6190
6315
  // src/auth/hooks/useGithubAuth.ts
6191
- var import_react9 = require("react");
6316
+ var import_react10 = require("react");
6192
6317
  var import_hooks5 = require("@djangocfg/ui-nextjs/hooks");
6193
6318
  var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
6194
6319
  const { sourceUrl, onSuccess, onError, onRequires2FA, redirectUrl, skipRedirect = false } = options;
6195
6320
  const router = (0, import_hooks5.useCfgRouter)();
6196
- const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
6197
- const [error, setError] = (0, import_react9.useState)(null);
6198
- const startGithubAuth = (0, import_react9.useCallback)(async () => {
6321
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
6322
+ const [error, setError] = (0, import_react10.useState)(null);
6323
+ const startGithubAuth = (0, import_react10.useCallback)(async () => {
6199
6324
  setIsLoading(true);
6200
6325
  setError(null);
6201
6326
  try {
@@ -6229,7 +6354,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
6229
6354
  setIsLoading(false);
6230
6355
  }
6231
6356
  }, [sourceUrl, onError]);
6232
- const handleGithubCallback = (0, import_react9.useCallback)(async (code, state) => {
6357
+ const handleGithubCallback = (0, import_react10.useCallback)(async (code, state) => {
6233
6358
  setIsLoading(true);
6234
6359
  setError(null);
6235
6360
  try {
@@ -6294,26 +6419,26 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
6294
6419
  }, "useGithubAuth");
6295
6420
 
6296
6421
  // src/auth/hooks/useTwoFactorSetup.ts
6297
- var import_react10 = require("react");
6422
+ var import_react11 = require("react");
6298
6423
  var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
6299
6424
  const { onComplete, onError } = options;
6300
- const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
6301
- const [error, setError] = (0, import_react10.useState)(null);
6302
- const [setupData, setSetupData] = (0, import_react10.useState)(null);
6303
- const [backupCodes, setBackupCodes] = (0, import_react10.useState)(null);
6304
- const [backupCodesWarning, setBackupCodesWarning] = (0, import_react10.useState)(null);
6305
- const [setupStep, setSetupStep] = (0, import_react10.useState)("idle");
6306
- const clearError = (0, import_react10.useCallback)(() => {
6425
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
6426
+ const [error, setError] = (0, import_react11.useState)(null);
6427
+ const [setupData, setSetupData] = (0, import_react11.useState)(null);
6428
+ const [backupCodes, setBackupCodes] = (0, import_react11.useState)(null);
6429
+ const [backupCodesWarning, setBackupCodesWarning] = (0, import_react11.useState)(null);
6430
+ const [setupStep, setSetupStep] = (0, import_react11.useState)("idle");
6431
+ const clearError = (0, import_react11.useCallback)(() => {
6307
6432
  setError(null);
6308
6433
  }, []);
6309
- const resetSetup = (0, import_react10.useCallback)(() => {
6434
+ const resetSetup = (0, import_react11.useCallback)(() => {
6310
6435
  setSetupData(null);
6311
6436
  setBackupCodes(null);
6312
6437
  setBackupCodesWarning(null);
6313
6438
  setSetupStep("idle");
6314
6439
  setError(null);
6315
6440
  }, []);
6316
- const startSetup = (0, import_react10.useCallback)(async (deviceName) => {
6441
+ const startSetup = (0, import_react11.useCallback)(async (deviceName) => {
6317
6442
  setIsLoading(true);
6318
6443
  setError(null);
6319
6444
  setSetupStep("scanning");
@@ -6343,7 +6468,7 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
6343
6468
  setIsLoading(false);
6344
6469
  }
6345
6470
  }, [onError]);
6346
- const confirmSetup = (0, import_react10.useCallback)(async (code) => {
6471
+ const confirmSetup = (0, import_react11.useCallback)(async (code) => {
6347
6472
  if (!setupData) {
6348
6473
  const msg = "Setup not started. Call startSetup() first.";
6349
6474
  setError(msg);
@@ -6398,16 +6523,16 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
6398
6523
  }, "useTwoFactorSetup");
6399
6524
 
6400
6525
  // src/auth/hooks/useTwoFactorStatus.ts
6401
- var import_react11 = require("react");
6526
+ var import_react12 = require("react");
6402
6527
  var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
6403
- const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
6404
- const [error, setError] = (0, import_react11.useState)(null);
6405
- const [has2FAEnabled, setHas2FAEnabled] = (0, import_react11.useState)(null);
6406
- const [devices, setDevices] = (0, import_react11.useState)([]);
6407
- const clearError = (0, import_react11.useCallback)(() => {
6528
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
6529
+ const [error, setError] = (0, import_react12.useState)(null);
6530
+ const [has2FAEnabled, setHas2FAEnabled] = (0, import_react12.useState)(null);
6531
+ const [devices, setDevices] = (0, import_react12.useState)([]);
6532
+ const clearError = (0, import_react12.useCallback)(() => {
6408
6533
  setError(null);
6409
6534
  }, []);
6410
- const fetchStatus = (0, import_react11.useCallback)(async () => {
6535
+ const fetchStatus = (0, import_react12.useCallback)(async () => {
6411
6536
  setIsLoading(true);
6412
6537
  setError(null);
6413
6538
  try {
@@ -6432,7 +6557,7 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
6432
6557
  setIsLoading(false);
6433
6558
  }
6434
6559
  }, []);
6435
- const disable2FA = (0, import_react11.useCallback)(async (code) => {
6560
+ const disable2FA = (0, import_react12.useCallback)(async (code) => {
6436
6561
  if (!code || code.length !== 6) {
6437
6562
  setError("Please enter a 6-digit code");
6438
6563
  return false;
@@ -6467,14 +6592,14 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
6467
6592
  }, "useTwoFactorStatus");
6468
6593
 
6469
6594
  // src/auth/hooks/useAuthGuard.ts
6470
- var import_react12 = require("react");
6595
+ var import_react13 = require("react");
6471
6596
  var import_hooks6 = require("@djangocfg/ui-nextjs/hooks");
6472
6597
  var useAuthGuard = /* @__PURE__ */ __name((options = {}) => {
6473
6598
  const { redirectTo = "/auth", requireAuth = true, saveRedirectUrl: shouldSaveUrl = true } = options;
6474
6599
  const { isAuthenticated, isLoading, saveRedirectUrl } = useAuth();
6475
6600
  const router = (0, import_hooks6.useCfgRouter)();
6476
- const [isRedirecting, setIsRedirecting] = (0, import_react12.useState)(false);
6477
- (0, import_react12.useEffect)(() => {
6601
+ const [isRedirecting, setIsRedirecting] = (0, import_react13.useState)(false);
6602
+ (0, import_react13.useEffect)(() => {
6478
6603
  if (!isLoading && requireAuth && !isAuthenticated && !isRedirecting) {
6479
6604
  if (shouldSaveUrl && typeof window !== "undefined") {
6480
6605
  const currentUrl = window.location.pathname + window.location.search;
@@ -6488,9 +6613,9 @@ var useAuthGuard = /* @__PURE__ */ __name((options = {}) => {
6488
6613
  }, "useAuthGuard");
6489
6614
 
6490
6615
  // src/auth/hooks/useLocalStorage.ts
6491
- var import_react13 = require("react");
6616
+ var import_react14 = require("react");
6492
6617
  function useLocalStorage2(key, initialValue) {
6493
- const [storedValue, setStoredValue] = (0, import_react13.useState)(() => {
6618
+ const [storedValue, setStoredValue] = (0, import_react14.useState)(() => {
6494
6619
  if (typeof window === "undefined") {
6495
6620
  return initialValue;
6496
6621
  }