@djangocfg/api 2.1.476 → 2.1.478

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 (42) hide show
  1. package/dist/auth.cjs +173 -121
  2. package/dist/auth.cjs.map +1 -1
  3. package/dist/auth.d.cts +36 -2
  4. package/dist/auth.d.ts +36 -2
  5. package/dist/auth.mjs +173 -121
  6. package/dist/auth.mjs.map +1 -1
  7. package/dist/clients.cjs +18 -0
  8. package/dist/clients.cjs.map +1 -1
  9. package/dist/clients.d.cts +49 -0
  10. package/dist/clients.d.ts +49 -0
  11. package/dist/clients.mjs +18 -0
  12. package/dist/clients.mjs.map +1 -1
  13. package/dist/hooks.cjs +133 -1
  14. package/dist/hooks.cjs.map +1 -1
  15. package/dist/hooks.d.cts +61 -1
  16. package/dist/hooks.d.ts +61 -1
  17. package/dist/hooks.mjs +133 -1
  18. package/dist/hooks.mjs.map +1 -1
  19. package/dist/index.cjs +18 -0
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +72 -4
  22. package/dist/index.d.ts +72 -4
  23. package/dist/index.mjs +18 -0
  24. package/dist/index.mjs.map +1 -1
  25. package/package.json +2 -2
  26. package/src/_api/generated/_cfg_accounts/hooks/index.ts +1 -0
  27. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpConsentPolicyRetrieve.ts +74 -0
  28. package/src/_api/generated/_cfg_accounts/openapi.json +76 -0
  29. package/src/_api/generated/_cfg_accounts/schemas/ConsentPolicy.ts +13 -0
  30. package/src/_api/generated/_cfg_accounts/schemas/MarketingConsentDefaultEnum.ts +9 -0
  31. package/src/_api/generated/_cfg_accounts/schemas/OTPRequestRequest.ts +2 -0
  32. package/src/_api/generated/_cfg_accounts/schemas/index.ts +2 -0
  33. package/src/_api/generated/openapi.json +76 -0
  34. package/src/_api/generated/sdk.gen.ts +40 -21
  35. package/src/_api/generated/types.gen.ts +47 -0
  36. package/src/auth/context/AuthContext.tsx +12 -4
  37. package/src/auth/context/types.ts +2 -2
  38. package/src/auth/hooks/useAuthForm.ts +15 -3
  39. package/src/auth/hooks/useAuthFormState.ts +5 -0
  40. package/src/auth/types/form.ts +27 -0
  41. package/src/auth/types/index.ts +1 -0
  42. package/src/hooks/index.ts +6 -0
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
 
3
3
  import type { User } from '../../';
4
- import type { OTPRequestResult } from '../types';
4
+ import type { OTPRequestConsent, OTPRequestResult } from '../types';
5
5
 
6
6
  // User profile type
7
7
  export type UserProfile = User;
@@ -49,7 +49,7 @@ export interface AuthContextType {
49
49
  clearSavedEmail: () => void;
50
50
 
51
51
  // OTP Methods - email only
52
- requestOTP: (identifier: string, sourceUrl?: string) => Promise<OTPRequestResult>;
52
+ requestOTP: (identifier: string, sourceUrl?: string, consent?: OTPRequestConsent) => Promise<OTPRequestResult>;
53
53
  verifyOTP: (identifier: string, otpCode: string, sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean) => Promise<{
54
54
  success: boolean;
55
55
  message: string;
@@ -23,6 +23,7 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormReturn => {
23
23
  sourceUrl,
24
24
  redirectUrl,
25
25
  requireTermsAcceptance = false,
26
+ marketingConsent: marketingConsentOption,
26
27
  authPath = '/auth',
27
28
  } = options;
28
29
 
@@ -52,6 +53,7 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormReturn => {
52
53
  otp,
53
54
  isLoading,
54
55
  acceptedTerms,
56
+ marketingConsent,
55
57
  twoFactorSessionId,
56
58
  twoFactorCode,
57
59
  useBackupCode,
@@ -139,7 +141,11 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormReturn => {
139
141
  clearError();
140
142
 
141
143
  try {
142
- const result = await requestOTP(identifier, sourceUrl);
144
+ // Only apps that opted in send consent fields — absent option ⇒ body unchanged.
145
+ const consent = marketingConsentOption
146
+ ? { marketingConsent: marketingConsent === true, disclosureVersion: marketingConsentOption.disclosureVersion }
147
+ : undefined;
148
+ const result = await requestOTP(identifier, sourceUrl, consent);
143
149
 
144
150
  if (result.success) {
145
151
  saveIdentifierToStorage(identifier);
@@ -164,6 +170,7 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormReturn => {
164
170
  }
165
171
  }, [
166
172
  identifier, acceptedTerms, requireTermsAcceptance,
173
+ marketingConsent, marketingConsentOption,
167
174
  validateIdentifier, requestOTP, saveIdentifierToStorage,
168
175
  setError, setIsLoading, setStep, clearError, setWebmail,
169
176
  startRateLimitCountdown, onIdentifierSuccess, onError, sourceUrl,
@@ -233,7 +240,12 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormReturn => {
233
240
  clearError();
234
241
 
235
242
  try {
236
- const result = await requestOTP(identifier, sourceUrl);
243
+ // Resend repeats the same OTP request — carry the same consent state so
244
+ // the backend never sees a consent-less duplicate of an opted-in request.
245
+ const consent = marketingConsentOption
246
+ ? { marketingConsent: marketingConsent === true, disclosureVersion: marketingConsentOption.disclosureVersion }
247
+ : undefined;
248
+ const result = await requestOTP(identifier, sourceUrl, consent);
237
249
 
238
250
  if (result.success) {
239
251
  saveIdentifierToStorage(identifier);
@@ -255,7 +267,7 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormReturn => {
255
267
  } finally {
256
268
  setIsLoading(false);
257
269
  }
258
- }, [identifier, requestOTP, saveIdentifierToStorage, setOtp, setError, setIsLoading, clearError, startRateLimitCountdown, setWebmail, onError, sourceUrl]);
270
+ }, [identifier, marketingConsent, marketingConsentOption, requestOTP, saveIdentifierToStorage, setOtp, setError, setIsLoading, clearError, startRateLimitCountdown, setWebmail, onError, sourceUrl]);
259
271
 
260
272
  const handleBackToIdentifier = useCallback(() => {
261
273
  setStep('identifier');
@@ -23,6 +23,9 @@ export const useAuthFormState = (
23
23
  const [otp, setOtp] = useState('');
24
24
  const [isLoading, setIsLoading] = useState(false);
25
25
  const [acceptedTerms, setAcceptedTerms] = useState(true);
26
+ // null until the marketing-consent feature (if enabled) resolves its
27
+ // jurisdiction-aware default — the layout owns that decision.
28
+ const [marketingConsent, setMarketingConsent] = useState<boolean | null>(null);
26
29
  const [step, setStep] = useState<AuthStep>('identifier');
27
30
  const [error, setError] = useState('');
28
31
  const [webmail, setWebmail] = useState<WebmailLink | null>(null);
@@ -64,6 +67,7 @@ export const useAuthFormState = (
64
67
  otp,
65
68
  isLoading,
66
69
  acceptedTerms,
70
+ marketingConsent,
67
71
  step,
68
72
  error,
69
73
  twoFactorSessionId,
@@ -78,6 +82,7 @@ export const useAuthFormState = (
78
82
  setIdentifier,
79
83
  setOtp,
80
84
  setAcceptedTerms,
85
+ setMarketingConsent,
81
86
  setError,
82
87
  clearError,
83
88
  setStep,
@@ -30,6 +30,17 @@ export interface OTPRequestResult {
30
30
  webmail?: WebmailLink | null;
31
31
  }
32
32
 
33
+ /**
34
+ * Marketing-consent payload attached to an OTP request when the consuming
35
+ * app enables the opt-in checkbox. Absent ⇒ the request body is unchanged.
36
+ */
37
+ export interface OTPRequestConsent {
38
+ /** Checkbox value at submit time. */
39
+ marketingConsent: boolean;
40
+ /** Version tag of the disclosure copy the user saw (e.g. "product-updates-reg-v1"). */
41
+ disclosureVersion: string;
42
+ }
43
+
33
44
  // ─────────────────────────────────────────────────────────────────────────────
34
45
  // Form State
35
46
  // ─────────────────────────────────────────────────────────────────────────────
@@ -43,6 +54,12 @@ export interface AuthFormState {
43
54
  isLoading: boolean;
44
55
  /** Terms acceptance state */
45
56
  acceptedTerms: boolean;
57
+ /**
58
+ * Marketing-consent checkbox state. `null` = feature not initialised (no
59
+ * checkbox rendered, or default not yet resolved); the layout owns the
60
+ * jurisdiction-aware default on mount.
61
+ */
62
+ marketingConsent: boolean | null;
46
63
  /** Current form step */
47
64
  step: AuthStep;
48
65
  /** Error message */
@@ -73,6 +90,7 @@ export interface AuthFormStateHandlers {
73
90
  setIdentifier: (identifier: string) => void;
74
91
  setOtp: (otp: string) => void;
75
92
  setAcceptedTerms: (accepted: boolean) => void;
93
+ setMarketingConsent: (consent: boolean | null) => void;
76
94
  setError: (error: string) => void;
77
95
  clearError: () => void;
78
96
  setStep: (step: AuthStep) => void;
@@ -161,6 +179,15 @@ export interface UseAuthFormOptions {
161
179
  redirectUrl?: string;
162
180
  /** If true, user must accept terms before submitting. Default: false */
163
181
  requireTermsAcceptance?: boolean;
182
+ /**
183
+ * Enables the marketing-consent opt-in: when set, the checkbox value +
184
+ * this disclosure version are sent with the OTP request. Absent ⇒ the
185
+ * request body is unchanged (backward compatible).
186
+ */
187
+ marketingConsent?: {
188
+ /** Version tag of the disclosure copy shown next to the checkbox. */
189
+ disclosureVersion: string;
190
+ };
164
191
  /** Path to auth page for auto-OTP detection. Default: '/auth' */
165
192
  authPath?: string;
166
193
  }
@@ -13,6 +13,7 @@ export type {
13
13
  AuthFormReturn,
14
14
  UseAuthFormOptions,
15
15
  OTPRequestResult,
16
+ OTPRequestConsent,
16
17
  WebmailLink,
17
18
  } from './form';
18
19
 
@@ -1 +1,7 @@
1
1
  export { useApiKey, type UseApiKeyReturn } from './useApiKey';
2
+
3
+ // Consent policy (GET /cfg/accounts/otp/consent-policy/) — server-decided
4
+ // default for the marketing-consent checkbox, derived from the request's
5
+ // country. Re-exported directly: the generated SWR hook needs no wrapping.
6
+ export { useCfgAccountsOtpConsentPolicyRetrieve } from '../_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpConsentPolicyRetrieve';
7
+ export type { ConsentPolicy } from '../_api/generated/_cfg_accounts/schemas/ConsentPolicy';