chore: add handling shared vault invites via websockets (#2475)

This commit is contained in:
Karol Sójko
2023-09-01 17:04:32 +02:00
committed by GitHub
parent 318a2caf08
commit 4ca291291c
12 changed files with 47 additions and 35 deletions

View File

@@ -1,6 +1,4 @@
import { AsymmetricMessageServerHash } from '../AsymmetricMessage/AsymmetricMessageServerHash' export interface SharedVaultInviteServerHash {
export interface SharedVaultInviteServerHash extends AsymmetricMessageServerHash {
uuid: string uuid: string
shared_vault_uuid: string shared_vault_uuid: string
user_uuid: string user_uuid: string

View File

@@ -67,3 +67,7 @@ export * from './User/SettingData'
export * from './User/UpdateSettingResponse' export * from './User/UpdateSettingResponse'
export * from './Notification/NotificationServerHash' export * from './Notification/NotificationServerHash'
export * from './SharedVaults/SharedVaultInviteServerHash'
export * from './SharedVaults/SharedVaultServerHash'
export * from './SharedVaults/SharedVaultUserServerHash'

View File

@@ -2,4 +2,5 @@ export enum WebSocketsServiceEvent {
UserRoleMessageReceived = 'WebSocketMessageReceived', UserRoleMessageReceived = 'WebSocketMessageReceived',
NotificationAddedForUser = 'NotificationAddedForUser', NotificationAddedForUser = 'NotificationAddedForUser',
MessageSentToUser = 'MessageSentToUser', MessageSentToUser = 'MessageSentToUser',
UserInvitedToSharedVault = 'UserInvitedToSharedVault',
} }

View File

@@ -71,6 +71,9 @@ export class WebSocketsService extends AbstractService<WebSocketsServiceEvent, D
case 'MESSAGE_SENT_TO_USER': case 'MESSAGE_SENT_TO_USER':
void this.notifyEvent(WebSocketsServiceEvent.MessageSentToUser, eventData) void this.notifyEvent(WebSocketsServiceEvent.MessageSentToUser, eventData)
break break
case 'USER_INVITED_TO_SHARED_VAULT':
void this.notifyEvent(WebSocketsServiceEvent.UserInvitedToSharedVault, eventData)
break
default: default:
break break
} }

View File

@@ -211,7 +211,7 @@ export class AsymmetricMessageService
const result = this._getUntrustedPayload.execute({ const result = this._getUntrustedPayload.execute({
privateKey: keys.getValue().encryption.privateKey, privateKey: keys.getValue().encryption.privateKey,
message, payload: message,
}) })
if (result.isFailed()) { if (result.isFailed()) {
@@ -236,7 +236,7 @@ export class AsymmetricMessageService
privateKey: keys.getValue().encryption.privateKey, privateKey: keys.getValue().encryption.privateKey,
sender: contact.getValue(), sender: contact.getValue(),
ownUserUuid: this.sessions.userUuid, ownUserUuid: this.sessions.userUuid,
message, payload: message,
}) })
if (result.isFailed()) { if (result.isFailed()) {

View File

@@ -18,7 +18,7 @@ describe('GetTrustedPayload', () => {
describe('execute', () => { describe('execute', () => {
const mockDto = { const mockDto = {
privateKey: 'test-private-key', privateKey: 'test-private-key',
message: {} as AsymmetricMessageServerHash, payload: {} as AsymmetricMessageServerHash,
sender: {} as TrustedContactInterface, sender: {} as TrustedContactInterface,
ownUserUuid: 'test-user-uuid', ownUserUuid: 'test-user-uuid',
} }

View File

@@ -1,4 +1,4 @@
import { AsymmetricMessageServerHash } from '@standardnotes/responses' import { AsymmetricMessageServerHash, SharedVaultInviteServerHash } from '@standardnotes/responses'
import { AsymmetricMessagePayload, TrustedContactInterface } from '@standardnotes/models' import { AsymmetricMessagePayload, TrustedContactInterface } from '@standardnotes/models'
import { DecryptMessage } from '../../Encryption/UseCase/Asymmetric/DecryptMessage' import { DecryptMessage } from '../../Encryption/UseCase/Asymmetric/DecryptMessage'
import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core' import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core'
@@ -8,12 +8,12 @@ export class GetTrustedPayload implements SyncUseCaseInterface<AsymmetricMessage
execute<M extends AsymmetricMessagePayload>(dto: { execute<M extends AsymmetricMessagePayload>(dto: {
privateKey: string privateKey: string
message: AsymmetricMessageServerHash payload: AsymmetricMessageServerHash | SharedVaultInviteServerHash
sender: TrustedContactInterface sender: TrustedContactInterface
ownUserUuid: string ownUserUuid: string
}): Result<M> { }): Result<M> {
const result = this.decryptMessage.execute<M>({ const result = this.decryptMessage.execute<M>({
message: dto.message.encrypted_message, message: dto.payload.encrypted_message,
sender: dto.sender, sender: dto.sender,
privateKey: dto.privateKey, privateKey: dto.privateKey,
}) })

View File

@@ -1,4 +1,4 @@
import { AsymmetricMessageServerHash } from '@standardnotes/responses' import { AsymmetricMessageServerHash, SharedVaultInviteServerHash } from '@standardnotes/responses'
import { AsymmetricMessagePayload } from '@standardnotes/models' import { AsymmetricMessagePayload } from '@standardnotes/models'
import { DecryptMessage } from '../../Encryption/UseCase/Asymmetric/DecryptMessage' import { DecryptMessage } from '../../Encryption/UseCase/Asymmetric/DecryptMessage'
import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core' import { Result, SyncUseCaseInterface } from '@standardnotes/domain-core'
@@ -8,10 +8,10 @@ export class GetUntrustedPayload implements SyncUseCaseInterface<AsymmetricMessa
execute<M extends AsymmetricMessagePayload>(dto: { execute<M extends AsymmetricMessagePayload>(dto: {
privateKey: string privateKey: string
message: AsymmetricMessageServerHash payload: AsymmetricMessageServerHash | SharedVaultInviteServerHash
}): Result<M> { }): Result<M> {
const result = this.decryptMessage.execute<M>({ const result = this.decryptMessage.execute<M>({
message: dto.message.encrypted_message, message: dto.payload.encrypted_message,
sender: undefined, sender: undefined,
privateKey: dto.privateKey, privateKey: dto.privateKey,
}) })

View File

@@ -1,3 +1,20 @@
import { UserInvitedToSharedVaultEvent } from '@standardnotes/domain-events'
import {
ClientDisplayableError,
SharedVaultInviteServerHash,
SharedVaultUserServerHash,
isClientDisplayableError,
isErrorResponse,
} from '@standardnotes/responses'
import { ContentType, Result } from '@standardnotes/domain-core'
import { SharedVaultInvitesServer } from '@standardnotes/api'
import {
AsymmetricMessageSharedVaultInvite,
PayloadEmitSource,
SharedVaultListingInterface,
TrustedContactInterface,
} from '@standardnotes/models'
import { AcceptVaultInvite } from './UseCase/AcceptVaultInvite' import { AcceptVaultInvite } from './UseCase/AcceptVaultInvite'
import { SyncEvent, SyncEventReceivedSharedVaultInvitesData } from './../Event/SyncEvent' import { SyncEvent, SyncEventReceivedSharedVaultInvitesData } from './../Event/SyncEvent'
import { InternalEventInterface } from './../Internal/InternalEventInterface' import { InternalEventInterface } from './../Internal/InternalEventInterface'
@@ -15,26 +32,12 @@ import { SyncServiceInterface } from './../Sync/SyncServiceInterface'
import { InternalEventBusInterface } from './../Internal/InternalEventBusInterface' import { InternalEventBusInterface } from './../Internal/InternalEventBusInterface'
import { SessionsClientInterface } from './../Session/SessionsClientInterface' import { SessionsClientInterface } from './../Session/SessionsClientInterface'
import { GetAllContacts } from './../Contacts/UseCase/GetAllContacts' import { GetAllContacts } from './../Contacts/UseCase/GetAllContacts'
import {
AsymmetricMessageSharedVaultInvite,
PayloadEmitSource,
SharedVaultListingInterface,
TrustedContactInterface,
} from '@standardnotes/models'
import { VaultInviteServiceInterface } from './VaultInviteServiceInterface' import { VaultInviteServiceInterface } from './VaultInviteServiceInterface'
import {
ClientDisplayableError,
SharedVaultInviteServerHash,
SharedVaultUserServerHash,
isClientDisplayableError,
isErrorResponse,
} from '@standardnotes/responses'
import { AbstractService } from './../Service/AbstractService' import { AbstractService } from './../Service/AbstractService'
import { VaultInviteServiceEvent } from './VaultInviteServiceEvent' import { VaultInviteServiceEvent } from './VaultInviteServiceEvent'
import { ContentType, Result } from '@standardnotes/domain-core'
import { SharedVaultInvitesServer } from '@standardnotes/api'
import { GetKeyPairs } from '../Encryption/UseCase/GetKeyPairs' import { GetKeyPairs } from '../Encryption/UseCase/GetKeyPairs'
import { DecryptErroredPayloads } from '../Encryption/UseCase/DecryptErroredPayloads' import { DecryptErroredPayloads } from '../Encryption/UseCase/DecryptErroredPayloads'
import { WebSocketsServiceEvent } from '../Api/WebSocketsServiceEvent'
export class VaultInviteService export class VaultInviteService
extends AbstractService<VaultInviteServiceEvent> extends AbstractService<VaultInviteServiceEvent>
@@ -98,6 +101,9 @@ export class VaultInviteService
case SyncEvent.ReceivedSharedVaultInvites: case SyncEvent.ReceivedSharedVaultInvites:
await this.processInboundInvites(event.payload as SyncEventReceivedSharedVaultInvitesData) await this.processInboundInvites(event.payload as SyncEventReceivedSharedVaultInvitesData)
break break
case WebSocketsServiceEvent.UserInvitedToSharedVault:
await this.processInboundInvites([(event as UserInvitedToSharedVaultEvent).payload.invite])
break
} }
} }
@@ -261,7 +267,7 @@ export class VaultInviteService
const sender = this._findContact.execute({ userUuid: invite.sender_uuid }) const sender = this._findContact.execute({ userUuid: invite.sender_uuid })
if (!sender.isFailed()) { if (!sender.isFailed()) {
const trustedMessage = this._getTrustedPayload.execute<AsymmetricMessageSharedVaultInvite>({ const trustedMessage = this._getTrustedPayload.execute<AsymmetricMessageSharedVaultInvite>({
message: invite, payload: invite,
privateKey: keys.getValue().encryption.privateKey, privateKey: keys.getValue().encryption.privateKey,
ownUserUuid: this.session.userUuid, ownUserUuid: this.session.userUuid,
sender: sender.getValue(), sender: sender.getValue(),
@@ -279,7 +285,7 @@ export class VaultInviteService
} }
const untrustedMessage = this._getUntrustedPayload.execute<AsymmetricMessageSharedVaultInvite>({ const untrustedMessage = this._getUntrustedPayload.execute<AsymmetricMessageSharedVaultInvite>({
message: invite, payload: invite,
privateKey: keys.getValue().encryption.privateKey, privateKey: keys.getValue().encryption.privateKey,
}) })

View File

@@ -38,7 +38,7 @@
"@standardnotes/api": "workspace:*", "@standardnotes/api": "workspace:*",
"@standardnotes/common": "^1.50.0", "@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.25.0", "@standardnotes/domain-core": "^1.25.0",
"@standardnotes/domain-events": "^2.121.0", "@standardnotes/domain-events": "^2.122.0",
"@standardnotes/encryption": "workspace:*", "@standardnotes/encryption": "workspace:*",
"@standardnotes/features": "workspace:*", "@standardnotes/features": "workspace:*",
"@standardnotes/files": "workspace:*", "@standardnotes/files": "workspace:*",

View File

@@ -4349,13 +4349,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@standardnotes/domain-events@npm:^2.121.0": "@standardnotes/domain-events@npm:^2.122.0":
version: 2.121.0 version: 2.122.0
resolution: "@standardnotes/domain-events@npm:2.121.0" resolution: "@standardnotes/domain-events@npm:2.122.0"
dependencies: dependencies:
"@standardnotes/predicates": 1.6.9 "@standardnotes/predicates": 1.6.9
"@standardnotes/security": 1.12.0 "@standardnotes/security": 1.12.0
checksum: 49d4a834212f24b4469487ce6126d554e50145dee665326e2fc0536a1890febbca4e8c07e37666bfced9d5bfd36d175edfeb1483876326a4c964805993dba7ec checksum: 9dd2f02f1c9c91b3380d0db88dba3e504aaa14b7e58dcb519611dd8b15edb27c111805eb0e34f1612751fb59428296a216e39b5711892f6c8f1fc1f057e61c50
languageName: node languageName: node
linkType: hard linkType: hard
@@ -4829,7 +4829,7 @@ __metadata:
"@standardnotes/api": "workspace:*" "@standardnotes/api": "workspace:*"
"@standardnotes/common": ^1.50.0 "@standardnotes/common": ^1.50.0
"@standardnotes/domain-core": ^1.25.0 "@standardnotes/domain-core": ^1.25.0
"@standardnotes/domain-events": ^2.121.0 "@standardnotes/domain-events": ^2.122.0
"@standardnotes/encryption": "workspace:*" "@standardnotes/encryption": "workspace:*"
"@standardnotes/features": "workspace:*" "@standardnotes/features": "workspace:*"
"@standardnotes/files": "workspace:*" "@standardnotes/files": "workspace:*"