@entropy-softworks/ui 2026.7.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -0
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/lib/components/auth/LockOverlay.d.ts +22 -0
- package/lib/components/auth/LockOverlay.d.ts.map +1 -0
- package/lib/components/auth/LockOverlay.jsx +82 -0
- package/lib/components/auth/LockOverlay.jsx.map +1 -0
- package/lib/components/auth/PasswordStrengthMeter.d.ts +12 -0
- package/lib/components/auth/PasswordStrengthMeter.d.ts.map +1 -0
- package/lib/components/auth/PasswordStrengthMeter.jsx +81 -0
- package/lib/components/auth/PasswordStrengthMeter.jsx.map +1 -0
- package/lib/components/auth/ProtectedRoute.d.ts +24 -0
- package/lib/components/auth/ProtectedRoute.d.ts.map +1 -0
- package/lib/components/auth/ProtectedRoute.jsx +56 -0
- package/lib/components/auth/ProtectedRoute.jsx.map +1 -0
- package/lib/components/auth/PwnedPasswordWarning.d.ts +13 -0
- package/lib/components/auth/PwnedPasswordWarning.d.ts.map +1 -0
- package/lib/components/auth/PwnedPasswordWarning.jsx +29 -0
- package/lib/components/auth/PwnedPasswordWarning.jsx.map +1 -0
- package/lib/components/auth/index.d.ts +5 -0
- package/lib/components/auth/index.d.ts.map +1 -0
- package/lib/components/auth/index.js +5 -0
- package/lib/components/auth/index.js.map +1 -0
- package/lib/components/bottom-nav.d.ts +25 -0
- package/lib/components/bottom-nav.d.ts.map +1 -0
- package/lib/components/bottom-nav.jsx +51 -0
- package/lib/components/bottom-nav.jsx.map +1 -0
- package/lib/components/button.d.ts +16 -0
- package/lib/components/button.d.ts.map +1 -0
- package/lib/components/button.jsx +73 -0
- package/lib/components/button.jsx.map +1 -0
- package/lib/components/card.d.ts +22 -0
- package/lib/components/card.d.ts.map +1 -0
- package/lib/components/card.jsx +36 -0
- package/lib/components/card.jsx.map +1 -0
- package/lib/components/checkbox.d.ts +12 -0
- package/lib/components/checkbox.d.ts.map +1 -0
- package/lib/components/checkbox.jsx +16 -0
- package/lib/components/checkbox.jsx.map +1 -0
- package/lib/components/connection-settings.d.ts +41 -0
- package/lib/components/connection-settings.d.ts.map +1 -0
- package/lib/components/connection-settings.jsx +354 -0
- package/lib/components/connection-settings.jsx.map +1 -0
- package/lib/components/context-menu.d.ts +52 -0
- package/lib/components/context-menu.d.ts.map +1 -0
- package/lib/components/context-menu.jsx +24 -0
- package/lib/components/context-menu.jsx.map +1 -0
- package/lib/components/data-table.d.ts +59 -0
- package/lib/components/data-table.d.ts.map +1 -0
- package/lib/components/data-table.jsx +101 -0
- package/lib/components/data-table.jsx.map +1 -0
- package/lib/components/dialog.d.ts +58 -0
- package/lib/components/dialog.d.ts.map +1 -0
- package/lib/components/dialog.jsx +197 -0
- package/lib/components/dialog.jsx.map +1 -0
- package/lib/components/dropdown-menu.d.ts +55 -0
- package/lib/components/dropdown-menu.d.ts.map +1 -0
- package/lib/components/dropdown-menu.jsx +38 -0
- package/lib/components/dropdown-menu.jsx.map +1 -0
- package/lib/components/entropy-boot-splash.d.ts +24 -0
- package/lib/components/entropy-boot-splash.d.ts.map +1 -0
- package/lib/components/entropy-boot-splash.jsx +83 -0
- package/lib/components/entropy-boot-splash.jsx.map +1 -0
- package/lib/components/entropy-mark-animated.d.ts +20 -0
- package/lib/components/entropy-mark-animated.d.ts.map +1 -0
- package/lib/components/entropy-mark-animated.jsx +148 -0
- package/lib/components/entropy-mark-animated.jsx.map +1 -0
- package/lib/components/entropy-mark-geometry.d.ts +8 -0
- package/lib/components/entropy-mark-geometry.d.ts.map +1 -0
- package/lib/components/entropy-mark-geometry.js +10 -0
- package/lib/components/entropy-mark-geometry.js.map +1 -0
- package/lib/components/entropy-mark-sequential.d.ts +12 -0
- package/lib/components/entropy-mark-sequential.d.ts.map +1 -0
- package/lib/components/entropy-mark-sequential.jsx +53 -0
- package/lib/components/entropy-mark-sequential.jsx.map +1 -0
- package/lib/components/entropy-mark.d.ts +29 -0
- package/lib/components/entropy-mark.d.ts.map +1 -0
- package/lib/components/entropy-mark.jsx +66 -0
- package/lib/components/entropy-mark.jsx.map +1 -0
- package/lib/components/error-boundary.d.ts +31 -0
- package/lib/components/error-boundary.d.ts.map +1 -0
- package/lib/components/error-boundary.jsx +40 -0
- package/lib/components/error-boundary.jsx.map +1 -0
- package/lib/components/index.d.ts +41 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +43 -0
- package/lib/components/index.js.map +1 -0
- package/lib/components/input.d.ts +26 -0
- package/lib/components/input.d.ts.map +1 -0
- package/lib/components/input.jsx +95 -0
- package/lib/components/input.jsx.map +1 -0
- package/lib/components/item-icon.d.ts +32 -0
- package/lib/components/item-icon.d.ts.map +1 -0
- package/lib/components/item-icon.jsx +54 -0
- package/lib/components/item-icon.jsx.map +1 -0
- package/lib/components/label.d.ts +13 -0
- package/lib/components/label.d.ts.map +1 -0
- package/lib/components/label.jsx +9 -0
- package/lib/components/label.jsx.map +1 -0
- package/lib/components/legal-dialog.d.ts +18 -0
- package/lib/components/legal-dialog.d.ts.map +1 -0
- package/lib/components/legal-dialog.jsx +31 -0
- package/lib/components/legal-dialog.jsx.map +1 -0
- package/lib/components/license-gate.d.ts +17 -0
- package/lib/components/license-gate.d.ts.map +1 -0
- package/lib/components/license-gate.jsx +21 -0
- package/lib/components/license-gate.jsx.map +1 -0
- package/lib/components/logo.d.ts +15 -0
- package/lib/components/logo.d.ts.map +1 -0
- package/lib/components/logo.jsx +20 -0
- package/lib/components/logo.jsx.map +1 -0
- package/lib/components/onboarding-wizard.d.ts +89 -0
- package/lib/components/onboarding-wizard.d.ts.map +1 -0
- package/lib/components/onboarding-wizard.jsx +185 -0
- package/lib/components/onboarding-wizard.jsx.map +1 -0
- package/lib/components/pagination.d.ts +43 -0
- package/lib/components/pagination.d.ts.map +1 -0
- package/lib/components/pagination.jsx +72 -0
- package/lib/components/pagination.jsx.map +1 -0
- package/lib/components/password-generator.d.ts +15 -0
- package/lib/components/password-generator.d.ts.map +1 -0
- package/lib/components/password-generator.jsx +273 -0
- package/lib/components/password-generator.jsx.map +1 -0
- package/lib/components/pin-pad.d.ts +20 -0
- package/lib/components/pin-pad.d.ts.map +1 -0
- package/lib/components/pin-pad.jsx +93 -0
- package/lib/components/pin-pad.jsx.map +1 -0
- package/lib/components/popover.d.ts +27 -0
- package/lib/components/popover.d.ts.map +1 -0
- package/lib/components/popover.jsx +18 -0
- package/lib/components/popover.jsx.map +1 -0
- package/lib/components/profile/ProfileDialog.d.ts +25 -0
- package/lib/components/profile/ProfileDialog.d.ts.map +1 -0
- package/lib/components/profile/ProfileDialog.jsx +71 -0
- package/lib/components/profile/ProfileDialog.jsx.map +1 -0
- package/lib/components/profile/ProfileTab.d.ts +12 -0
- package/lib/components/profile/ProfileTab.d.ts.map +1 -0
- package/lib/components/profile/ProfileTab.jsx +112 -0
- package/lib/components/profile/ProfileTab.jsx.map +1 -0
- package/lib/components/profile/SecurityTab.d.ts +32 -0
- package/lib/components/profile/SecurityTab.d.ts.map +1 -0
- package/lib/components/profile/SecurityTab.jsx +145 -0
- package/lib/components/profile/SecurityTab.jsx.map +1 -0
- package/lib/components/profile/index.d.ts +4 -0
- package/lib/components/profile/index.d.ts.map +1 -0
- package/lib/components/profile/index.js +4 -0
- package/lib/components/profile/index.js.map +1 -0
- package/lib/components/segmented-toggle.d.ts +28 -0
- package/lib/components/segmented-toggle.d.ts.map +1 -0
- package/lib/components/segmented-toggle.jsx +64 -0
- package/lib/components/segmented-toggle.jsx.map +1 -0
- package/lib/components/separator.d.ts +13 -0
- package/lib/components/separator.d.ts.map +1 -0
- package/lib/components/separator.jsx +16 -0
- package/lib/components/separator.jsx.map +1 -0
- package/lib/components/server-settings.d.ts +27 -0
- package/lib/components/server-settings.d.ts.map +1 -0
- package/lib/components/server-settings.jsx +307 -0
- package/lib/components/server-settings.jsx.map +1 -0
- package/lib/components/settings/AccountSection.d.ts +26 -0
- package/lib/components/settings/AccountSection.d.ts.map +1 -0
- package/lib/components/settings/AccountSection.jsx +32 -0
- package/lib/components/settings/AccountSection.jsx.map +1 -0
- package/lib/components/settings/DangerZoneSection.d.ts +13 -0
- package/lib/components/settings/DangerZoneSection.d.ts.map +1 -0
- package/lib/components/settings/DangerZoneSection.jsx +16 -0
- package/lib/components/settings/DangerZoneSection.jsx.map +1 -0
- package/lib/components/settings/GeneralSection.d.ts +11 -0
- package/lib/components/settings/GeneralSection.d.ts.map +1 -0
- package/lib/components/settings/GeneralSection.jsx +12 -0
- package/lib/components/settings/GeneralSection.jsx.map +1 -0
- package/lib/components/settings/SupportSection.d.ts +11 -0
- package/lib/components/settings/SupportSection.d.ts.map +1 -0
- package/lib/components/settings/SupportSection.jsx +22 -0
- package/lib/components/settings/SupportSection.jsx.map +1 -0
- package/lib/components/settings/index.d.ts +5 -0
- package/lib/components/settings/index.d.ts.map +1 -0
- package/lib/components/settings/index.js +5 -0
- package/lib/components/settings/index.js.map +1 -0
- package/lib/components/settings-row.d.ts +28 -0
- package/lib/components/settings-row.d.ts.map +1 -0
- package/lib/components/settings-row.jsx +68 -0
- package/lib/components/settings-row.jsx.map +1 -0
- package/lib/components/skeleton.d.ts +8 -0
- package/lib/components/skeleton.d.ts.map +1 -0
- package/lib/components/skeleton.jsx +24 -0
- package/lib/components/skeleton.jsx.map +1 -0
- package/lib/components/social-connections.d.ts +15 -0
- package/lib/components/social-connections.d.ts.map +1 -0
- package/lib/components/social-connections.jsx +31 -0
- package/lib/components/social-connections.jsx.map +1 -0
- package/lib/components/stat-card.d.ts +29 -0
- package/lib/components/stat-card.d.ts.map +1 -0
- package/lib/components/stat-card.jsx +36 -0
- package/lib/components/stat-card.jsx.map +1 -0
- package/lib/components/tag-chip.d.ts +18 -0
- package/lib/components/tag-chip.d.ts.map +1 -0
- package/lib/components/tag-chip.jsx +54 -0
- package/lib/components/tag-chip.jsx.map +1 -0
- package/lib/components/tag-multi-select.d.ts +27 -0
- package/lib/components/tag-multi-select.d.ts.map +1 -0
- package/lib/components/tag-multi-select.jsx +65 -0
- package/lib/components/tag-multi-select.jsx.map +1 -0
- package/lib/components/text.d.ts +22 -0
- package/lib/components/text.d.ts.map +1 -0
- package/lib/components/text.jsx +43 -0
- package/lib/components/text.jsx.map +1 -0
- package/lib/components/toast/ToastPortal.d.ts +11 -0
- package/lib/components/toast/ToastPortal.d.ts.map +1 -0
- package/lib/components/toast/ToastPortal.jsx +15 -0
- package/lib/components/toast/ToastPortal.jsx.map +1 -0
- package/lib/components/toast/ToastPortal.web.d.ts +14 -0
- package/lib/components/toast/ToastPortal.web.d.ts.map +1 -0
- package/lib/components/toast/ToastPortal.web.jsx +39 -0
- package/lib/components/toast/ToastPortal.web.jsx.map +1 -0
- package/lib/components/toast/index.d.ts +3 -0
- package/lib/components/toast/index.d.ts.map +1 -0
- package/lib/components/toast/index.js +3 -0
- package/lib/components/toast/index.js.map +1 -0
- package/lib/components/toast/toast-config.d.ts +14 -0
- package/lib/components/toast/toast-config.d.ts.map +1 -0
- package/lib/components/toast/toast-config.jsx +24 -0
- package/lib/components/toast/toast-config.jsx.map +1 -0
- package/lib/components/tooltip.d.ts +30 -0
- package/lib/components/tooltip.d.ts.map +1 -0
- package/lib/components/tooltip.jsx +14 -0
- package/lib/components/tooltip.jsx.map +1 -0
- package/lib/components/totp-display.d.ts +23 -0
- package/lib/components/totp-display.d.ts.map +1 -0
- package/lib/components/totp-display.jsx +132 -0
- package/lib/components/totp-display.jsx.map +1 -0
- package/lib/components/user-avatar.d.ts +18 -0
- package/lib/components/user-avatar.d.ts.map +1 -0
- package/lib/components/user-avatar.jsx +25 -0
- package/lib/components/user-avatar.jsx.map +1 -0
- package/lib/context/AppConfigContext.d.ts +56 -0
- package/lib/context/AppConfigContext.d.ts.map +1 -0
- package/lib/context/AppConfigContext.jsx +14 -0
- package/lib/context/AppConfigContext.jsx.map +1 -0
- package/lib/context/NavigationContext.d.ts +42 -0
- package/lib/context/NavigationContext.d.ts.map +1 -0
- package/lib/context/NavigationContext.jsx +53 -0
- package/lib/context/NavigationContext.jsx.map +1 -0
- package/lib/context/NotificationContext.d.ts +32 -0
- package/lib/context/NotificationContext.d.ts.map +1 -0
- package/lib/context/NotificationContext.jsx +49 -0
- package/lib/context/NotificationContext.jsx.map +1 -0
- package/lib/context/ThemeContext.d.ts +12 -0
- package/lib/context/ThemeContext.d.ts.map +1 -0
- package/lib/context/ThemeContext.jsx +66 -0
- package/lib/context/ThemeContext.jsx.map +1 -0
- package/lib/context/index.d.ts +5 -0
- package/lib/context/index.d.ts.map +1 -0
- package/lib/context/index.js +5 -0
- package/lib/context/index.js.map +1 -0
- package/lib/flags.d.ts +9 -0
- package/lib/flags.d.ts.map +1 -0
- package/lib/flags.js +37 -0
- package/lib/flags.js.map +1 -0
- package/lib/forms/form-error.d.ts +12 -0
- package/lib/forms/form-error.d.ts.map +1 -0
- package/lib/forms/form-error.jsx +14 -0
- package/lib/forms/form-error.jsx.map +1 -0
- package/lib/forms/index.d.ts +3 -0
- package/lib/forms/index.d.ts.map +1 -0
- package/lib/forms/index.js +3 -0
- package/lib/forms/index.js.map +1 -0
- package/lib/forms/shake-field.d.ts +18 -0
- package/lib/forms/shake-field.d.ts.map +1 -0
- package/lib/forms/shake-field.jsx +30 -0
- package/lib/forms/shake-field.jsx.map +1 -0
- package/lib/hooks/index.d.ts +6 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/index.js +6 -0
- package/lib/hooks/index.js.map +1 -0
- package/lib/hooks/useAuth.d.ts +109 -0
- package/lib/hooks/useAuth.d.ts.map +1 -0
- package/lib/hooks/useAuth.jsx +404 -0
- package/lib/hooks/useAuth.jsx.map +1 -0
- package/lib/hooks/useAutoLock.d.ts +22 -0
- package/lib/hooks/useAutoLock.d.ts.map +1 -0
- package/lib/hooks/useAutoLock.js +85 -0
- package/lib/hooks/useAutoLock.js.map +1 -0
- package/lib/hooks/useDebouncedValue.d.ts +19 -0
- package/lib/hooks/useDebouncedValue.d.ts.map +1 -0
- package/lib/hooks/useDebouncedValue.js +29 -0
- package/lib/hooks/useDebouncedValue.js.map +1 -0
- package/lib/hooks/useShakeAnimation.d.ts +17 -0
- package/lib/hooks/useShakeAnimation.d.ts.map +1 -0
- package/lib/hooks/useShakeAnimation.js +22 -0
- package/lib/hooks/useShakeAnimation.js.map +1 -0
- package/lib/hooks/useUploadBlobUrl.d.ts +13 -0
- package/lib/hooks/useUploadBlobUrl.d.ts.map +1 -0
- package/lib/hooks/useUploadBlobUrl.js +60 -0
- package/lib/hooks/useUploadBlobUrl.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +47 -0
- package/lib/index.js.map +1 -0
- package/lib/screens/auth/AccountPickerScreen.d.ts +24 -0
- package/lib/screens/auth/AccountPickerScreen.d.ts.map +1 -0
- package/lib/screens/auth/AccountPickerScreen.jsx +47 -0
- package/lib/screens/auth/AccountPickerScreen.jsx.map +1 -0
- package/lib/screens/auth/AuthScreen.d.ts +59 -0
- package/lib/screens/auth/AuthScreen.d.ts.map +1 -0
- package/lib/screens/auth/AuthScreen.jsx +594 -0
- package/lib/screens/auth/AuthScreen.jsx.map +1 -0
- package/lib/screens/auth/ConsentScreen.d.ts +27 -0
- package/lib/screens/auth/ConsentScreen.d.ts.map +1 -0
- package/lib/screens/auth/ConsentScreen.jsx +55 -0
- package/lib/screens/auth/ConsentScreen.jsx.map +1 -0
- package/lib/screens/auth/ErrorScreen.d.ts +20 -0
- package/lib/screens/auth/ErrorScreen.d.ts.map +1 -0
- package/lib/screens/auth/ErrorScreen.jsx +43 -0
- package/lib/screens/auth/ErrorScreen.jsx.map +1 -0
- package/lib/screens/auth/ExpiredLinkScreen.d.ts +19 -0
- package/lib/screens/auth/ExpiredLinkScreen.d.ts.map +1 -0
- package/lib/screens/auth/ExpiredLinkScreen.jsx +38 -0
- package/lib/screens/auth/ExpiredLinkScreen.jsx.map +1 -0
- package/lib/screens/auth/ForgotPasswordScreen.d.ts +4 -0
- package/lib/screens/auth/ForgotPasswordScreen.d.ts.map +1 -0
- package/lib/screens/auth/ForgotPasswordScreen.jsx +123 -0
- package/lib/screens/auth/ForgotPasswordScreen.jsx.map +1 -0
- package/lib/screens/auth/ImportDataScreen.d.ts +17 -0
- package/lib/screens/auth/ImportDataScreen.d.ts.map +1 -0
- package/lib/screens/auth/ImportDataScreen.jsx +73 -0
- package/lib/screens/auth/ImportDataScreen.jsx.map +1 -0
- package/lib/screens/auth/LoginScreen.d.ts +38 -0
- package/lib/screens/auth/LoginScreen.d.ts.map +1 -0
- package/lib/screens/auth/LoginScreen.jsx +326 -0
- package/lib/screens/auth/LoginScreen.jsx.map +1 -0
- package/lib/screens/auth/MfaChallengeScreen.d.ts +4 -0
- package/lib/screens/auth/MfaChallengeScreen.d.ts.map +1 -0
- package/lib/screens/auth/MfaChallengeScreen.jsx +139 -0
- package/lib/screens/auth/MfaChallengeScreen.jsx.map +1 -0
- package/lib/screens/auth/MfaEnrollScreen.d.ts +12 -0
- package/lib/screens/auth/MfaEnrollScreen.d.ts.map +1 -0
- package/lib/screens/auth/MfaEnrollScreen.jsx +267 -0
- package/lib/screens/auth/MfaEnrollScreen.jsx.map +1 -0
- package/lib/screens/auth/PasskeyEnrollScreen.d.ts +18 -0
- package/lib/screens/auth/PasskeyEnrollScreen.d.ts.map +1 -0
- package/lib/screens/auth/PasskeyEnrollScreen.jsx +51 -0
- package/lib/screens/auth/PasskeyEnrollScreen.jsx.map +1 -0
- package/lib/screens/auth/PrivacyPolicyScreen.d.ts +19 -0
- package/lib/screens/auth/PrivacyPolicyScreen.d.ts.map +1 -0
- package/lib/screens/auth/PrivacyPolicyScreen.jsx +143 -0
- package/lib/screens/auth/PrivacyPolicyScreen.jsx.map +1 -0
- package/lib/screens/auth/RegisterScreen.d.ts +14 -0
- package/lib/screens/auth/RegisterScreen.d.ts.map +1 -0
- package/lib/screens/auth/RegisterScreen.jsx +296 -0
- package/lib/screens/auth/RegisterScreen.jsx.map +1 -0
- package/lib/screens/auth/ResetPasswordScreen.d.ts +12 -0
- package/lib/screens/auth/ResetPasswordScreen.d.ts.map +1 -0
- package/lib/screens/auth/ResetPasswordScreen.jsx +276 -0
- package/lib/screens/auth/ResetPasswordScreen.jsx.map +1 -0
- package/lib/screens/auth/ServerConfigScreen.d.ts +18 -0
- package/lib/screens/auth/ServerConfigScreen.d.ts.map +1 -0
- package/lib/screens/auth/ServerConfigScreen.jsx +259 -0
- package/lib/screens/auth/ServerConfigScreen.jsx.map +1 -0
- package/lib/screens/auth/TermsOfServiceScreen.d.ts +30 -0
- package/lib/screens/auth/TermsOfServiceScreen.d.ts.map +1 -0
- package/lib/screens/auth/TermsOfServiceScreen.jsx +130 -0
- package/lib/screens/auth/TermsOfServiceScreen.jsx.map +1 -0
- package/lib/screens/auth/VerifyEmailScreen.d.ts +4 -0
- package/lib/screens/auth/VerifyEmailScreen.d.ts.map +1 -0
- package/lib/screens/auth/VerifyEmailScreen.jsx +249 -0
- package/lib/screens/auth/VerifyEmailScreen.jsx.map +1 -0
- package/lib/screens/auth/WelcomeScreen.d.ts +17 -0
- package/lib/screens/auth/WelcomeScreen.d.ts.map +1 -0
- package/lib/screens/auth/WelcomeScreen.jsx +58 -0
- package/lib/screens/auth/WelcomeScreen.jsx.map +1 -0
- package/lib/screens/auth/index.d.ts +19 -0
- package/lib/screens/auth/index.d.ts.map +1 -0
- package/lib/screens/auth/index.js +19 -0
- package/lib/screens/auth/index.js.map +1 -0
- package/lib/screens/index.d.ts +2 -0
- package/lib/screens/index.d.ts.map +1 -0
- package/lib/screens/index.js +2 -0
- package/lib/screens/index.js.map +1 -0
- package/lib/services/api-config.d.ts +87 -0
- package/lib/services/api-config.d.ts.map +1 -0
- package/lib/services/api-config.js +202 -0
- package/lib/services/api-config.js.map +1 -0
- package/lib/services/auth.service.d.ts +140 -0
- package/lib/services/auth.service.d.ts.map +1 -0
- package/lib/services/auth.service.js +376 -0
- package/lib/services/auth.service.js.map +1 -0
- package/lib/services/favicon.d.ts +46 -0
- package/lib/services/favicon.d.ts.map +1 -0
- package/lib/services/favicon.js +84 -0
- package/lib/services/favicon.js.map +1 -0
- package/lib/services/hibp-cache.d.ts +23 -0
- package/lib/services/hibp-cache.d.ts.map +1 -0
- package/lib/services/hibp-cache.js +56 -0
- package/lib/services/hibp-cache.js.map +1 -0
- package/lib/services/hibp.d.ts +28 -0
- package/lib/services/hibp.d.ts.map +1 -0
- package/lib/services/hibp.js +92 -0
- package/lib/services/hibp.js.map +1 -0
- package/lib/services/index.d.ts +8 -0
- package/lib/services/index.d.ts.map +1 -0
- package/lib/services/index.js +7 -0
- package/lib/services/index.js.map +1 -0
- package/lib/services/passkey.d.ts +10 -0
- package/lib/services/passkey.d.ts.map +1 -0
- package/lib/services/passkey.js +192 -0
- package/lib/services/passkey.js.map +1 -0
- package/lib/utils/api-fetch.d.ts +11 -0
- package/lib/utils/api-fetch.d.ts.map +1 -0
- package/lib/utils/api-fetch.js +52 -0
- package/lib/utils/api-fetch.js.map +1 -0
- package/lib/utils/clipboard.d.ts +31 -0
- package/lib/utils/clipboard.d.ts.map +1 -0
- package/lib/utils/clipboard.js +66 -0
- package/lib/utils/clipboard.js.map +1 -0
- package/lib/utils/cn.d.ts +9 -0
- package/lib/utils/cn.d.ts.map +1 -0
- package/lib/utils/cn.js +12 -0
- package/lib/utils/cn.js.map +1 -0
- package/lib/utils/debounce.d.ts +13 -0
- package/lib/utils/debounce.d.ts.map +1 -0
- package/lib/utils/debounce.js +28 -0
- package/lib/utils/debounce.js.map +1 -0
- package/lib/utils/error.d.ts +9 -0
- package/lib/utils/error.d.ts.map +1 -0
- package/lib/utils/error.js +11 -0
- package/lib/utils/error.js.map +1 -0
- package/lib/utils/fetch.d.ts +17 -0
- package/lib/utils/fetch.d.ts.map +1 -0
- package/lib/utils/fetch.js +29 -0
- package/lib/utils/fetch.js.map +1 -0
- package/lib/utils/http-error.d.ts +41 -0
- package/lib/utils/http-error.d.ts.map +1 -0
- package/lib/utils/http-error.js +63 -0
- package/lib/utils/http-error.js.map +1 -0
- package/lib/utils/index.d.ts +11 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +11 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/palette.d.ts +46 -0
- package/lib/utils/palette.d.ts.map +1 -0
- package/lib/utils/palette.js +75 -0
- package/lib/utils/palette.js.map +1 -0
- package/lib/utils/password.d.ts +20 -0
- package/lib/utils/password.d.ts.map +1 -0
- package/lib/utils/password.js +51 -0
- package/lib/utils/password.js.map +1 -0
- package/lib/utils/settings-storage.d.ts +3 -0
- package/lib/utils/settings-storage.d.ts.map +1 -0
- package/lib/utils/settings-storage.js +62 -0
- package/lib/utils/settings-storage.js.map +1 -0
- package/lib/utils/validation.d.ts +29 -0
- package/lib/utils/validation.d.ts.map +1 -0
- package/lib/utils/validation.js +58 -0
- package/lib/utils/validation.js.map +1 -0
- package/package.json +204 -0
- package/src/components/__tests__/data-table.test.ts +94 -0
- package/src/components/__tests__/pagination.test.ts +73 -0
- package/src/components/__tests__/stat-card.test.ts +21 -0
- package/src/components/auth/LockOverlay.tsx +122 -0
- package/src/components/auth/PasswordStrengthMeter.tsx +96 -0
- package/src/components/auth/ProtectedRoute.tsx +91 -0
- package/src/components/auth/PwnedPasswordWarning.tsx +54 -0
- package/src/components/auth/index.ts +10 -0
- package/src/components/bottom-nav.tsx +99 -0
- package/src/components/button.tsx +144 -0
- package/src/components/card.tsx +82 -0
- package/src/components/checkbox.tsx +48 -0
- package/src/components/connection-settings.tsx +583 -0
- package/src/components/context-menu.tsx +95 -0
- package/src/components/data-table.tsx +223 -0
- package/src/components/dialog.tsx +376 -0
- package/src/components/dropdown-menu.tsx +120 -0
- package/src/components/entropy-boot-splash.tsx +114 -0
- package/src/components/entropy-mark-animated.tsx +260 -0
- package/src/components/entropy-mark-geometry.ts +11 -0
- package/src/components/entropy-mark-sequential.tsx +132 -0
- package/src/components/entropy-mark.tsx +135 -0
- package/src/components/error-boundary.tsx +70 -0
- package/src/components/index.ts +156 -0
- package/src/components/input.tsx +246 -0
- package/src/components/item-icon.tsx +111 -0
- package/src/components/label.tsx +25 -0
- package/src/components/legal-dialog.tsx +47 -0
- package/src/components/license-gate.tsx +28 -0
- package/src/components/logo.tsx +34 -0
- package/src/components/onboarding-wizard.tsx +353 -0
- package/src/components/pagination.tsx +154 -0
- package/src/components/password-generator.tsx +393 -0
- package/src/components/pin-pad.tsx +156 -0
- package/src/components/popover.tsx +38 -0
- package/src/components/profile/ProfileDialog.tsx +129 -0
- package/src/components/profile/ProfileTab.tsx +151 -0
- package/src/components/profile/SecurityTab.tsx +229 -0
- package/src/components/profile/index.ts +3 -0
- package/src/components/segmented-toggle.tsx +119 -0
- package/src/components/separator.tsx +41 -0
- package/src/components/server-settings.tsx +442 -0
- package/src/components/settings/AccountSection.tsx +76 -0
- package/src/components/settings/DangerZoneSection.tsx +37 -0
- package/src/components/settings/GeneralSection.tsx +39 -0
- package/src/components/settings/SupportSection.tsx +53 -0
- package/src/components/settings/index.ts +4 -0
- package/src/components/settings-row.tsx +126 -0
- package/src/components/skeleton.tsx +48 -0
- package/src/components/social-connections.tsx +55 -0
- package/src/components/stat-card.tsx +64 -0
- package/src/components/tag-chip.tsx +78 -0
- package/src/components/tag-multi-select.tsx +136 -0
- package/src/components/text.tsx +77 -0
- package/src/components/toast/ToastPortal.tsx +16 -0
- package/src/components/toast/ToastPortal.web.tsx +47 -0
- package/src/components/toast/index.ts +2 -0
- package/src/components/toast/toast-config.tsx +31 -0
- package/src/components/tooltip.tsx +30 -0
- package/src/components/totp-display.tsx +207 -0
- package/src/components/user-avatar.tsx +46 -0
- package/src/context/AppConfigContext.tsx +76 -0
- package/src/context/NavigationContext.tsx +75 -0
- package/src/context/NotificationContext.tsx +69 -0
- package/src/context/ThemeContext.tsx +83 -0
- package/src/context/__tests__/NavigationContext.test.tsx +53 -0
- package/src/context/index.ts +24 -0
- package/src/flags.ts +44 -0
- package/src/forms/form-error.tsx +20 -0
- package/src/forms/index.ts +2 -0
- package/src/forms/shake-field.tsx +52 -0
- package/src/hooks/__tests__/useUploadBlobUrl.test.tsx +77 -0
- package/src/hooks/index.ts +18 -0
- package/src/hooks/useAuth.tsx +567 -0
- package/src/hooks/useAutoLock.ts +110 -0
- package/src/hooks/useDebouncedValue.ts +32 -0
- package/src/hooks/useShakeAnimation.ts +42 -0
- package/src/hooks/useUploadBlobUrl.ts +75 -0
- package/src/index.ts +48 -0
- package/src/screens/auth/AccountPickerScreen.tsx +103 -0
- package/src/screens/auth/AuthScreen.tsx +941 -0
- package/src/screens/auth/ConsentScreen.tsx +118 -0
- package/src/screens/auth/ErrorScreen.tsx +96 -0
- package/src/screens/auth/ExpiredLinkScreen.tsx +87 -0
- package/src/screens/auth/ForgotPasswordScreen.tsx +182 -0
- package/src/screens/auth/ImportDataScreen.tsx +112 -0
- package/src/screens/auth/LoginScreen.tsx +484 -0
- package/src/screens/auth/MfaChallengeScreen.tsx +216 -0
- package/src/screens/auth/MfaEnrollScreen.tsx +388 -0
- package/src/screens/auth/PasskeyEnrollScreen.tsx +96 -0
- package/src/screens/auth/PrivacyPolicyScreen.tsx +249 -0
- package/src/screens/auth/RegisterScreen.tsx +430 -0
- package/src/screens/auth/ResetPasswordScreen.tsx +377 -0
- package/src/screens/auth/ServerConfigScreen.tsx +388 -0
- package/src/screens/auth/TermsOfServiceScreen.tsx +236 -0
- package/src/screens/auth/VerifyEmailScreen.tsx +310 -0
- package/src/screens/auth/WelcomeScreen.tsx +78 -0
- package/src/screens/auth/index.ts +36 -0
- package/src/screens/index.ts +1 -0
- package/src/services/__tests__/api-config.test.ts +67 -0
- package/src/services/__tests__/favicon.test.ts +88 -0
- package/src/services/__tests__/hibp-cache.test.ts +37 -0
- package/src/services/__tests__/hibp.test.ts +39 -0
- package/src/services/api-config.ts +260 -0
- package/src/services/auth.service.ts +498 -0
- package/src/services/favicon.ts +102 -0
- package/src/services/hibp-cache.ts +71 -0
- package/src/services/hibp.ts +120 -0
- package/src/services/index.ts +52 -0
- package/src/services/passkey.ts +213 -0
- package/src/types/external.d.ts +24 -0
- package/src/utils/__tests__/clipboard.test.ts +59 -0
- package/src/utils/__tests__/cn.test.ts +24 -0
- package/src/utils/__tests__/debounce.test.ts +42 -0
- package/src/utils/__tests__/error.test.ts +18 -0
- package/src/utils/__tests__/http-error.test.ts +33 -0
- package/src/utils/__tests__/palette.test.ts +22 -0
- package/src/utils/__tests__/password.test.ts +55 -0
- package/src/utils/__tests__/settings-storage.test.ts +15 -0
- package/src/utils/__tests__/validation.test.ts +52 -0
- package/src/utils/api-fetch.ts +61 -0
- package/src/utils/clipboard.ts +69 -0
- package/src/utils/cn.ts +12 -0
- package/src/utils/debounce.ts +33 -0
- package/src/utils/error.ts +10 -0
- package/src/utils/fetch.ts +33 -0
- package/src/utils/http-error.ts +81 -0
- package/src/utils/index.ts +23 -0
- package/src/utils/palette.ts +105 -0
- package/src/utils/password.ts +64 -0
- package/src/utils/settings-storage.ts +68 -0
- package/src/utils/validation.ts +71 -0
- package/styles/globals.css +262 -0
- package/tailwind-preset.js +163 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
import { apiFetch } from "../utils/api-fetch";
|
|
3
|
+
import { extractApiError, extractErrorMessage } from "../utils/http-error";
|
|
4
|
+
import { validateEmail as validateEmailUtil, validatePassword as validatePasswordUtil, validateUsername as validateUsernameUtil, } from "../utils/validation";
|
|
5
|
+
import * as ApiConfig from "./api-config";
|
|
6
|
+
import { clearCachedPolicy as clearHibpPolicyCache } from "./hibp-cache";
|
|
7
|
+
// Native persists the user record in SecureStore so the next app launch
|
|
8
|
+
// has it before /auth/me lands. Web keeps it in process memory only —
|
|
9
|
+
// sessionStorage is XSS-readable and the cookie-bound session lets us
|
|
10
|
+
// re-fetch the record from the server on the next mount without a
|
|
11
|
+
// noticeable UX regression. See SECURITY.md.
|
|
12
|
+
const USER_DATA_KEY_SUFFIX = "user_data";
|
|
13
|
+
let inMemoryUser = null;
|
|
14
|
+
function userDataKey() {
|
|
15
|
+
return `${ApiConfig.getStoragePrefix()}_${USER_DATA_KEY_SUFFIX}`;
|
|
16
|
+
}
|
|
17
|
+
async function persistUser(user) {
|
|
18
|
+
if (Platform.OS === "web") {
|
|
19
|
+
inMemoryUser = user;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
await ApiConfig.kvPut(userDataKey(), JSON.stringify(user));
|
|
23
|
+
}
|
|
24
|
+
async function clearPersistedUser() {
|
|
25
|
+
if (Platform.OS === "web") {
|
|
26
|
+
inMemoryUser = null;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
await ApiConfig.kvPut(userDataKey(), null);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Normalize a login/register response body into an {@link AuthResponse}.
|
|
33
|
+
* Single-tenant servers wrap the user as `{ user, session_token }`;
|
|
34
|
+
* the multi-tenant IdP (access) returns the user record directly and
|
|
35
|
+
* establishes the session via an HttpOnly cookie (no bearer token).
|
|
36
|
+
*/
|
|
37
|
+
async function parseAuthResponse(response) {
|
|
38
|
+
const json = await response.json();
|
|
39
|
+
if (json && typeof json === "object" && "user" in json) {
|
|
40
|
+
return json;
|
|
41
|
+
}
|
|
42
|
+
return { user: json, session_token: "" };
|
|
43
|
+
}
|
|
44
|
+
async function loadPersistedUser() {
|
|
45
|
+
if (Platform.OS === "web") {
|
|
46
|
+
return inMemoryUser;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const userJson = await ApiConfig.kvGet(userDataKey());
|
|
50
|
+
if (!userJson) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return JSON.parse(userJson);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Auth client for Entropy Softworks servers. Apps call `configureApi`
|
|
61
|
+
* (from `@entropy-softworks/ui/services`) at startup so storage keys and
|
|
62
|
+
* the base URL are wired up before any of these methods run.
|
|
63
|
+
*/
|
|
64
|
+
class AuthService {
|
|
65
|
+
static loadServerUrlOverride = ApiConfig.loadServerUrlOverride;
|
|
66
|
+
static getBaseUrl = ApiConfig.getBaseUrl;
|
|
67
|
+
static setBaseUrl = ApiConfig.setBaseUrl;
|
|
68
|
+
static resetBaseUrl = ApiConfig.resetBaseUrl;
|
|
69
|
+
static getSessionToken = ApiConfig.getSessionToken;
|
|
70
|
+
/**
|
|
71
|
+
* Persist the session credential + user record produced by an
|
|
72
|
+
* alternative auth path (passkey-finish, magic-link, etc.) so the
|
|
73
|
+
* rest of `useAuth` / `getCurrentUser` sees the same state the
|
|
74
|
+
* password `login` flow leaves behind.
|
|
75
|
+
*
|
|
76
|
+
* Web: session credential is a server-set HttpOnly cookie; only
|
|
77
|
+
* the user record persists here, and it lives in process memory
|
|
78
|
+
* (NOT sessionStorage) so an XSS exploit cannot read it.
|
|
79
|
+
* Native: token goes through SecureStore, user record goes
|
|
80
|
+
* through SecureStore alongside it.
|
|
81
|
+
*/
|
|
82
|
+
static async persistAuthSession(data) {
|
|
83
|
+
// Both writes target independent storage keys; parallelising them
|
|
84
|
+
// saves one round-trip on the login / register hot path.
|
|
85
|
+
await Promise.all([ApiConfig.storeSessionToken(data.session_token), persistUser(data.user)]);
|
|
86
|
+
}
|
|
87
|
+
static async login(email, password) {
|
|
88
|
+
// NFC-normalize every password that crosses the wire so the
|
|
89
|
+
// server-side auth hash agrees with whatever key the client
|
|
90
|
+
// derived from the same string. Without this a master password
|
|
91
|
+
// typed on a keyboard / IME that emits combining-character
|
|
92
|
+
// sequences on one device and precomposed forms on another
|
|
93
|
+
// produces two different hashes — login looks like wrong
|
|
94
|
+
// password while everything visually matches. See
|
|
95
|
+
// `shared/crypto/webcrypto.ts deriveMasterKey` for the
|
|
96
|
+
// client-side twin.
|
|
97
|
+
const pw = password.normalize("NFC");
|
|
98
|
+
// Multi-tenant IdP (access): { tenant, identifier, password } where the
|
|
99
|
+
// identifier is an email OR username and the tenant is contextual (set
|
|
100
|
+
// via ApiConfig.setTenant from the OIDC flow). Single-tenant servers use
|
|
101
|
+
// the { email, password } contract. `email` is the identifier either way.
|
|
102
|
+
const body = ApiConfig.getAuthMode() === "multi-tenant"
|
|
103
|
+
? { tenant: ApiConfig.getTenant(), identifier: email, password: pw }
|
|
104
|
+
: { email, password: pw };
|
|
105
|
+
const response = await apiFetch("/auth/login", {
|
|
106
|
+
method: "POST",
|
|
107
|
+
headers: { "Content-Type": "application/json" },
|
|
108
|
+
body: JSON.stringify(body),
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
throw await extractApiError(response, "Login failed");
|
|
112
|
+
}
|
|
113
|
+
const data = await parseAuthResponse(response);
|
|
114
|
+
await AuthService.persistAuthSession(data);
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
117
|
+
static async register(email, username, password, displayName) {
|
|
118
|
+
const body = { email, password: password.normalize("NFC") };
|
|
119
|
+
if (username) {
|
|
120
|
+
body.username = username;
|
|
121
|
+
}
|
|
122
|
+
if (displayName !== undefined) {
|
|
123
|
+
body.display_name = displayName;
|
|
124
|
+
}
|
|
125
|
+
const response = await apiFetch("/auth/register", {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: { "Content-Type": "application/json" },
|
|
128
|
+
body: JSON.stringify(body),
|
|
129
|
+
});
|
|
130
|
+
if (!response.ok) {
|
|
131
|
+
throw await extractApiError(response, "Registration failed");
|
|
132
|
+
}
|
|
133
|
+
const data = await parseAuthResponse(response);
|
|
134
|
+
await AuthService.persistAuthSession(data);
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
137
|
+
static async logout() {
|
|
138
|
+
try {
|
|
139
|
+
await apiFetch("/auth/logout", { method: "POST" });
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
// Logout network call failed — still clear local state below.
|
|
143
|
+
// Surface the underlying reason in dev so a half-broken logout
|
|
144
|
+
// (server session still alive after the user thinks they're
|
|
145
|
+
// gone) doesn't slip past unnoticed. In production we always
|
|
146
|
+
// clear local state so the UX is "logged out" even if the
|
|
147
|
+
// server didn't get the request.
|
|
148
|
+
if (__DEV__) {
|
|
149
|
+
console.warn("[auth] /auth/logout failed; clearing local state anyway:", e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
await ApiConfig.clearSessionToken();
|
|
154
|
+
await clearPersistedUser();
|
|
155
|
+
clearHibpPolicyCache();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
static async getCurrentUser() {
|
|
159
|
+
return loadPersistedUser();
|
|
160
|
+
}
|
|
161
|
+
static async refreshUserData() {
|
|
162
|
+
try {
|
|
163
|
+
if (!(await this.isAuthenticated())) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
const response = await apiFetch("/auth/me", { method: "GET" });
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
if (response.status === 401) {
|
|
169
|
+
await this.logout();
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const user = await response.json();
|
|
174
|
+
await persistUser(user);
|
|
175
|
+
return user;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Web: HttpOnly cookies aren't readable from JS. We use the
|
|
183
|
+
* presence of the (non-HttpOnly) `csrf_token` cookie — set by the
|
|
184
|
+
* server alongside the session cookie at login — as the
|
|
185
|
+
* "authenticated" probe. Falls back to the in-memory user record if
|
|
186
|
+
* cookies are unreadable (SSR / non-browser test envs).
|
|
187
|
+
* Native: a token in SecureStore.
|
|
188
|
+
*/
|
|
189
|
+
static async isAuthenticated() {
|
|
190
|
+
if (Platform.OS === "web") {
|
|
191
|
+
if (typeof document !== "undefined" && document.cookie) {
|
|
192
|
+
if (/(?:^|;\s*)csrf_token=/.test(document.cookie)) {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return (await this.getCurrentUser()) !== null;
|
|
197
|
+
}
|
|
198
|
+
const token = await ApiConfig.getSessionToken();
|
|
199
|
+
return token !== null;
|
|
200
|
+
}
|
|
201
|
+
static async hasRole(role) {
|
|
202
|
+
const user = await this.getCurrentUser();
|
|
203
|
+
return user?.role === role;
|
|
204
|
+
}
|
|
205
|
+
static async deleteAccount(password) {
|
|
206
|
+
const response = await apiFetch("/auth/delete", {
|
|
207
|
+
method: "DELETE",
|
|
208
|
+
headers: { "Content-Type": "application/json" },
|
|
209
|
+
body: JSON.stringify({ password: password.normalize("NFC") }),
|
|
210
|
+
});
|
|
211
|
+
if (!response.ok) {
|
|
212
|
+
throw new Error(await extractErrorMessage(response, "Failed to delete account"));
|
|
213
|
+
}
|
|
214
|
+
await ApiConfig.clearSessionToken();
|
|
215
|
+
await clearPersistedUser();
|
|
216
|
+
}
|
|
217
|
+
static async changePassword(currentPassword, newPassword, reWrappedKey) {
|
|
218
|
+
const body = {
|
|
219
|
+
current_password: currentPassword.normalize("NFC"),
|
|
220
|
+
new_password: newPassword.normalize("NFC"),
|
|
221
|
+
};
|
|
222
|
+
if (reWrappedKey) {
|
|
223
|
+
body.symmetric_key_enc = reWrappedKey.symmetric_key_enc;
|
|
224
|
+
body.pbkdf2_salt = reWrappedKey.pbkdf2_salt;
|
|
225
|
+
}
|
|
226
|
+
const response = await apiFetch("/auth/password", {
|
|
227
|
+
method: "PUT",
|
|
228
|
+
headers: { "Content-Type": "application/json" },
|
|
229
|
+
body: JSON.stringify(body),
|
|
230
|
+
});
|
|
231
|
+
if (!response.ok) {
|
|
232
|
+
throw new Error(await extractErrorMessage(response, "Failed to change password"));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
static async changeEmail(newEmail, password) {
|
|
236
|
+
const response = await apiFetch("/auth/email", {
|
|
237
|
+
method: "PUT",
|
|
238
|
+
headers: { "Content-Type": "application/json" },
|
|
239
|
+
body: JSON.stringify({ new_email: newEmail, password: password.normalize("NFC") }),
|
|
240
|
+
});
|
|
241
|
+
if (!response.ok) {
|
|
242
|
+
throw new Error(await extractErrorMessage(response, "Failed to change email"));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
static async updateDisplayName(displayName) {
|
|
246
|
+
const response = await apiFetch("/auth/display-name", {
|
|
247
|
+
method: "PUT",
|
|
248
|
+
headers: { "Content-Type": "application/json" },
|
|
249
|
+
body: JSON.stringify({ display_name: displayName }),
|
|
250
|
+
});
|
|
251
|
+
if (!response.ok) {
|
|
252
|
+
throw new Error(await extractErrorMessage(response, "Failed to update display name"));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
static async setupMfa() {
|
|
256
|
+
const response = await apiFetch("/auth/mfa/setup", { method: "POST" });
|
|
257
|
+
if (!response.ok) {
|
|
258
|
+
throw new Error(await extractErrorMessage(response, "Failed to set up MFA"));
|
|
259
|
+
}
|
|
260
|
+
return await response.json();
|
|
261
|
+
}
|
|
262
|
+
static async verifyMfaSetup(code) {
|
|
263
|
+
const response = await apiFetch("/auth/mfa/verify-setup", {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: { "Content-Type": "application/json" },
|
|
266
|
+
body: JSON.stringify({ code }),
|
|
267
|
+
});
|
|
268
|
+
if (!response.ok) {
|
|
269
|
+
throw new Error(await extractErrorMessage(response, "Invalid verification code"));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
static async verifyMfa(code) {
|
|
273
|
+
const response = await apiFetch("/auth/mfa/verify", {
|
|
274
|
+
method: "POST",
|
|
275
|
+
headers: { "Content-Type": "application/json" },
|
|
276
|
+
body: JSON.stringify({ code }),
|
|
277
|
+
});
|
|
278
|
+
if (!response.ok) {
|
|
279
|
+
throw new Error(await extractErrorMessage(response, "Invalid MFA code"));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
static async disableMfa(password) {
|
|
283
|
+
const response = await apiFetch("/auth/mfa", {
|
|
284
|
+
method: "DELETE",
|
|
285
|
+
headers: { "Content-Type": "application/json" },
|
|
286
|
+
body: JSON.stringify({ password: password.normalize("NFC") }),
|
|
287
|
+
});
|
|
288
|
+
if (!response.ok) {
|
|
289
|
+
throw new Error(await extractErrorMessage(response, "Failed to disable MFA"));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
static async forgotPassword(email) {
|
|
293
|
+
// Multi-tenant IdP scopes the reset request to a tenant.
|
|
294
|
+
const body = ApiConfig.getAuthMode() === "multi-tenant"
|
|
295
|
+
? { tenant: ApiConfig.getTenant(), email }
|
|
296
|
+
: { email };
|
|
297
|
+
const response = await apiFetch("/auth/forgot-password", {
|
|
298
|
+
method: "POST",
|
|
299
|
+
headers: { "Content-Type": "application/json" },
|
|
300
|
+
body: JSON.stringify(body),
|
|
301
|
+
});
|
|
302
|
+
if (!response.ok) {
|
|
303
|
+
throw new Error(await extractErrorMessage(response, "Failed to send reset email"));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
static async validateResetCode(code) {
|
|
307
|
+
const response = await apiFetch("/auth/validate-reset-code", {
|
|
308
|
+
method: "POST",
|
|
309
|
+
headers: { "Content-Type": "application/json" },
|
|
310
|
+
body: JSON.stringify({ code }),
|
|
311
|
+
});
|
|
312
|
+
if (!response.ok) {
|
|
313
|
+
throw await extractApiError(response, "Invalid or expired code");
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
static async resetPassword(code, newPassword) {
|
|
317
|
+
const response = await apiFetch("/auth/reset-password", {
|
|
318
|
+
method: "POST",
|
|
319
|
+
headers: { "Content-Type": "application/json" },
|
|
320
|
+
body: JSON.stringify({ code, new_password: newPassword.normalize("NFC") }),
|
|
321
|
+
});
|
|
322
|
+
if (!response.ok) {
|
|
323
|
+
throw await extractApiError(response, "Failed to reset password");
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
static async verifyEmail(code) {
|
|
327
|
+
const response = await apiFetch("/auth/verify-email", {
|
|
328
|
+
method: "POST",
|
|
329
|
+
headers: { "Content-Type": "application/json" },
|
|
330
|
+
body: JSON.stringify({ code }),
|
|
331
|
+
});
|
|
332
|
+
if (!response.ok) {
|
|
333
|
+
throw new Error(await extractErrorMessage(response, "Email verification failed"));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
static async resendVerification() {
|
|
337
|
+
const response = await apiFetch("/auth/resend-verification", { method: "POST" });
|
|
338
|
+
if (!response.ok) {
|
|
339
|
+
throw new Error(await extractErrorMessage(response, "Failed to resend verification email"));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
static async completeOnboarding() {
|
|
343
|
+
const response = await apiFetch("/auth/complete-onboarding", { method: "POST" });
|
|
344
|
+
if (!response.ok) {
|
|
345
|
+
throw new Error(await extractErrorMessage(response, "Failed to complete onboarding"));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Public server configuration (feature flags) — read pre-auth to adapt the
|
|
350
|
+
* UI, e.g. whether MFA enrollment is mandatory during onboarding. Returns
|
|
351
|
+
* permissive defaults if the endpoint is unavailable so onboarding never
|
|
352
|
+
* hard-blocks on a missing/older server.
|
|
353
|
+
*/
|
|
354
|
+
static async getServerConfig() {
|
|
355
|
+
try {
|
|
356
|
+
const response = await apiFetch("/config", { method: "GET" });
|
|
357
|
+
if (!response.ok) {
|
|
358
|
+
return { require_mfa_enrollment: false, registration_enabled: true };
|
|
359
|
+
}
|
|
360
|
+
return (await response.json());
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
return { require_mfa_enrollment: false, registration_enabled: true };
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// Validator hints kept on the class as re-exports of the canonical
|
|
367
|
+
// free functions in `utils/validation`. The server enforces the same
|
|
368
|
+
// rules authoritatively (see entropy-auth's `password::policy`); the
|
|
369
|
+
// versions here are UI-only previews so the user sees feedback before
|
|
370
|
+
// the round-trip.
|
|
371
|
+
static validatePassword = validatePasswordUtil;
|
|
372
|
+
static validateEmail = validateEmailUtil;
|
|
373
|
+
static validateUsername = validateUsernameUtil;
|
|
374
|
+
}
|
|
375
|
+
export default AuthService;
|
|
376
|
+
//# sourceMappingURL=auth.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Favicon-resolution helpers shared between mobile + extension.
|
|
3
|
+
*
|
|
4
|
+
* Items in the vault (and analogues in other Entropy apps) store an
|
|
5
|
+
* `icon_url` reference that may be:
|
|
6
|
+
*
|
|
7
|
+
* * a `custom:<uploadId>` marker for a server-side upload — resolved
|
|
8
|
+
* at render time through the auth-aware transport;
|
|
9
|
+
* * an arbitrary public URL (logo CDN, etc.) — used verbatim;
|
|
10
|
+
* * `null` / empty — the renderer derives a favicon URL from the
|
|
11
|
+
* item's site URL via the server's favicon-proxy endpoint.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Build the favicon-proxy URL for a site, or return `null` when no
|
|
15
|
+
* proxy URL can be built. The caller falls back to its default
|
|
16
|
+
* placeholder when null is returned.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildFaviconUrl(siteUrl: string | null | undefined, faviconPath?: string): string | null;
|
|
19
|
+
/** Wrap a raw upload id as a `custom:<id>` reference for storage. */
|
|
20
|
+
export declare function customIconRef(uploadId: string): string;
|
|
21
|
+
/** True if the stored icon reference points at a custom upload. */
|
|
22
|
+
export declare function isCustomIconRef(iconRef: string | null | undefined): boolean;
|
|
23
|
+
/** Extract the upload id from a `custom:<id>` reference. */
|
|
24
|
+
export declare function customIconId(iconRef: string | null | undefined): string | null;
|
|
25
|
+
/** Tagged result describing how the renderer should source an item's icon. */
|
|
26
|
+
export type ResolvedIcon = {
|
|
27
|
+
kind: "upload";
|
|
28
|
+
uploadId: string;
|
|
29
|
+
} | {
|
|
30
|
+
kind: "url";
|
|
31
|
+
uri: string;
|
|
32
|
+
} | {
|
|
33
|
+
kind: "none";
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Pick the right source for an item's icon. Returning a tagged variant
|
|
37
|
+
* (rather than always coercing to a URL string) lets the renderer
|
|
38
|
+
* handle the auth-required upload case differently from public-favicon
|
|
39
|
+
* URLs without sniffing path patterns at the call site.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveIcon(opts: {
|
|
42
|
+
iconUrl?: string | null;
|
|
43
|
+
siteUrl?: string | null;
|
|
44
|
+
faviconPath?: string;
|
|
45
|
+
}): ResolvedIcon;
|
|
46
|
+
//# sourceMappingURL=favicon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favicon.d.ts","sourceRoot":"","sources":["../../src/services/favicon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,WAAW,SAAa,GACvB,MAAM,GAAG,IAAI,CA6Bf;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE3E;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAM9E;AAED,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,YAAY,CAUf"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Favicon-resolution helpers shared between mobile + extension.
|
|
3
|
+
*
|
|
4
|
+
* Items in the vault (and analogues in other Entropy apps) store an
|
|
5
|
+
* `icon_url` reference that may be:
|
|
6
|
+
*
|
|
7
|
+
* * a `custom:<uploadId>` marker for a server-side upload — resolved
|
|
8
|
+
* at render time through the auth-aware transport;
|
|
9
|
+
* * an arbitrary public URL (logo CDN, etc.) — used verbatim;
|
|
10
|
+
* * `null` / empty — the renderer derives a favicon URL from the
|
|
11
|
+
* item's site URL via the server's favicon-proxy endpoint.
|
|
12
|
+
*/
|
|
13
|
+
import { getBaseUrl } from "./api-config";
|
|
14
|
+
const CUSTOM_ICON_PREFIX = "custom:";
|
|
15
|
+
/**
|
|
16
|
+
* Build the favicon-proxy URL for a site, or return `null` when no
|
|
17
|
+
* proxy URL can be built. The caller falls back to its default
|
|
18
|
+
* placeholder when null is returned.
|
|
19
|
+
*/
|
|
20
|
+
export function buildFaviconUrl(siteUrl, faviconPath = "/favicon") {
|
|
21
|
+
if (!siteUrl) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const trimmed = siteUrl.trim();
|
|
25
|
+
if (!trimmed) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
let normalized = trimmed;
|
|
29
|
+
// Reject non-http(s) schemes up front. If we skipped this and just
|
|
30
|
+
// prepended `https://`, an `ftp:` input would parse as
|
|
31
|
+
// `https://ftp://…` — `URL` accepts it, the protocol comes out as
|
|
32
|
+
// `https:`, and a non-web origin leaks into the favicon proxy query.
|
|
33
|
+
const explicitScheme = /^([a-z][a-z0-9+.-]*):\/\//i.exec(normalized)?.[1];
|
|
34
|
+
if (explicitScheme && !/^https?$/i.test(explicitScheme)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (!/^https?:\/\//i.test(normalized)) {
|
|
38
|
+
normalized = `https://${normalized}`;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const parsed = new URL(normalized);
|
|
42
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return `${getBaseUrl()}${faviconPath}?url=${encodeURIComponent(parsed.toString())}`;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Wrap a raw upload id as a `custom:<id>` reference for storage. */
|
|
52
|
+
export function customIconRef(uploadId) {
|
|
53
|
+
return `${CUSTOM_ICON_PREFIX}${uploadId}`;
|
|
54
|
+
}
|
|
55
|
+
/** True if the stored icon reference points at a custom upload. */
|
|
56
|
+
export function isCustomIconRef(iconRef) {
|
|
57
|
+
return !!iconRef && iconRef.startsWith(CUSTOM_ICON_PREFIX);
|
|
58
|
+
}
|
|
59
|
+
/** Extract the upload id from a `custom:<id>` reference. */
|
|
60
|
+
export function customIconId(iconRef) {
|
|
61
|
+
if (!iconRef || !iconRef.startsWith(CUSTOM_ICON_PREFIX)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const id = iconRef.slice(CUSTOM_ICON_PREFIX.length);
|
|
65
|
+
return id || null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Pick the right source for an item's icon. Returning a tagged variant
|
|
69
|
+
* (rather than always coercing to a URL string) lets the renderer
|
|
70
|
+
* handle the auth-required upload case differently from public-favicon
|
|
71
|
+
* URLs without sniffing path patterns at the call site.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveIcon(opts) {
|
|
74
|
+
if (opts.iconUrl) {
|
|
75
|
+
const uploadId = customIconId(opts.iconUrl);
|
|
76
|
+
if (uploadId) {
|
|
77
|
+
return { kind: "upload", uploadId };
|
|
78
|
+
}
|
|
79
|
+
return { kind: "url", uri: opts.iconUrl };
|
|
80
|
+
}
|
|
81
|
+
const fav = buildFaviconUrl(opts.siteUrl, opts.faviconPath);
|
|
82
|
+
return fav ? { kind: "url", uri: fav } : { kind: "none" };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=favicon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favicon.js","sourceRoot":"","sources":["../../src/services/favicon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAErC;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAkC,EAClC,WAAW,GAAG,UAAU;IAExB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,UAAU,GAAG,OAAO,CAAC;IACzB,mEAAmE;IACnE,uDAAuD;IACvD,kEAAkE;IAClE,qEAAqE;IACrE,MAAM,cAAc,GAAG,4BAA4B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1E,IAAI,cAAc,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,UAAU,GAAG,WAAW,UAAU,EAAE,CAAC;IACvC,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,UAAU,EAAE,GAAG,WAAW,QAAQ,kBAAkB,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,GAAG,kBAAkB,GAAG,QAAQ,EAAE,CAAC;AAC5C,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,OAAkC;IAChE,OAAO,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAC7D,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,YAAY,CAAC,OAAkC;IAC7D,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACpD,OAAO,EAAE,IAAI,IAAI,CAAC;AACpB,CAAC;AAQD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAI3B;IACC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACtC,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IAC5C,CAAC;IACD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5D,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface HibpPolicy {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
enforce: boolean;
|
|
4
|
+
block_threshold: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function getCachedPolicy(): HibpPolicy | null;
|
|
7
|
+
export declare function setCachedPolicy(policy: HibpPolicy): void;
|
|
8
|
+
export declare function clearCachedPolicy(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Fetch the HIBP policy from the server (`GET /config`). Result is
|
|
11
|
+
* memoized in the in-process cache for the lifetime of the app — call
|
|
12
|
+
* once at startup (typically from `<AuthProvider onBeforeCheckAuth>`).
|
|
13
|
+
* Server-unreachable falls back to `DEFAULT_POLICY` so the caller is
|
|
14
|
+
* never blocked.
|
|
15
|
+
*/
|
|
16
|
+
export declare function fetchHibpPolicy(): Promise<HibpPolicy>;
|
|
17
|
+
/**
|
|
18
|
+
* Synchronous view of the cached policy. Returns the default when
|
|
19
|
+
* `fetchHibpPolicy` hasn't completed yet; suitable for render-time
|
|
20
|
+
* gating where blocking is unacceptable.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getHibpPolicy(): HibpPolicy;
|
|
23
|
+
//# sourceMappingURL=hibp-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hibp-cache.d.ts","sourceRoot":"","sources":["../../src/services/hibp-cache.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAeD,wBAAgB,eAAe,IAAI,UAAU,GAAG,IAAI,CAEnD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAExD;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC,CAiB3D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAE1C"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared HIBP policy cache — separated to avoid circular imports between
|
|
3
|
+
* `auth.service` (which clears it) and the consumer's policy fetcher.
|
|
4
|
+
*/
|
|
5
|
+
import { apiFetch } from "../utils/api-fetch";
|
|
6
|
+
/** Conservative default — block re-use of widely-leaked passwords. */
|
|
7
|
+
const DEFAULT_POLICY = {
|
|
8
|
+
enabled: true,
|
|
9
|
+
enforce: true,
|
|
10
|
+
block_threshold: 1000,
|
|
11
|
+
};
|
|
12
|
+
let cachedPolicy = null;
|
|
13
|
+
export function getCachedPolicy() {
|
|
14
|
+
return cachedPolicy;
|
|
15
|
+
}
|
|
16
|
+
export function setCachedPolicy(policy) {
|
|
17
|
+
cachedPolicy = policy;
|
|
18
|
+
}
|
|
19
|
+
export function clearCachedPolicy() {
|
|
20
|
+
cachedPolicy = null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fetch the HIBP policy from the server (`GET /config`). Result is
|
|
24
|
+
* memoized in the in-process cache for the lifetime of the app — call
|
|
25
|
+
* once at startup (typically from `<AuthProvider onBeforeCheckAuth>`).
|
|
26
|
+
* Server-unreachable falls back to `DEFAULT_POLICY` so the caller is
|
|
27
|
+
* never blocked.
|
|
28
|
+
*/
|
|
29
|
+
export async function fetchHibpPolicy() {
|
|
30
|
+
const cached = cachedPolicy;
|
|
31
|
+
if (cached) {
|
|
32
|
+
return cached;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const response = await apiFetch("/config");
|
|
36
|
+
if (response.ok) {
|
|
37
|
+
const config = await response.json();
|
|
38
|
+
cachedPolicy = config.hibp;
|
|
39
|
+
return config.hibp;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Server unreachable — fall through to default.
|
|
44
|
+
}
|
|
45
|
+
cachedPolicy = DEFAULT_POLICY;
|
|
46
|
+
return DEFAULT_POLICY;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Synchronous view of the cached policy. Returns the default when
|
|
50
|
+
* `fetchHibpPolicy` hasn't completed yet; suitable for render-time
|
|
51
|
+
* gating where blocking is unacceptable.
|
|
52
|
+
*/
|
|
53
|
+
export function getHibpPolicy() {
|
|
54
|
+
return cachedPolicy ?? DEFAULT_POLICY;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=hibp-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hibp-cache.js","sourceRoot":"","sources":["../../src/services/hibp-cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAY9C,sEAAsE;AACtE,MAAM,cAAc,GAAe;IACjC,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,eAAe,EAAE,IAAI;CACtB,CAAC;AAEF,IAAI,YAAY,GAAsB,IAAI,CAAC;AAE3C,MAAM,UAAU,eAAe;IAC7B,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAkB;IAChD,YAAY,GAAG,MAAM,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,MAAM,GAAG,YAAY,CAAC;IAC5B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,MAAM,GAAiB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnD,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;YAC3B,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;IACD,YAAY,GAAG,cAAc,CAAC;IAC9B,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,YAAY,IAAI,cAAc,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Have-I-Been-Pwned password lookup using `k`-anonymity.
|
|
3
|
+
*
|
|
4
|
+
* Sends only the first five hex characters of the SHA-1 hash to the HIBP
|
|
5
|
+
* API. The full hash and plaintext never leave the device. Designed to be
|
|
6
|
+
* called from a debounced password-input change handler — see `debounce`
|
|
7
|
+
* below.
|
|
8
|
+
*/
|
|
9
|
+
export interface PwnedPasswordResult {
|
|
10
|
+
/** `true` = breached, `false` = safe, `null` = check failed (unknown). */
|
|
11
|
+
isPwned: boolean | null;
|
|
12
|
+
count: number;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function checkPasswordPwned(password: string): Promise<PwnedPasswordResult>;
|
|
16
|
+
export interface PwnedMessage {
|
|
17
|
+
title: string;
|
|
18
|
+
message: string;
|
|
19
|
+
severity: "error" | "warning" | "info";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build a user-friendly message for a HIBP result. The policy comes from
|
|
23
|
+
* the shared cache populated by the consumer (see `hibp-cache.ts`). If no
|
|
24
|
+
* policy is cached, falls back to a non-enforcing default.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getPwnedMessage(result: PwnedPasswordResult): PwnedMessage;
|
|
27
|
+
export { debounce } from "../utils/debounce";
|
|
28
|
+
//# sourceMappingURL=hibp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hibp.d.ts","sourceRoot":"","sources":["../../src/services/hibp.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6CvF;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,mBAAmB,GAAG,YAAY,CAoCzE;AAID,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC"}
|