@djangocfg/api 2.1.546 → 2.1.548

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.
Files changed (44) hide show
  1. package/README.md +25 -0
  2. package/dist/auth.cjs +339 -73
  3. package/dist/auth.cjs.map +1 -1
  4. package/dist/auth.d.cts +106 -2
  5. package/dist/auth.d.ts +106 -2
  6. package/dist/auth.mjs +339 -73
  7. package/dist/auth.mjs.map +1 -1
  8. package/dist/clients.cjs +18 -0
  9. package/dist/clients.cjs.map +1 -1
  10. package/dist/clients.d.cts +96 -0
  11. package/dist/clients.d.ts +96 -0
  12. package/dist/clients.mjs +18 -0
  13. package/dist/clients.mjs.map +1 -1
  14. package/dist/hooks.cjs.map +1 -1
  15. package/dist/hooks.mjs.map +1 -1
  16. package/dist/index.cjs +18 -0
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +171 -3
  19. package/dist/index.d.ts +171 -3
  20. package/dist/index.mjs +18 -0
  21. package/dist/index.mjs.map +1 -1
  22. package/package.json +2 -2
  23. package/src/_api/generated/_cfg_accounts/hooks/index.ts +1 -0
  24. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenCreate.ts +64 -0
  25. package/src/_api/generated/_cfg_accounts/openapi.json +157 -0
  26. package/src/_api/generated/_cfg_accounts/schemas/PasswordLoginError.ts +13 -0
  27. package/src/_api/generated/_cfg_accounts/schemas/PasswordLoginRequest.ts +13 -0
  28. package/src/_api/generated/_cfg_accounts/schemas/PasswordLoginResponse.ts +18 -0
  29. package/src/_api/generated/_cfg_accounts/schemas/index.ts +3 -0
  30. package/src/_api/generated/openapi.json +157 -0
  31. package/src/_api/generated/sdk.gen.ts +20 -1
  32. package/src/_api/generated/types.gen.ts +149 -0
  33. package/src/auth/__tests__/guard.test.ts +65 -0
  34. package/src/auth/__tests__/passwordLogin.test.tsx +239 -0
  35. package/src/auth/context/AccountsContext.tsx +32 -7
  36. package/src/auth/context/AuthContext.tsx +104 -1
  37. package/src/auth/context/types.ts +10 -1
  38. package/src/auth/hooks/useAuthForm.ts +84 -0
  39. package/src/auth/hooks/useAuthFormState.ts +3 -0
  40. package/src/auth/types/form.ts +41 -1
  41. package/src/auth/types/index.ts +2 -0
  42. package/src/auth/utils/analytics.ts +1 -0
  43. package/src/auth/utils/guard.ts +27 -1
  44. package/src/auth/utils/index.ts +1 -0
package/dist/auth.mjs CHANGED
@@ -973,6 +973,7 @@ var formatCountdown = /* @__PURE__ */ __name((s) => {
973
973
  var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "") => {
974
974
  const [identifier, setIdentifier] = useState2(initialIdentifier);
975
975
  const [otp, setOtp] = useState2("");
976
+ const [password, setPassword] = useState2("");
976
977
  const [isLoading, setIsLoading] = useState2(false);
977
978
  const [acceptedTerms, setAcceptedTerms] = useState2(true);
978
979
  const [marketingConsent, setMarketingConsent] = useState2(null);
@@ -1008,6 +1009,7 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "") => {
1008
1009
  // State
1009
1010
  identifier,
1010
1011
  otp,
1012
+ password,
1011
1013
  isLoading,
1012
1014
  acceptedTerms,
1013
1015
  marketingConsent,
@@ -1025,6 +1027,7 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "") => {
1025
1027
  // Handlers
1026
1028
  setIdentifier,
1027
1029
  setOtp,
1030
+ setPassword,
1028
1031
  setAcceptedTerms,
1029
1032
  setMarketingConsent,
1030
1033
  setRememberMe,
@@ -2239,6 +2242,24 @@ var CfgAccountsAuth = class {
2239
2242
  static {
2240
2243
  __name(this, "CfgAccountsAuth");
2241
2244
  }
2245
+ /**
2246
+ * Obtain a JWT pair with email + password.
2247
+ *
2248
+ * Returns the same envelope as OTP verify: either ``requires_2fa=True`` with
2249
+ * a session id, or the token pair plus the user object. Failures are uniform
2250
+ * (401 ``invalid_credentials``) whether the email is unknown, the password is
2251
+ * wrong, or the account is inactive/soft-deleted — no enumeration.
2252
+ */
2253
+ static cfgAccountsTokenCreate(options) {
2254
+ return (options.client ?? client).post({
2255
+ url: "/cfg/accounts/token/",
2256
+ ...options,
2257
+ headers: {
2258
+ "Content-Type": "application/json",
2259
+ ...options.headers
2260
+ }
2261
+ });
2262
+ }
2242
2263
  /**
2243
2264
  * Revoke a refresh token (logout).
2244
2265
  *
@@ -2427,6 +2448,7 @@ var AnalyticsEvent = /* @__PURE__ */ ((AnalyticsEvent2) => {
2427
2448
  AnalyticsEvent2["AUTH_OTP_REQUEST"] = "auth_otp_request";
2428
2449
  AnalyticsEvent2["AUTH_LOGIN_SUCCESS"] = "auth_login_success";
2429
2450
  AnalyticsEvent2["AUTH_OTP_VERIFY_FAIL"] = "auth_otp_verify_fail";
2451
+ AnalyticsEvent2["AUTH_PASSWORD_LOGIN_FAIL"] = "auth_password_login_fail";
2430
2452
  AnalyticsEvent2["AUTH_SESSION_EXPIRED"] = "auth_session_expired";
2431
2453
  AnalyticsEvent2["AUTH_TOKEN_REFRESH"] = "auth_token_refresh";
2432
2454
  AnalyticsEvent2["AUTH_TOKEN_REFRESH_FAIL"] = "auth_token_refresh_fail";
@@ -2866,12 +2888,14 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
2866
2888
  const {
2867
2889
  requestOTP,
2868
2890
  verifyOTP,
2891
+ login,
2869
2892
  getSavedEmail,
2870
2893
  saveEmail
2871
2894
  } = useAuth();
2872
2895
  const {
2873
2896
  identifier,
2874
2897
  otp,
2898
+ password,
2875
2899
  acceptedTerms,
2876
2900
  marketingConsent,
2877
2901
  rememberMe,
@@ -3023,6 +3047,78 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
3023
3047
  e.preventDefault();
3024
3048
  await submitOTP(identifier, otp);
3025
3049
  }, [identifier, otp, submitOTP]);
3050
+ const submitPassword = useCallback5(async (submitIdentifier, submitPassword_) => {
3051
+ if (!submitIdentifier || !validateIdentifier2(submitIdentifier)) {
3052
+ const msg = "Please enter a valid email address";
3053
+ setError(msg);
3054
+ onError?.(msg);
3055
+ return false;
3056
+ }
3057
+ if (!submitPassword_) {
3058
+ const msg = "Please enter your password";
3059
+ setError(msg);
3060
+ onError?.(msg);
3061
+ return false;
3062
+ }
3063
+ setIsLoading(true);
3064
+ clearError();
3065
+ try {
3066
+ const result = await login(submitIdentifier, submitPassword_, {
3067
+ redirectUrl,
3068
+ skipRedirect: true,
3069
+ rememberMe
3070
+ });
3071
+ if (result.requires_2fa && result.session_id) {
3072
+ authLogger.info("2FA required after password login");
3073
+ setTwoFactorSessionId(result.session_id);
3074
+ setShouldPrompt2FA(result.should_prompt_2fa || false);
3075
+ setStep("2fa");
3076
+ saveIdentifierToStorage(submitIdentifier);
3077
+ return true;
3078
+ }
3079
+ if (result.success) {
3080
+ saveIdentifierToStorage(submitIdentifier);
3081
+ authLogger.info("Password login successful, showing success screen");
3082
+ setStep("success");
3083
+ onOTPSuccess?.();
3084
+ return true;
3085
+ }
3086
+ if (result.retryAfter) {
3087
+ startRateLimitCountdown(result.retryAfter);
3088
+ clearError();
3089
+ } else {
3090
+ setError(result.message);
3091
+ onError?.(result.message);
3092
+ }
3093
+ return false;
3094
+ } catch {
3095
+ const msg = "An unexpected error occurred";
3096
+ setError(msg);
3097
+ onError?.(msg);
3098
+ return false;
3099
+ } finally {
3100
+ setIsLoading(false);
3101
+ }
3102
+ }, [
3103
+ login,
3104
+ validateIdentifier2,
3105
+ saveIdentifierToStorage,
3106
+ setError,
3107
+ setIsLoading,
3108
+ clearError,
3109
+ startRateLimitCountdown,
3110
+ onOTPSuccess,
3111
+ onError,
3112
+ redirectUrl,
3113
+ rememberMe,
3114
+ setTwoFactorSessionId,
3115
+ setShouldPrompt2FA,
3116
+ setStep
3117
+ ]);
3118
+ const handlePasswordSubmit = useCallback5(async (e) => {
3119
+ e.preventDefault();
3120
+ await submitPassword(identifier, password);
3121
+ }, [identifier, password, submitPassword]);
3026
3122
  const handleResendOTP = useCallback5(async () => {
3027
3123
  setIsLoading(true);
3028
3124
  clearError();
@@ -3116,6 +3212,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
3116
3212
  // Submit handlers
3117
3213
  handleIdentifierSubmit,
3118
3214
  handleOTPSubmit,
3215
+ handlePasswordSubmit,
3119
3216
  handleResendOTP,
3120
3217
  handleBackToIdentifier,
3121
3218
  forceOTPStep,
@@ -4227,119 +4324,197 @@ __name(useCfgAccountsProfileUpdateUpdate, "useCfgAccountsProfileUpdateUpdate");
4227
4324
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenBlacklistCreate.ts
4228
4325
  import useSWRMutation15 from "swr/mutation";
4229
4326
 
4230
- // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenRefreshCreate.ts
4327
+ // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenCreate.ts
4231
4328
  import useSWRMutation16 from "swr/mutation";
4232
4329
 
4233
- // src/_api/generated/_cfg_accounts/schemas/TokenRefresh.ts
4330
+ // src/_api/generated/_cfg_accounts/schemas/PasswordLoginResponse.ts
4234
4331
  import { z as z20 } from "zod";
4235
- var TokenRefreshSchema = z20.object({
4236
- access: z20.string(),
4237
- refresh: z20.string()
4332
+ var PasswordLoginResponseSchema = z20.object({
4333
+ requires_2fa: z20.boolean().default(false).optional(),
4334
+ session_id: z20.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i).nullable().optional(),
4335
+ refresh: z20.string().nullable().optional(),
4336
+ access: z20.string().nullable().optional(),
4337
+ user: UserSchema.nullable().optional(),
4338
+ should_prompt_2fa: z20.boolean().optional(),
4339
+ persistent_session: z20.boolean().optional()
4238
4340
  });
4239
4341
 
4240
- // src/_api/generated/_cfg_accounts/schemas/APIKeyRequest.ts
4342
+ // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenCreate.ts
4343
+ function useCfgAccountsTokenCreate(config) {
4344
+ return useSWRMutation16(
4345
+ ["cfg_accounts_token_create"],
4346
+ async (_key, { arg }) => {
4347
+ const res = await CfgAccountsAuth.cfgAccountsTokenCreate({ ...arg, throwOnError: true });
4348
+ const data = res.data;
4349
+ const parsed = PasswordLoginResponseSchema.safeParse(data);
4350
+ if (!parsed.success) {
4351
+ console.warn(
4352
+ "[zod] response did not match schema",
4353
+ {
4354
+ operation: "cfg_accounts_token_create",
4355
+ method: "POST",
4356
+ path: "/cfg/accounts/token/",
4357
+ issues: parsed.error.issues,
4358
+ data
4359
+ }
4360
+ );
4361
+ if (typeof window !== "undefined") {
4362
+ try {
4363
+ window.dispatchEvent(
4364
+ new CustomEvent("zod-validation-error", {
4365
+ detail: {
4366
+ operation: "cfg_accounts_token_create",
4367
+ method: "POST",
4368
+ path: "/cfg/accounts/token/",
4369
+ issues: parsed.error.issues,
4370
+ data,
4371
+ timestamp: /* @__PURE__ */ new Date()
4372
+ },
4373
+ bubbles: true,
4374
+ cancelable: false
4375
+ })
4376
+ );
4377
+ } catch {
4378
+ }
4379
+ }
4380
+ return data;
4381
+ }
4382
+ return parsed.data;
4383
+ },
4384
+ config
4385
+ );
4386
+ }
4387
+ __name(useCfgAccountsTokenCreate, "useCfgAccountsTokenCreate");
4388
+
4389
+ // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenRefreshCreate.ts
4390
+ import useSWRMutation17 from "swr/mutation";
4391
+
4392
+ // src/_api/generated/_cfg_accounts/schemas/TokenRefresh.ts
4241
4393
  import { z as z21 } from "zod";
4242
- var APIKeyRequestSchema = z21.object({
4243
- key: z21.string().min(1),
4244
- reissued_at: z21.string().datetime({ offset: true }).nullable(),
4245
- created_at: z21.string().datetime({ offset: true })
4394
+ var TokenRefreshSchema = z21.object({
4395
+ access: z21.string(),
4396
+ refresh: z21.string()
4246
4397
  });
4247
4398
 
4248
- // src/_api/generated/_cfg_accounts/schemas/APIKeyTestRequest.ts
4399
+ // src/_api/generated/_cfg_accounts/schemas/APIKeyRequest.ts
4249
4400
  import { z as z22 } from "zod";
4250
- var APIKeyTestRequestSchema = z22.object({
4251
- key: z22.string().min(1)
4401
+ var APIKeyRequestSchema = z22.object({
4402
+ key: z22.string().min(1),
4403
+ reissued_at: z22.string().datetime({ offset: true }).nullable(),
4404
+ created_at: z22.string().datetime({ offset: true })
4252
4405
  });
4253
4406
 
4254
- // src/_api/generated/_cfg_accounts/schemas/CfgUserUpdateRequest.ts
4407
+ // src/_api/generated/_cfg_accounts/schemas/APIKeyTestRequest.ts
4255
4408
  import { z as z23 } from "zod";
4256
- var CfgUserUpdateRequestSchema = z23.object({
4257
- first_name: z23.string().max(50).optional(),
4258
- last_name: z23.string().max(50).optional(),
4259
- company: z23.string().max(100).optional(),
4260
- phone: z23.string().max(20).optional(),
4261
- position: z23.string().max(100).optional(),
4262
- language: z23.string().max(10).optional(),
4263
- timezone: z23.string().max(64).optional()
4409
+ var APIKeyTestRequestSchema = z23.object({
4410
+ key: z23.string().min(1)
4264
4411
  });
4265
4412
 
4266
- // src/_api/generated/_cfg_accounts/schemas/OAuthAuthorizeRequestRequest.ts
4413
+ // src/_api/generated/_cfg_accounts/schemas/CfgUserUpdateRequest.ts
4267
4414
  import { z as z24 } from "zod";
4268
- var OAuthAuthorizeRequestRequestSchema = z24.object({
4269
- redirect_uri: z24.string().optional(),
4270
- source_url: z24.string().optional()
4415
+ var CfgUserUpdateRequestSchema = z24.object({
4416
+ first_name: z24.string().max(50).optional(),
4417
+ last_name: z24.string().max(50).optional(),
4418
+ company: z24.string().max(100).optional(),
4419
+ phone: z24.string().max(20).optional(),
4420
+ position: z24.string().max(100).optional(),
4421
+ language: z24.string().max(10).optional(),
4422
+ timezone: z24.string().max(64).optional()
4271
4423
  });
4272
4424
 
4273
- // src/_api/generated/_cfg_accounts/schemas/OAuthCallbackRequestRequest.ts
4425
+ // src/_api/generated/_cfg_accounts/schemas/OAuthAuthorizeRequestRequest.ts
4274
4426
  import { z as z25 } from "zod";
4275
- var OAuthCallbackRequestRequestSchema = z25.object({
4276
- code: z25.string().min(10).max(500),
4277
- state: z25.string().min(20).max(100),
4427
+ var OAuthAuthorizeRequestRequestSchema = z25.object({
4278
4428
  redirect_uri: z25.string().optional(),
4279
- remember_me: z25.boolean().default(false).optional()
4429
+ source_url: z25.string().optional()
4280
4430
  });
4281
4431
 
4282
- // src/_api/generated/_cfg_accounts/schemas/OAuthDisconnectRequestRequest.ts
4432
+ // src/_api/generated/_cfg_accounts/schemas/OAuthCallbackRequestRequest.ts
4283
4433
  import { z as z26 } from "zod";
4284
- var OAuthDisconnectRequestRequestSchema = z26.object({
4285
- provider: OAuthProviderEnumSchema
4434
+ var OAuthCallbackRequestRequestSchema = z26.object({
4435
+ code: z26.string().min(10).max(500),
4436
+ state: z26.string().min(20).max(100),
4437
+ redirect_uri: z26.string().optional(),
4438
+ remember_me: z26.boolean().default(false).optional()
4286
4439
  });
4287
4440
 
4288
- // src/_api/generated/_cfg_accounts/schemas/OAuthError.ts
4441
+ // src/_api/generated/_cfg_accounts/schemas/OAuthDisconnectRequestRequest.ts
4289
4442
  import { z as z27 } from "zod";
4290
- var OAuthErrorSchema = z27.object({
4291
- error: z27.string(),
4292
- error_description: z27.string().optional()
4443
+ var OAuthDisconnectRequestRequestSchema = z27.object({
4444
+ provider: OAuthProviderEnumSchema
4293
4445
  });
4294
4446
 
4295
- // src/_api/generated/_cfg_accounts/schemas/OTPErrorResponse.ts
4447
+ // src/_api/generated/_cfg_accounts/schemas/OAuthError.ts
4296
4448
  import { z as z28 } from "zod";
4297
- var OTPErrorResponseSchema = z28.object({
4449
+ var OAuthErrorSchema = z28.object({
4298
4450
  error: z28.string(),
4299
- error_code: z28.string().nullable().optional(),
4300
- retry_after: z28.number().int().nullable().optional()
4451
+ error_description: z28.string().optional()
4301
4452
  });
4302
4453
 
4303
- // src/_api/generated/_cfg_accounts/schemas/OTPRequestRequest.ts
4454
+ // src/_api/generated/_cfg_accounts/schemas/OTPErrorResponse.ts
4304
4455
  import { z as z29 } from "zod";
4305
- var OTPRequestRequestSchema = z29.object({
4306
- identifier: z29.string().min(1),
4307
- source_url: z29.string().optional(),
4308
- marketing_consent: z29.boolean().nullable().optional(),
4309
- consent_disclosure_version: z29.string().max(64).optional()
4456
+ var OTPErrorResponseSchema = z29.object({
4457
+ error: z29.string(),
4458
+ error_code: z29.string().nullable().optional(),
4459
+ retry_after: z29.number().int().nullable().optional()
4310
4460
  });
4311
4461
 
4312
- // src/_api/generated/_cfg_accounts/schemas/OTPVerifyRequest.ts
4462
+ // src/_api/generated/_cfg_accounts/schemas/OTPRequestRequest.ts
4313
4463
  import { z as z30 } from "zod";
4314
- var OTPVerifyRequestSchema = z30.object({
4464
+ var OTPRequestRequestSchema = z30.object({
4315
4465
  identifier: z30.string().min(1),
4316
- otp: z30.string().min(4).max(4),
4317
4466
  source_url: z30.string().optional(),
4318
- remember_me: z30.boolean().default(false).optional()
4467
+ marketing_consent: z30.boolean().nullable().optional(),
4468
+ consent_disclosure_version: z30.string().max(64).optional()
4319
4469
  });
4320
4470
 
4321
- // src/_api/generated/_cfg_accounts/schemas/PatchedCfgUserUpdateRequest.ts
4471
+ // src/_api/generated/_cfg_accounts/schemas/OTPVerifyRequest.ts
4322
4472
  import { z as z31 } from "zod";
4323
- var PatchedCfgUserUpdateRequestSchema = z31.object({
4324
- first_name: z31.string().max(50).optional(),
4325
- last_name: z31.string().max(50).optional(),
4326
- company: z31.string().max(100).optional(),
4327
- phone: z31.string().max(20).optional(),
4328
- position: z31.string().max(100).optional(),
4329
- language: z31.string().max(10).optional(),
4330
- timezone: z31.string().max(64).optional()
4473
+ var OTPVerifyRequestSchema = z31.object({
4474
+ identifier: z31.string().min(1),
4475
+ otp: z31.string().min(4).max(4),
4476
+ source_url: z31.string().optional(),
4477
+ remember_me: z31.boolean().default(false).optional()
4331
4478
  });
4332
4479
 
4333
- // src/_api/generated/_cfg_accounts/schemas/TokenBlacklistRequest.ts
4480
+ // src/_api/generated/_cfg_accounts/schemas/PasswordLoginError.ts
4334
4481
  import { z as z32 } from "zod";
4335
- var TokenBlacklistRequestSchema = z32.object({
4336
- refresh: z32.string().min(1)
4482
+ var PasswordLoginErrorSchema = z32.object({
4483
+ error: z32.string(),
4484
+ error_code: z32.string(),
4485
+ retry_after: z32.number().int().nullable().optional()
4337
4486
  });
4338
4487
 
4339
- // src/_api/generated/_cfg_accounts/schemas/TokenRefreshRequest.ts
4488
+ // src/_api/generated/_cfg_accounts/schemas/PasswordLoginRequest.ts
4340
4489
  import { z as z33 } from "zod";
4341
- var TokenRefreshRequestSchema = z33.object({
4342
- refresh: z33.string().min(1)
4490
+ var PasswordLoginRequestSchema = z33.object({
4491
+ remember_me: z33.boolean().default(false).optional(),
4492
+ email: z33.email(),
4493
+ password: z33.string()
4494
+ });
4495
+
4496
+ // src/_api/generated/_cfg_accounts/schemas/PatchedCfgUserUpdateRequest.ts
4497
+ import { z as z34 } from "zod";
4498
+ var PatchedCfgUserUpdateRequestSchema = z34.object({
4499
+ first_name: z34.string().max(50).optional(),
4500
+ last_name: z34.string().max(50).optional(),
4501
+ company: z34.string().max(100).optional(),
4502
+ phone: z34.string().max(20).optional(),
4503
+ position: z34.string().max(100).optional(),
4504
+ language: z34.string().max(10).optional(),
4505
+ timezone: z34.string().max(64).optional()
4506
+ });
4507
+
4508
+ // src/_api/generated/_cfg_accounts/schemas/TokenBlacklistRequest.ts
4509
+ import { z as z35 } from "zod";
4510
+ var TokenBlacklistRequestSchema = z35.object({
4511
+ refresh: z35.string().min(1)
4512
+ });
4513
+
4514
+ // src/_api/generated/_cfg_accounts/schemas/TokenRefreshRequest.ts
4515
+ import { z as z36 } from "zod";
4516
+ var TokenRefreshRequestSchema = z36.object({
4517
+ refresh: z36.string().min(1)
4343
4518
  });
4344
4519
 
4345
4520
  // src/auth/context/AccountsContext.tsx
@@ -4376,6 +4551,7 @@ function AccountsProvider({ children }) {
4376
4551
  const { trigger: triggerAvatar } = useCfgAccountsProfileAvatarCreate();
4377
4552
  const { trigger: triggerOtpRequest } = useCfgAccountsOtpRequestCreate();
4378
4553
  const { trigger: triggerOtpVerify } = useCfgAccountsOtpVerifyCreate();
4554
+ const { trigger: triggerPasswordLogin } = useCfgAccountsTokenCreate();
4379
4555
  const refreshProfile = useCallback10(async (options) => {
4380
4556
  const { callerId, force } = options || {};
4381
4557
  if (!hasApiOrigin()) {
@@ -4425,22 +4601,30 @@ function AccountsProvider({ children }) {
4425
4601
  const result = await triggerOtpRequest({ body: data });
4426
4602
  return result;
4427
4603
  }, [triggerOtpRequest]);
4428
- const verifyOTP = useCallback10(async (data) => {
4429
- const result = await triggerOtpVerify({ body: data });
4604
+ const settleLoginEnvelope = useCallback10(async (result, callerId) => {
4430
4605
  if (result.requires_2fa && result.session_id) {
4431
4606
  authLogger.info("2FA required, session:", result.session_id);
4432
- return result;
4607
+ return;
4433
4608
  }
4434
4609
  if (result.access && result.refresh) {
4435
4610
  auth.setSession({ access: result.access, refresh: result.refresh });
4436
4611
  try {
4437
- await refreshProfile({ callerId: "verifyOTP", force: true });
4612
+ await refreshProfile({ callerId, force: true });
4438
4613
  } catch (profileError2) {
4439
- authLogger.warn("Profile refresh failed after OTP verify (tokens are saved):", profileError2);
4614
+ authLogger.warn(`Profile refresh failed after ${callerId} (tokens are saved):`, profileError2);
4440
4615
  }
4441
4616
  }
4617
+ }, [refreshProfile]);
4618
+ const verifyOTP = useCallback10(async (data) => {
4619
+ const result = await triggerOtpVerify({ body: data });
4620
+ await settleLoginEnvelope(result, "verifyOTP");
4442
4621
  return result;
4443
- }, [triggerOtpVerify, refreshProfile]);
4622
+ }, [triggerOtpVerify, settleLoginEnvelope]);
4623
+ const loginWithPassword = useCallback10(async (data) => {
4624
+ const result = await triggerPasswordLogin({ body: data });
4625
+ await settleLoginEnvelope(result, "loginWithPassword");
4626
+ return result;
4627
+ }, [triggerPasswordLogin, settleLoginEnvelope]);
4444
4628
  const logout = useCallback10(() => {
4445
4629
  const refresh = auth.getRefreshToken();
4446
4630
  if (refresh) {
@@ -4463,6 +4647,7 @@ function AccountsProvider({ children }) {
4463
4647
  refreshProfile,
4464
4648
  requestOTP,
4465
4649
  verifyOTP,
4650
+ loginWithPassword,
4466
4651
  logout
4467
4652
  }), [
4468
4653
  profile,
@@ -4474,6 +4659,7 @@ function AccountsProvider({ children }) {
4474
4659
  refreshProfile,
4475
4660
  requestOTP,
4476
4661
  verifyOTP,
4662
+ loginWithPassword,
4477
4663
  logout
4478
4664
  ]);
4479
4665
  return /* @__PURE__ */ jsx(AccountsContext.Provider, { value, children });
@@ -4710,6 +4896,72 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4710
4896
  },
4711
4897
  [setStoredEmail, redirectManager, router]
4712
4898
  );
4899
+ const login = useCallback11(
4900
+ async (email, password, options) => {
4901
+ const { redirectUrl, skipRedirect, rememberMe = false } = options || {};
4902
+ try {
4903
+ pendingManualNavRef.current = Boolean(skipRedirect);
4904
+ const result = await accountsRef.current.loginWithPassword({
4905
+ email,
4906
+ password,
4907
+ remember_me: rememberMe
4908
+ });
4909
+ if (result.requires_2fa && result.session_id) {
4910
+ authLogger.info("2FA required, session:", result.session_id);
4911
+ return {
4912
+ success: true,
4913
+ message: "Password verified, 2FA required",
4914
+ requires_2fa: true,
4915
+ session_id: result.session_id,
4916
+ should_prompt_2fa: result.should_prompt_2fa
4917
+ };
4918
+ }
4919
+ if (!result.access || !result.refresh) {
4920
+ authLogger.error("Password login returned invalid response:", result);
4921
+ return { success: false, message: "Invalid login response" };
4922
+ }
4923
+ setStoredEmail(email);
4924
+ Analytics.event("auth_login_success" /* AUTH_LOGIN_SUCCESS */, {
4925
+ category: "auth" /* AUTH */,
4926
+ label: "password"
4927
+ });
4928
+ if (result.user?.id) {
4929
+ Analytics.setUser(String(result.user.id));
4930
+ }
4931
+ if (!skipRedirect) {
4932
+ const saved = redirectManager.hasRedirect() ? redirectManager.getRedirect() : null;
4933
+ if (saved) redirectManager.clearRedirect();
4934
+ const finalRedirectUrl = saved || redirectUrl || routesRef.current.defaultCallback;
4935
+ authLogger.info("Redirecting after auth to:", finalRedirectUrl);
4936
+ router.hardPush(finalRedirectUrl);
4937
+ }
4938
+ return {
4939
+ success: true,
4940
+ message: "Login successful",
4941
+ user: result.user,
4942
+ should_prompt_2fa: result.should_prompt_2fa
4943
+ };
4944
+ } catch (error) {
4945
+ authLogger.error("Password login error:", error);
4946
+ Analytics.event("auth_password_login_fail" /* AUTH_PASSWORD_LOGIN_FAIL */, {
4947
+ category: "auth" /* AUTH */,
4948
+ label: "password"
4949
+ });
4950
+ if (error instanceof APIError) {
4951
+ const body = error.response;
4952
+ return {
4953
+ success: false,
4954
+ statusCode: error.statusCode,
4955
+ message: apiErrorMessage(error),
4956
+ errorCode: body?.error_code,
4957
+ retryAfter: typeof body?.retry_after === "number" ? body.retry_after : void 0
4958
+ };
4959
+ }
4960
+ return { success: false, message: "Failed to sign in" };
4961
+ }
4962
+ },
4963
+ [setStoredEmail, redirectManager, router]
4964
+ );
4713
4965
  const refreshToken = useCallback11(async () => {
4714
4966
  const access = await auth.refreshNow();
4715
4967
  if (access) {
@@ -4764,6 +5016,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4764
5016
  clearSavedEmail: clearStoredEmail,
4765
5017
  requestOTP,
4766
5018
  verifyOTP,
5019
+ login,
4767
5020
  refreshToken,
4768
5021
  logout,
4769
5022
  saveRedirectUrl: redirectManager.setRedirect,
@@ -4786,6 +5039,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4786
5039
  clearStoredEmail,
4787
5040
  requestOTP,
4788
5041
  verifyOTP,
5042
+ login,
4789
5043
  refreshToken,
4790
5044
  logout,
4791
5045
  redirectManager,
@@ -4829,6 +5083,10 @@ var defaultAuthState = {
4829
5083
  authLogger.warn("useAuth: verifyOTP called outside AuthProvider");
4830
5084
  return { success: false, message: "AuthProvider not available" };
4831
5085
  }, "verifyOTP"),
5086
+ login: /* @__PURE__ */ __name(async () => {
5087
+ authLogger.warn("useAuth: login called outside AuthProvider");
5088
+ return { success: false, message: "AuthProvider not available" };
5089
+ }, "login"),
4832
5090
  refreshToken: /* @__PURE__ */ __name(async () => {
4833
5091
  authLogger.warn("useAuth: refreshToken called outside AuthProvider");
4834
5092
  return { success: false, message: "AuthProvider not available" };
@@ -4889,9 +5147,16 @@ var formatAuthError = /* @__PURE__ */ __name((error) => {
4889
5147
  }, "formatAuthError");
4890
5148
 
4891
5149
  // src/auth/utils/guard.ts
5150
+ function isForbidden(s) {
5151
+ return Boolean(
5152
+ s.mounted && s.requireAuth && s.requireStaff && !s.authLoading && s.isAuthenticated && !s.isAdminUser
5153
+ );
5154
+ }
5155
+ __name(isForbidden, "isForbidden");
4892
5156
  function resolveGuardIsLoading(s) {
4893
5157
  if (!s.mounted) return true;
4894
5158
  if (!s.requireAuth) return false;
5159
+ if (isForbidden(s)) return false;
4895
5160
  return s.authLoading || s.isRedirecting || !s.isAuthenticated;
4896
5161
  }
4897
5162
  __name(resolveGuardIsLoading, "resolveGuardIsLoading");
@@ -4922,6 +5187,7 @@ export {
4922
5187
  getCachedProfile,
4923
5188
  hasValidCache,
4924
5189
  isAllowedAuthPath,
5190
+ isForbidden,
4925
5191
  logger,
4926
5192
  normalizePath,
4927
5193
  peekSavedRedirect,