chore: handle messages via websockets (#2473)

* chore: handle messages via websockets

* chore: update domain events

* fix: specs

* fix: adjust server revision creation delay
This commit is contained in:
Karol Sójko
2023-09-01 13:07:15 +02:00
committed by GitHub
parent de165c7456
commit bd2172b773
13 changed files with 47 additions and 41 deletions

View File

@@ -2,7 +2,7 @@ export interface AsymmetricMessageServerHash {
uuid: string uuid: string
recipient_uuid: string recipient_uuid: string
sender_uuid: string sender_uuid: string
replaceabilityIdentifier?: string replaceability_identifier: string | null
encrypted_message: string encrypted_message: string
created_at_timestamp: number created_at_timestamp: number
updated_at_timestamp: number updated_at_timestamp: number

View File

@@ -1,7 +0,0 @@
import { Either } from '@standardnotes/common'
import { UserRolesChangedEventPayload, NotificationAddedForUserEventPayload } from '@standardnotes/domain-events'
export interface WebSocketsEventData {
type: string
payload: Either<UserRolesChangedEventPayload, NotificationAddedForUserEventPayload>
}

View File

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

View File

@@ -1,18 +1,13 @@
import { isErrorResponse } from '@standardnotes/responses' import { isErrorResponse } from '@standardnotes/responses'
import { import { DomainEventInterface } from '@standardnotes/domain-events'
DomainEventInterface,
UserRolesChangedEvent,
NotificationAddedForUserEvent,
} from '@standardnotes/domain-events'
import { WebSocketApiServiceInterface } from '@standardnotes/api' import { WebSocketApiServiceInterface } from '@standardnotes/api'
import { WebSocketsServiceEvent } from './WebSocketsServiceEvent' import { WebSocketsServiceEvent } from './WebSocketsServiceEvent'
import { StorageServiceInterface } from '../Storage/StorageServiceInterface' import { StorageServiceInterface } from '../Storage/StorageServiceInterface'
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface' import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
import { AbstractService } from '../Service/AbstractService' import { AbstractService } from '../Service/AbstractService'
import { StorageKey } from '../Storage/StorageKeys' import { StorageKey } from '../Storage/StorageKeys'
import { WebSocketsEventData } from './WebSocketsEventData'
export class WebSocketsService extends AbstractService<WebSocketsServiceEvent, WebSocketsEventData> { export class WebSocketsService extends AbstractService<WebSocketsServiceEvent, DomainEventInterface> {
private webSocket?: WebSocket private webSocket?: WebSocket
constructor( constructor(
@@ -68,13 +63,13 @@ export class WebSocketsService extends AbstractService<WebSocketsServiceEvent, W
const eventData: DomainEventInterface = JSON.parse(messageEvent.data) const eventData: DomainEventInterface = JSON.parse(messageEvent.data)
switch (eventData.type) { switch (eventData.type) {
case 'USER_ROLES_CHANGED': case 'USER_ROLES_CHANGED':
void this.notifyEvent(WebSocketsServiceEvent.UserRoleMessageReceived, eventData as UserRolesChangedEvent) void this.notifyEvent(WebSocketsServiceEvent.UserRoleMessageReceived, eventData)
break break
case 'NOTIFICATION_ADDED_FOR_USER': case 'NOTIFICATION_ADDED_FOR_USER':
void this.notifyEvent( void this.notifyEvent(WebSocketsServiceEvent.NotificationAddedForUser, eventData)
WebSocketsServiceEvent.NotificationAddedForUser, break
eventData as NotificationAddedForUserEvent, case 'MESSAGE_SENT_TO_USER':
) void this.notifyEvent(WebSocketsServiceEvent.MessageSentToUser, eventData)
break break
default: default:
break break

View File

@@ -90,6 +90,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
}, },
{ {
uuid: 'misc-message', uuid: 'misc-message',
@@ -98,6 +99,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 1, created_at_timestamp: 1,
updated_at_timestamp: 1, updated_at_timestamp: 1,
replaceability_identifier: null,
}, },
] ]
@@ -135,6 +137,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
} }
const decryptedMessagePayload: AsymmetricMessageTrustedContactShare = { const decryptedMessagePayload: AsymmetricMessageTrustedContactShare = {
@@ -168,6 +171,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
}, },
{ {
uuid: 'older-message', uuid: 'older-message',
@@ -176,6 +180,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 1, created_at_timestamp: 1,
updated_at_timestamp: 1, updated_at_timestamp: 1,
replaceability_identifier: null,
}, },
] ]
@@ -202,6 +207,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
} }
const decryptedMessagePayload: AsymmetricMessageTrustedContactShare = { const decryptedMessagePayload: AsymmetricMessageTrustedContactShare = {
@@ -230,6 +236,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
} }
const decryptedMessagePayload: AsymmetricMessageSenderKeypairChanged = { const decryptedMessagePayload: AsymmetricMessageSenderKeypairChanged = {
@@ -259,6 +266,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
} }
const decryptedMessagePayload: AsymmetricMessageSharedVaultRootKeyChanged = { const decryptedMessagePayload: AsymmetricMessageSharedVaultRootKeyChanged = {
@@ -287,6 +295,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
} }
const decryptedMessagePayload: AsymmetricMessageSharedVaultMetadataChanged = { const decryptedMessagePayload: AsymmetricMessageSharedVaultMetadataChanged = {
@@ -317,6 +326,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
} }
const decryptedMessagePayload: AsymmetricMessageSharedVaultInvite = { const decryptedMessagePayload: AsymmetricMessageSharedVaultInvite = {
@@ -343,6 +353,7 @@ describe('AsymmetricMessageService', () => {
encrypted_message: 'encrypted_message', encrypted_message: 'encrypted_message',
created_at_timestamp: 2, created_at_timestamp: 2,
updated_at_timestamp: 2, updated_at_timestamp: 2,
replaceability_identifier: null,
} }
const decryptedMessagePayload: AsymmetricMessageTrustedContactShare = { const decryptedMessagePayload: AsymmetricMessageTrustedContactShare = {

View File

@@ -1,14 +1,6 @@
import { GetKeyPairs } from './../Encryption/UseCase/GetKeyPairs' import { MessageSentToUserEvent } from '@standardnotes/domain-events'
import { SyncServiceInterface } from './../Sync/SyncServiceInterface'
import { SessionsClientInterface } from './../Session/SessionsClientInterface'
import { MutatorClientInterface } from './../Mutator/MutatorClientInterface'
import { AsymmetricMessageServerHash } from '@standardnotes/responses' import { AsymmetricMessageServerHash } from '@standardnotes/responses'
import { SyncEvent, SyncEventReceivedAsymmetricMessagesData } from '../Event/SyncEvent' import { AsymmetricMessageServer } from '@standardnotes/api'
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
import { InternalEventHandlerInterface } from '../Internal/InternalEventHandlerInterface'
import { InternalEventInterface } from '../Internal/InternalEventInterface'
import { AbstractService } from '../Service/AbstractService'
import { GetTrustedPayload } from './UseCase/GetTrustedPayload'
import { import {
AsymmetricMessageSharedVaultRootKeyChanged, AsymmetricMessageSharedVaultRootKeyChanged,
AsymmetricMessagePayloadType, AsymmetricMessagePayloadType,
@@ -21,8 +13,19 @@ import {
PayloadEmitSource, PayloadEmitSource,
VaultListingInterface, VaultListingInterface,
} from '@standardnotes/models' } from '@standardnotes/models'
import { Result } from '@standardnotes/domain-core'
import { GetKeyPairs } from './../Encryption/UseCase/GetKeyPairs'
import { SyncServiceInterface } from './../Sync/SyncServiceInterface'
import { SessionsClientInterface } from './../Session/SessionsClientInterface'
import { MutatorClientInterface } from './../Mutator/MutatorClientInterface'
import { SyncEvent, SyncEventReceivedAsymmetricMessagesData } from '../Event/SyncEvent'
import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface'
import { InternalEventHandlerInterface } from '../Internal/InternalEventHandlerInterface'
import { InternalEventInterface } from '../Internal/InternalEventInterface'
import { AbstractService } from '../Service/AbstractService'
import { GetTrustedPayload } from './UseCase/GetTrustedPayload'
import { HandleRootKeyChangedMessage } from './UseCase/HandleRootKeyChangedMessage' import { HandleRootKeyChangedMessage } from './UseCase/HandleRootKeyChangedMessage'
import { AsymmetricMessageServer } from '@standardnotes/api'
import { GetOutboundMessages } from './UseCase/GetOutboundMessages' import { GetOutboundMessages } from './UseCase/GetOutboundMessages'
import { GetInboundMessages } from './UseCase/GetInboundMessages' import { GetInboundMessages } from './UseCase/GetInboundMessages'
import { GetVault } from '../Vault/UseCase/GetVault' import { GetVault } from '../Vault/UseCase/GetVault'
@@ -32,7 +35,7 @@ import { FindContact } from '../Contacts/UseCase/FindContact'
import { CreateOrEditContact } from '../Contacts/UseCase/CreateOrEditContact' import { CreateOrEditContact } from '../Contacts/UseCase/CreateOrEditContact'
import { ReplaceContactData } from '../Contacts/UseCase/ReplaceContactData' import { ReplaceContactData } from '../Contacts/UseCase/ReplaceContactData'
import { EncryptionProviderInterface } from '../Encryption/EncryptionProviderInterface' import { EncryptionProviderInterface } from '../Encryption/EncryptionProviderInterface'
import { Result } from '@standardnotes/domain-core' import { WebSocketsServiceEvent } from '../Api/WebSocketsServiceEvent'
export class AsymmetricMessageService export class AsymmetricMessageService
extends AbstractService extends AbstractService
@@ -82,6 +85,9 @@ export class AsymmetricMessageService
case SyncEvent.ReceivedAsymmetricMessages: case SyncEvent.ReceivedAsymmetricMessages:
void this.handleRemoteReceivedAsymmetricMessages(event.payload as SyncEventReceivedAsymmetricMessagesData) void this.handleRemoteReceivedAsymmetricMessages(event.payload as SyncEventReceivedAsymmetricMessagesData)
break break
case WebSocketsServiceEvent.MessageSentToUser:
void this.handleRemoteReceivedAsymmetricMessages([(event as MessageSentToUserEvent).payload.message])
break
} }
} }

View File

@@ -37,7 +37,7 @@ export class ResendMessage implements UseCaseInterface<void> {
const sendMessageResult = await this.sendMessage.execute({ const sendMessageResult = await this.sendMessage.execute({
recipientUuid: params.recipient.contactUuid, recipientUuid: params.recipient.contactUuid,
encryptedMessage: encryptedMessage.getValue(), encryptedMessage: encryptedMessage.getValue(),
replaceabilityIdentifier: params.rawMessage.replaceabilityIdentifier, replaceabilityIdentifier: params.rawMessage.replaceability_identifier || undefined,
}) })
return sendMessageResult return sendMessageResult

View File

@@ -4,7 +4,6 @@ export * from './Api/ApiServiceEventData'
export * from './Api/LegacyApiServiceInterface' export * from './Api/LegacyApiServiceInterface'
export * from './Api/MetaReceivedData' export * from './Api/MetaReceivedData'
export * from './Api/SessionRefreshedData' export * from './Api/SessionRefreshedData'
export * from './Api/WebSocketsEventData'
export * from './Api/WebsocketsService' export * from './Api/WebsocketsService'
export * from './Api/WebSocketsServiceEvent' export * from './Api/WebSocketsServiceEvent'
export * from './Application/AppGroupManagedApplication' export * from './Application/AppGroupManagedApplication'

View File

@@ -267,6 +267,7 @@ describe('history manager', () => {
it('should save initial revisions on server', async () => { it('should save initial revisions on server', async () => {
const item = await Factory.createSyncedNote(application) const item = await Factory.createSyncedNote(application)
expect(item).to.be.ok
await Factory.sleep(Factory.ServerRevisionCreationDelay) await Factory.sleep(Factory.ServerRevisionCreationDelay)

View File

@@ -288,7 +288,7 @@ export async function storagePayloadCount(application) {
* Controlled via docker/syncing-server-js.env * Controlled via docker/syncing-server-js.env
*/ */
export const ServerRevisionFrequency = 2.1 export const ServerRevisionFrequency = 2.1
export const ServerRevisionCreationDelay = 1.0 export const ServerRevisionCreationDelay = 1.5
export function yesterday() { export function yesterday() {
return new Date(new Date().setDate(new Date().getDate() - 1)) return new Date(new Date().setDate(new Date().getDate() - 1))

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.120.0", "@standardnotes/domain-events": "^2.121.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.120.0": "@standardnotes/domain-events@npm:^2.121.0":
version: 2.120.0 version: 2.121.0
resolution: "@standardnotes/domain-events@npm:2.120.0" resolution: "@standardnotes/domain-events@npm:2.121.0"
dependencies: dependencies:
"@standardnotes/predicates": 1.6.9 "@standardnotes/predicates": 1.6.9
"@standardnotes/security": 1.12.0 "@standardnotes/security": 1.12.0
checksum: bcd6caf10bc050199db4d0fb13605d43773418c1420efea583381ae6cd33a1a365451a61f3d8d6e08d19a52005e5d67ad2b4c8f3b8f951269b1a2a4bc0ac33cf checksum: 49d4a834212f24b4469487ce6126d554e50145dee665326e2fc0536a1890febbca4e8c07e37666bfced9d5bfd36d175edfeb1483876326a4c964805993dba7ec
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.120.0 "@standardnotes/domain-events": ^2.121.0
"@standardnotes/encryption": "workspace:*" "@standardnotes/encryption": "workspace:*"
"@standardnotes/features": "workspace:*" "@standardnotes/features": "workspace:*"
"@standardnotes/files": "workspace:*" "@standardnotes/files": "workspace:*"