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:
Binary file not shown.
@@ -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
|
||||||
|
|||||||
@@ -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>
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export enum WebSocketsServiceEvent {
|
export enum WebSocketsServiceEvent {
|
||||||
UserRoleMessageReceived = 'WebSocketMessageReceived',
|
UserRoleMessageReceived = 'WebSocketMessageReceived',
|
||||||
NotificationAddedForUser = 'NotificationAddedForUser',
|
NotificationAddedForUser = 'NotificationAddedForUser',
|
||||||
|
MessageSentToUser = 'MessageSentToUser',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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:*",
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@@ -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:*"
|
||||||
|
|||||||
Reference in New Issue
Block a user