@digitaldefiance/express-suite-react-components 2.9.38 → 2.9.39

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 (257) hide show
  1. package/package.json +5 -4
  2. package/src/auth/Private.d.ts +6 -0
  3. package/src/auth/Private.d.ts.map +1 -0
  4. package/src/auth/Private.js +14 -0
  5. package/src/auth/PrivateRoute.d.ts +8 -0
  6. package/src/auth/PrivateRoute.d.ts.map +1 -0
  7. package/src/auth/PrivateRoute.js +23 -0
  8. package/src/auth/UnAuth.d.ts +6 -0
  9. package/src/auth/UnAuth.d.ts.map +1 -0
  10. package/src/auth/UnAuth.js +14 -0
  11. package/src/auth/UnAuthRoute.d.ts +8 -0
  12. package/src/auth/UnAuthRoute.d.ts.map +1 -0
  13. package/src/auth/UnAuthRoute.js +22 -0
  14. package/src/auth/{index.ts → index.d.ts} +2 -1
  15. package/src/auth/index.d.ts.map +1 -0
  16. package/src/auth/index.js +10 -0
  17. package/src/components/ApiAccess.d.ts +16 -0
  18. package/src/components/ApiAccess.d.ts.map +1 -0
  19. package/src/components/ApiAccess.js +77 -0
  20. package/src/components/BackupCodeLoginForm.d.ts +43 -0
  21. package/src/components/BackupCodeLoginForm.d.ts.map +1 -0
  22. package/src/components/BackupCodeLoginForm.js +139 -0
  23. package/src/components/BackupCodesForm.d.ts +26 -0
  24. package/src/components/BackupCodesForm.d.ts.map +1 -0
  25. package/src/components/BackupCodesForm.js +120 -0
  26. package/src/components/ChangePasswordForm.d.ts +26 -0
  27. package/src/components/ChangePasswordForm.d.ts.map +1 -0
  28. package/src/components/ChangePasswordForm.js +78 -0
  29. package/src/components/ConfirmationDialog.d.ts +13 -0
  30. package/src/components/ConfirmationDialog.d.ts.map +1 -0
  31. package/src/components/ConfirmationDialog.js +10 -0
  32. package/src/components/CurrencyCodeSelector.d.ts +9 -0
  33. package/src/components/CurrencyCodeSelector.d.ts.map +1 -0
  34. package/src/components/CurrencyCodeSelector.js +31 -0
  35. package/src/components/CurrencyInput.d.ts +13 -0
  36. package/src/components/CurrencyInput.d.ts.map +1 -0
  37. package/src/components/CurrencyInput.js +22 -0
  38. package/src/components/DashboardPage.d.ts +8 -0
  39. package/src/components/DashboardPage.d.ts.map +1 -0
  40. package/src/components/DashboardPage.js +10 -0
  41. package/src/components/DropdownMenu.d.ts +9 -0
  42. package/src/components/DropdownMenu.d.ts.map +1 -0
  43. package/src/components/DropdownMenu.js +56 -0
  44. package/src/components/ExpirationSecondsSelector.d.ts +13 -0
  45. package/src/components/ExpirationSecondsSelector.d.ts.map +1 -0
  46. package/src/components/ExpirationSecondsSelector.js +32 -0
  47. package/src/components/Flag.d.ts +20 -0
  48. package/src/components/Flag.d.ts.map +1 -0
  49. package/src/components/Flag.js +43 -0
  50. package/src/components/ForgotPasswordForm.d.ts +18 -0
  51. package/src/components/ForgotPasswordForm.d.ts.map +1 -0
  52. package/src/components/ForgotPasswordForm.js +61 -0
  53. package/src/components/LoginForm.d.ts +44 -0
  54. package/src/components/LoginForm.d.ts.map +1 -0
  55. package/src/components/LoginForm.js +122 -0
  56. package/src/components/LogoutPage.d.ts +8 -0
  57. package/src/components/LogoutPage.d.ts.map +1 -0
  58. package/src/components/LogoutPage.js +16 -0
  59. package/src/components/RegisterForm.d.ts +56 -0
  60. package/src/components/RegisterForm.d.ts.map +1 -0
  61. package/src/components/RegisterForm.js +140 -0
  62. package/src/components/ResetPasswordForm.d.ts +23 -0
  63. package/src/components/ResetPasswordForm.d.ts.map +1 -0
  64. package/src/components/ResetPasswordForm.js +78 -0
  65. package/src/components/SideMenu.d.ts +8 -0
  66. package/src/components/SideMenu.d.ts.map +1 -0
  67. package/src/components/SideMenu.js +25 -0
  68. package/src/components/SideMenuListItem.d.ts +13 -0
  69. package/src/components/SideMenuListItem.d.ts.map +1 -0
  70. package/src/components/SideMenuListItem.js +44 -0
  71. package/src/components/TopMenu.d.ts +24 -0
  72. package/src/components/TopMenu.d.ts.map +1 -0
  73. package/src/components/TopMenu.js +35 -0
  74. package/src/components/TranslatedTitle.d.ts +7 -0
  75. package/src/components/TranslatedTitle.d.ts.map +1 -0
  76. package/src/components/TranslatedTitle.js +15 -0
  77. package/src/components/UserLanguageSelector.d.ts +4 -0
  78. package/src/components/UserLanguageSelector.d.ts.map +1 -0
  79. package/src/components/UserLanguageSelector.js +31 -0
  80. package/src/components/UserMenu.d.ts +4 -0
  81. package/src/components/UserMenu.d.ts.map +1 -0
  82. package/src/components/UserMenu.js +12 -0
  83. package/src/components/UserSettingsForm.d.ts +57 -0
  84. package/src/components/UserSettingsForm.d.ts.map +1 -0
  85. package/src/components/UserSettingsForm.js +126 -0
  86. package/src/components/VerifyEmailPage.d.ts +23 -0
  87. package/src/components/VerifyEmailPage.d.ts.map +1 -0
  88. package/src/components/VerifyEmailPage.js +70 -0
  89. package/src/components/{index.ts → index.d.ts} +1 -1
  90. package/src/components/index.d.ts.map +1 -0
  91. package/src/components/index.js +28 -0
  92. package/src/contexts/AuthProvider.d.ts +152 -0
  93. package/src/contexts/AuthProvider.d.ts.map +1 -0
  94. package/src/contexts/AuthProvider.js +502 -0
  95. package/src/contexts/I18nProvider.d.ts +16 -0
  96. package/src/contexts/I18nProvider.d.ts.map +1 -0
  97. package/src/contexts/I18nProvider.js +46 -0
  98. package/src/contexts/MenuContext.d.ts +20 -0
  99. package/src/contexts/MenuContext.d.ts.map +1 -0
  100. package/src/contexts/MenuContext.js +273 -0
  101. package/src/contexts/SuiteConfigProvider.d.ts +44 -0
  102. package/src/contexts/SuiteConfigProvider.d.ts.map +1 -0
  103. package/src/contexts/SuiteConfigProvider.js +43 -0
  104. package/src/contexts/ThemeProvider.d.ts +15 -0
  105. package/src/contexts/ThemeProvider.d.ts.map +1 -0
  106. package/src/contexts/ThemeProvider.js +36 -0
  107. package/src/contexts/{index.ts → index.d.ts} +1 -0
  108. package/src/contexts/index.d.ts.map +1 -0
  109. package/src/contexts/index.js +8 -0
  110. package/src/hooks/{index.ts → index.d.ts} +1 -0
  111. package/src/hooks/index.d.ts.map +1 -0
  112. package/src/hooks/index.js +8 -0
  113. package/src/hooks/useBackupCodes.d.ts +15 -0
  114. package/src/hooks/useBackupCodes.d.ts.map +1 -0
  115. package/src/hooks/useBackupCodes.js +74 -0
  116. package/src/hooks/useEmailVerification.d.ts +10 -0
  117. package/src/hooks/useEmailVerification.d.ts.map +1 -0
  118. package/src/hooks/useEmailVerification.js +40 -0
  119. package/src/hooks/useExpiringValue.d.ts +14 -0
  120. package/src/hooks/useExpiringValue.d.ts.map +1 -0
  121. package/src/hooks/useExpiringValue.js +53 -0
  122. package/src/hooks/useLocalStorage.d.ts +2 -0
  123. package/src/hooks/useLocalStorage.d.ts.map +1 -0
  124. package/src/hooks/useLocalStorage.js +15 -0
  125. package/src/hooks/useUserSettings.d.ts +48 -0
  126. package/src/hooks/useUserSettings.d.ts.map +1 -0
  127. package/src/hooks/useUserSettings.js +169 -0
  128. package/src/{index.ts → index.d.ts} +1 -1
  129. package/src/index.d.ts.map +1 -0
  130. package/src/index.js +12 -0
  131. package/src/interfaces/IAppConfig.d.ts +6 -0
  132. package/src/interfaces/IAppConfig.d.ts.map +1 -0
  133. package/src/interfaces/IAppConfig.js +2 -0
  134. package/src/interfaces/IMenuConfig.d.ts +11 -0
  135. package/src/interfaces/IMenuConfig.d.ts.map +1 -0
  136. package/src/interfaces/IMenuConfig.js +2 -0
  137. package/src/interfaces/IMenuOption.d.ts +58 -0
  138. package/src/interfaces/IMenuOption.d.ts.map +1 -0
  139. package/src/interfaces/IMenuOption.js +2 -0
  140. package/src/interfaces/index.d.ts +4 -0
  141. package/src/interfaces/index.d.ts.map +1 -0
  142. package/src/interfaces/index.js +6 -0
  143. package/src/services/__mocks__/authService.d.ts +21 -0
  144. package/src/services/__mocks__/authService.d.ts.map +1 -0
  145. package/src/services/__mocks__/authService.js +15 -0
  146. package/src/services/api.d.ts +3 -0
  147. package/src/services/api.d.ts.map +1 -0
  148. package/src/services/api.js +14 -0
  149. package/src/services/authService.d.ts +72 -0
  150. package/src/services/authService.d.ts.map +1 -0
  151. package/src/services/authService.js +335 -0
  152. package/src/services/authenticatedApi.d.ts +3 -0
  153. package/src/services/authenticatedApi.d.ts.map +1 -0
  154. package/src/services/authenticatedApi.js +18 -0
  155. package/src/services/index.d.ts +4 -0
  156. package/src/services/index.d.ts.map +1 -0
  157. package/src/services/index.js +6 -0
  158. package/src/types/MenuType.d.ts +11 -0
  159. package/src/types/MenuType.d.ts.map +1 -0
  160. package/src/types/MenuType.js +12 -0
  161. package/src/types/expirationSeconds.d.ts +3 -0
  162. package/src/types/expirationSeconds.d.ts.map +1 -0
  163. package/src/types/expirationSeconds.js +17 -0
  164. package/src/types/index.d.ts +2 -0
  165. package/src/types/index.d.ts.map +1 -0
  166. package/src/types/index.js +4 -0
  167. package/src/types/translation.d.ts +10 -0
  168. package/src/types/translation.d.ts.map +1 -0
  169. package/src/types/translation.js +9 -0
  170. package/src/wrappers/BackupCodeLoginWrapper.d.ts +8 -0
  171. package/src/wrappers/BackupCodeLoginWrapper.d.ts.map +1 -0
  172. package/src/wrappers/BackupCodeLoginWrapper.js +20 -0
  173. package/src/wrappers/BackupCodesWrapper.d.ts +7 -0
  174. package/src/wrappers/BackupCodesWrapper.d.ts.map +1 -0
  175. package/src/wrappers/BackupCodesWrapper.js +17 -0
  176. package/src/wrappers/ChangePasswordFormWrapper.d.ts +8 -0
  177. package/src/wrappers/ChangePasswordFormWrapper.d.ts.map +1 -0
  178. package/src/wrappers/ChangePasswordFormWrapper.js +21 -0
  179. package/src/wrappers/LoginFormWrapper.d.ts +9 -0
  180. package/src/wrappers/LoginFormWrapper.d.ts.map +1 -0
  181. package/src/wrappers/LoginFormWrapper.js +43 -0
  182. package/src/wrappers/LogoutPageWrapper.d.ts +9 -0
  183. package/src/wrappers/LogoutPageWrapper.d.ts.map +1 -0
  184. package/src/wrappers/LogoutPageWrapper.js +21 -0
  185. package/src/wrappers/RegisterFormWrapper.d.ts +9 -0
  186. package/src/wrappers/RegisterFormWrapper.d.ts.map +1 -0
  187. package/src/wrappers/RegisterFormWrapper.js +31 -0
  188. package/src/wrappers/UserSettingsFormWrapper.d.ts +8 -0
  189. package/src/wrappers/UserSettingsFormWrapper.d.ts.map +1 -0
  190. package/src/wrappers/UserSettingsFormWrapper.js +24 -0
  191. package/src/wrappers/VerifyEmailPageWrapper.d.ts +8 -0
  192. package/src/wrappers/VerifyEmailPageWrapper.d.ts.map +1 -0
  193. package/src/wrappers/VerifyEmailPageWrapper.js +20 -0
  194. package/src/wrappers/{index.tsx → index.d.ts} +1 -8
  195. package/src/wrappers/index.d.ts.map +1 -0
  196. package/src/wrappers/index.js +20 -0
  197. package/LICENSE +0 -21
  198. package/src/auth/Private.tsx +0 -17
  199. package/src/auth/PrivateRoute.tsx +0 -28
  200. package/src/auth/UnAuth.tsx +0 -16
  201. package/src/auth/UnAuthRoute.tsx +0 -30
  202. package/src/components/ApiAccess.tsx +0 -174
  203. package/src/components/BackupCodeLoginForm.tsx +0 -488
  204. package/src/components/BackupCodesForm.tsx +0 -286
  205. package/src/components/ChangePasswordForm.tsx +0 -272
  206. package/src/components/ConfirmationDialog.tsx +0 -48
  207. package/src/components/CurrencyCodeSelector.tsx +0 -60
  208. package/src/components/CurrencyInput.tsx +0 -80
  209. package/src/components/DashboardPage.tsx +0 -24
  210. package/src/components/DropdownMenu.tsx +0 -92
  211. package/src/components/ExpirationSecondsSelector.tsx +0 -60
  212. package/src/components/Flag.tsx +0 -52
  213. package/src/components/ForgotPasswordForm.tsx +0 -173
  214. package/src/components/LoginForm.tsx +0 -455
  215. package/src/components/LogoutPage.tsx +0 -21
  216. package/src/components/RegisterForm.tsx +0 -602
  217. package/src/components/ResetPasswordForm.tsx +0 -246
  218. package/src/components/SideMenu.tsx +0 -46
  219. package/src/components/SideMenuListItem.tsx +0 -74
  220. package/src/components/TopMenu.tsx +0 -145
  221. package/src/components/TranslatedTitle.tsx +0 -29
  222. package/src/components/UserLanguageSelector.tsx +0 -45
  223. package/src/components/UserMenu.tsx +0 -15
  224. package/src/components/UserSettingsForm.tsx +0 -505
  225. package/src/components/VerifyEmailPage.tsx +0 -184
  226. package/src/contexts/AuthProvider.spec.tsx +0 -1195
  227. package/src/contexts/AuthProvider.tsx +0 -924
  228. package/src/contexts/I18nProvider.tsx +0 -114
  229. package/src/contexts/MenuContext.tsx +0 -398
  230. package/src/contexts/SuiteConfigProvider.tsx +0 -93
  231. package/src/contexts/ThemeProvider.tsx +0 -67
  232. package/src/hooks/useBackupCodes.ts +0 -105
  233. package/src/hooks/useEmailVerification.ts +0 -49
  234. package/src/hooks/useExpiringValue.ts +0 -78
  235. package/src/hooks/useLocalStorage.ts +0 -18
  236. package/src/hooks/useUserSettings.ts +0 -269
  237. package/src/interfaces/IAppConfig.ts +0 -5
  238. package/src/interfaces/IMenuConfig.ts +0 -11
  239. package/src/interfaces/IMenuOption.ts +0 -55
  240. package/src/interfaces/index.ts +0 -3
  241. package/src/services/__mocks__/authService.ts +0 -14
  242. package/src/services/api.ts +0 -13
  243. package/src/services/authService.ts +0 -500
  244. package/src/services/authenticatedApi.ts +0 -17
  245. package/src/services/index.ts +0 -3
  246. package/src/types/MenuType.ts +0 -15
  247. package/src/types/expirationSeconds.ts +0 -18
  248. package/src/types/index.ts +0 -1
  249. package/src/types/translation.ts +0 -20
  250. package/src/wrappers/BackupCodeLoginWrapper.tsx +0 -34
  251. package/src/wrappers/BackupCodesWrapper.tsx +0 -28
  252. package/src/wrappers/ChangePasswordFormWrapper.tsx +0 -34
  253. package/src/wrappers/LoginFormWrapper.tsx +0 -59
  254. package/src/wrappers/LogoutPageWrapper.tsx +0 -30
  255. package/src/wrappers/RegisterFormWrapper.tsx +0 -61
  256. package/src/wrappers/UserSettingsFormWrapper.tsx +0 -39
  257. package/src/wrappers/VerifyEmailPageWrapper.tsx +0 -27
@@ -1,924 +0,0 @@
1
- import {
2
- AESGCMService,
3
- Constants as AppConstants,
4
- ECIESService,
5
- EmailString,
6
- Member as FrontendMember,
7
- IECIESConfig,
8
- PasswordLoginService,
9
- Pbkdf2Service,
10
- SecureString,
11
- } from '@digitaldefiance/ecies-lib';
12
- import {
13
- CoreLanguageCode,
14
- CurrencyCode,
15
- Timezone,
16
- } from '@digitaldefiance/i18n-lib';
17
- import {
18
- IConstants,
19
- IRequestUserDTO,
20
- ISuccessMessage,
21
- IUserSettings,
22
- SuiteCoreComponentId,
23
- SuiteCoreStringKey,
24
- } from '@digitaldefiance/suite-core-lib';
25
- import { Wallet } from '@ethereumjs/wallet';
26
- import { PaletteMode } from '@mui/material';
27
- import {
28
- createContext,
29
- ReactNode,
30
- useCallback,
31
- useContext,
32
- useEffect,
33
- useMemo,
34
- useState,
35
- } from 'react';
36
- import { useExpiringValue } from '../hooks/useExpiringValue';
37
- import { useLocalStorage } from '../hooks/useLocalStorage';
38
- import { useUserSettings } from '../hooks/useUserSettings';
39
- import { createAuthService } from '../services/authService';
40
- import { createAuthenticatedApiClient } from '../services/authenticatedApi';
41
- import { useI18n } from './I18nProvider';
42
- import { useTheme } from './ThemeProvider';
43
-
44
- export interface AuthContextData {
45
- /**
46
- * True if the user has a global admin role
47
- */
48
- admin: boolean;
49
- /**
50
- * Counter that increments on login/logout to trigger effects in dependent components
51
- */
52
- authState: number;
53
- /**
54
- * Performs a server side backup-code login
55
- * @param identifier
56
- * @param code
57
- * @param isEmail
58
- * @param recoverMnemonic
59
- * @param newPassword
60
- * @returns
61
- */
62
- backupCodeLogin: (
63
- identifier: string,
64
- code: string,
65
- isEmail: boolean,
66
- recoverMnemonic: boolean,
67
- newPassword?: string
68
- ) => Promise<
69
- | { token: string; codeCount: number; mnemonic?: string; message?: string }
70
- | { error: string; status?: number }
71
- >;
72
- /**
73
- * Verifies the stored token (if any) and updates auth state
74
- * @returns void
75
- */
76
- checkAuth: () => void;
77
- /**
78
- * Changes the stored browser password login mnemonic
79
- * @param currentPassword
80
- * @param newPassword
81
- * @returns
82
- */
83
- changePassword: (
84
- currentPassword: string,
85
- newPassword: string
86
- ) => Promise<
87
- | ISuccessMessage
88
- | {
89
- error: string;
90
- errorType?: string | undefined;
91
- }
92
- >;
93
- clearMnemonic: () => void;
94
- clearWallet: () => void;
95
- colorMode?: PaletteMode;
96
- currencyCode?: CurrencyCode;
97
- directLogin: (
98
- mnemonic: SecureString,
99
- username?: string,
100
- email?: EmailString,
101
- expireMnemonicSeconds?: number,
102
- expireWalletSeconds?: number
103
- ) => Promise<
104
- | { token: string; user: IRequestUserDTO; wallet: Wallet }
105
- | { error: string; errorType?: string }
106
- >;
107
- emailChallengeLogin: (
108
- mnemonic: SecureString,
109
- token: string,
110
- username?: string,
111
- email?: EmailString,
112
- expireMnemonicSeconds?: number,
113
- expireWalletSeconds?: number
114
- ) => Promise<
115
- | { token: string; user: IRequestUserDTO; wallet: Wallet; message: string }
116
- | { error: string; errorType?: string }
117
- >;
118
- isAuthenticated: boolean;
119
- // True only while the app is determining initial auth state (e.g., on first load or refresh)
120
- isCheckingAuth: boolean;
121
- isBrowserPasswordLoginAvailable?: () => boolean;
122
- loading: boolean;
123
- logout: () => void;
124
- mnemonic?: SecureString;
125
- mnemonicExpirationSeconds: number;
126
- passwordLogin: (
127
- password: SecureString,
128
- username?: string,
129
- email?: EmailString
130
- ) => Promise<
131
- | { token: string; user: IRequestUserDTO; wallet: Wallet }
132
- | { error: string; errorType?: string }
133
- >;
134
- requestEmailLogin: (
135
- username?: string,
136
- email?: EmailString
137
- ) => Promise<string | { error: string; errorType?: string }>;
138
- refreshToken: () => Promise<{ token: string; user: IRequestUserDTO }>;
139
- register: (
140
- username: string,
141
- email: string,
142
- timezone: string,
143
- password?: string
144
- ) => Promise<
145
- | {
146
- success: boolean;
147
- message: string;
148
- mnemonic: string;
149
- }
150
- | {
151
- error: string;
152
- errorType?: string;
153
- field?: string;
154
- errors?: Array<{ path: string; msg: string }>;
155
- }
156
- >;
157
- serverPublicKey: string | null;
158
- /**
159
- * Gets the remaining time in seconds for the mnemonic expiration
160
- * @returns Number of seconds remaining, or 0 if no mnemonic is set
161
- */
162
- getMnemonicRemainingTime: () => number;
163
- /**
164
- * Gets the remaining time in seconds for the wallet expiration
165
- * @returns Number of seconds remaining, or 0 if no wallet is set
166
- */
167
- getWalletRemainingTime: () => number;
168
- setMnemonic: (mnemonic: SecureString, durationSeconds?: number) => void;
169
- setMnemonicExpirationSeconds: (seconds: number) => void;
170
- setWalletExpirationSeconds: (seconds: number) => void;
171
- setUpBrowserPasswordLogin: (
172
- mnemonic: SecureString,
173
- password: SecureString,
174
- username?: string,
175
- email?: EmailString
176
- ) => Promise<
177
- | { success: boolean; message: string }
178
- | { error: string; errorType?: string }
179
- >;
180
- setUser: (user: IRequestUserDTO | null) => Promise<void>;
181
- setUserSetting: (setting?: Partial<IUserSettings>) => Promise<void>;
182
- setWallet: (wallet: Wallet, durationSeconds?: number) => void;
183
- user: FrontendMember | null;
184
- userData: IRequestUserDTO | null;
185
- userSettings: IUserSettings | undefined;
186
- token: string | null;
187
- wallet?: Wallet;
188
- walletExpirationSeconds: number;
189
- verifyToken: (token: string) => Promise<boolean>;
190
- }
191
-
192
- export type AuthProviderProps = {
193
- children: ReactNode;
194
- baseUrl: string;
195
- constants: IConstants;
196
- eciesConfig: IECIESConfig;
197
- /**
198
- * Optional callback to handle navigation after logout
199
- * If not provided, logout will only clear auth state without navigation
200
- */
201
- onLogout?: () => void;
202
- };
203
-
204
- export const AuthContext = createContext<AuthContextData>(
205
- {} as AuthContextData
206
- );
207
-
208
- const AuthProviderInner = ({
209
- children,
210
- baseUrl,
211
- constants,
212
- eciesConfig,
213
- onLogout,
214
- }: AuthProviderProps) => {
215
- const { tComponent } = useI18n();
216
- const { setColorMode: themeSetPaletteMode, mode: colorMode } = useTheme();
217
-
218
- const authService = useMemo(
219
- () => createAuthService(constants, baseUrl, eciesConfig),
220
- [constants, baseUrl, eciesConfig]
221
- );
222
- const authenticatedApi = useMemo(
223
- () => createAuthenticatedApiClient(baseUrl),
224
- [baseUrl]
225
- );
226
-
227
- // Use the custom hooks for expiring values
228
- const mnemonicManager = useExpiringValue<SecureString>(
229
- constants.DefaultExpireMemoryMnemonicSeconds,
230
- 'mnemonicExpirationSeconds'
231
- );
232
- const walletManager = useExpiringValue<Wallet>(
233
- constants.DefaultExpireMemoryWalletSeconds,
234
- 'walletExpirationSeconds'
235
- );
236
-
237
- // Use localStorage hook for expiration settings
238
- const [mnemonicExpirationSeconds, _setMnemonicExpirationSeconds] =
239
- useLocalStorage(
240
- 'mnemonicExpirationSeconds',
241
- constants.DefaultExpireMemoryMnemonicSeconds
242
- );
243
- const [walletExpirationSeconds, _setWalletExpirationSeconds] =
244
- useLocalStorage(
245
- 'walletExpirationSeconds',
246
- constants.DefaultExpireMemoryWalletSeconds
247
- );
248
- const [serverPublicKey, setServerPublicKey] = useState<string | null>(null);
249
- const [user, setUser] = useState<IRequestUserDTO | null>(null);
250
- const [frontendUser, setFrontendUser] = useState<FrontendMember | null>(null);
251
- const [isAuthenticated, setIsAuthenticated] = useState(false);
252
- const [isGlobalAdmin, setIsGlobalAdmin] = useState(false);
253
- const [loading, setLoading] = useState(true);
254
- // Separate flag so route guards don't unmount during actions (e.g., register/login)
255
- const [isCheckingAuth, setIsCheckingAuth] = useState(true);
256
- const [token, setToken] = useState<string | null>(null);
257
- const [authState, setAuthState] = useState(0);
258
-
259
- // Use the user settings hook for settings management
260
- const { userSettings, setUserSettingAndUpdateSettings } = useUserSettings({
261
- authenticatedApi,
262
- isAuthenticated,
263
- });
264
-
265
- // Helper functions to calculate remaining time (now provided by the hooks)
266
- const getMnemonicRemainingTime = mnemonicManager.getRemainingTime;
267
- const getWalletRemainingTime = walletManager.getRemainingTime;
268
-
269
- // Wrapper functions to match the interface (the localStorage hook handles storage automatically)
270
- const setMnemonicExpirationSeconds = _setMnemonicExpirationSeconds;
271
- const setWalletExpirationSeconds = _setWalletExpirationSeconds;
272
-
273
- // Sync user language with i18n provider when the user's saved language changes.
274
- // Important: do NOT depend on currentLanguage here, or we'll run when the UI
275
- // language changes and inadvertently revert to the older user.siteLanguage,
276
- // causing a second update request with English US.
277
- useEffect(() => {
278
- if (user?.siteLanguage) {
279
- (async () => {
280
- await setUserSettingAndUpdateSettings({
281
- siteLanguage: user.siteLanguage,
282
- });
283
- })();
284
- }
285
- // We intentionally only react to changes in the user's saved language.
286
- // eslint-disable-next-line react-hooks/exhaustive-deps
287
- }, [user?.siteLanguage]);
288
-
289
- const setMnemonic = useCallback(
290
- (mnemonic: SecureString, durationSeconds?: number) => {
291
- const finalDurationSeconds = durationSeconds ?? mnemonicExpirationSeconds;
292
-
293
- // Store the duration to localStorage if provided
294
- if (durationSeconds !== undefined) {
295
- _setMnemonicExpirationSeconds(durationSeconds);
296
- }
297
-
298
- // Only save to storage if a custom duration was provided
299
- return mnemonicManager.setValue(
300
- mnemonic,
301
- finalDurationSeconds,
302
- durationSeconds !== undefined
303
- );
304
- },
305
- // mnemonicManager is intentionally excluded as it's a stable reference from useExpiringValue
306
- // eslint-disable-next-line react-hooks/exhaustive-deps
307
- [
308
- mnemonicExpirationSeconds,
309
- mnemonicManager.setValue,
310
- _setMnemonicExpirationSeconds,
311
- ]
312
- );
313
-
314
- const setWallet = useCallback(
315
- (wallet: Wallet, durationSeconds?: number) => {
316
- const finalDurationSeconds = durationSeconds ?? walletExpirationSeconds;
317
-
318
- // Store the duration to localStorage if provided
319
- if (durationSeconds !== undefined) {
320
- _setWalletExpirationSeconds(durationSeconds);
321
- }
322
-
323
- // Only save to storage if a custom duration was provided
324
- return walletManager.setValue(
325
- wallet,
326
- finalDurationSeconds,
327
- durationSeconds !== undefined
328
- );
329
- },
330
- // walletManager is intentionally excluded as it's a stable reference from useExpiringValue
331
- // eslint-disable-next-line react-hooks/exhaustive-deps
332
- [
333
- walletExpirationSeconds,
334
- walletManager.setValue,
335
- _setWalletExpirationSeconds,
336
- ]
337
- );
338
-
339
- const clearMnemonic = mnemonicManager.clearValue;
340
- const clearWallet = walletManager.clearValue;
341
-
342
- const checkAuth = useCallback(async () => {
343
- const token = localStorage.getItem('authToken');
344
- if (!token) {
345
- setUser(null);
346
- setIsAuthenticated(false);
347
- setLoading(false);
348
- setIsCheckingAuth(false);
349
- setToken(null);
350
- setFrontendUser(null);
351
- setServerPublicKey(null);
352
- await setUserSettingAndUpdateSettings(undefined);
353
- themeSetPaletteMode('light');
354
- clearMnemonic();
355
- clearWallet();
356
- return;
357
- }
358
-
359
- try {
360
- const userData = await authService.verifyToken(token);
361
- if ('error' in userData && typeof userData.error === 'string') {
362
- setIsAuthenticated(false);
363
- setToken(null);
364
- } else if ('id' in userData && 'email' in userData) {
365
- const userDataDTO: IRequestUserDTO = userData as IRequestUserDTO;
366
- setUser(userDataDTO);
367
- setIsGlobalAdmin(userDataDTO.roles.some((r) => r.admin));
368
- setIsAuthenticated(true);
369
- setToken(token);
370
- await setUserSettingAndUpdateSettings({
371
- darkMode: userDataDTO.darkMode,
372
- currency: new CurrencyCode(userDataDTO.currency),
373
- timezone: new Timezone(userDataDTO.timezone),
374
- siteLanguage: userDataDTO.siteLanguage as CoreLanguageCode,
375
- email: new EmailString(userDataDTO.email),
376
- directChallenge: userDataDTO.directChallenge,
377
- });
378
- }
379
- } catch (error) {
380
- console.error('Token verification failed:', error);
381
- setUser(null);
382
- setIsAuthenticated(false);
383
- await setUserSettingAndUpdateSettings(undefined);
384
- localStorage.removeItem('authToken');
385
- } finally {
386
- setLoading(false);
387
- setIsCheckingAuth(false);
388
- }
389
- }, [
390
- authService,
391
- clearMnemonic,
392
- clearWallet,
393
- setUserSettingAndUpdateSettings,
394
- themeSetPaletteMode,
395
- ]);
396
-
397
- useEffect(() => {
398
- const token = localStorage.getItem('authToken');
399
- if (token) {
400
- (async () => {
401
- await checkAuth();
402
- })();
403
- } else {
404
- setLoading(false);
405
- setIsCheckingAuth(false);
406
- }
407
- // eslint-disable-next-line react-hooks/exhaustive-deps
408
- }, [authState]); // Only run when authState changes (login/logout), not when checkAuth is recreated
409
-
410
- const directLogin: AuthContextData['directLogin'] = useCallback(
411
- async (
412
- mnemonic,
413
- username,
414
- email,
415
- expireMnemonicSeconds,
416
- expireWalletSeconds
417
- ) => {
418
- setLoading(true);
419
- const loginResult = await authService.directLogin(
420
- mnemonic,
421
- username,
422
- email
423
- );
424
- setLoading(false);
425
- if (
426
- typeof loginResult === 'object' &&
427
- 'token' in loginResult &&
428
- 'user' in loginResult &&
429
- 'wallet' in loginResult
430
- ) {
431
- setMnemonic(mnemonic, expireMnemonicSeconds);
432
- setUser(loginResult.user);
433
- setWallet(loginResult.wallet, expireWalletSeconds);
434
- setIsAuthenticated(true);
435
- setAuthState((prev) => prev + 1);
436
- localStorage.setItem('authToken', loginResult.token);
437
- localStorage.setItem('user', JSON.stringify(loginResult.user));
438
- await setUserSettingAndUpdateSettings({
439
- darkMode: loginResult.user.darkMode,
440
- currency: new CurrencyCode(loginResult.user.currency),
441
- timezone: new Timezone(loginResult.user.timezone),
442
- siteLanguage: loginResult.user.siteLanguage as CoreLanguageCode,
443
- email: new EmailString(loginResult.user.email),
444
- directChallenge: loginResult.user.directChallenge,
445
- });
446
- return loginResult;
447
- }
448
- return loginResult;
449
- },
450
- [authService, setMnemonic, setWallet, setUserSettingAndUpdateSettings]
451
- );
452
-
453
- const emailChallengeLogin: AuthContextData['emailChallengeLogin'] =
454
- useCallback(
455
- async (
456
- mnemonic,
457
- token,
458
- username,
459
- email,
460
- expireMnemonicSeconds,
461
- expireWalletSeconds
462
- ) => {
463
- setLoading(true);
464
- const loginResult = await authService.emailChallengeLogin(
465
- mnemonic,
466
- token,
467
- username,
468
- email
469
- );
470
- setLoading(false);
471
- if (
472
- typeof loginResult === 'object' &&
473
- 'token' in loginResult &&
474
- 'user' in loginResult &&
475
- 'wallet' in loginResult
476
- ) {
477
- setMnemonic(mnemonic, expireMnemonicSeconds);
478
- setUser(loginResult.user);
479
- setWallet(loginResult.wallet, expireWalletSeconds);
480
- setIsAuthenticated(true);
481
- setAuthState((prev) => prev + 1);
482
- localStorage.setItem('authToken', loginResult.token);
483
- localStorage.setItem('user', JSON.stringify(loginResult.user));
484
- await setUserSettingAndUpdateSettings({
485
- darkMode: loginResult.user.darkMode,
486
- currency: new CurrencyCode(loginResult.user.currency),
487
- timezone: new Timezone(loginResult.user.timezone),
488
- siteLanguage: loginResult.user.siteLanguage as CoreLanguageCode,
489
- email: new EmailString(loginResult.user.email),
490
- directChallenge: loginResult.user.directChallenge,
491
- });
492
- return loginResult;
493
- }
494
- return loginResult;
495
- },
496
- [authService, setMnemonic, setWallet, setUserSettingAndUpdateSettings]
497
- );
498
- const getPasswordLoginService = useCallback(() => {
499
- const eciesService: ECIESService = new ECIESService(eciesConfig);
500
- const aesGcmService = new AESGCMService();
501
- return new PasswordLoginService(
502
- aesGcmService,
503
- eciesService,
504
- new Pbkdf2Service(
505
- AppConstants.PBKDF2_PROFILES,
506
- AppConstants.ECIES,
507
- AppConstants.PBKDF2
508
- )
509
- );
510
- }, [eciesConfig]);
511
-
512
- const isBrowserPasswordLoginAvailable = useCallback(() => {
513
- const storedEncryptedPassword = localStorage.getItem('encryptedPassword');
514
- return !!storedEncryptedPassword;
515
- }, []);
516
-
517
- const passwordLogin: AuthContextData['passwordLogin'] = useCallback(
518
- async (password: SecureString, username?: string, email?: EmailString) => {
519
- if (!isBrowserPasswordLoginAvailable()) {
520
- return {
521
- error: tComponent<SuiteCoreStringKey>(
522
- SuiteCoreComponentId,
523
- SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup
524
- ),
525
- errorType: 'PasswordLoginNotSetup',
526
- };
527
- }
528
- setLoading(true);
529
- const passwordLoginService: PasswordLoginService =
530
- getPasswordLoginService();
531
- const { wallet, mnemonic } =
532
- await passwordLoginService.getWalletAndMnemonicFromLocalStorageBundle(
533
- password
534
- );
535
- const loginResult = await authService.directLogin(
536
- mnemonic,
537
- username,
538
- email
539
- );
540
- setLoading(false);
541
- setWallet(wallet);
542
- setMnemonic(mnemonic);
543
- // Set theme based on user's darkMode preference if login succeeded
544
- if ('user' in loginResult) {
545
- await setUserSettingAndUpdateSettings({
546
- darkMode: loginResult.user.darkMode,
547
- currency: new CurrencyCode(loginResult.user.currency),
548
- timezone: new Timezone(loginResult.user.timezone),
549
- siteLanguage: loginResult.user.siteLanguage as CoreLanguageCode,
550
- email: new EmailString(loginResult.user.email),
551
- directChallenge: loginResult.user.directChallenge,
552
- });
553
- }
554
- return loginResult;
555
- },
556
- [
557
- authService,
558
- getPasswordLoginService,
559
- setMnemonic,
560
- setWallet,
561
- tComponent,
562
- isBrowserPasswordLoginAvailable,
563
- setUserSettingAndUpdateSettings,
564
- ]
565
- );
566
-
567
- const refreshToken: AuthContextData['refreshToken'] =
568
- useCallback(async () => {
569
- try {
570
- const result = await authService.refreshToken();
571
- localStorage.setItem('authToken', result.token);
572
- localStorage.setItem('user', JSON.stringify(result.user));
573
- setUser(result.user);
574
- setIsAuthenticated(true);
575
- return result;
576
- } catch (error) {
577
- setUser(null);
578
- setIsAuthenticated(false);
579
- localStorage.removeItem('authToken');
580
- localStorage.removeItem('user');
581
- throw error;
582
- }
583
- }, [authService]);
584
-
585
- const register: AuthContextData['register'] = useCallback(
586
- async (
587
- username: string,
588
- email: string,
589
- timezone: string,
590
- password?: string
591
- ) => {
592
- const registerResult = await authService.register(
593
- username,
594
- email,
595
- timezone,
596
- password
597
- );
598
- return registerResult as Awaited<ReturnType<AuthContextData['register']>>;
599
- },
600
- [authService]
601
- );
602
-
603
- const requestEmailLogin = useCallback(
604
- async (
605
- username?: string,
606
- email?: EmailString
607
- ): Promise<string | { error: string; errorType?: string }> => {
608
- setLoading(true);
609
- const result = await authService.requestEmailLogin(username, email);
610
- setLoading(false);
611
- return result;
612
- },
613
- [authService]
614
- );
615
-
616
- const setUpBrowserPasswordLogin = useCallback(
617
- async (
618
- mnemonic: SecureString,
619
- password: SecureString
620
- ): Promise<
621
- | { success: boolean; message: string }
622
- | { error: string; errorType?: string }
623
- > => {
624
- setLoading(true);
625
- const passwordLoginService: PasswordLoginService =
626
- getPasswordLoginService();
627
- try {
628
- const wallet =
629
- await passwordLoginService.setupPasswordLoginLocalStorageBundle(
630
- mnemonic,
631
- password
632
- );
633
- setLoading(false);
634
- setWallet(wallet);
635
- setMnemonic(mnemonic);
636
- return {
637
- success: true,
638
- message: tComponent<SuiteCoreStringKey>(
639
- SuiteCoreComponentId,
640
- SuiteCoreStringKey.PasswordLogin_Setup_Success
641
- ),
642
- };
643
- } catch {
644
- setLoading(false);
645
- return {
646
- success: false,
647
- message: tComponent<SuiteCoreStringKey>(
648
- SuiteCoreComponentId,
649
- SuiteCoreStringKey.PasswordLogin_Setup_Failure
650
- ),
651
- };
652
- }
653
- },
654
- [getPasswordLoginService, setMnemonic, setWallet, tComponent]
655
- );
656
-
657
- const backupCodeLogin = useCallback(
658
- async (
659
- identifier: string,
660
- code: string,
661
- isEmail: boolean,
662
- recoverMnemonic: boolean,
663
- newPassword?: string
664
- ): Promise<
665
- | {
666
- token: string;
667
- codeCount: number;
668
- mnemonic?: string;
669
- message?: string;
670
- }
671
- | { error: string; status?: number }
672
- > => {
673
- setLoading(true);
674
- const loginResult = await authService.backupCodeLogin(
675
- identifier,
676
- code,
677
- isEmail,
678
- recoverMnemonic,
679
- newPassword
680
- );
681
- setLoading(false);
682
- if (typeof loginResult === 'object' && 'token' in loginResult) {
683
- localStorage.setItem('authToken', loginResult.token);
684
- if (loginResult.user) {
685
- setUser(loginResult.user);
686
- setIsAuthenticated(true);
687
- await setUserSettingAndUpdateSettings({
688
- darkMode: loginResult.user.darkMode,
689
- currency: new CurrencyCode(loginResult.user.currency),
690
- timezone: new Timezone(loginResult.user.timezone),
691
- siteLanguage: loginResult.user.siteLanguage as CoreLanguageCode,
692
- email: new EmailString(loginResult.user.email),
693
- directChallenge: loginResult.user.directChallenge,
694
- });
695
- }
696
- setAuthState((prev) => prev + 1);
697
- return {
698
- token: loginResult.token,
699
- mnemonic: loginResult.mnemonic,
700
- message: loginResult.message,
701
- codeCount: loginResult.codeCount,
702
- };
703
- }
704
- return loginResult;
705
- },
706
- [authService, setUserSettingAndUpdateSettings]
707
- );
708
-
709
- const logout = useCallback(async () => {
710
- localStorage.removeItem('user');
711
- localStorage.removeItem('authToken');
712
- clearMnemonic();
713
- setUser(null);
714
- clearWallet();
715
- setIsAuthenticated(false);
716
- await setUserSettingAndUpdateSettings(undefined);
717
- setAuthState((prev) => prev + 1);
718
-
719
- // Call the optional navigation callback if provided
720
- if (onLogout) {
721
- onLogout();
722
- }
723
- }, [onLogout, clearMnemonic, clearWallet, setUserSettingAndUpdateSettings]);
724
-
725
- const verifyToken = useCallback(
726
- async (token: string) => {
727
- const requestUser = await authService.verifyToken(token);
728
- if (typeof requestUser === 'object' && 'error' in requestUser) {
729
- setIsAuthenticated(false);
730
- await setUserSettingAndUpdateSettings(undefined);
731
- return false;
732
- } else {
733
- setUser(requestUser);
734
- setIsAuthenticated(true);
735
- return true;
736
- }
737
- },
738
- [authService, setUserSettingAndUpdateSettings]
739
- );
740
-
741
- const changePassword = useCallback(
742
- async (
743
- currentPassword: string,
744
- newPassword: string
745
- ): Promise<
746
- | ISuccessMessage
747
- | {
748
- error: string;
749
- errorType?: string | undefined;
750
- }
751
- > => {
752
- if (!isBrowserPasswordLoginAvailable()) {
753
- return {
754
- error: tComponent<SuiteCoreStringKey>(
755
- SuiteCoreComponentId,
756
- SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup
757
- ),
758
- errorType: 'PasswordLoginNotSetup',
759
- };
760
- }
761
- setLoading(true);
762
- try {
763
- const passwordLoginService: PasswordLoginService =
764
- getPasswordLoginService();
765
- const { mnemonic, wallet } =
766
- await passwordLoginService.getWalletAndMnemonicFromLocalStorageBundle(
767
- new SecureString(currentPassword)
768
- );
769
- if (!mnemonic) {
770
- setLoading(false);
771
- return {
772
- error: tComponent<SuiteCoreStringKey>(
773
- SuiteCoreComponentId,
774
- SuiteCoreStringKey.PasswordLogin_InvalidCurrentPassword
775
- ),
776
- errorType: 'InvalidCurrentPassword',
777
- };
778
- }
779
- await passwordLoginService.setupPasswordLoginLocalStorageBundle(
780
- mnemonic,
781
- new SecureString(newPassword)
782
- );
783
- setLoading(false);
784
- setWallet(wallet);
785
- setMnemonic(mnemonic);
786
- return {
787
- success: true,
788
- message: tComponent<SuiteCoreStringKey>(
789
- SuiteCoreComponentId,
790
- SuiteCoreStringKey.PasswordChange_Success
791
- ),
792
- };
793
- } catch {
794
- setLoading(false);
795
- return { error: 'Password change failed' };
796
- }
797
- },
798
- [
799
- getPasswordLoginService,
800
- setMnemonic,
801
- setWallet,
802
- tComponent,
803
- isBrowserPasswordLoginAvailable,
804
- ]
805
- );
806
-
807
- const contextValue = useMemo(() => {
808
- const setUserAndIsAuthenticated = async (
809
- newUser: IRequestUserDTO | null
810
- ) => {
811
- setUser(newUser);
812
- setIsAuthenticated(!!newUser);
813
- };
814
-
815
- return {
816
- admin: isGlobalAdmin,
817
- authState,
818
- backupCodeLogin,
819
- changePassword,
820
- checkAuth,
821
- clearMnemonic,
822
- clearWallet,
823
- colorMode,
824
- currencyCode: userSettings?.currency,
825
- directLogin,
826
- emailChallengeLogin,
827
- getMnemonicRemainingTime,
828
- getWalletRemainingTime,
829
- isAuthenticated,
830
- isCheckingAuth,
831
- isBrowserPasswordLoginAvailable,
832
- loading,
833
- logout,
834
- mnemonic: mnemonicManager.value,
835
- mnemonicExpirationSeconds,
836
- passwordLogin,
837
- refreshToken,
838
- register,
839
- requestEmailLogin,
840
- serverPublicKey,
841
- setMnemonic,
842
- setMnemonicExpirationSeconds,
843
- setUpBrowserPasswordLogin,
844
- setUser: setUserAndIsAuthenticated,
845
- setUserSetting: setUserSettingAndUpdateSettings,
846
- setWallet,
847
- setWalletExpirationSeconds,
848
- token,
849
- user: frontendUser,
850
- userData: user,
851
- userSettings,
852
- verifyToken,
853
- wallet: walletManager.value,
854
- walletExpirationSeconds,
855
- };
856
- // authenticatedApi is intentionally excluded as it's a stable reference from useMemo
857
- // eslint-disable-next-line react-hooks/exhaustive-deps
858
- }, [
859
- authState,
860
- backupCodeLogin,
861
- changePassword,
862
- checkAuth,
863
- clearMnemonic,
864
- clearWallet,
865
- colorMode,
866
- directLogin,
867
- emailChallengeLogin,
868
- frontendUser,
869
- getMnemonicRemainingTime,
870
- getWalletRemainingTime,
871
- isAuthenticated,
872
- isCheckingAuth,
873
- isGlobalAdmin,
874
- isBrowserPasswordLoginAvailable,
875
- loading,
876
- logout,
877
- mnemonicManager.value,
878
- mnemonicExpirationSeconds,
879
- passwordLogin,
880
- refreshToken,
881
- register,
882
- requestEmailLogin,
883
- serverPublicKey,
884
- setMnemonic,
885
- setMnemonicExpirationSeconds,
886
- setUpBrowserPasswordLogin,
887
- setUserSettingAndUpdateSettings,
888
- setWallet,
889
- setWalletExpirationSeconds,
890
- token,
891
- user,
892
- userSettings,
893
- verifyToken,
894
- walletManager.value,
895
- walletExpirationSeconds,
896
- ]);
897
-
898
- return (
899
- <AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>
900
- );
901
- };
902
-
903
- export const AuthProvider = ({
904
- children,
905
- baseUrl,
906
- constants,
907
- eciesConfig,
908
- onLogout,
909
- }: AuthProviderProps) => {
910
- return (
911
- <AuthProviderInner
912
- baseUrl={baseUrl}
913
- constants={constants}
914
- eciesConfig={eciesConfig}
915
- onLogout={onLogout}
916
- >
917
- {children}
918
- </AuthProviderInner>
919
- );
920
- };
921
-
922
- export const useAuth = () => {
923
- return useContext(AuthContext);
924
- };