internal: change password preprocessing step (#2347)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { AsymmetricMessageServiceInterface } from './../AsymmetricMessage/AsymmetricMessageServiceInterface'
|
||||
import { SyncOptions } from './../Sync/SyncOptions'
|
||||
import { ImportDataReturnType } from './../Mutator/ImportDataUseCase'
|
||||
import { ChallengeServiceInterface } from './../Challenge/ChallengeServiceInterface'
|
||||
@@ -102,6 +103,8 @@ export interface ApplicationInterface {
|
||||
get vaults(): VaultServiceInterface
|
||||
get challenges(): ChallengeServiceInterface
|
||||
get alerts(): AlertService
|
||||
get asymmetric(): AsymmetricMessageServiceInterface
|
||||
|
||||
readonly identifier: ApplicationIdentifier
|
||||
readonly platform: Platform
|
||||
deviceInterface: DeviceInterface
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MutatorClientInterface } from './../Mutator/MutatorClientInterface'
|
||||
import { ContactServiceInterface } from './../Contacts/ContactServiceInterface'
|
||||
import { AsymmetricMessageServerHash, ClientDisplayableError } from '@standardnotes/responses'
|
||||
import { AsymmetricMessageServerHash, ClientDisplayableError, isClientDisplayableError } from '@standardnotes/responses'
|
||||
import { SyncEvent, SyncEventReceivedAsymmetricMessagesData } from '../Event/SyncEvent'
|
||||
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
|
||||
import { InternalEventHandlerInterface } from '../Internal/InternalEventHandlerInterface'
|
||||
@@ -27,8 +27,12 @@ import { SendOwnContactChangeMessage } from './UseCase/SendOwnContactChangeMessa
|
||||
import { GetOutboundAsymmetricMessages } from './UseCase/GetOutboundAsymmetricMessages'
|
||||
import { GetInboundAsymmetricMessages } from './UseCase/GetInboundAsymmetricMessages'
|
||||
import { GetVaultUseCase } from '../Vaults/UseCase/GetVault'
|
||||
import { AsymmetricMessageServiceInterface } from './AsymmetricMessageServiceInterface'
|
||||
|
||||
export class AsymmetricMessageService extends AbstractService implements InternalEventHandlerInterface {
|
||||
export class AsymmetricMessageService
|
||||
extends AbstractService
|
||||
implements AsymmetricMessageServiceInterface, InternalEventHandlerInterface
|
||||
{
|
||||
private messageServer: AsymmetricMessageServer
|
||||
|
||||
constructor(
|
||||
@@ -69,7 +73,16 @@ export class AsymmetricMessageService extends AbstractService implements Interna
|
||||
return usecase.execute()
|
||||
}
|
||||
|
||||
async sendOwnContactChangeEventToAllContacts(data: UserKeyPairChangedEventData): Promise<void> {
|
||||
public async downloadAndProcessInboundMessages(): Promise<void> {
|
||||
const messages = await this.getInboundMessages()
|
||||
if (isClientDisplayableError(messages)) {
|
||||
return
|
||||
}
|
||||
|
||||
await this.handleRemoteReceivedAsymmetricMessages(messages)
|
||||
}
|
||||
|
||||
private async sendOwnContactChangeEventToAllContacts(data: UserKeyPairChangedEventData): Promise<void> {
|
||||
if (!data.oldKeyPair || !data.oldSigningKeyPair) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { AsymmetricMessageServerHash, ClientDisplayableError } from '@standardnotes/responses'
|
||||
|
||||
export interface AsymmetricMessageServiceInterface {
|
||||
getOutboundMessages(): Promise<AsymmetricMessageServerHash[] | ClientDisplayableError>
|
||||
getInboundMessages(): Promise<AsymmetricMessageServerHash[] | ClientDisplayableError>
|
||||
downloadAndProcessInboundMessages(): Promise<void>
|
||||
}
|
||||
@@ -237,7 +237,7 @@ export class ContactService
|
||||
}
|
||||
|
||||
findTrustedContactForInvite(invite: SharedVaultInviteServerHash): TrustedContactInterface | undefined {
|
||||
return this.findTrustedContact(invite.user_uuid)
|
||||
return this.findTrustedContact(invite.sender_uuid)
|
||||
}
|
||||
|
||||
getCollaborationIDForTrustedContact(contact: TrustedContactInterface): string {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { PublicKeySet } from '@standardnotes/encryption'
|
||||
|
||||
export class SelfContactManager {
|
||||
public selfContact?: TrustedContactInterface
|
||||
private shouldReloadSelfContact = true
|
||||
|
||||
private isReloadingSelfContact = false
|
||||
private eventDisposers: (() => void)[] = []
|
||||
|
||||
@@ -32,16 +32,14 @@ export class SelfContactManager {
|
||||
private session: SessionsClientInterface,
|
||||
private singletons: SingletonManagerInterface,
|
||||
) {
|
||||
this.eventDisposers.push(
|
||||
items.addObserver(ContentType.TrustedContact, () => {
|
||||
this.shouldReloadSelfContact = true
|
||||
}),
|
||||
)
|
||||
|
||||
this.eventDisposers.push(
|
||||
sync.addEventObserver((event) => {
|
||||
if (event === SyncEvent.SyncCompletedWithAllItemsUploaded || event === SyncEvent.LocalDataIncrementalLoad) {
|
||||
void this.reloadSelfContact()
|
||||
if (event === SyncEvent.LocalDataIncrementalLoad) {
|
||||
this.loadSelfContactFromDatabase()
|
||||
}
|
||||
|
||||
if (event === SyncEvent.SyncCompletedWithAllItemsUploaded) {
|
||||
void this.reloadSelfContactAndCreateIfNecessary()
|
||||
}
|
||||
}),
|
||||
)
|
||||
@@ -49,13 +47,21 @@ export class SelfContactManager {
|
||||
|
||||
public async handleApplicationStage(stage: ApplicationStage): Promise<void> {
|
||||
if (stage === ApplicationStage.LoadedDatabase_12) {
|
||||
this.selfContact = this.singletons.findSingleton<TrustedContactInterface>(
|
||||
ContentType.UserPrefs,
|
||||
TrustedContact.singletonPredicate,
|
||||
)
|
||||
this.loadSelfContactFromDatabase()
|
||||
}
|
||||
}
|
||||
|
||||
private loadSelfContactFromDatabase(): void {
|
||||
if (this.selfContact) {
|
||||
return
|
||||
}
|
||||
|
||||
this.selfContact = this.singletons.findSingleton<TrustedContactInterface>(
|
||||
ContentType.TrustedContact,
|
||||
TrustedContact.singletonPredicate,
|
||||
)
|
||||
}
|
||||
|
||||
public async updateWithNewPublicKeySet(publicKeySet: PublicKeySet) {
|
||||
if (!InternalFeatureService.get().isFeatureEnabled(InternalFeature.Vaults)) {
|
||||
return
|
||||
@@ -74,12 +80,16 @@ export class SelfContactManager {
|
||||
})
|
||||
}
|
||||
|
||||
private async reloadSelfContact() {
|
||||
private async reloadSelfContactAndCreateIfNecessary() {
|
||||
if (!InternalFeatureService.get().isFeatureEnabled(InternalFeature.Vaults)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.shouldReloadSelfContact || this.isReloadingSelfContact) {
|
||||
if (this.selfContact) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.isReloadingSelfContact) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,17 +115,13 @@ export class SelfContactManager {
|
||||
}),
|
||||
}
|
||||
|
||||
try {
|
||||
this.selfContact = await this.singletons.findOrCreateSingleton<TrustedContactContent, TrustedContact>(
|
||||
TrustedContact.singletonPredicate,
|
||||
ContentType.TrustedContact,
|
||||
FillItemContent<TrustedContactContent>(content),
|
||||
)
|
||||
this.selfContact = await this.singletons.findOrCreateSingleton<TrustedContactContent, TrustedContact>(
|
||||
TrustedContact.singletonPredicate,
|
||||
ContentType.TrustedContact,
|
||||
FillItemContent<TrustedContactContent>(content),
|
||||
)
|
||||
|
||||
this.shouldReloadSelfContact = false
|
||||
} finally {
|
||||
this.isReloadingSelfContact = false
|
||||
}
|
||||
this.isReloadingSelfContact = false
|
||||
}
|
||||
|
||||
deinit() {
|
||||
|
||||
@@ -283,6 +283,7 @@ export class EncryptionService
|
||||
const usecase = new CreateNewItemsKeyWithRollbackUseCase(
|
||||
this.mutator,
|
||||
this.items,
|
||||
this.storage,
|
||||
this.operators,
|
||||
this.rootKeyManager,
|
||||
)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { StorageServiceInterface } from './../../../Storage/StorageServiceInterface'
|
||||
import { ItemsKeyMutator, OperatorManager, findDefaultItemsKey } from '@standardnotes/encryption'
|
||||
import { MutatorClientInterface } from '../../../Mutator/MutatorClientInterface'
|
||||
import { ItemManagerInterface } from '../../../Item/ItemManagerInterface'
|
||||
import { RootKeyManager } from '../../RootKey/RootKeyManager'
|
||||
import { CreateNewDefaultItemsKeyUseCase } from './CreateNewDefaultItemsKey'
|
||||
import { RemoveItemsLocallyUseCase } from '../../../UseCase/RemoveItemsLocally'
|
||||
|
||||
export class CreateNewItemsKeyWithRollbackUseCase {
|
||||
private createDefaultItemsKeyUseCase = new CreateNewDefaultItemsKeyUseCase(
|
||||
@@ -12,9 +14,12 @@ export class CreateNewItemsKeyWithRollbackUseCase {
|
||||
this.rootKeyManager,
|
||||
)
|
||||
|
||||
private removeItemsLocallyUsecase = new RemoveItemsLocallyUseCase(this.items, this.storage)
|
||||
|
||||
constructor(
|
||||
private mutator: MutatorClientInterface,
|
||||
private items: ItemManagerInterface,
|
||||
private storage: StorageServiceInterface,
|
||||
private operatorManager: OperatorManager,
|
||||
private rootKeyManager: RootKeyManager,
|
||||
) {}
|
||||
@@ -24,7 +29,7 @@ export class CreateNewItemsKeyWithRollbackUseCase {
|
||||
const newDefaultItemsKey = await this.createDefaultItemsKeyUseCase.execute()
|
||||
|
||||
const rollback = async () => {
|
||||
await this.mutator.setItemToBeDeleted(newDefaultItemsKey)
|
||||
await this.removeItemsLocallyUsecase.execute([newDefaultItemsKey])
|
||||
|
||||
if (currentDefaultItemsKey) {
|
||||
await this.mutator.changeItem<ItemsKeyMutator>(currentDefaultItemsKey, (mutator) => {
|
||||
|
||||
@@ -111,7 +111,9 @@ export class SharedVaultService
|
||||
)
|
||||
|
||||
this.eventDisposers.push(
|
||||
items.addObserver<TrustedContactInterface>(ContentType.TrustedContact, ({ changed, inserted, source }) => {
|
||||
items.addObserver<TrustedContactInterface>(ContentType.TrustedContact, async ({ changed, inserted, source }) => {
|
||||
await this.reprocessCachedInvitesTrustStatusAfterTrustedContactsChange()
|
||||
|
||||
if (source === PayloadEmitSource.LocalChanged && inserted.length > 0) {
|
||||
void this.handleCreationOfNewTrustedContacts(inserted)
|
||||
}
|
||||
@@ -250,8 +252,6 @@ export class SharedVaultService
|
||||
}
|
||||
|
||||
private async handleTrustedContactsChange(contacts: TrustedContactInterface[]): Promise<void> {
|
||||
await this.reprocessCachedInvitesTrustStatusAfterTrustedContactsChange()
|
||||
|
||||
for (const contact of contacts) {
|
||||
await this.shareContactWithUserAdministeredSharedVaults(contact)
|
||||
}
|
||||
@@ -328,28 +328,9 @@ export class SharedVaultService
|
||||
}
|
||||
|
||||
private async reprocessCachedInvitesTrustStatusAfterTrustedContactsChange(): Promise<void> {
|
||||
const cachedInvites = this.getCachedPendingInviteRecords()
|
||||
const cachedInvites = this.getCachedPendingInviteRecords().map((record) => record.invite)
|
||||
|
||||
for (const record of cachedInvites) {
|
||||
if (record.trusted) {
|
||||
continue
|
||||
}
|
||||
|
||||
const trustedMessageUseCase = new GetAsymmetricMessageTrustedPayload<AsymmetricMessageSharedVaultInvite>(
|
||||
this.encryption,
|
||||
this.contacts,
|
||||
)
|
||||
|
||||
const trustedMessage = trustedMessageUseCase.execute({
|
||||
message: record.invite,
|
||||
privateKey: this.encryption.getKeyPair().privateKey,
|
||||
})
|
||||
|
||||
if (trustedMessage) {
|
||||
record.message = trustedMessage
|
||||
record.trusted = true
|
||||
}
|
||||
}
|
||||
await this.processInboundInvites(cachedInvites)
|
||||
}
|
||||
|
||||
private async processInboundInvites(invites: SharedVaultInviteServerHash[]): Promise<void> {
|
||||
|
||||
@@ -3,10 +3,12 @@ import { StorageServiceInterface } from '../../Storage/StorageServiceInterface'
|
||||
import { EncryptionProviderInterface } from '@standardnotes/encryption'
|
||||
import { ItemManagerInterface } from '../../Item/ItemManagerInterface'
|
||||
import { AnyItemInterface, VaultListingInterface } from '@standardnotes/models'
|
||||
import { Uuids } from '@standardnotes/utils'
|
||||
import { MutatorClientInterface } from '../../Mutator/MutatorClientInterface'
|
||||
import { RemoveItemsLocallyUseCase } from '../../UseCase/RemoveItemsLocally'
|
||||
|
||||
export class DeleteExternalSharedVaultUseCase {
|
||||
private removeItemsLocallyUsecase = new RemoveItemsLocallyUseCase(this.items, this.storage)
|
||||
|
||||
constructor(
|
||||
private items: ItemManagerInterface,
|
||||
private mutator: MutatorClientInterface,
|
||||
@@ -28,15 +30,13 @@ export class DeleteExternalSharedVaultUseCase {
|
||||
* The data will be removed locally without syncing the items
|
||||
*/
|
||||
private async deleteDataSharedByVaultUsers(vault: VaultListingInterface): Promise<void> {
|
||||
const vaultItems = this.items
|
||||
.allTrackedItems()
|
||||
.filter((item) => item.key_system_identifier === vault.systemIdentifier)
|
||||
this.items.removeItemsLocally(vaultItems as AnyItemInterface[])
|
||||
const vaultItems = <AnyItemInterface[]>(
|
||||
this.items.allTrackedItems().filter((item) => item.key_system_identifier === vault.systemIdentifier)
|
||||
)
|
||||
|
||||
const itemsKeys = this.encryption.keys.getKeySystemItemsKeys(vault.systemIdentifier)
|
||||
this.items.removeItemsLocally(itemsKeys)
|
||||
|
||||
await this.storage.deletePayloadsWithUuids([...Uuids(vaultItems), ...Uuids(itemsKeys)])
|
||||
await this.removeItemsLocallyUsecase.execute([...vaultItems, ...itemsKeys])
|
||||
}
|
||||
|
||||
private async deleteDataOwnedByThisUser(vault: VaultListingInterface): Promise<void> {
|
||||
|
||||
14
packages/services/src/Domain/UseCase/RemoveItemsLocally.ts
Normal file
14
packages/services/src/Domain/UseCase/RemoveItemsLocally.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { StorageServiceInterface } from '../Storage/StorageServiceInterface'
|
||||
import { ItemManagerInterface } from '../Item/ItemManagerInterface'
|
||||
import { AnyItemInterface } from '@standardnotes/models'
|
||||
import { Uuids } from '@standardnotes/utils'
|
||||
|
||||
export class RemoveItemsLocallyUseCase {
|
||||
constructor(private readonly items: ItemManagerInterface, private readonly storage: StorageServiceInterface) {}
|
||||
|
||||
async execute(items: AnyItemInterface[]): Promise<void> {
|
||||
this.items.removeItemsLocally(items)
|
||||
|
||||
await this.storage.deletePayloadsWithUuids(Uuids(items))
|
||||
}
|
||||
}
|
||||
@@ -589,7 +589,6 @@ export class UserService
|
||||
|
||||
this.lockSyncing()
|
||||
|
||||
/** Now, change the credentials on the server. Roll back on failure */
|
||||
const { response } = await this.sessionManager.changeCredentials({
|
||||
currentServerPassword: currentRootKey.serverPassword as string,
|
||||
newRootKey: newRootKey,
|
||||
|
||||
@@ -9,6 +9,7 @@ export * from './Application/DeinitMode'
|
||||
export * from './Application/DeinitSource'
|
||||
|
||||
export * from './AsymmetricMessage/AsymmetricMessageService'
|
||||
export * from './AsymmetricMessage/AsymmetricMessageServiceInterface'
|
||||
|
||||
export * from './Auth/AuthClientInterface'
|
||||
export * from './Auth/AuthManager'
|
||||
|
||||
Reference in New Issue
Block a user