internal: change password preprocessing step (#2347)
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { Fragment, FunctionComponent, useState } from 'react'
|
||||
import { Fragment, FunctionComponent, useEffect, useState } from 'react'
|
||||
import { Text, Title, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
|
||||
import {
|
||||
ButtonType,
|
||||
ClientDisplayableError,
|
||||
ContentType,
|
||||
DisplayStringForContentType,
|
||||
EncryptedItemInterface,
|
||||
} from '@standardnotes/snjs'
|
||||
@@ -12,13 +12,18 @@ import Button from '@/Components/Button/Button'
|
||||
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
|
||||
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
|
||||
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
|
||||
import { ErrorCircle } from '@/Components/UIElements/ErrorCircle'
|
||||
import { useApplication } from '@/Components/ApplicationProvider'
|
||||
|
||||
type Props = { viewControllerManager: ViewControllerManager }
|
||||
const ErroredItems: FunctionComponent = () => {
|
||||
const application = useApplication()
|
||||
const [erroredItems, setErroredItems] = useState(application.items.invalidNonVaultedItems)
|
||||
|
||||
const ErroredItems: FunctionComponent<Props> = ({ viewControllerManager }: Props) => {
|
||||
const app = viewControllerManager.application
|
||||
|
||||
const [erroredItems, setErroredItems] = useState(app.items.invalidNonVaultedItems)
|
||||
useEffect(() => {
|
||||
return application.streamItems(ContentType.Any, () => {
|
||||
setErroredItems(application.items.invalidNonVaultedItems)
|
||||
})
|
||||
}, [application])
|
||||
|
||||
const getContentTypeDisplay = (item: EncryptedItemInterface): string => {
|
||||
const display = DisplayStringForContentType(item.content_type)
|
||||
@@ -34,7 +39,7 @@ const ErroredItems: FunctionComponent<Props> = ({ viewControllerManager }: Props
|
||||
}
|
||||
|
||||
const deleteItems = async (items: EncryptedItemInterface[]): Promise<void> => {
|
||||
const confirmed = await app.alertService.confirm(
|
||||
const confirmed = await application.alertService.confirm(
|
||||
`Are you sure you want to permanently delete ${items.length} item(s)?`,
|
||||
undefined,
|
||||
'Delete',
|
||||
@@ -44,30 +49,35 @@ const ErroredItems: FunctionComponent<Props> = ({ viewControllerManager }: Props
|
||||
return
|
||||
}
|
||||
|
||||
void app.mutator.deleteItems(items).then(() => {
|
||||
void app.sync.sync()
|
||||
void application.mutator.deleteItems(items).then(() => {
|
||||
void application.sync.sync()
|
||||
})
|
||||
|
||||
setErroredItems(app.items.invalidItems)
|
||||
setErroredItems(application.items.invalidItems)
|
||||
}
|
||||
|
||||
const attemptDecryption = (item: EncryptedItemInterface): void => {
|
||||
const errorOrTrue = app.canAttemptDecryptionOfItem(item)
|
||||
const errorOrTrue = application.canAttemptDecryptionOfItem(item)
|
||||
|
||||
if (errorOrTrue instanceof ClientDisplayableError) {
|
||||
void app.alertService.showErrorAlert(errorOrTrue)
|
||||
void application.alertService.showErrorAlert(errorOrTrue)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
app.presentKeyRecoveryWizard()
|
||||
application.presentKeyRecoveryWizard()
|
||||
}
|
||||
|
||||
if (erroredItems.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<PreferencesGroup>
|
||||
<PreferencesSegment>
|
||||
<Title>
|
||||
Error decrypting items <span className="ml-1 text-warning">⚠️</span>
|
||||
<Title className="flex flex-row items-center gap-2">
|
||||
<ErrorCircle />
|
||||
Error decrypting items
|
||||
</Title>
|
||||
<Text>{`${erroredItems.length} items are errored and could not be decrypted.`}</Text>
|
||||
<div className="flex">
|
||||
@@ -75,7 +85,7 @@ const ErroredItems: FunctionComponent<Props> = ({ viewControllerManager }: Props
|
||||
className="mt-3 mr-2 min-w-20"
|
||||
label="Export all"
|
||||
onClick={() => {
|
||||
void app.getArchiveService().downloadEncryptedItems(erroredItems)
|
||||
void application.getArchiveService().downloadEncryptedItems(erroredItems)
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
@@ -95,10 +105,8 @@ const ErroredItems: FunctionComponent<Props> = ({ viewControllerManager }: Props
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<Subtitle>{`${getContentTypeDisplay(item)} created on ${item.createdAtString}`}</Subtitle>
|
||||
<Text>
|
||||
<div>Item ID: {item.uuid}</div>
|
||||
<div>Last Modified: {item.updatedAtString}</div>
|
||||
</Text>
|
||||
<Text>Item ID: {item.uuid}</Text>
|
||||
<Text>Last Modified: {item.updatedAtString}</Text>
|
||||
<div className="flex">
|
||||
<Button
|
||||
className="mt-3 mr-2 min-w-20"
|
||||
@@ -111,7 +119,7 @@ const ErroredItems: FunctionComponent<Props> = ({ viewControllerManager }: Props
|
||||
className="mt-3 mr-2 min-w-20"
|
||||
label="Export"
|
||||
onClick={() => {
|
||||
void app.getArchiveService().downloadEncryptedItem(item)
|
||||
void application.getArchiveService().downloadEncryptedItem(item)
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
|
||||
@@ -30,9 +30,7 @@ const Security: FunctionComponent<SecurityProps> = (props) => {
|
||||
return (
|
||||
<PreferencesPane>
|
||||
<Encryption viewControllerManager={props.viewControllerManager} />
|
||||
{props.application.items.invalidNonVaultedItems.length > 0 && (
|
||||
<ErroredItems viewControllerManager={props.viewControllerManager} />
|
||||
)}
|
||||
{props.application.items.invalidNonVaultedItems.length > 0 && <ErroredItems />}
|
||||
<Protections application={props.application} />
|
||||
<TwoFactorAuthWrapper
|
||||
mfaProvider={props.mfaProvider}
|
||||
|
||||
@@ -25,7 +25,7 @@ const ContactItem = ({ contact }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<ModalOverlay isOpen={isContactModalOpen} close={closeContactModal}>
|
||||
<EditContactModal editContactUuid={contact.uuid} onCloseDialog={closeContactModal} />
|
||||
<EditContactModal editContactUuid={contact.contactUuid} onCloseDialog={closeContactModal} />
|
||||
</ModalOverlay>
|
||||
|
||||
<div className="bg-gray-100 flex flex-row gap-3.5 rounded-lg py-2.5 px-3.5 shadow-md">
|
||||
|
||||
@@ -5,33 +5,36 @@ import ModalOverlay from '@/Components/Modal/ModalOverlay'
|
||||
import { PendingSharedVaultInviteRecord } from '@standardnotes/snjs'
|
||||
import { useCallback, useState } from 'react'
|
||||
import EditContactModal from '../Contacts/EditContactModal'
|
||||
import { CheckmarkCircle } from '../../../../UIElements/CheckmarkCircle'
|
||||
|
||||
type Props = {
|
||||
invite: PendingSharedVaultInviteRecord
|
||||
inviteRecord: PendingSharedVaultInviteRecord
|
||||
}
|
||||
|
||||
const InviteItem = ({ invite }: Props) => {
|
||||
const InviteItem = ({ inviteRecord }: Props) => {
|
||||
const application = useApplication()
|
||||
const [isAddContactModalOpen, setIsAddContactModalOpen] = useState(false)
|
||||
|
||||
const isTrusted = invite.trusted
|
||||
const inviteData = invite.message.data
|
||||
const isTrusted = inviteRecord.trusted
|
||||
const inviteData = inviteRecord.message.data
|
||||
|
||||
const addAsTrustedContact = useCallback(() => {
|
||||
setIsAddContactModalOpen(true)
|
||||
}, [])
|
||||
|
||||
const acceptInvite = useCallback(async () => {
|
||||
await application.sharedVaults.acceptPendingSharedVaultInvite(invite)
|
||||
}, [application.sharedVaults, invite])
|
||||
await application.sharedVaults.acceptPendingSharedVaultInvite(inviteRecord)
|
||||
}, [application.sharedVaults, inviteRecord])
|
||||
|
||||
const closeAddContactModal = () => setIsAddContactModalOpen(false)
|
||||
const collaborationId = application.contacts.getCollaborationIDFromInvite(invite.invite)
|
||||
const collaborationId = application.contacts.getCollaborationIDFromInvite(inviteRecord.invite)
|
||||
|
||||
const trustedContact = application.contacts.findTrustedContactForInvite(inviteRecord.invite)
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalOverlay isOpen={isAddContactModalOpen} close={closeAddContactModal}>
|
||||
<EditContactModal fromInvite={invite} onCloseDialog={closeAddContactModal} />
|
||||
<EditContactModal fromInvite={inviteRecord} onCloseDialog={closeAddContactModal} />
|
||||
</ModalOverlay>
|
||||
|
||||
<div className="bg-gray-100 flex flex-row gap-3.5 rounded-lg py-2.5 px-3.5 shadow-md">
|
||||
@@ -41,9 +44,16 @@ const InviteItem = ({ invite }: Props) => {
|
||||
<span className="mr-auto overflow-hidden text-ellipsis text-sm">
|
||||
Vault Description: {inviteData.metadata.description}
|
||||
</span>
|
||||
<span className="mr-auto overflow-hidden text-ellipsis text-sm">
|
||||
Sender CollaborationID: {collaborationId}
|
||||
</span>
|
||||
{trustedContact ? (
|
||||
<div className="flex flex-row gap-2">
|
||||
<span className="overflow-hidden text-ellipsis text-sm">Trusted Sender: {trustedContact.name}</span>
|
||||
<CheckmarkCircle />
|
||||
</div>
|
||||
) : (
|
||||
<span className="mr-auto overflow-hidden text-ellipsis text-sm">
|
||||
Sender CollaborationID: {collaborationId}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<div className="mt-2.5 flex flex-row">
|
||||
{isTrusted ? (
|
||||
|
||||
@@ -40,31 +40,36 @@ const Vaults = () => {
|
||||
setVaults(vaultService.getVaults())
|
||||
}, [vaultService])
|
||||
|
||||
const fetchInvites = useCallback(async () => {
|
||||
await sharedVaultService.downloadInboundInvites()
|
||||
const invites = sharedVaultService.getCachedPendingInviteRecords()
|
||||
setInvites(invites)
|
||||
const updateInvites = useCallback(async () => {
|
||||
setInvites(sharedVaultService.getCachedPendingInviteRecords())
|
||||
}, [sharedVaultService])
|
||||
|
||||
const updateContacts = useCallback(async () => {
|
||||
setContacts(contactService.getAllContacts())
|
||||
}, [contactService])
|
||||
|
||||
const updateAllData = useCallback(async () => {
|
||||
await Promise.all([updateVaults(), updateInvites(), updateContacts()])
|
||||
}, [updateContacts, updateInvites, updateVaults])
|
||||
|
||||
useEffect(() => {
|
||||
return application.sharedVaults.addEventObserver((event) => {
|
||||
if (event === SharedVaultServiceEvent.SharedVaultStatusChanged) {
|
||||
void fetchInvites()
|
||||
void updateAllData()
|
||||
}
|
||||
})
|
||||
})
|
||||
}, [application.sharedVaults, updateAllData])
|
||||
|
||||
useEffect(() => {
|
||||
return application.streamItems([ContentType.VaultListing, ContentType.TrustedContact], () => {
|
||||
void updateVaults()
|
||||
void fetchInvites()
|
||||
void updateContacts()
|
||||
void updateAllData()
|
||||
})
|
||||
}, [application, updateVaults, fetchInvites, updateContacts])
|
||||
}, [application, updateAllData])
|
||||
|
||||
useEffect(() => {
|
||||
void sharedVaultService.downloadInboundInvites()
|
||||
void updateAllData()
|
||||
}, [updateAllData, sharedVaultService])
|
||||
|
||||
const createNewVault = useCallback(async () => {
|
||||
setIsVaultModalOpen(true)
|
||||
@@ -74,12 +79,6 @@ const Vaults = () => {
|
||||
setIsAddContactModalOpen(true)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
void updateVaults()
|
||||
void fetchInvites()
|
||||
void updateContacts()
|
||||
}, [updateContacts, updateVaults, fetchInvites])
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalOverlay isOpen={isAddContactModalOpen} close={closeAddContactModal}>
|
||||
@@ -95,7 +94,7 @@ const Vaults = () => {
|
||||
<Title>Incoming Invites</Title>
|
||||
<div className="my-2 flex flex-col">
|
||||
{invites.map((invite) => {
|
||||
return <InviteItem invite={invite} key={invite.invite.uuid} />
|
||||
return <InviteItem inviteRecord={invite} key={invite.invite.uuid} />
|
||||
})}
|
||||
</div>
|
||||
</PreferencesSegment>
|
||||
|
||||
@@ -28,9 +28,8 @@ export const VaultModalInvites = ({
|
||||
<div className="mb-3 text-lg">Pending Invites</div>
|
||||
{invites.map((invite) => {
|
||||
const contact = application.contacts.findTrustedContactForInvite(invite)
|
||||
|
||||
return (
|
||||
<div className="bg-gray-100 flex flex-row gap-3.5 rounded-lg py-2.5 px-3.5 shadow-md">
|
||||
<div key={invite.uuid} className="bg-gray-100 flex flex-row gap-3.5 rounded-lg py-2.5 px-3.5 shadow-md">
|
||||
<Icon type={'user'} size="custom" className="mt-2.5 h-5.5 w-5.5 flex-shrink-0" />
|
||||
<div className="flex flex-col gap-2 py-1.5">
|
||||
<span className="mr-auto overflow-hidden text-ellipsis text-base font-bold">
|
||||
|
||||
Reference in New Issue
Block a user