@djangocfg/api 2.1.541 → 2.1.543

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 (67) hide show
  1. package/README.md +1 -2
  2. package/dist/auth-server.cjs +1 -0
  3. package/dist/auth-server.cjs.map +1 -1
  4. package/dist/auth.cjs +156 -170
  5. package/dist/auth.cjs.map +1 -1
  6. package/dist/auth.d.cts +134 -29
  7. package/dist/auth.d.ts +134 -29
  8. package/dist/auth.mjs +168 -183
  9. package/dist/auth.mjs.map +1 -1
  10. package/dist/clients.cjs +4 -99
  11. package/dist/clients.cjs.map +1 -1
  12. package/dist/clients.d.cts +4 -136
  13. package/dist/clients.d.ts +4 -136
  14. package/dist/clients.mjs +3 -99
  15. package/dist/clients.mjs.map +1 -1
  16. package/dist/hooks.cjs +1 -0
  17. package/dist/hooks.cjs.map +1 -1
  18. package/dist/hooks.d.cts +2 -4
  19. package/dist/hooks.d.ts +2 -4
  20. package/dist/hooks.mjs.map +1 -1
  21. package/dist/index.cjs +4 -100
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +10 -340
  24. package/dist/index.d.ts +10 -340
  25. package/dist/index.mjs +3 -100
  26. package/dist/index.mjs.map +1 -1
  27. package/package.json +5 -4
  28. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRetrieve.ts +8 -2
  29. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthConnectionsList.ts +8 -2
  30. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthProvidersRetrieve.ts +8 -2
  31. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpConsentPolicyRetrieve.ts +8 -2
  32. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileRetrieve.ts +8 -2
  33. package/src/_api/generated/_cfg_accounts/openapi.json +0 -45
  34. package/src/_api/generated/_cfg_accounts/schemas/User.ts +0 -2
  35. package/src/_api/generated/_cfg_accounts/schemas/index.ts +0 -1
  36. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpBackupCodesRetrieve.ts +8 -2
  37. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpDevicesRetrieve.ts +8 -2
  38. package/src/_api/generated/index.ts +1 -5
  39. package/src/_api/generated/openapi.json +0 -135
  40. package/src/_api/generated/sdk.gen.ts +1 -20
  41. package/src/_api/generated/types.gen.ts +0 -79
  42. package/src/_api/index.ts +1 -1
  43. package/src/auth/__tests__/useTwoFactorStatus.test.ts +2 -2
  44. package/src/auth/context/AccountsContext.tsx +15 -11
  45. package/src/auth/hooks/useAuthForm.ts +0 -1
  46. package/src/auth/hooks/useCfgRouter.ts +1 -4
  47. package/src/auth/hooks/useGithubAuth.ts +25 -3
  48. package/src/auth/hooks/useLocalStorage.ts +7 -30
  49. package/src/auth/hooks/useSessionStorage.ts +6 -29
  50. package/src/auth/hooks/useTwoFactorVerify.ts +5 -9
  51. package/src/auth/utils/analytics.ts +22 -2
  52. package/src/auth/utils/errors.ts +22 -11
  53. package/src/auth/utils/storage.ts +64 -0
  54. package/src/clients.ts +2 -4
  55. package/src/index.ts +0 -2
  56. package/src/log-control.ts +1 -1
  57. package/src/server.ts +0 -4
  58. package/src/_api/generated/_cfg_accounts/schemas/CentrifugoToken.ts +0 -14
  59. package/src/_api/generated/_cfg_centrifugo/api.ts +0 -87
  60. package/src/_api/generated/_cfg_centrifugo/hooks/index.ts +0 -4
  61. package/src/_api/generated/_cfg_centrifugo/hooks/useCfgCentrifugoAuthTokenRetrieve.ts +0 -74
  62. package/src/_api/generated/_cfg_centrifugo/index.ts +0 -29
  63. package/src/_api/generated/_cfg_centrifugo/openapi.json +0 -136
  64. package/src/_api/generated/_cfg_centrifugo/schemas/ConnectionTokenResponse.ts +0 -14
  65. package/src/_api/generated/_cfg_centrifugo/schemas/index.ts +0 -4
  66. package/src/_api/generated/_cfg_centrifugo/sdk.gen.ts +0 -5
  67. package/src/_api/generated/_cfg_centrifugo/types.gen.ts +0 -5
package/dist/auth.d.cts CHANGED
@@ -24,27 +24,6 @@ type SessionSnapshot = {
24
24
  accessExpiresAt: number | null;
25
25
  };
26
26
 
27
- /**
28
- * Nested serializer for Centrifugo WebSocket connection token.
29
- */
30
- type CentrifugoToken = {
31
- /**
32
- * JWT token for Centrifugo WebSocket connection
33
- */
34
- token: string;
35
- /**
36
- * Centrifugo WebSocket URL
37
- */
38
- centrifugo_url: string;
39
- /**
40
- * Token expiration time (ISO 8601)
41
- */
42
- expires_at: string;
43
- /**
44
- * List of allowed channels for this user
45
- */
46
- channels: Array<string>;
47
- };
48
27
  /**
49
28
  * Serializer for updating user profile.
50
29
  */
@@ -60,6 +39,59 @@ type CfgUserUpdateRequest = {
60
39
  */
61
40
  timezone?: string;
62
41
  };
42
+ /**
43
+ * Response with JWT tokens after OAuth authentication.
44
+ *
45
+ * When 2FA is required:
46
+ * - requires_2fa: True
47
+ * - session_id: UUID of 2FA verification session
48
+ * - access/refresh/user: null
49
+ *
50
+ * When 2FA is not required:
51
+ * - requires_2fa: False
52
+ * - session_id: null
53
+ * - access/refresh/user: populated
54
+ */
55
+ type OAuthTokenResponse = {
56
+ /**
57
+ * True if 2FA verification is required
58
+ */
59
+ requires_2fa?: boolean;
60
+ /**
61
+ * 2FA session ID (only when requires_2fa=True)
62
+ */
63
+ session_id?: string | null;
64
+ /**
65
+ * JWT access token (null when requires_2fa=True)
66
+ */
67
+ access?: string | null;
68
+ /**
69
+ * JWT refresh token (null when requires_2fa=True)
70
+ */
71
+ refresh?: string | null;
72
+ /**
73
+ * Authenticated user info (null when requires_2fa=True)
74
+ */
75
+ user?: {
76
+ [key: string]: unknown;
77
+ } | null;
78
+ /**
79
+ * True if a new user was created during this OAuth flow
80
+ */
81
+ is_new_user?: boolean;
82
+ /**
83
+ * True if a new OAuth connection was created
84
+ */
85
+ is_new_connection?: boolean;
86
+ /**
87
+ * True if user should be prompted to enable 2FA
88
+ */
89
+ should_prompt_2fa?: boolean;
90
+ /**
91
+ * Whether this login should persist across browser restarts
92
+ */
93
+ persistent_session?: boolean;
94
+ };
63
95
  /**
64
96
  * Serializer for OTP request.
65
97
  */
@@ -170,6 +202,49 @@ type PatchedCfgUserUpdateRequest = {
170
202
  */
171
203
  timezone?: string;
172
204
  };
205
+ /**
206
+ * User data returned after 2FA verification.
207
+ */
208
+ type TotpVerifyUser = {
209
+ readonly id: number;
210
+ readonly email: string;
211
+ first_name?: string | null;
212
+ last_name?: string | null;
213
+ /**
214
+ * Get user's full name.
215
+ */
216
+ readonly full_name: string;
217
+ /**
218
+ * Get user's initials for avatar fallback.
219
+ */
220
+ readonly initials: string;
221
+ /**
222
+ * Get formatted username for display.
223
+ */
224
+ readonly display_username: string;
225
+ company?: string | null;
226
+ phone?: string | null;
227
+ position?: string | null;
228
+ language?: string | null;
229
+ timezone?: string | null;
230
+ readonly avatar: string | null;
231
+ /**
232
+ * Staff status
233
+ *
234
+ * Designates whether the user can log into this admin site.
235
+ */
236
+ readonly is_staff: boolean;
237
+ /**
238
+ * Superuser status
239
+ *
240
+ * Designates that this user has all permissions without explicitly assigning them.
241
+ */
242
+ readonly is_superuser: boolean;
243
+ readonly date_joined: string;
244
+ readonly last_login: string | null;
245
+ readonly unanswered_messages_count: number;
246
+ readonly api_key: string | null;
247
+ };
173
248
  /**
174
249
  * Serializer for user details.
175
250
  */
@@ -211,7 +286,6 @@ type User = {
211
286
  readonly date_joined: string;
212
287
  readonly last_login: string | null;
213
288
  readonly unanswered_messages_count: number;
214
- readonly centrifugo: CentrifugoToken | null;
215
289
  readonly api_key: string | null;
216
290
  };
217
291
  /**
@@ -544,7 +618,7 @@ interface AuthProviderProps {
544
618
  enabled?: boolean;
545
619
  }
546
620
 
547
- declare const AuthContext: React__default.Context<AuthContextType>;
621
+ declare const AuthContext: React__default.Context<AuthContextType | undefined>;
548
622
  /**
549
623
  * AuthProvider — wraps AccountsProvider + AuthProviderInternal.
550
624
  *
@@ -705,11 +779,25 @@ declare const useAutoAuth: (options?: UseAutoAuthOptions) => {
705
779
  isAllowedPath: boolean;
706
780
  };
707
781
 
782
+ /**
783
+ * The user payload as the OAuth endpoint declares it.
784
+ *
785
+ * Derived from the generated response rather than restated, so a schema change
786
+ * reaches callers through `make gen` instead of drifting silently. Today the
787
+ * backend types it as a free-form object; when it names a real user model, this
788
+ * narrows on its own.
789
+ */
790
+ type OAuthUser = NonNullable<OAuthTokenResponse['user']>;
708
791
  interface UseGithubAuthOptions {
709
792
  sourceUrl?: string;
710
793
  /** Keep the completed browser session for 30 days. */
711
794
  rememberMe?: boolean;
712
- onSuccess?: (user: any, isNewUser: boolean) => void;
795
+ /**
796
+ * The OAuth endpoint's OpenAPI schema types `user` as a free-form object, so
797
+ * this is what the server actually promises — not a `User`. Narrow it at the
798
+ * call site; typing it tighter here would be an assertion, not a fact.
799
+ */
800
+ onSuccess?: (user: OAuthUser, isNewUser: boolean) => void;
713
801
  onError?: (error: string) => void;
714
802
  /** Callback when 2FA is required */
715
803
  onRequires2FA?: (sessionId: string, shouldPrompt2FA: boolean) => void;
@@ -746,7 +834,7 @@ declare const useGithubAuth: (options?: UseGithubAuthOptions) => UseGithubAuthRe
746
834
 
747
835
  interface UseTwoFactorVerifyOptions {
748
836
  /** Callback on successful 2FA verification */
749
- onSuccess?: (user: any) => void;
837
+ onSuccess?: (user: TotpVerifyUser) => void;
750
838
  /** Callback on error */
751
839
  onError?: (error: string) => void;
752
840
  /** URL to redirect after successful verification */
@@ -1036,9 +1124,14 @@ declare const useDeleteAccount: () => UseDeleteAccountReturn;
1036
1124
  declare const validateEmail: (email: string) => boolean;
1037
1125
 
1038
1126
  /**
1039
- * Format authentication error for display
1127
+ * Format authentication error for display.
1128
+ *
1129
+ * Each candidate is checked to be a string before it is returned. Under the
1130
+ * previous `any` the check was only that the property was truthy, so a DRF
1131
+ * field-error object (`{detail: {email: [...]}}`) reached the UI as
1132
+ * "[object Object]" — an error message that tells the user nothing.
1040
1133
  */
1041
- declare const formatAuthError: (error: any) => string;
1134
+ declare const formatAuthError: (error: unknown) => string;
1042
1135
 
1043
1136
  /**
1044
1137
  * Pure auth-guard state resolution.
@@ -1136,15 +1229,27 @@ declare enum AnalyticsCategory {
1136
1229
  }
1137
1230
  type AnalyticsEventType = `${AnalyticsEvent}`;
1138
1231
  type AnalyticsCategoryType = `${AnalyticsCategory}`;
1232
+ /**
1233
+ * What an analytics backend can actually carry.
1234
+ *
1235
+ * GA4 and OpenPanel serialise a property to a scalar; an object or a function
1236
+ * arrives as "[object Object]" without erroring anywhere. Declaring the wider
1237
+ * `unknown` here promised a forwarding guarantee no implementation keeps, and
1238
+ * it made this sink incompatible with `AnalyticsEventProperties` in
1239
+ * `@djangocfg/analytics` — the two describe the same channel and must agree.
1240
+ * Kept as a local declaration rather than an import: `api` does not depend on
1241
+ * `analytics`, and one shared four-member union is not worth that edge.
1242
+ */
1243
+ type AnalyticsPropertyValue = string | number | boolean | null;
1139
1244
  interface AnalyticsEventParams {
1140
1245
  category?: AnalyticsCategoryType;
1141
1246
  label?: string;
1142
1247
  value?: number;
1143
- [key: string]: any;
1248
+ [key: string]: AnalyticsPropertyValue | undefined;
1144
1249
  }
1145
1250
  /** What an analytics implementation must provide to receive auth events. */
1146
1251
  interface AnalyticsSink {
1147
- event(name: string, params?: Record<string, any>): void;
1252
+ event(name: string, params?: Record<string, AnalyticsPropertyValue | undefined>): void;
1148
1253
  setUser(userId: string | null): void;
1149
1254
  }
1150
1255
  /**
package/dist/auth.d.ts CHANGED
@@ -24,27 +24,6 @@ type SessionSnapshot = {
24
24
  accessExpiresAt: number | null;
25
25
  };
26
26
 
27
- /**
28
- * Nested serializer for Centrifugo WebSocket connection token.
29
- */
30
- type CentrifugoToken = {
31
- /**
32
- * JWT token for Centrifugo WebSocket connection
33
- */
34
- token: string;
35
- /**
36
- * Centrifugo WebSocket URL
37
- */
38
- centrifugo_url: string;
39
- /**
40
- * Token expiration time (ISO 8601)
41
- */
42
- expires_at: string;
43
- /**
44
- * List of allowed channels for this user
45
- */
46
- channels: Array<string>;
47
- };
48
27
  /**
49
28
  * Serializer for updating user profile.
50
29
  */
@@ -60,6 +39,59 @@ type CfgUserUpdateRequest = {
60
39
  */
61
40
  timezone?: string;
62
41
  };
42
+ /**
43
+ * Response with JWT tokens after OAuth authentication.
44
+ *
45
+ * When 2FA is required:
46
+ * - requires_2fa: True
47
+ * - session_id: UUID of 2FA verification session
48
+ * - access/refresh/user: null
49
+ *
50
+ * When 2FA is not required:
51
+ * - requires_2fa: False
52
+ * - session_id: null
53
+ * - access/refresh/user: populated
54
+ */
55
+ type OAuthTokenResponse = {
56
+ /**
57
+ * True if 2FA verification is required
58
+ */
59
+ requires_2fa?: boolean;
60
+ /**
61
+ * 2FA session ID (only when requires_2fa=True)
62
+ */
63
+ session_id?: string | null;
64
+ /**
65
+ * JWT access token (null when requires_2fa=True)
66
+ */
67
+ access?: string | null;
68
+ /**
69
+ * JWT refresh token (null when requires_2fa=True)
70
+ */
71
+ refresh?: string | null;
72
+ /**
73
+ * Authenticated user info (null when requires_2fa=True)
74
+ */
75
+ user?: {
76
+ [key: string]: unknown;
77
+ } | null;
78
+ /**
79
+ * True if a new user was created during this OAuth flow
80
+ */
81
+ is_new_user?: boolean;
82
+ /**
83
+ * True if a new OAuth connection was created
84
+ */
85
+ is_new_connection?: boolean;
86
+ /**
87
+ * True if user should be prompted to enable 2FA
88
+ */
89
+ should_prompt_2fa?: boolean;
90
+ /**
91
+ * Whether this login should persist across browser restarts
92
+ */
93
+ persistent_session?: boolean;
94
+ };
63
95
  /**
64
96
  * Serializer for OTP request.
65
97
  */
@@ -170,6 +202,49 @@ type PatchedCfgUserUpdateRequest = {
170
202
  */
171
203
  timezone?: string;
172
204
  };
205
+ /**
206
+ * User data returned after 2FA verification.
207
+ */
208
+ type TotpVerifyUser = {
209
+ readonly id: number;
210
+ readonly email: string;
211
+ first_name?: string | null;
212
+ last_name?: string | null;
213
+ /**
214
+ * Get user's full name.
215
+ */
216
+ readonly full_name: string;
217
+ /**
218
+ * Get user's initials for avatar fallback.
219
+ */
220
+ readonly initials: string;
221
+ /**
222
+ * Get formatted username for display.
223
+ */
224
+ readonly display_username: string;
225
+ company?: string | null;
226
+ phone?: string | null;
227
+ position?: string | null;
228
+ language?: string | null;
229
+ timezone?: string | null;
230
+ readonly avatar: string | null;
231
+ /**
232
+ * Staff status
233
+ *
234
+ * Designates whether the user can log into this admin site.
235
+ */
236
+ readonly is_staff: boolean;
237
+ /**
238
+ * Superuser status
239
+ *
240
+ * Designates that this user has all permissions without explicitly assigning them.
241
+ */
242
+ readonly is_superuser: boolean;
243
+ readonly date_joined: string;
244
+ readonly last_login: string | null;
245
+ readonly unanswered_messages_count: number;
246
+ readonly api_key: string | null;
247
+ };
173
248
  /**
174
249
  * Serializer for user details.
175
250
  */
@@ -211,7 +286,6 @@ type User = {
211
286
  readonly date_joined: string;
212
287
  readonly last_login: string | null;
213
288
  readonly unanswered_messages_count: number;
214
- readonly centrifugo: CentrifugoToken | null;
215
289
  readonly api_key: string | null;
216
290
  };
217
291
  /**
@@ -544,7 +618,7 @@ interface AuthProviderProps {
544
618
  enabled?: boolean;
545
619
  }
546
620
 
547
- declare const AuthContext: React__default.Context<AuthContextType>;
621
+ declare const AuthContext: React__default.Context<AuthContextType | undefined>;
548
622
  /**
549
623
  * AuthProvider — wraps AccountsProvider + AuthProviderInternal.
550
624
  *
@@ -705,11 +779,25 @@ declare const useAutoAuth: (options?: UseAutoAuthOptions) => {
705
779
  isAllowedPath: boolean;
706
780
  };
707
781
 
782
+ /**
783
+ * The user payload as the OAuth endpoint declares it.
784
+ *
785
+ * Derived from the generated response rather than restated, so a schema change
786
+ * reaches callers through `make gen` instead of drifting silently. Today the
787
+ * backend types it as a free-form object; when it names a real user model, this
788
+ * narrows on its own.
789
+ */
790
+ type OAuthUser = NonNullable<OAuthTokenResponse['user']>;
708
791
  interface UseGithubAuthOptions {
709
792
  sourceUrl?: string;
710
793
  /** Keep the completed browser session for 30 days. */
711
794
  rememberMe?: boolean;
712
- onSuccess?: (user: any, isNewUser: boolean) => void;
795
+ /**
796
+ * The OAuth endpoint's OpenAPI schema types `user` as a free-form object, so
797
+ * this is what the server actually promises — not a `User`. Narrow it at the
798
+ * call site; typing it tighter here would be an assertion, not a fact.
799
+ */
800
+ onSuccess?: (user: OAuthUser, isNewUser: boolean) => void;
713
801
  onError?: (error: string) => void;
714
802
  /** Callback when 2FA is required */
715
803
  onRequires2FA?: (sessionId: string, shouldPrompt2FA: boolean) => void;
@@ -746,7 +834,7 @@ declare const useGithubAuth: (options?: UseGithubAuthOptions) => UseGithubAuthRe
746
834
 
747
835
  interface UseTwoFactorVerifyOptions {
748
836
  /** Callback on successful 2FA verification */
749
- onSuccess?: (user: any) => void;
837
+ onSuccess?: (user: TotpVerifyUser) => void;
750
838
  /** Callback on error */
751
839
  onError?: (error: string) => void;
752
840
  /** URL to redirect after successful verification */
@@ -1036,9 +1124,14 @@ declare const useDeleteAccount: () => UseDeleteAccountReturn;
1036
1124
  declare const validateEmail: (email: string) => boolean;
1037
1125
 
1038
1126
  /**
1039
- * Format authentication error for display
1127
+ * Format authentication error for display.
1128
+ *
1129
+ * Each candidate is checked to be a string before it is returned. Under the
1130
+ * previous `any` the check was only that the property was truthy, so a DRF
1131
+ * field-error object (`{detail: {email: [...]}}`) reached the UI as
1132
+ * "[object Object]" — an error message that tells the user nothing.
1040
1133
  */
1041
- declare const formatAuthError: (error: any) => string;
1134
+ declare const formatAuthError: (error: unknown) => string;
1042
1135
 
1043
1136
  /**
1044
1137
  * Pure auth-guard state resolution.
@@ -1136,15 +1229,27 @@ declare enum AnalyticsCategory {
1136
1229
  }
1137
1230
  type AnalyticsEventType = `${AnalyticsEvent}`;
1138
1231
  type AnalyticsCategoryType = `${AnalyticsCategory}`;
1232
+ /**
1233
+ * What an analytics backend can actually carry.
1234
+ *
1235
+ * GA4 and OpenPanel serialise a property to a scalar; an object or a function
1236
+ * arrives as "[object Object]" without erroring anywhere. Declaring the wider
1237
+ * `unknown` here promised a forwarding guarantee no implementation keeps, and
1238
+ * it made this sink incompatible with `AnalyticsEventProperties` in
1239
+ * `@djangocfg/analytics` — the two describe the same channel and must agree.
1240
+ * Kept as a local declaration rather than an import: `api` does not depend on
1241
+ * `analytics`, and one shared four-member union is not worth that edge.
1242
+ */
1243
+ type AnalyticsPropertyValue = string | number | boolean | null;
1139
1244
  interface AnalyticsEventParams {
1140
1245
  category?: AnalyticsCategoryType;
1141
1246
  label?: string;
1142
1247
  value?: number;
1143
- [key: string]: any;
1248
+ [key: string]: AnalyticsPropertyValue | undefined;
1144
1249
  }
1145
1250
  /** What an analytics implementation must provide to receive auth events. */
1146
1251
  interface AnalyticsSink {
1147
- event(name: string, params?: Record<string, any>): void;
1252
+ event(name: string, params?: Record<string, AnalyticsPropertyValue | undefined>): void;
1148
1253
  setUser(userId: string | null): void;
1149
1254
  }
1150
1255
  /**