@rapidmx/web-client 0.4.0 → 0.6.0
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/README.md +88 -0
- package/apps/admin/audit-log/index.tsx +35 -8
- package/apps/admin/data-requests/index.tsx +480 -485
- package/apps/admin/distribution-lists/[uid].tsx +19 -1
- package/apps/admin/escrow-scopes/[uid].tsx +348 -237
- package/apps/admin/escrow-scopes/new/index.tsx +8 -2
- package/apps/admin/index.tsx +19 -1
- package/apps/admin/ingest-queue/index.tsx +44 -5
- package/apps/admin/mailboxes/[uid].tsx +211 -184
- package/apps/admin/quarantine/index.tsx +46 -14
- package/apps/admin/transport-rules/[uid].tsx +30 -1
- package/apps/admin/transport-rules/_transportRuleConfig.tsx +38 -2
- package/apps/admin/transport-rules/index.tsx +24 -6
- package/apps/admin/transport-rules/new/index.tsx +30 -1
- package/apps/escrow/_layout.tsx +2 -3
- package/apps/escrow/audit-log/index.tsx +196 -168
- package/apps/escrow/matters/[uid].tsx +621 -521
- package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +22 -1
- package/apps/shared/components/admin/layout/AdminShell.tsx +28 -9
- package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -0
- package/apps/shared/components/admin/mailboxes/ResourceSettingsCard.tsx +3 -3
- package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +55 -11
- package/apps/shared/components/admin/settings/BrandingForm.tsx +15 -4
- package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +18 -7
- package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +10 -2
- package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +6 -0
- package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +45 -12
- package/apps/shared/components/admin/settings/PluginsManager.tsx +1235 -595
- package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +174 -98
- package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +49 -13
- package/apps/shared/components/admin/setup/SetupWizard.tsx +150 -34
- package/apps/shared/components/admin/signOut.ts +79 -0
- package/apps/shared/components/admin/usePagedList.tsx +129 -0
- package/apps/shared/components/calendar/EventModal.tsx +717 -549
- package/apps/shared/components/calendar/MonthView.tsx +173 -139
- package/apps/shared/components/calendar/RecurrenceEditor.tsx +222 -180
- package/apps/shared/components/calendar/SplitDayView.tsx +143 -137
- package/apps/shared/components/calendar/TimeGridView.tsx +244 -198
- package/apps/shared/components/calendar/allDay.ts +124 -0
- package/apps/shared/components/calendar/layout/CalendarShell.tsx +194 -192
- package/apps/shared/components/contacts/ContactDetailPane.tsx +100 -21
- package/apps/shared/components/contacts/ContactForm.tsx +377 -348
- package/apps/shared/components/contacts/ContactsSidebar.tsx +6 -2
- package/apps/shared/components/contacts/KeyChangeReview.tsx +192 -0
- package/apps/shared/components/contacts/contactKeys.ts +78 -0
- package/apps/shared/components/contacts/layout/ContactsShell.tsx +199 -197
- package/apps/shared/components/escrow/layout/EscrowShell.tsx +148 -134
- package/apps/shared/components/layout/AppShell.tsx +123 -33
- package/apps/shared/components/layout/BrandingChrome.tsx +48 -10
- package/apps/shared/components/layout/KeyEnrollmentGate.tsx +389 -298
- package/apps/shared/components/layout/MailboxProvisioning.tsx +19 -3
- package/apps/shared/components/layout/RecoveryCodeUnlock.tsx +350 -0
- package/apps/shared/components/layout/UnlockPromptProvider.tsx +257 -128
- package/apps/shared/components/mail/ConversationThreadPane.tsx +216 -181
- package/apps/shared/components/mail/MessageDetailPane.tsx +1318 -630
- package/apps/shared/components/mail/compose/ComposeContext.tsx +20 -15
- package/apps/shared/components/mail/compose/ComposeWindow.tsx +854 -132
- package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -0
- package/apps/shared/components/mail/layout/MailShell.tsx +420 -408
- package/apps/shared/components/mail/pinnedSigners.ts +124 -0
- package/apps/shared/components/mail/verificationSeals.ts +125 -0
- package/apps/shared/components/mail/writableMailboxes.ts +101 -0
- package/apps/shared/components/rules/RuleBuilder.tsx +311 -276
- package/apps/shared/components/settings/layout/SettingsShell.tsx +23 -9
- package/apps/shared/components/tasks/layout/TasksShell.tsx +201 -199
- package/apps/shared/mail/listAllPages.ts +39 -0
- package/apps/shared/plugins/pluginNav.ts +73 -0
- package/apps/shared/search/LocalIndexLifecycle.tsx +64 -55
- package/apps/shared/search/localIndexBuilder.ts +481 -179
- package/apps/shared/search/localIndexRpcClient.ts +231 -29
- package/apps/shared/search/localIndexSchema.ts +15 -6
- package/apps/shared/search/localIndexStorage.ts +98 -0
- package/apps/shared/search/localIndexVFS.ts +32 -1
- package/apps/shared/search/localIndexWorker.ts +648 -186
- package/apps/www/calendar/index.tsx +438 -417
- package/apps/www/contacts/[uid].tsx +21 -2
- package/apps/www/contacts/index.tsx +116 -12
- package/apps/www/index.tsx +1314 -1041
- package/apps/www/messages/[uid].tsx +18 -6
- package/apps/www/settings/auto-reply/index.tsx +134 -129
- package/apps/www/settings/encryption/index.tsx +739 -216
- package/apps/www/settings/filters/[uid].tsx +171 -155
- package/apps/www/settings/filters/new/index.tsx +8 -1
- package/apps/www/settings/focused-inbox/index.tsx +150 -148
- package/apps/www/settings/privacy/index.tsx +494 -436
- package/apps/www/settings/read-receipts/index.tsx +148 -125
- package/apps/www/settings/sharing/index.tsx +17 -14
- package/apps/www/tasks/index.tsx +638 -579
- package/dist/apps/admin/_404.d.ts +2 -0
- package/dist/apps/admin/_500.d.ts +2 -0
- package/dist/apps/admin/_layout.d.ts +8 -0
- package/dist/apps/admin/audit-log/index.d.ts +11 -0
- package/dist/apps/admin/audit-log/index.js +38 -8
- package/dist/apps/admin/branding/index.d.ts +3 -0
- package/dist/apps/admin/data-requests/index.d.ts +3 -0
- package/dist/apps/admin/data-requests/index.js +52 -72
- package/dist/apps/admin/distribution-lists/[uid].d.ts +7 -0
- package/dist/apps/admin/distribution-lists/[uid].js +1 -1
- package/dist/apps/admin/distribution-lists/index.d.ts +3 -0
- package/dist/apps/admin/distribution-lists/new/index.d.ts +3 -0
- package/dist/apps/admin/domains/[uid].d.ts +7 -0
- package/dist/apps/admin/domains/index.d.ts +3 -0
- package/dist/apps/admin/domains/new/index.d.ts +3 -0
- package/dist/apps/admin/encryption-policy/index.d.ts +3 -0
- package/dist/apps/admin/escrow-scopes/[uid].d.ts +21 -0
- package/dist/apps/admin/escrow-scopes/[uid].js +91 -12
- package/dist/apps/admin/escrow-scopes/index.d.ts +3 -0
- package/dist/apps/admin/escrow-scopes/new/index.d.ts +3 -0
- package/dist/apps/admin/escrow-scopes/new/index.js +8 -3
- package/dist/apps/admin/index.d.ts +3 -0
- package/dist/apps/admin/index.js +4 -1
- package/dist/apps/admin/ingest-queue/index.d.ts +4 -0
- package/dist/apps/admin/ingest-queue/index.js +24 -6
- package/dist/apps/admin/mailbox-policy/index.d.ts +3 -0
- package/dist/apps/admin/mailboxes/[uid].d.ts +7 -0
- package/dist/apps/admin/mailboxes/[uid].js +20 -4
- package/dist/apps/admin/mailboxes/new/index.d.ts +3 -0
- package/dist/apps/admin/plugins/index.d.ts +3 -0
- package/dist/apps/admin/quarantine/index.d.ts +6 -0
- package/dist/apps/admin/quarantine/index.js +20 -11
- package/dist/apps/admin/retention-policy/index.d.ts +3 -0
- package/dist/apps/admin/setup/index.d.ts +3 -0
- package/dist/apps/admin/transport-rules/[uid].d.ts +7 -0
- package/dist/apps/admin/transport-rules/[uid].js +18 -2
- package/dist/apps/admin/transport-rules/_transportRuleConfig.d.ts +21 -0
- package/dist/apps/admin/transport-rules/_transportRuleConfig.js +19 -0
- package/dist/apps/admin/transport-rules/index.d.ts +3 -0
- package/dist/apps/admin/transport-rules/index.js +22 -6
- package/dist/apps/admin/transport-rules/new/index.d.ts +3 -0
- package/dist/apps/admin/transport-rules/new/index.js +18 -2
- package/dist/apps/escrow/_layout.d.ts +10 -0
- package/dist/apps/escrow/_layout.js +3 -3
- package/dist/apps/escrow/audit-log/index.d.ts +9 -0
- package/dist/apps/escrow/audit-log/index.js +26 -1
- package/dist/apps/escrow/index.d.ts +3 -0
- package/dist/apps/escrow/matters/[uid].d.ts +7 -0
- package/dist/apps/escrow/matters/[uid].js +77 -42
- package/dist/apps/escrow/matters/new/index.d.ts +3 -0
- package/dist/apps/shared/components/admin/distributionLists/MemberListCard.d.ts +17 -0
- package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.d.ts +32 -0
- package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +11 -2
- package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +32 -0
- package/dist/apps/shared/components/admin/layout/AdminShell.js +15 -6
- package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.d.ts +12 -0
- package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +72 -0
- package/dist/apps/shared/components/admin/mailboxes/MailboxTable.d.ts +6 -0
- package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.d.ts +19 -0
- package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +3 -3
- package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.d.ts +12 -0
- package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +22 -4
- package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +9 -0
- package/dist/apps/shared/components/admin/settings/BrandingForm.js +15 -4
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +12 -0
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +13 -7
- package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.d.ts +12 -0
- package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +7 -2
- package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.d.ts +9 -0
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.d.ts +19 -0
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +6 -0
- package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.d.ts +10 -0
- package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +34 -12
- package/dist/apps/shared/components/admin/settings/PluginsManager.d.ts +4 -0
- package/dist/apps/shared/components/admin/settings/PluginsManager.js +390 -78
- package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.d.ts +9 -0
- package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +40 -11
- package/dist/apps/shared/components/admin/setup/EscrowSetupStep.d.ts +14 -0
- package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +29 -13
- package/dist/apps/shared/components/admin/setup/SetupWizard.d.ts +36 -0
- package/dist/apps/shared/components/admin/setup/SetupWizard.js +87 -21
- package/dist/apps/shared/components/admin/signOut.d.ts +23 -0
- package/dist/apps/shared/components/admin/signOut.js +75 -0
- package/dist/apps/shared/components/admin/usePagedList.d.ts +39 -0
- package/dist/apps/shared/components/admin/usePagedList.js +99 -0
- package/dist/apps/shared/components/calendar/CalendarListSidebar.d.ts +26 -0
- package/dist/apps/shared/components/calendar/EventModal.d.ts +46 -0
- package/dist/apps/shared/components/calendar/EventModal.js +142 -21
- package/dist/apps/shared/components/calendar/MonthView.d.ts +15 -0
- package/dist/apps/shared/components/calendar/MonthView.js +12 -5
- package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +20 -0
- package/dist/apps/shared/components/calendar/RecurrenceEditor.js +40 -5
- package/dist/apps/shared/components/calendar/ResourcePicker.d.ts +19 -0
- package/dist/apps/shared/components/calendar/SplitDayView.d.ts +28 -0
- package/dist/apps/shared/components/calendar/SplitDayView.js +10 -4
- package/dist/apps/shared/components/calendar/TimeGridView.d.ts +17 -0
- package/dist/apps/shared/components/calendar/TimeGridView.js +23 -7
- package/dist/apps/shared/components/calendar/allDay.d.ts +51 -0
- package/dist/apps/shared/components/calendar/allDay.js +111 -0
- package/dist/apps/shared/components/calendar/layout/CalendarShell.d.ts +40 -0
- package/dist/apps/shared/components/calendar/layout/CalendarShell.js +3 -3
- package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +23 -0
- package/dist/apps/shared/components/contacts/ContactDetailPane.js +43 -5
- package/dist/apps/shared/components/contacts/ContactForm.d.ts +20 -0
- package/dist/apps/shared/components/contacts/ContactForm.js +32 -10
- package/dist/apps/shared/components/contacts/ContactsSidebar.d.ts +40 -0
- package/dist/apps/shared/components/contacts/ContactsSidebar.js +2 -2
- package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +25 -0
- package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +40 -0
- package/dist/apps/shared/components/contacts/KeyChangeReview.js +63 -0
- package/dist/apps/shared/components/contacts/contactKeys.d.ts +29 -0
- package/dist/apps/shared/components/contacts/contactKeys.js +64 -0
- package/dist/apps/shared/components/contacts/layout/ContactsShell.d.ts +21 -0
- package/dist/apps/shared/components/contacts/layout/ContactsShell.js +2 -2
- package/dist/apps/shared/components/escrow/layout/EscrowShell.d.ts +25 -0
- package/dist/apps/shared/components/escrow/layout/EscrowShell.js +24 -5
- package/dist/apps/shared/components/forms/StringListField.d.ts +22 -0
- package/dist/apps/shared/components/layout/AppShell.d.ts +49 -0
- package/dist/apps/shared/components/layout/AppShell.js +97 -26
- package/dist/apps/shared/components/layout/BrandingChrome.d.ts +18 -0
- package/dist/apps/shared/components/layout/BrandingChrome.js +45 -10
- package/dist/apps/shared/components/layout/KeyEnrollmentGate.d.ts +51 -0
- package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +49 -12
- package/dist/apps/shared/components/layout/MailboxProvisioning.d.ts +13 -0
- package/dist/apps/shared/components/layout/MailboxProvisioning.js +10 -2
- package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +66 -0
- package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +174 -0
- package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +45 -0
- package/dist/apps/shared/components/layout/UnlockPromptProvider.js +73 -14
- package/dist/apps/shared/components/layout/UserMenu.d.ts +23 -0
- package/dist/apps/shared/components/mail/ConversationList.d.ts +11 -0
- package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +23 -0
- package/dist/apps/shared/components/mail/ConversationThreadPane.js +50 -12
- package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +93 -0
- package/dist/apps/shared/components/mail/MessageDetailPane.js +441 -36
- package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +58 -0
- package/dist/apps/shared/components/mail/compose/ComposeContext.js +9 -6
- package/dist/apps/shared/components/mail/compose/ComposeToolbar.d.ts +15 -0
- package/dist/apps/shared/components/mail/compose/ComposeWindow.d.ts +37 -0
- package/dist/apps/shared/components/mail/compose/ComposeWindow.js +699 -128
- package/dist/apps/shared/components/mail/compose/EmojiPicker.d.ts +14 -0
- package/dist/apps/shared/components/mail/compose/GifPicker.d.ts +13 -0
- package/dist/apps/shared/components/mail/compose/RichTextEditor.d.ts +34 -0
- package/dist/apps/shared/components/mail/compose/ScheduleSendPicker.d.ts +16 -0
- package/dist/apps/shared/components/mail/compose/composeFlushRegistry.d.ts +27 -0
- package/dist/apps/shared/components/mail/compose/composeFlushRegistry.js +50 -0
- package/dist/apps/shared/components/mail/layout/MailShell.d.ts +57 -0
- package/dist/apps/shared/components/mail/layout/MailShell.js +13 -4
- package/dist/apps/shared/components/mail/pinnedSigners.d.ts +33 -0
- package/dist/apps/shared/components/mail/pinnedSigners.js +98 -0
- package/dist/apps/shared/components/mail/verificationSeals.d.ts +22 -0
- package/dist/apps/shared/components/mail/verificationSeals.js +112 -0
- package/dist/apps/shared/components/mail/writableMailboxes.d.ts +15 -0
- package/dist/apps/shared/components/mail/writableMailboxes.js +87 -0
- package/dist/apps/shared/components/rules/RuleBuilder.d.ts +70 -0
- package/dist/apps/shared/components/rules/RuleBuilder.js +34 -6
- package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +41 -0
- package/dist/apps/shared/components/settings/layout/SettingsShell.js +19 -9
- package/dist/apps/shared/components/tasks/TasksSidebar.d.ts +41 -0
- package/dist/apps/shared/components/tasks/TasksToolbar.d.ts +14 -0
- package/dist/apps/shared/components/tasks/layout/TasksShell.d.ts +24 -0
- package/dist/apps/shared/components/tasks/layout/TasksShell.js +2 -2
- package/dist/apps/shared/mail/findWellKnownFolderUid.d.ts +5 -0
- package/dist/apps/shared/mail/listAllPages.d.ts +17 -0
- package/dist/apps/shared/mail/listAllPages.js +25 -0
- package/dist/apps/shared/plugins/pluginNav.d.ts +39 -0
- package/dist/apps/shared/plugins/pluginNav.js +33 -0
- package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +13 -0
- package/dist/apps/shared/search/LocalIndexLifecycle.js +58 -54
- package/dist/apps/shared/search/localIndexBlockCipher.d.ts +36 -0
- package/dist/apps/shared/search/localIndexBuilder.d.ts +85 -0
- package/dist/apps/shared/search/localIndexBuilder.js +292 -37
- package/dist/apps/shared/search/localIndexKey.d.ts +4 -0
- package/dist/apps/shared/search/localIndexRpcClient.d.ts +71 -0
- package/dist/apps/shared/search/localIndexRpcClient.js +191 -26
- package/dist/apps/shared/search/localIndexSchema.d.ts +111 -0
- package/dist/apps/shared/search/localIndexSchema.js +12 -6
- package/dist/apps/shared/search/localIndexSizePreference.d.ts +27 -0
- package/dist/apps/shared/search/localIndexStorage.d.ts +28 -0
- package/dist/apps/shared/search/localIndexStorage.js +86 -0
- package/dist/apps/shared/search/localIndexVFS.d.ts +101 -0
- package/dist/apps/shared/search/localIndexVFS.js +68 -40
- package/dist/apps/shared/search/localIndexWorker.d.ts +145 -0
- package/dist/apps/shared/search/localIndexWorker.js +519 -173
- package/dist/apps/shared/search/searchTier2.d.ts +30 -0
- package/dist/apps/www/_404.d.ts +2 -0
- package/dist/apps/www/_500.d.ts +2 -0
- package/dist/apps/www/_layout.d.ts +14 -0
- package/dist/apps/www/calendar/index.d.ts +3 -0
- package/dist/apps/www/calendar/index.js +28 -10
- package/dist/apps/www/contacts/[uid].d.ts +13 -0
- package/dist/apps/www/contacts/[uid].js +13 -2
- package/dist/apps/www/contacts/index.d.ts +3 -0
- package/dist/apps/www/contacts/index.js +80 -10
- package/dist/apps/www/index.d.ts +3 -0
- package/dist/apps/www/index.js +339 -108
- package/dist/apps/www/messages/[uid].d.ts +11 -0
- package/dist/apps/www/messages/[uid].js +18 -6
- package/dist/apps/www/settings/auto-reply/index.d.ts +4 -0
- package/dist/apps/www/settings/auto-reply/index.js +9 -4
- package/dist/apps/www/settings/encryption/index.d.ts +7 -0
- package/dist/apps/www/settings/encryption/index.js +514 -97
- package/dist/apps/www/settings/filters/[uid].d.ts +8 -0
- package/dist/apps/www/settings/filters/[uid].js +22 -7
- package/dist/apps/www/settings/filters/_mailFilterRuleConfig.d.ts +11 -0
- package/dist/apps/www/settings/filters/index.d.ts +4 -0
- package/dist/apps/www/settings/filters/new/index.d.ts +4 -0
- package/dist/apps/www/settings/filters/new/index.js +8 -2
- package/dist/apps/www/settings/focused-inbox/index.d.ts +4 -0
- package/dist/apps/www/settings/focused-inbox/index.js +3 -1
- package/dist/apps/www/settings/labels/index.d.ts +4 -0
- package/dist/apps/www/settings/privacy/index.d.ts +4 -0
- package/dist/apps/www/settings/privacy/index.js +57 -22
- package/dist/apps/www/settings/read-receipts/index.d.ts +4 -0
- package/dist/apps/www/settings/read-receipts/index.js +10 -3
- package/dist/apps/www/settings/sharing/index.d.ts +4 -0
- package/dist/apps/www/settings/sharing/index.js +7 -11
- package/dist/apps/www/settings/signatures/[uid].d.ts +8 -0
- package/dist/apps/www/settings/signatures/index.d.ts +4 -0
- package/dist/apps/www/settings/signatures/new/index.d.ts +4 -0
- package/dist/apps/www/settings/signatures/signatureDefaults.d.ts +10 -0
- package/dist/apps/www/tasks/index.d.ts +3 -0
- package/dist/apps/www/tasks/index.js +50 -10
- package/package.json +3 -3
- package/apps/shared/components/booking/AvailabilityEditor.tsx +0 -118
- package/apps/www/settings/booking-types/[uid].tsx +0 -300
- package/apps/www/settings/booking-types/index.tsx +0 -98
- package/apps/www/settings/booking-types/new/index.tsx +0 -212
- package/dist/apps/shared/components/booking/AvailabilityEditor.js +0 -45
- package/dist/apps/www/settings/booking-types/[uid].js +0 -129
- package/dist/apps/www/settings/booking-types/index.js +0 -29
- package/dist/apps/www/settings/booking-types/new/index.js +0 -86
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* The trusted signing-key fingerprints for a received message's sender, for `evaluateMessageSecurity()`'s
|
|
7
|
+
* `pinnedSignerFingerprints`: the keys key discovery already pinned on the contacts in the reading mailbox's own
|
|
8
|
+
* contacts folder(s). Reads only stored contacts - never triggers a Discovery lookup, which must not happen on
|
|
9
|
+
* message receipt.
|
|
10
|
+
*
|
|
11
|
+
* `MessageDetailPane` renders once per opened message (and once per message in a thread), so each mailbox's
|
|
12
|
+
* contact list is fetched once and reused for `CONTACTS_CACHE_TTL_MS`; a failed load isn't cached. Any failure
|
|
13
|
+
* leaves the caller with no pins, which `evaluateMessageSecurity()` reports as an unverified signer - never as
|
|
14
|
+
* verified.
|
|
15
|
+
*
|
|
16
|
+
* The cache is dropped (`clearPinnedSignerCache()`) whenever a key session locks (subscribed on first use), on sign-out
|
|
17
|
+
* (`AppShell`), and after the reader adds, edits or deletes contacts (the contacts pages) - so a contact removed
|
|
18
|
+
* because its key was revoked doesn't keep vouching for signatures until the TTL runs out.
|
|
19
|
+
*/
|
|
20
|
+
import {
|
|
21
|
+
Contact,
|
|
22
|
+
PINNED_FINGERPRINT_MAX_PAGES,
|
|
23
|
+
PINNED_FINGERPRINT_PAGE_SIZE,
|
|
24
|
+
SignerKeyState,
|
|
25
|
+
listContacts,
|
|
26
|
+
pinnedSigningFingerprintsFor,
|
|
27
|
+
signerKeyStateFor,
|
|
28
|
+
} from "@rapidmx/react-shared/contacts/contactsApi.js";
|
|
29
|
+
import { keyPinnedSince } from "../contacts/contactKeys.js";
|
|
30
|
+
import { listFolders } from "@rapidmx/react-shared/mail/mailApi.js";
|
|
31
|
+
import { subscribeKeySession } from "@rapidmx/react-shared/crypto/keySession.js";
|
|
32
|
+
|
|
33
|
+
/** How long one mailbox's loaded contact list is reused before it is fetched again. */
|
|
34
|
+
export const CONTACTS_CACHE_TTL_MS = 60_000;
|
|
35
|
+
|
|
36
|
+
const contactsCache = new Map<string, { loadedAt: number; contacts: Promise<Contact[]> }>();
|
|
37
|
+
|
|
38
|
+
/** Forgets every cached contact list - on sign-out, a key-session lock, after the reader changes their contacts, and
|
|
39
|
+
* in tests. */
|
|
40
|
+
export function clearPinnedSignerCache(): void {
|
|
41
|
+
contactsCache.clear();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let lockSubscribed = false;
|
|
45
|
+
|
|
46
|
+
/** Subscribes (once, lazily - a module-level subscription would run in every page that merely imports this) to key
|
|
47
|
+
* session changes, clearing the cache whenever any mailbox's keys are locked. */
|
|
48
|
+
function subscribeToLocksOnce(): void {
|
|
49
|
+
if (lockSubscribed) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
lockSubscribed = true;
|
|
53
|
+
subscribeKeySession((event) => {
|
|
54
|
+
if (event.state === "locked") {
|
|
55
|
+
clearPinnedSignerCache();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function loadMailboxContacts(mailboxUid: string): Promise<Contact[]> {
|
|
61
|
+
const folders = await listFolders(mailboxUid);
|
|
62
|
+
const contacts: Contact[] = [];
|
|
63
|
+
for (const folder of folders.filter((f) => f.type === "contacts")) {
|
|
64
|
+
for (let page = 0; page < PINNED_FINGERPRINT_MAX_PAGES; page++) {
|
|
65
|
+
const batch = await listContacts(folder.uid, { limit: PINNED_FINGERPRINT_PAGE_SIZE, page });
|
|
66
|
+
contacts.push(...batch);
|
|
67
|
+
if (batch.length < PINNED_FINGERPRINT_PAGE_SIZE) {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return contacts;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** `mailboxUid`'s contacts, from the cache when fresh. Rejects if they can't be loaded. */
|
|
76
|
+
function cachedMailboxContacts(mailboxUid: string): Promise<Contact[]> {
|
|
77
|
+
subscribeToLocksOnce();
|
|
78
|
+
let entry = contactsCache.get(mailboxUid);
|
|
79
|
+
if (!entry || Date.now() - entry.loadedAt > CONTACTS_CACHE_TTL_MS) {
|
|
80
|
+
const created = { loadedAt: Date.now(), contacts: loadMailboxContacts(mailboxUid) };
|
|
81
|
+
contactsCache.set(mailboxUid, created);
|
|
82
|
+
created.contacts.catch(() => {
|
|
83
|
+
if (contactsCache.get(mailboxUid) === created) {
|
|
84
|
+
contactsCache.delete(mailboxUid);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
entry = created;
|
|
88
|
+
}
|
|
89
|
+
return entry.contacts;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** The sender `address`'s pinned signing fingerprints from `mailboxUid`'s contacts. Rejects if they can't be loaded. */
|
|
93
|
+
export async function getPinnedSignerFingerprints(mailboxUid: string, address: string): Promise<string[]> {
|
|
94
|
+
return pinnedSigningFingerprintsFor(await cachedMailboxContacts(mailboxUid), address);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** A sender's signing-key state (`signerKeyStateFor()`) plus what a key-changed notice needs to show and link. */
|
|
98
|
+
export interface SenderKeyState extends SignerKeyState {
|
|
99
|
+
/** The contact holding the first pinned signing key, else the one holding the conflict, else the first match. */
|
|
100
|
+
contactUid?: string;
|
|
101
|
+
/** When the first pinned signing key started being trusted - see `keyPinnedSince()`. */
|
|
102
|
+
pinnedSince?: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** The sender `address`'s signing-key state from `mailboxUid`'s (cached) contacts, for a "signing key changed" comparison
|
|
106
|
+
* or to spot a recorded conflict. Reads stored contacts only. Rejects if they can't be loaded. */
|
|
107
|
+
export async function getSignerKeyState(mailboxUid: string, address: string): Promise<SenderKeyState> {
|
|
108
|
+
const contacts = await cachedMailboxContacts(mailboxUid);
|
|
109
|
+
const state = signerKeyStateFor(contacts, address);
|
|
110
|
+
const wanted = address.trim().toLowerCase();
|
|
111
|
+
const matching = contacts.filter((contact) => contact.emails.some((email) => email.address.trim().toLowerCase() === wanted));
|
|
112
|
+
// `signerKeyStateFor()` keeps the contacts' own key objects, so the holder is found by identity.
|
|
113
|
+
const pinned = state.pinned[0];
|
|
114
|
+
const holder = matching.find((candidate) => (candidate.keys ?? []).includes(pinned));
|
|
115
|
+
const contact =
|
|
116
|
+
holder ??
|
|
117
|
+
matching.find((candidate) => (candidate.keyConflicts ?? []).some((conflict) => conflict.useType === "sign")) ??
|
|
118
|
+
matching[0];
|
|
119
|
+
return {
|
|
120
|
+
...state,
|
|
121
|
+
...(contact ? { contactUid: contact.uid } : {}),
|
|
122
|
+
...(holder ? { pinnedSince: keyPinnedSince(holder, pinned) } : {}),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* The web client's side of verification seals (`@rapidmx/react-shared`'s `crypto/verificationSeal.ts`): the vault's
|
|
7
|
+
* current `masterKeyGeneration` a seal is checked and written under, and best-effort seal writes.
|
|
8
|
+
*
|
|
9
|
+
* **Vault generation.** `getVaultGeneration()` reads `KeyVault.masterKeyGeneration` once per mailbox and reuses it for
|
|
10
|
+
* `VAULT_GENERATION_TTL_MS`; a failed read isn't cached. A vault that doesn't report a non-negative integer generation
|
|
11
|
+
* (a server predating it) counts as unavailable, and callers then evaluate without seals at all. The cache is dropped
|
|
12
|
+
* whenever a key session locks (subscribed on first use), so a rekey followed by a re-unlock is picked up.
|
|
13
|
+
*
|
|
14
|
+
* **Writes.** `sendVerificationSeal()` stores `sealToWrite` with `setMessageVerificationSeal()` and never rejects. Each
|
|
15
|
+
* message is written at most once per master key generation per page session - a seal carries the time it was built,
|
|
16
|
+
* so every evaluation of the same message produces a different one, and sending each would only draw 409s. A `409`
|
|
17
|
+
* (the server kept its seal), `400`, `403` or `404` is final; any other failure (a network error) lets a later
|
|
18
|
+
* evaluation try again, never a retry loop. A stored seal is remembered (`currentVerificationSeal()`) so a message
|
|
19
|
+
* reopened before its list copy is refreshed opens that seal instead of building another.
|
|
20
|
+
*/
|
|
21
|
+
import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
|
|
22
|
+
import { getKeyVault } from "@rapidmx/react-shared/crypto/keyvaultApi.js";
|
|
23
|
+
import { subscribeKeySession } from "@rapidmx/react-shared/crypto/keySession.js";
|
|
24
|
+
import { type Message, setMessageVerificationSeal } from "@rapidmx/react-shared/mail/mailApi.js";
|
|
25
|
+
import type { SealToWrite } from "@rapidmx/react-shared/crypto/messageSecurity.js";
|
|
26
|
+
|
|
27
|
+
/** How long one mailbox's vault generation is reused before it is read again. */
|
|
28
|
+
export const VAULT_GENERATION_TTL_MS = 60_000;
|
|
29
|
+
|
|
30
|
+
/** Statuses after which a seal write is never attempted again for that message and generation. */
|
|
31
|
+
const FINAL_WRITE_STATUSES = new Set([400, 403, 404, 409]);
|
|
32
|
+
|
|
33
|
+
const generationCache = new Map<string, { loadedAt: number; generation: Promise<number | undefined> }>();
|
|
34
|
+
/** `messageUid:generation` for every write sent (or in flight) this session. */
|
|
35
|
+
const attemptedWrites = new Set<string>();
|
|
36
|
+
/** Seals this session stored, by message uid. */
|
|
37
|
+
const storedSeals = new Map<string, SealToWrite>();
|
|
38
|
+
|
|
39
|
+
let lockSubscribed = false;
|
|
40
|
+
|
|
41
|
+
/** Forgets the cached vault generations and this session's seal writes - in tests. */
|
|
42
|
+
export function clearVerificationSealCache(): void {
|
|
43
|
+
generationCache.clear();
|
|
44
|
+
attemptedWrites.clear();
|
|
45
|
+
storedSeals.clear();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function subscribeToLocksOnce(): void {
|
|
49
|
+
if (lockSubscribed) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
lockSubscribed = true;
|
|
53
|
+
subscribeKeySession((event) => {
|
|
54
|
+
if (event.state === "locked") {
|
|
55
|
+
generationCache.clear();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Reads `mailboxUid`'s current vault `masterKeyGeneration`, uncached: `undefined` when the vault can't be read or
|
|
61
|
+
* reports none. Never rejects. */
|
|
62
|
+
export async function readVaultGeneration(mailboxUid: string): Promise<number | undefined> {
|
|
63
|
+
try {
|
|
64
|
+
const { masterKeyGeneration } = await getKeyVault(mailboxUid);
|
|
65
|
+
return Number.isSafeInteger(masterKeyGeneration) && masterKeyGeneration! >= 0 ? masterKeyGeneration : undefined;
|
|
66
|
+
} catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** `mailboxUid`'s current vault `masterKeyGeneration`, or `undefined` when it can't be read. Never rejects. */
|
|
72
|
+
export function getVaultGeneration(mailboxUid: string): Promise<number | undefined> {
|
|
73
|
+
subscribeToLocksOnce();
|
|
74
|
+
const entry = generationCache.get(mailboxUid);
|
|
75
|
+
if (entry && Date.now() - entry.loadedAt <= VAULT_GENERATION_TTL_MS) {
|
|
76
|
+
return entry.generation;
|
|
77
|
+
}
|
|
78
|
+
const created = { loadedAt: Date.now(), generation: readVaultGeneration(mailboxUid) };
|
|
79
|
+
generationCache.set(mailboxUid, created);
|
|
80
|
+
void created.generation.then((generation) => {
|
|
81
|
+
// Only a readable generation is reused; an unavailable one is read again next time.
|
|
82
|
+
if (generation === undefined && generationCache.get(mailboxUid) === created) {
|
|
83
|
+
generationCache.delete(mailboxUid);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return created.generation;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The seal to check `message` against: the one this session stored for it when that is newer than the message's own
|
|
90
|
+
* copy (which may predate the write), else the message's `verificationSeal`/`verificationSealGeneration`. */
|
|
91
|
+
export function currentVerificationSeal(message: Pick<Message, "uid" | "verificationSeal" | "verificationSealGeneration">): {
|
|
92
|
+
seal?: string;
|
|
93
|
+
sealGeneration?: number;
|
|
94
|
+
} {
|
|
95
|
+
const stored = storedSeals.get(message.uid);
|
|
96
|
+
if (stored && (message.verificationSealGeneration === undefined || stored.masterKeyGeneration > message.verificationSealGeneration)) {
|
|
97
|
+
return { seal: stored.seal, sealGeneration: stored.masterKeyGeneration };
|
|
98
|
+
}
|
|
99
|
+
return { seal: message.verificationSeal, sealGeneration: message.verificationSealGeneration };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Whether `sendVerificationSeal()` would still send a seal for `messageUid` at `generation`. */
|
|
103
|
+
export function verificationSealPending(messageUid: string, generation: number): boolean {
|
|
104
|
+
return !attemptedWrites.has(`${messageUid}:${generation}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Stores `sealToWrite` on `messageUid`, best effort - see this module's doc comment. Resolves `true` when a request was
|
|
108
|
+
* sent, `false` when the write was skipped as already attempted. Never rejects. */
|
|
109
|
+
export async function sendVerificationSeal(messageUid: string, sealToWrite: SealToWrite): Promise<boolean> {
|
|
110
|
+
const key = `${messageUid}:${sealToWrite.masterKeyGeneration}`;
|
|
111
|
+
if (attemptedWrites.has(key)) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
attemptedWrites.add(key);
|
|
115
|
+
try {
|
|
116
|
+
await setMessageVerificationSeal(messageUid, sealToWrite.seal, sealToWrite.masterKeyGeneration);
|
|
117
|
+
storedSeals.set(messageUid, sealToWrite);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
// `VerificationSealConflictError` is an `ApiRequestError` with status 409.
|
|
120
|
+
if (!(err instanceof ApiRequestError && FINAL_WRITE_STATUSES.has(err.status))) {
|
|
121
|
+
attemptedWrites.delete(key);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* Which of the caller's accessible mailboxes they can actually create things in (send from, create
|
|
7
|
+
* events/contacts/to-dos in). `listMailboxes()` returns view-only shares too, and `Mailbox` itself carries
|
|
8
|
+
* no per-caller access role, so a "viewer" delegate used to be offered mailboxes every create would 403 in.
|
|
9
|
+
*
|
|
10
|
+
* The signal: an owned mailbox (or any mailbox, for a trusted caller) is always writable; for any other,
|
|
11
|
+
* `getMyMailboxAccess()`'s `canCreate` - the server's own ACL evaluation of the exact action a create needs.
|
|
12
|
+
* One request per mailbox per page load: results are cached in a module-level map, with concurrent callers
|
|
13
|
+
* sharing one in-flight request. A failure (network, an older server without that route) is "unknown" and
|
|
14
|
+
* isn't cached: the server still enforces access on the create itself, and hiding a usable mailbox over a
|
|
15
|
+
* transient error would be worse than offering one that later errors.
|
|
16
|
+
*
|
|
17
|
+
* Nothing waits on these checks: pickers list every mailbox straight away and drop view-only ones as each
|
|
18
|
+
* answer arrives.
|
|
19
|
+
*/
|
|
20
|
+
import { useEffect, useMemo, useState } from "react";
|
|
21
|
+
import type { Mailbox } from "@rapidmx/react-shared/mail/mailApi.js";
|
|
22
|
+
import { getMyMailboxAccess } from "@rapidmx/react-shared/mail/mailboxAccessApi.js";
|
|
23
|
+
|
|
24
|
+
/** `true` writable, `false` known view-only, `undefined` couldn't tell (treated as writable). */
|
|
25
|
+
export type MailboxWritability = boolean | undefined;
|
|
26
|
+
|
|
27
|
+
const inFlight = new Map<string, Promise<MailboxWritability>>();
|
|
28
|
+
const settled = new Map<string, boolean>();
|
|
29
|
+
|
|
30
|
+
/** Forgets every cached answer - for tests, and anything that changes the caller's access mid-session. */
|
|
31
|
+
export function clearMailboxWritabilityCache(): void {
|
|
32
|
+
inFlight.clear();
|
|
33
|
+
settled.clear();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isImplicitlyWritable(mailbox: Mailbox, userUid: string | undefined, trusted: boolean | undefined): boolean {
|
|
37
|
+
return !!trusted || (!!userUid && mailbox.ownerUserUid === userUid);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The already-known answer for `mailbox`, without making a request. */
|
|
41
|
+
export function peekMailboxWritability(mailbox: Mailbox, userUid: string | undefined, trusted?: boolean): MailboxWritability {
|
|
42
|
+
return isImplicitlyWritable(mailbox, userUid, trusted) ? true : settled.get(mailbox.uid);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Whether the caller can create items in `mailbox`. Never rejects. */
|
|
46
|
+
export function getMailboxWritability(mailbox: Mailbox, userUid: string | undefined, trusted?: boolean): Promise<MailboxWritability> {
|
|
47
|
+
const known = peekMailboxWritability(mailbox, userUid, trusted);
|
|
48
|
+
if (known !== undefined) {
|
|
49
|
+
return Promise.resolve(known);
|
|
50
|
+
}
|
|
51
|
+
let request = inFlight.get(mailbox.uid);
|
|
52
|
+
if (!request) {
|
|
53
|
+
request = getMyMailboxAccess(mailbox.uid).then(
|
|
54
|
+
(access) => {
|
|
55
|
+
settled.set(mailbox.uid, access.canCreate);
|
|
56
|
+
inFlight.delete(mailbox.uid);
|
|
57
|
+
return access.canCreate;
|
|
58
|
+
},
|
|
59
|
+
() => {
|
|
60
|
+
// Not cached - a later check may succeed.
|
|
61
|
+
inFlight.delete(mailbox.uid);
|
|
62
|
+
return undefined;
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
inFlight.set(mailbox.uid, request);
|
|
66
|
+
}
|
|
67
|
+
return request;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Per-mailbox writability answers for `mailboxes`, filled in as each one arrives (already-known answers are
|
|
71
|
+
* present from the first render). */
|
|
72
|
+
export function useMailboxWritability(mailboxes: Mailbox[], userUid: string | undefined, trusted?: boolean): Record<string, MailboxWritability> {
|
|
73
|
+
const [answers, setAnswers] = useState<Record<string, MailboxWritability>>({});
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
let cancelled = false;
|
|
76
|
+
for (const mailbox of mailboxes) {
|
|
77
|
+
void getMailboxWritability(mailbox, userUid, trusted).then((writable) => {
|
|
78
|
+
if (!cancelled) {
|
|
79
|
+
setAnswers((prev) => ({ ...prev, [mailbox.uid]: writable }));
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return () => {
|
|
84
|
+
cancelled = true;
|
|
85
|
+
};
|
|
86
|
+
}, [mailboxes, userUid, trusted]);
|
|
87
|
+
return useMemo(() => {
|
|
88
|
+
const merged: Record<string, MailboxWritability> = {};
|
|
89
|
+
for (const mailbox of mailboxes) {
|
|
90
|
+
merged[mailbox.uid] = answers[mailbox.uid] ?? peekMailboxWritability(mailbox, userUid, trusted);
|
|
91
|
+
}
|
|
92
|
+
return merged;
|
|
93
|
+
}, [answers, mailboxes, userUid, trusted]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** `mailboxes` minus any known to be view-only, always keeping `keepUid` (the picker's current/default value,
|
|
97
|
+
* so the control never shows a value missing from its own options). Lists everything until told otherwise. */
|
|
98
|
+
export function useWritableMailboxes(mailboxes: Mailbox[], userUid: string | undefined, keepUid?: string, trusted?: boolean): Mailbox[] {
|
|
99
|
+
const writability = useMailboxWritability(mailboxes, userUid, trusted);
|
|
100
|
+
return useMemo(() => mailboxes.filter((mb) => mb.uid === keepUid || writability[mb.uid] !== false), [mailboxes, writability, keepUid]);
|
|
101
|
+
}
|