From 950af121cdab98cae9809aaeac030cf1206840d4 Mon Sep 17 00:00:00 2001 From: Mo Date: Wed, 7 Jun 2023 11:19:16 -0500 Subject: [PATCH] feat: asymmetric messages --- packages/syncing-server/bin/server.ts | 2 +- ...84528646896-create_shared_vault_invites.ts | 2 +- .../Bootstrap/CommonContainerConfigLoader.ts | 26 ++-- .../src/Bootstrap/DataSource.ts | 4 +- .../Bootstrap/ServerContainerConfigLoader.ts | 36 ++--- .../syncing-server/src/Bootstrap/Types.ts | 11 +- .../Bootstrap/WorkerContainerConfigLoader.ts | 12 -- .../AsymmetricMessagesController.ts | 136 ++++++++++++++++++ .../SharedVaultInvitesController.ts | 12 +- .../Factory/AsymmetricMessageFactory.ts | 32 +++++ .../AsymmetricMessageFactoryInterface.ts | 7 + .../Factory/AsymmetricMessageHash.ts | 9 ++ .../Model/AsymmetricMessage.ts | 40 ++++++ .../AsymmetricMessageRepositoryInterface.ts | 19 +++ .../TypeORMAsymmetricMessageRepository.ts | 57 ++++++++ .../Service/AsymmetricMessageService.ts | 82 +++++++++++ .../AsymmetricMessageServiceInterface.ts | 15 ++ .../Service/CreateAsymmetricMessageDTO.ts | 6 + .../Service/GetUserAsymmetricMessagesDTO.ts | 4 + .../Service/UpdateAsymmetricMessageDTO.ts | 6 + .../UserCredentialsChangedEventHandler.ts | 48 ------- .../Item/SyncResponse/SyncResponse20200115.ts | 4 +- .../SyncResponseFactory20200115.ts | 16 +-- .../Factory/SharedVaultInviteFactory.ts | 6 +- .../Factory/SharedVaultInviteHash.ts | 2 +- .../Model/SharedVaultInvite.ts | 8 +- .../SharedVaultInviteRepositoryInterface.ts | 2 +- .../TypeORMSharedVaultInviteRepository.ts | 6 +- .../Service/CreateInviteDTO.ts | 8 +- .../Service/SharedVaultInviteService.ts | 18 +-- .../Service/UpdateInviteDTO.ts | 6 +- .../src/Domain/UseCase/SyncItems.ts | 8 +- .../src/Domain/UseCase/SyncItemsResponse.ts | 4 +- .../Projection/AsymmetricMessageProjection.ts | 9 ++ .../Projection/AsymmetricMessageProjector.ts | 30 ++++ .../Projection/SharedVaultInviteProjection.ts | 2 +- .../Projection/SharedVaultInviteProjector.ts | 6 +- 37 files changed, 549 insertions(+), 152 deletions(-) create mode 100644 packages/syncing-server/src/Controller/AsymmetricMessagesController.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactory.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactoryInterface.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageHash.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Model/AsymmetricMessage.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Repository/AsymmetricMessageRepositoryInterface.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Repository/TypeORMAsymmetricMessageRepository.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageService.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageServiceInterface.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Service/CreateAsymmetricMessageDTO.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Service/GetUserAsymmetricMessagesDTO.ts create mode 100644 packages/syncing-server/src/Domain/AsymmetricMessage/Service/UpdateAsymmetricMessageDTO.ts delete mode 100644 packages/syncing-server/src/Domain/Handler/UserCredentialsChangedEventHandler.ts create mode 100644 packages/syncing-server/src/Projection/AsymmetricMessageProjection.ts create mode 100644 packages/syncing-server/src/Projection/AsymmetricMessageProjector.ts diff --git a/packages/syncing-server/bin/server.ts b/packages/syncing-server/bin/server.ts index 05ee8ec8c..907f7053b 100644 --- a/packages/syncing-server/bin/server.ts +++ b/packages/syncing-server/bin/server.ts @@ -7,7 +7,7 @@ import '../src/Controller/ItemsController' import '../src/Controller/SharedVaultsController' import '../src/Controller/SharedVaultUsersController' import '../src/Controller/SharedVaultInvitesController' -import '../src/Controller/ContactsController' +import '../src/Controller/AsymmetricMessagesController' import helmet from 'helmet' import * as cors from 'cors' diff --git a/packages/syncing-server/migrations/mysql/1684528646896-create_shared_vault_invites.ts b/packages/syncing-server/migrations/mysql/1684528646896-create_shared_vault_invites.ts index 2eae9e36a..2eba3d607 100644 --- a/packages/syncing-server/migrations/mysql/1684528646896-create_shared_vault_invites.ts +++ b/packages/syncing-server/migrations/mysql/1684528646896-create_shared_vault_invites.ts @@ -26,7 +26,7 @@ export class CreateSharedVaultInvites1684528646896 implements MigrationInterface isNullable: false, }), new TableColumn({ - name: 'inviter_uuid', + name: 'sender_uuid', type: 'varchar', length: '255', isNullable: false, diff --git a/packages/syncing-server/src/Bootstrap/CommonContainerConfigLoader.ts b/packages/syncing-server/src/Bootstrap/CommonContainerConfigLoader.ts index 8d45a06c8..c77d25573 100644 --- a/packages/syncing-server/src/Bootstrap/CommonContainerConfigLoader.ts +++ b/packages/syncing-server/src/Bootstrap/CommonContainerConfigLoader.ts @@ -1,5 +1,5 @@ import { TypeORMSharedVaultInviteRepository } from '../Domain/SharedVaultInvite/Repository/TypeORMSharedVaultInviteRepository' -import { Contact } from './../Domain/Contact/Model/Contact' +import { AsymmetricMessage } from './../Domain/AsymmetricMessage/Model/AsymmetricMessage' import { SharedVaultInvite } from '../Domain/SharedVaultInvite/Model/SharedVaultInvite' import { SharedVaultUser } from '../Domain/SharedVaultUser/Model/SharedVaultUser' import { SharedVault } from '../Domain/SharedVault/Model/SharedVault' @@ -33,16 +33,16 @@ import { SharedVaultProjection } from '../Projection/SharedVaultProjection' import { SharedVaultProjector } from '../Projection/SharedVaultProjector' import { SharedVaultInviteProjection } from '../Projection/SharedVaultInviteProjection' import { SharedVaultInviteProjector } from '../Projection/SharedVaultInviteProjector' -import { ContactProjection } from '../Projection/ContactProjection' -import { ContactProjector } from '../Projection/ContactProjector' +import { AsymmetricMessageProjection } from '../Projection/AsymmetricMessageProjection' +import { AsymmetricMessageProjector } from '../Projection/AsymmetricMessageProjector' import { SharedVaultInviteRepositoryInterface } from '../Domain/SharedVaultInvite/Repository/SharedVaultInviteRepositoryInterface' -import { ContactsRepositoryInterface } from '../Domain/Contact/Repository/ContactRepositoryInterface' -import { TypeORMContactRepository } from '../Domain/Contact/Repository/TypeORMContactRepository' +import { TypeORMAsymmetricMessageRepository } from '../Domain/AsymmetricMessage/Repository/TypeORMAsymmetricMessageRepository' import { UserEventsRepositoryInterface } from '../Domain/UserEvent/Repository/UserEventRepositoryInterface' import { TypeORMUserEventRepository } from '../Domain/UserEvent/Repository/TypeORMUserEventRepository' import { UserEvent } from '../Domain/UserEvent/Model/UserEvent' import { UserEventProjection } from '../Projection/UserEventProjection' import { UserEventProjector } from '../Projection/UserEventProjector' +import { AsymmetricMessageRepositoryInterface } from '../Domain/AsymmetricMessage/Repository/AsymmetricMessageRepositoryInterface' // eslint-disable-next-line @typescript-eslint/no-var-requires const newrelicFormatter = require('@newrelic/winston-enricher') @@ -117,9 +117,9 @@ export class CommonContainerConfigLoader { return new TypeORMSharedVaultInviteRepository(context.container.get(TYPES.ORMSharedVaultInviteRepository)) }) container - .bind(TYPES.ContactRepository) + .bind(TYPES.AsymmetricMessageRepository) .toDynamicValue((context: interfaces.Context) => { - return new TypeORMContactRepository(context.container.get(TYPES.ORMContactRepository)) + return new TypeORMAsymmetricMessageRepository(context.container.get(TYPES.ORMAsymmetricMessageRepository)) }) container .bind(TYPES.UserEventRepository) @@ -139,8 +139,8 @@ export class CommonContainerConfigLoader { .bind>(TYPES.ORMSharedVaultInviteRepository) .toDynamicValue(() => AppDataSource.getRepository(SharedVaultInvite)) container - .bind>(TYPES.ORMContactRepository) - .toDynamicValue(() => AppDataSource.getRepository(Contact)) + .bind>(TYPES.ORMAsymmetricMessageRepository) + .toDynamicValue(() => AppDataSource.getRepository(AsymmetricMessage)) container .bind>(TYPES.ORMUserEventRepository) .toDynamicValue(() => AppDataSource.getRepository(UserEvent)) @@ -166,9 +166,11 @@ export class CommonContainerConfigLoader { .toDynamicValue(() => { return new SharedVaultInviteProjector() }) - container.bind>(TYPES.ContactProjector).toDynamicValue(() => { - return new ContactProjector() - }) + container + .bind>(TYPES.AsymmetricMessageProjector) + .toDynamicValue(() => { + return new AsymmetricMessageProjector() + }) container.bind>(TYPES.UserEventProjector).toDynamicValue(() => { return new UserEventProjector() }) diff --git a/packages/syncing-server/src/Bootstrap/DataSource.ts b/packages/syncing-server/src/Bootstrap/DataSource.ts index 7fc7e2258..13acd2a2d 100644 --- a/packages/syncing-server/src/Bootstrap/DataSource.ts +++ b/packages/syncing-server/src/Bootstrap/DataSource.ts @@ -1,5 +1,5 @@ +import { AsymmetricMessage } from './../Domain/AsymmetricMessage/Model/AsymmetricMessage' import { UserEvent } from './../Domain/UserEvent/Model/UserEvent' -import { Contact } from './../Domain/Contact/Model/Contact' import { SharedVaultInvite } from '../Domain/SharedVaultInvite/Model/SharedVaultInvite' import { SharedVaultUser } from '../Domain/SharedVaultUser/Model/SharedVaultUser' import { DataSource, LoggerOptions } from 'typeorm' @@ -43,7 +43,7 @@ const replicationConfig = { const commonDataSourceOptions = { maxQueryExecutionTime, - entities: [Item, SharedVault, SharedVaultUser, SharedVaultInvite, Contact, UserEvent], + entities: [Item, SharedVault, SharedVaultUser, SharedVaultInvite, AsymmetricMessage, UserEvent], migrations: [`dist/migrations/${isConfiguredForMySQL ? 'mysql' : 'sqlite'}/*.js`], migrationsRun: true, logging: env.get('DB_DEBUG_LEVEL'), diff --git a/packages/syncing-server/src/Bootstrap/ServerContainerConfigLoader.ts b/packages/syncing-server/src/Bootstrap/ServerContainerConfigLoader.ts index 21f6ad0f9..f6a0b5798 100644 --- a/packages/syncing-server/src/Bootstrap/ServerContainerConfigLoader.ts +++ b/packages/syncing-server/src/Bootstrap/ServerContainerConfigLoader.ts @@ -1,5 +1,5 @@ import { SaveItem } from './../Domain/UseCase/SaveItem/SaveItem' -import { ContactFactory } from './../Domain/Contact/Factory/ContactFactory' +import { AsymmetricMessageFactory } from './../Domain/AsymmetricMessage/Factory/AsymmetricMessageFactory' import { SharedVaultServiceInterface } from '../Domain/SharedVault/Service/SharedVaultServiceInterface' import { SharedVaultUserFactory } from '../Domain/SharedVaultUser/Factory/SharedVaultUserFactory' @@ -44,9 +44,9 @@ import { SharedVaultUserServiceInterface } from '../Domain/SharedVaultUser/Servi import { SharedVaultInviteServiceInterface } from '../Domain/SharedVaultInvite/Service/SharedVaultInviteServiceInterface' import { SharedVaultInviteService } from '../Domain/SharedVaultInvite/Service/SharedVaultInviteService' import { SharedVaultInviteFactory } from '../Domain/SharedVaultInvite/Factory/SharedVaultInviteFactory' -import { ContactServiceInterface } from '../Domain/Contact/Service/ContactServiceInterface' -import { ContactService } from '../Domain/Contact/Service/ContactService' -import { ContactFactoryInterface } from '../Domain/Contact/Factory/ContactFactoryInterface' +import { AsymmetricMessageServiceInterface } from '../Domain/AsymmetricMessage/Service/AsymmetricMessageServiceInterface' +import { AsymmetricMessageService } from '../Domain/AsymmetricMessage/Service/AsymmetricMessageService' +import { AsymmetricMessageFactoryInterface } from '../Domain/AsymmetricMessage/Factory/AsymmetricMessageFactoryInterface' import { SharedVaultSnjsVersionFilter } from '../Domain/Item/SaveRule/SharedVaultSnjsVersionFilter' import { CreateSharedVaultFileValetToken } from '../Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken' import { UserEventServiceInterface } from '../Domain/UserEvent/Service/UserEventServiceInterface' @@ -106,7 +106,7 @@ export class ServerContainerConfigLoader extends CommonContainerConfigLoader { context.container.get(TYPES.ItemService), context.container.get(TYPES.SharedVaultService), context.container.get(TYPES.SharedVaultInviteService), - context.container.get(TYPES.ContactService), + context.container.get(TYPES.AsymmetricMessageService), context.container.get(TYPES.UserEventService), ) }) @@ -189,13 +189,15 @@ export class ServerContainerConfigLoader extends CommonContainerConfigLoader { context.container.get(TYPES.Timer), ) }) - container.bind(TYPES.ContactService).toDynamicValue((context: interfaces.Context) => { - return new ContactService( - context.container.get(TYPES.ContactRepository), - context.container.get(TYPES.ContactFactory), - context.container.get(TYPES.Timer), - ) - }) + container + .bind(TYPES.AsymmetricMessageService) + .toDynamicValue((context: interfaces.Context) => { + return new AsymmetricMessageService( + context.container.get(TYPES.AsymmetricMessageRepository), + context.container.get(TYPES.AsymmetricMessageFactory), + context.container.get(TYPES.Timer), + ) + }) container.bind(TYPES.UserEventService).toDynamicValue((context: interfaces.Context) => { return new UserEventService( context.container.get(TYPES.UserEventRepository), @@ -217,7 +219,7 @@ export class ServerContainerConfigLoader extends CommonContainerConfigLoader { context.container.get(TYPES.ItemConflictProjector), context.container.get(TYPES.SavedItemProjector), context.container.get(TYPES.SharedVaultInviteProjector), - context.container.get(TYPES.ContactProjector), + context.container.get(TYPES.AsymmetricMessageProjector), context.container.get(TYPES.SharedVaultProjector), context.container.get(TYPES.UserEventProjector), ) @@ -249,9 +251,11 @@ export class ServerContainerConfigLoader extends CommonContainerConfigLoader { .toDynamicValue((context: interfaces.Context) => { return new SharedVaultInviteFactory(context.container.get(TYPES.Timer)) }) - container.bind(TYPES.ContactFactory).toDynamicValue((context: interfaces.Context) => { - return new ContactFactory(context.container.get(TYPES.Timer)) - }) + container + .bind(TYPES.AsymmetricMessageFactory) + .toDynamicValue((context: interfaces.Context) => { + return new AsymmetricMessageFactory(context.container.get(TYPES.Timer)) + }) container.bind(TYPES.UserEventFactory).toDynamicValue((context: interfaces.Context) => { return new UserEventFactory(context.container.get(TYPES.Timer)) }) diff --git a/packages/syncing-server/src/Bootstrap/Types.ts b/packages/syncing-server/src/Bootstrap/Types.ts index 64c93595d..fc81d279a 100644 --- a/packages/syncing-server/src/Bootstrap/Types.ts +++ b/packages/syncing-server/src/Bootstrap/Types.ts @@ -11,7 +11,7 @@ const TYPES = { ItemRepository: Symbol.for('ItemRepository'), SharedVaultRepository: Symbol.for('SharedVaultRepository'), SharedVaultUserRepository: Symbol.for('SharedVaultUserRepository'), - ContactRepository: Symbol.for('ContactRepository'), + AsymmetricMessageRepository: Symbol.for('AsymmetricMessageRepository'), SharedVaultInviteRepository: Symbol.for('SharedVaultInviteRepository'), UserEventRepository: Symbol.for('UserEventRepository'), @@ -19,7 +19,7 @@ const TYPES = { ORMItemRepository: Symbol.for('ORMItemRepository'), ORMSharedVaultRepository: Symbol.for('ORMSharedVaultRepository'), ORMSharedVaultUserRepository: Symbol.for('ORMSharedVaultUserRepository'), - ORMContactRepository: Symbol.for('ORMContactRepository'), + ORMAsymmetricMessageRepository: Symbol.for('ORMAsymmetricMessageRepository'), ORMSharedVaultInviteRepository: Symbol.for('ORMSharedVaultInviteRepository'), ORMUserEventRepository: Symbol.for('ORMUserEventRepository'), @@ -32,14 +32,14 @@ const TYPES = { ItemConflictProjector: Symbol.for('ItemConflictProjector'), SharedVaultProjector: Symbol.for('SharedVaultProjector'), SharedVaultUserProjector: Symbol.for('SharedVaultUserProjector'), - ContactProjector: Symbol.for('ContactProjector'), + AsymmetricMessageProjector: Symbol.for('AsymmetricMessageProjector'), SharedVaultInviteProjector: Symbol.for('SharedVaultInviteProjector'), UserEventProjector: Symbol.for('UserEventProjector'), // Services SharedVaultService: Symbol.for('SharedVaultService'), SharedVaultUserService: Symbol.for('SharedVaultUserService'), - ContactService: Symbol.for('ContactService'), + AsymmetricMessageService: Symbol.for('AsymmetricMessageService'), SharedVaultInviteService: Symbol.for('SharedVaultInviteService'), UserEventService: Symbol.for('UserEventService'), @@ -47,7 +47,7 @@ const TYPES = { ItemFactory: Symbol.for('ItemFactory'), SharedVaultFactory: Symbol.for('SharedVaultFactory'), SharedVaultUserFactory: Symbol.for('SharedVaultUserFactory'), - ContactFactory: Symbol.for('ContactFactory'), + AsymmetricMessageFactory: Symbol.for('AsymmetricMessageFactory'), SharedVaultInviteFactory: Symbol.for('SharedVaultInviteFactory'), UserEventFactory: Symbol.for('UserEventFactory'), @@ -78,7 +78,6 @@ const TYPES = { SaveItem: Symbol.for('SaveItem'), CreateSharedVaultFileReadValetToken: Symbol.for('CreateSharedVaultFileReadValetToken'), // Handlers - UserCredentialsChangedEventHandler: Symbol.for('UserCredentialsChangedEventHandler'), AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'), DuplicateItemSyncedEventHandler: Symbol.for('DuplicateItemSyncedEventHandler'), EmailBackupRequestedEventHandler: Symbol.for('EmailBackupRequestedEventHandler'), diff --git a/packages/syncing-server/src/Bootstrap/WorkerContainerConfigLoader.ts b/packages/syncing-server/src/Bootstrap/WorkerContainerConfigLoader.ts index b8d54cdf6..0723644b8 100644 --- a/packages/syncing-server/src/Bootstrap/WorkerContainerConfigLoader.ts +++ b/packages/syncing-server/src/Bootstrap/WorkerContainerConfigLoader.ts @@ -30,7 +30,6 @@ import { EmailBackupRequestedEventHandler } from '../Domain/Handler/EmailBackupR import { ItemRevisionCreationRequestedEventHandler } from '../Domain/Handler/ItemRevisionCreationRequestedEventHandler' import { FSItemBackupService } from '../Infra/FS/FSItemBackupService' import { CommonContainerConfigLoader } from './CommonContainerConfigLoader' -import { UserCredentialsChangedEventHandler } from '../Domain/Handler/UserCredentialsChangedEventHandler' import { SharedVaultFileUploadedEventHandler } from '../Domain/Handler/SharedVaultFileUploadedEventHandler' import { SharedVaultFileRemovedEventHandler } from '../Domain/Handler/SharedVaultFileRemovedEventHandler' @@ -135,16 +134,6 @@ export class WorkerContainerConfigLoader extends CommonContainerConfigLoader { ) }) - container - .bind(TYPES.UserCredentialsChangedEventHandler) - .toDynamicValue((context: interfaces.Context) => { - return new UserCredentialsChangedEventHandler( - context.container.get(TYPES.ContactRepository), - context.container.get(TYPES.SharedVaultInviteRepository), - context.container.get(TYPES.Timer), - ) - }) - container .bind(TYPES.SharedVaultFileUploadedEventHandler) .to(SharedVaultFileUploadedEventHandler) @@ -202,7 +191,6 @@ export class WorkerContainerConfigLoader extends CommonContainerConfigLoader { ['ACCOUNT_DELETION_REQUESTED', context.container.get(TYPES.AccountDeletionRequestedEventHandler)], ['EMAIL_BACKUP_REQUESTED', context.container.get(TYPES.EmailBackupRequestedEventHandler)], ['ITEM_REVISION_CREATION_REQUESTED', context.container.get(TYPES.ItemRevisionCreationRequestedEventHandler)], - ['USER_CREDENTIALS_CHANGED', container.get(TYPES.UserCredentialsChangedEventHandler)], ['SHARED_VAULT_FILE_REMOVED', container.get(TYPES.SharedVaultFileRemovedEventHandler)], ['SHARED_VAULT_FILE_UPLOADED', container.get(TYPES.SharedVaultFileUploadedEventHandler)], ]) diff --git a/packages/syncing-server/src/Controller/AsymmetricMessagesController.ts b/packages/syncing-server/src/Controller/AsymmetricMessagesController.ts new file mode 100644 index 000000000..3791e7c2a --- /dev/null +++ b/packages/syncing-server/src/Controller/AsymmetricMessagesController.ts @@ -0,0 +1,136 @@ +import { Request, Response } from 'express' +import { + BaseHttpController, + controller, + httpPost, + results, + httpDelete, + httpGet, + httpPatch, +} from 'inversify-express-utils' +import TYPES from '../Bootstrap/Types' +import { inject } from 'inversify' +import { AsymmetricMessageServiceInterface } from '../Domain/AsymmetricMessage/Service/AsymmetricMessageServiceInterface' +import { AsymmetricMessageProjector } from '../Projection/AsymmetricMessageProjector' + +@controller('/asymmetric-messages') +export class AsymmetricMessagesController extends BaseHttpController { + constructor( + @inject(TYPES.AsymmetricMessageService) private asymmetricMessageService: AsymmetricMessageServiceInterface, + @inject(TYPES.AsymmetricMessageProjector) private asymmetricMessageProjector: AsymmetricMessageProjector, + ) { + super() + } + + @httpGet('/', TYPES.AuthMiddleware) + public async getAsymmetricMessages( + _request: Request, + response: Response, + ): Promise { + const result = await this.asymmetricMessageService.getMessagesForUser({ + userUuid: response.locals.user.uuid, + }) + + if (!result) { + return this.errorResponse(400, 'Could not get shared vault messages') + } + + const projected = result.map((message) => this.asymmetricMessageProjector.projectFull(message)) + + return this.json({ messages: projected }) + } + + @httpPost('/', TYPES.AuthMiddleware) + public async createAsymmetricMessage( + request: Request, + response: Response, + ): Promise { + const result = await this.asymmetricMessageService.createMessage({ + senderUuid: response.locals.user.uuid, + userUuid: request.body.messagee_uuid, + senderPublicKey: request.body.sender_public_key, + encryptedMessage: request.body.encrypted_message, + }) + + if (!result) { + return this.errorResponse(400, 'Could not create message') + } + + return this.json({ message: this.asymmetricMessageProjector.projectFull(result) }) + } + + @httpPatch('/:messageUuid', TYPES.AuthMiddleware) + public async updateAsymmetricMessage( + request: Request, + response: Response, + ): Promise { + const result = await this.asymmetricMessageService.updateMessage({ + senderUuid: response.locals.user.uuid, + messageUuid: request.params.messageUuid, + senderPublicKey: request.body.sender_public_key, + encryptedMessage: request.body.encrypted_message, + }) + + if (!result) { + return this.errorResponse(400, 'Could not update message') + } + + return this.json({ message: this.asymmetricMessageProjector.projectFull(result) }) + } + + @httpDelete('/inbound', TYPES.AuthMiddleware) + public async deleteInboundAsymmetricMessages( + _request: Request, + response: Response, + ): Promise { + await this.asymmetricMessageService.deleteAllInboundMessages({ + userUuid: response.locals.user.uuid, + }) + + return this.json({ success: true }) + } + + @httpGet('/outbound', TYPES.AuthMiddleware) + public async getOutboundAsymmetricMessages( + _request: Request, + response: Response, + ): Promise { + const result = await this.asymmetricMessageService.getOutboundMessagesForUser({ + userUuid: response.locals.user.uuid, + }) + + if (!result) { + return this.errorResponse(400, 'Could not get shared vault messages') + } + + const projected = result.map((message) => this.asymmetricMessageProjector.projectFull(message)) + + return this.json({ messages: projected }) + } + + @httpDelete('/:messageUuid', TYPES.AuthMiddleware) + public async deleteAsymmetricMessage( + request: Request, + response: Response, + ): Promise { + const result = await this.asymmetricMessageService.deleteMessage({ + originatorUuid: response.locals.user.uuid, + messageUuid: request.params.messageUuid, + }) + + if (!result) { + return this.errorResponse(400, 'Could not delete message') + } + + return this.json({ success: true }) + } + + private errorResponse(status: number, message?: string, tag?: string) { + return this.json( + { + error: { message, tag }, + }, + status, + ) + } +} diff --git a/packages/syncing-server/src/Controller/SharedVaultInvitesController.ts b/packages/syncing-server/src/Controller/SharedVaultInvitesController.ts index 2d772f891..c097e1f9d 100644 --- a/packages/syncing-server/src/Controller/SharedVaultInvitesController.ts +++ b/packages/syncing-server/src/Controller/SharedVaultInvitesController.ts @@ -28,11 +28,11 @@ export class SharedVaultInvitesController extends BaseHttpController { response: Response, ): Promise { const result = await this.sharedVaultInviteService.createInvite({ - originatorUuid: response.locals.user.uuid, + senderUuid: response.locals.user.uuid, sharedVaultUuid: request.params.sharedVaultUuid, userUuid: request.body.invitee_uuid, - inviterPublicKey: request.body.sender_public_key, - encryptedVaultKeyContent: request.body.encrypted_message, + senderPublicKey: request.body.sender_public_key, + encryptedMessage: request.body.encrypted_message, permissions: request.body.permissions, }) @@ -49,10 +49,10 @@ export class SharedVaultInvitesController extends BaseHttpController { response: Response, ): Promise { const result = await this.sharedVaultInviteService.updateInvite({ - originatorUuid: response.locals.user.uuid, + senderUuid: response.locals.user.uuid, inviteUuid: request.params.inviteUuid, - inviterPublicKey: request.body.sender_public_key, - encryptedVaultKeyContent: request.body.encrypted_message, + senderPublicKey: request.body.sender_public_key, + encryptedMessage: request.body.encrypted_message, permissions: request.body.permissions, }) diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactory.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactory.ts new file mode 100644 index 000000000..86f49b6e9 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactory.ts @@ -0,0 +1,32 @@ +import { TimerInterface } from '@standardnotes/time' +import { AsymmetricMessageFactoryInterface } from './AsymmetricMessageFactoryInterface' +import { AsymmetricMessageHash } from './AsymmetricMessageHash' +import { AsymmetricMessage } from '../Model/AsymmetricMessage' + +export class AsymmetricMessageFactory implements AsymmetricMessageFactoryInterface { + constructor(private timer: TimerInterface) {} + + create(dto: AsymmetricMessageHash): AsymmetricMessage { + const newAsymmetricMessage = new AsymmetricMessage() + newAsymmetricMessage.uuid = dto.uuid + newAsymmetricMessage.userUuid = dto.user_uuid + newAsymmetricMessage.senderUuid = dto.sender_uuid + newAsymmetricMessage.senderPublicKey = dto.sender_public_key + newAsymmetricMessage.encryptedMessage = dto.encrypted_message + + const now = this.timer.getTimestampInMicroseconds() + newAsymmetricMessage.updatedAtTimestamp = now + newAsymmetricMessage.createdAtTimestamp = now + + if (dto.created_at_timestamp) { + newAsymmetricMessage.createdAtTimestamp = dto.created_at_timestamp + } + + return newAsymmetricMessage + } + + createStub(dto: AsymmetricMessageHash): AsymmetricMessage { + const item = this.create(dto) + return item + } +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactoryInterface.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactoryInterface.ts new file mode 100644 index 000000000..f5f8c5fa1 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageFactoryInterface.ts @@ -0,0 +1,7 @@ +import { AsymmetricMessage } from '../Model/AsymmetricMessage' +import { AsymmetricMessageHash } from './AsymmetricMessageHash' + +export interface AsymmetricMessageFactoryInterface { + create(dto: AsymmetricMessageHash): AsymmetricMessage + createStub(dto: AsymmetricMessageHash): AsymmetricMessage +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageHash.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageHash.ts new file mode 100644 index 000000000..b91131bdc --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Factory/AsymmetricMessageHash.ts @@ -0,0 +1,9 @@ +export type AsymmetricMessageHash = { + uuid: string + user_uuid: string + sender_uuid: string + sender_public_key: string + encrypted_message: string + created_at_timestamp?: number + updated_at_timestamp?: number +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Model/AsymmetricMessage.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Model/AsymmetricMessage.ts new file mode 100644 index 000000000..cc9857d82 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Model/AsymmetricMessage.ts @@ -0,0 +1,40 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm' + +@Entity({ name: 'asymmetric_messages' }) +export class AsymmetricMessage { + @PrimaryGeneratedColumn('uuid') + declare uuid: string + + @Column({ + name: 'user_uuid', + length: 36, + }) + declare userUuid: string + + @Column({ + name: 'sender_uuid', + }) + declare senderUuid: string + + @Column({ + name: 'sender_public_key', + }) + declare senderPublicKey: string + + @Column({ + name: 'encrypted_message', + }) + declare encryptedMessage: string + + @Column({ + name: 'created_at_timestamp', + type: 'bigint', + }) + declare createdAtTimestamp: number + + @Column({ + name: 'updated_at_timestamp', + type: 'bigint', + }) + declare updatedAtTimestamp: number +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Repository/AsymmetricMessageRepositoryInterface.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Repository/AsymmetricMessageRepositoryInterface.ts new file mode 100644 index 000000000..d2776db42 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Repository/AsymmetricMessageRepositoryInterface.ts @@ -0,0 +1,19 @@ +import { AsymmetricMessage } from '../Model/AsymmetricMessage' + +export type AsymmetricMessageQuery = { + userUuid: string +} + +export type AsymmetricMessageFindAllForUserQuery = { + userUuid?: string + lastSyncTime?: number + senderUuid?: string +} + +export interface AsymmetricMessageRepositoryInterface { + findByUuid(asymmetricMessageUuid: string): Promise + create(sharedVault: AsymmetricMessage): Promise + save(asymmetricMessage: AsymmetricMessage): Promise + remove(sharedVault: AsymmetricMessage): Promise + findAll(query: AsymmetricMessageFindAllForUserQuery): Promise +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Repository/TypeORMAsymmetricMessageRepository.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Repository/TypeORMAsymmetricMessageRepository.ts new file mode 100644 index 000000000..928fd630b --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Repository/TypeORMAsymmetricMessageRepository.ts @@ -0,0 +1,57 @@ +import { AsymmetricMessage } from '../Model/AsymmetricMessage' +import { Repository, SelectQueryBuilder } from 'typeorm' +import { + AsymmetricMessageFindAllForUserQuery, + AsymmetricMessageRepositoryInterface, +} from './AsymmetricMessageRepositoryInterface' + +export class TypeORMAsymmetricMessageRepository implements AsymmetricMessageRepositoryInterface { + constructor(private ormRepository: Repository) {} + + async create(asymmetricMessage: AsymmetricMessage): Promise { + return this.ormRepository.save(asymmetricMessage) + } + + async save(asymmetricMessage: AsymmetricMessage): Promise { + return this.ormRepository.save(asymmetricMessage) + } + + findByUuid(uuid: string): Promise { + return this.ormRepository + .createQueryBuilder('asymmetric_message') + .where('asymmetric_message.uuid = :uuid', { + uuid, + }) + .getOne() + } + + async remove(asymmetricMessage: AsymmetricMessage): Promise { + return this.ormRepository.remove(asymmetricMessage) + } + + async findAll(query: AsymmetricMessageFindAllForUserQuery): Promise { + return this.createFindAllQueryBuilder(query).getMany() + } + + private createFindAllQueryBuilder( + query: AsymmetricMessageFindAllForUserQuery, + ): SelectQueryBuilder { + const queryBuilder = this.ormRepository.createQueryBuilder('asymmetric_message') + + if (query.userUuid) { + queryBuilder.where('asymmetric_message.user_uuid = :userUuid', { userUuid: query.userUuid }) + } else if (query.senderUuid) { + queryBuilder.where('asymmetric_message.sender_uuid = :senderUuid', { + senderUuid: query.senderUuid, + }) + } + + if (query.lastSyncTime) { + queryBuilder.andWhere('asymmetric_message.updated_at_timestamp > :lastSyncTime', { + lastSyncTime: query.lastSyncTime, + }) + } + + return queryBuilder + } +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageService.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageService.ts new file mode 100644 index 000000000..c994b350d --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageService.ts @@ -0,0 +1,82 @@ +import { UpdateAsymmetricMessageDTO } from './UpdateAsymmetricMessageDTO' +import { TimerInterface } from '@standardnotes/time' +import { AsymmetricMessage } from '../Model/AsymmetricMessage' +import { AsymmetricMessageFactoryInterface } from '../Factory/AsymmetricMessageFactoryInterface' +import { v4 as uuidv4 } from 'uuid' +import { AsymmetricMessageRepositoryInterface } from '../Repository/AsymmetricMessageRepositoryInterface' +import { AsymmetricMessageServiceInterface } from './AsymmetricMessageServiceInterface' +import { GetUserAsymmetricMessagesDTO } from './GetUserAsymmetricMessagesDTO' +import { CreateAsymmetricMessageDTO } from './CreateAsymmetricMessageDTO' + +export class AsymmetricMessageService implements AsymmetricMessageServiceInterface { + constructor( + private asymmetricMessageRepository: AsymmetricMessageRepositoryInterface, + private asymmetricMessageFactory: AsymmetricMessageFactoryInterface, + private timer: TimerInterface, + ) {} + + async createMessage(dto: CreateAsymmetricMessageDTO): Promise { + const timestamp = this.timer.getTimestampInMicroseconds() + + const asymmetricMessage = this.asymmetricMessageFactory.create({ + uuid: uuidv4(), + user_uuid: dto.userUuid, + sender_uuid: dto.senderUuid, + sender_public_key: dto.senderPublicKey, + encrypted_message: dto.encryptedMessage, + created_at_timestamp: timestamp, + updated_at_timestamp: timestamp, + }) + + return this.asymmetricMessageRepository.create(asymmetricMessage) + } + + async updateMessage(dto: UpdateAsymmetricMessageDTO): Promise { + const asymmetricMessage = await this.asymmetricMessageRepository.findByUuid(dto.messageUuid) + if (!asymmetricMessage || asymmetricMessage.senderUuid !== dto.senderUuid) { + return null + } + + asymmetricMessage.senderPublicKey = dto.senderPublicKey + asymmetricMessage.encryptedMessage = dto.encryptedMessage + asymmetricMessage.updatedAtTimestamp = this.timer.getTimestampInMicroseconds() + + return this.asymmetricMessageRepository.save(asymmetricMessage) + } + + getMessagesForUser(dto: GetUserAsymmetricMessagesDTO): Promise { + return this.asymmetricMessageRepository.findAll(dto) + } + + getOutboundMessagesForUser(dto: { userUuid: string }): Promise { + return this.asymmetricMessageRepository.findAll({ + senderUuid: dto.userUuid, + }) + } + + async deleteAllInboundMessages(dto: { userUuid: string }): Promise { + const inboundMessages = await this.asymmetricMessageRepository.findAll({ + userUuid: dto.userUuid, + }) + + for (const message of inboundMessages) { + await this.asymmetricMessageRepository.remove(message) + } + } + + async deleteMessage(dto: { originatorUuid: string; messageUuid: string }): Promise { + const message = await this.asymmetricMessageRepository.findByUuid(dto.messageUuid) + if (!message) { + return false + } + + const isAuthorized = message.senderUuid === dto.originatorUuid || message.userUuid === dto.originatorUuid + if (!isAuthorized) { + return false + } + + await this.asymmetricMessageRepository.remove(message) + + return true + } +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageServiceInterface.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageServiceInterface.ts new file mode 100644 index 000000000..054a092f1 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/AsymmetricMessageServiceInterface.ts @@ -0,0 +1,15 @@ +import { UpdateAsymmetricMessageDTO } from './UpdateAsymmetricMessageDTO' +import { AsymmetricMessage } from '../Model/AsymmetricMessage' +import { GetUserAsymmetricMessagesDTO } from './GetUserAsymmetricMessagesDTO' +import { CreateAsymmetricMessageDTO } from './CreateAsymmetricMessageDTO' + +export interface AsymmetricMessageServiceInterface { + createMessage(dto: CreateAsymmetricMessageDTO): Promise + updateMessage(dto: UpdateAsymmetricMessageDTO): Promise + + getMessagesForUser(dto: GetUserAsymmetricMessagesDTO): Promise + getOutboundMessagesForUser(dto: { userUuid: string }): Promise + + deleteAllInboundMessages(dto: { userUuid: string }): Promise + deleteMessage(dto: { originatorUuid: string; messageUuid: string }): Promise +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Service/CreateAsymmetricMessageDTO.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/CreateAsymmetricMessageDTO.ts new file mode 100644 index 000000000..a5803fe04 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/CreateAsymmetricMessageDTO.ts @@ -0,0 +1,6 @@ +export type CreateAsymmetricMessageDTO = { + userUuid: string + senderUuid: string + senderPublicKey: string + encryptedMessage: string +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Service/GetUserAsymmetricMessagesDTO.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/GetUserAsymmetricMessagesDTO.ts new file mode 100644 index 000000000..1544cf933 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/GetUserAsymmetricMessagesDTO.ts @@ -0,0 +1,4 @@ +export interface GetUserAsymmetricMessagesDTO { + userUuid: string + lastSyncTime?: number +} diff --git a/packages/syncing-server/src/Domain/AsymmetricMessage/Service/UpdateAsymmetricMessageDTO.ts b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/UpdateAsymmetricMessageDTO.ts new file mode 100644 index 000000000..fecacdb28 --- /dev/null +++ b/packages/syncing-server/src/Domain/AsymmetricMessage/Service/UpdateAsymmetricMessageDTO.ts @@ -0,0 +1,6 @@ +export type UpdateAsymmetricMessageDTO = { + messageUuid: string + senderUuid: string + senderPublicKey: string + encryptedMessage: string +} diff --git a/packages/syncing-server/src/Domain/Handler/UserCredentialsChangedEventHandler.ts b/packages/syncing-server/src/Domain/Handler/UserCredentialsChangedEventHandler.ts deleted file mode 100644 index bca7e1c5b..000000000 --- a/packages/syncing-server/src/Domain/Handler/UserCredentialsChangedEventHandler.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { - DomainEventHandlerInterface, - UserCredentialsChangedEvent, - UserCredentialsChangedEventPayload, -} from '@standardnotes/domain-events' -import { TimerInterface } from '@standardnotes/time' -import { ContactsRepositoryInterface } from '../Contact/Repository/ContactRepositoryInterface' -import { SharedVaultInviteRepositoryInterface } from '../SharedVaultInvite/Repository/SharedVaultInviteRepositoryInterface' - -export class UserCredentialsChangedEventHandler implements DomainEventHandlerInterface { - constructor( - private contactRepository: ContactsRepositoryInterface, - private sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface, - private timer: TimerInterface, - ) {} - - async handle(event: UserCredentialsChangedEvent): Promise { - await this.updatePublicKeyOfAllContacts(event.payload) - - await this.nullifyPendingInboundSharedVaultInvites(event.payload) - } - - private async updatePublicKeyOfAllContacts(payload: UserCredentialsChangedEventPayload): Promise { - const contacts = await this.contactRepository.findAll({ contactUuid: payload.userUuid }) - for (const contact of contacts) { - if (contact.contactPublicKey === payload.newPublicKey) { - continue - } - - contact.contactPublicKey = payload.newPublicKey - contact.contactSigningPublicKey = payload.newSigningPublicKey - - contact.updatedAtTimestamp = this.timer.getTimestampInMicroseconds() - - await this.contactRepository.save(contact) - } - } - - private async nullifyPendingInboundSharedVaultInvites(payload: UserCredentialsChangedEventPayload): Promise { - const inboundInvites = await this.sharedVaultInviteRepository.findAll({ - userUuid: payload.userUuid, - }) - - for (const invite of inboundInvites) { - await this.sharedVaultInviteRepository.remove(invite) - } - } -} diff --git a/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponse20200115.ts b/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponse20200115.ts index d621133ef..322856c39 100644 --- a/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponse20200115.ts +++ b/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponse20200115.ts @@ -1,4 +1,4 @@ -import { ContactProjection } from '../../../Projection/ContactProjection' +import { AsymmetricMessageProjection } from './../../../Projection/AsymmetricMessageProjection' import { SharedVaultInviteProjection } from '../../../Projection/SharedVaultInviteProjection' import { SharedVaultProjection } from '../../../Projection/SharedVaultProjection' import { ItemConflictProjection } from '../../../Projection/ItemConflictProjection' @@ -12,7 +12,7 @@ export type SyncResponse20200115 = { conflicts: Array sync_token: string cursor_token?: string - contacts: Array + asymmetric_messages: Array shared_vaults: Array shared_vault_invites: Array user_events: Array diff --git a/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponseFactory20200115.ts b/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponseFactory20200115.ts index bb3d5a2b8..72d157485 100644 --- a/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponseFactory20200115.ts +++ b/packages/syncing-server/src/Domain/Item/SyncResponse/SyncResponseFactory20200115.ts @@ -1,5 +1,6 @@ +import { AsymmetricMessageProjection } from './../../../Projection/AsymmetricMessageProjection' +import { AsymmetricMessage } from './../../AsymmetricMessage/Model/AsymmetricMessage' import { SharedVaultInvite } from '../../SharedVaultInvite/Model/SharedVaultInvite' -import { Contact } from './../../Contact/Model/Contact' import { ProjectorInterface } from '../../../Projection/ProjectorInterface' import { SyncItemsResponse } from '../../UseCase/SyncItemsResponse' import { Item } from '../Item' @@ -9,7 +10,6 @@ import { ItemProjection } from '../../../Projection/ItemProjection' import { SyncResponse20200115 } from './SyncResponse20200115' import { SyncResponseFactoryInterface } from './SyncResponseFactoryInterface' import { SavedItemProjection } from '../../../Projection/SavedItemProjection' -import { ContactProjection } from '../../../Projection/ContactProjection' import { SharedVaultInviteProjection } from '../../../Projection/SharedVaultInviteProjection' import { SharedVaultProjection } from '../../../Projection/SharedVaultProjection' import { SharedVault } from '../../SharedVault/Model/SharedVault' @@ -22,7 +22,7 @@ export class SyncResponseFactory20200115 implements SyncResponseFactoryInterface private itemConflictProjector: ProjectorInterface, private savedItemProjector: ProjectorInterface, private sharedVaultInviteProjector: ProjectorInterface, - private contactProjector: ProjectorInterface, + private asymmetricMessageProjector: ProjectorInterface, private sharedVaultProjector: ProjectorInterface, private userEventProjector: ProjectorInterface, ) {} @@ -53,9 +53,9 @@ export class SyncResponseFactory20200115 implements SyncResponseFactoryInterface sharedVaultInvites.push(this.sharedVaultInviteProjector.projectFull(sharedVaultInvite)) } - const contacts = [] - for (const contact of syncItemsResponse.contacts) { - contacts.push(this.contactProjector.projectFull(contact)) + const asymmetricMessages = [] + for (const contact of syncItemsResponse.asymmetricMessages) { + asymmetricMessages.push(this.asymmetricMessageProjector.projectFull(contact)) } const userEvents = [] @@ -69,10 +69,10 @@ export class SyncResponseFactory20200115 implements SyncResponseFactoryInterface conflicts, sync_token: syncItemsResponse.syncToken, cursor_token: syncItemsResponse.cursorToken, + asymmetric_messages: asymmetricMessages, + user_events: userEvents, shared_vaults: sharedVaults, shared_vault_invites: sharedVaultInvites, - user_events: userEvents, - contacts, } } } diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteFactory.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteFactory.ts index 1260af0f1..2230c8895 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteFactory.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteFactory.ts @@ -11,9 +11,9 @@ export class SharedVaultInviteFactory implements SharedVaultInviteFactoryInterfa newSharedVaultInvite.uuid = dto.uuid newSharedVaultInvite.userUuid = dto.user_uuid newSharedVaultInvite.sharedVaultUuid = dto.shared_vault_uuid - newSharedVaultInvite.inviterUuid = dto.inviter_uuid - newSharedVaultInvite.inviterPublicKey = dto.sender_public_key - newSharedVaultInvite.encryptedVaultKeyContent = dto.encrypted_message + newSharedVaultInvite.senderUuid = dto.sender_uuid + newSharedVaultInvite.senderPublicKey = dto.sender_public_key + newSharedVaultInvite.encryptedMessage = dto.encrypted_message newSharedVaultInvite.permissions = dto.permissions const now = this.timer.getTimestampInMicroseconds() diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteHash.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteHash.ts index e15a10744..2eb17326a 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteHash.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Factory/SharedVaultInviteHash.ts @@ -4,7 +4,7 @@ export type SharedVaultInviteHash = { uuid: string user_uuid: string shared_vault_uuid: string - inviter_uuid: string + sender_uuid: string sender_public_key: string encrypted_message: string permissions: SharedVaultUserPermission diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Model/SharedVaultInvite.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Model/SharedVaultInvite.ts index 74d46485f..9bbdbe449 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Model/SharedVaultInvite.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Model/SharedVaultInvite.ts @@ -19,19 +19,19 @@ export class SharedVaultInvite { declare userUuid: string @Column({ - name: 'inviter_uuid', + name: 'sender_uuid', }) - declare inviterUuid: string + declare senderUuid: string @Column({ name: 'sender_public_key', }) - declare inviterPublicKey: string + declare senderPublicKey: string @Column({ name: 'encrypted_message', }) - declare encryptedVaultKeyContent: string + declare encryptedMessage: string @Column({ name: 'permissions', diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/SharedVaultInviteRepositoryInterface.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/SharedVaultInviteRepositoryInterface.ts index 3cc3a936c..9ece908a0 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/SharedVaultInviteRepositoryInterface.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/SharedVaultInviteRepositoryInterface.ts @@ -7,7 +7,7 @@ export type SharedVaultInviteQuery = { export type SharedVaultInviteFindAllForUserQuery = { userUuid?: string lastSyncTime?: number - inviterUuid?: string + senderUuid?: string } export type SharedVaultInviteFindAllForSharedVault = { diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/TypeORMSharedVaultInviteRepository.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/TypeORMSharedVaultInviteRepository.ts index 238e5f83d..cb30b7305 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/TypeORMSharedVaultInviteRepository.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Repository/TypeORMSharedVaultInviteRepository.ts @@ -54,9 +54,9 @@ export class TypeORMSharedVaultInviteRepository implements SharedVaultInviteRepo if (query.userUuid) { queryBuilder.where('shared_vault_invite.user_uuid = :userUuid', { userUuid: query.userUuid }) - } else if (query.inviterUuid) { - queryBuilder.where('shared_vault_invite.inviter_uuid = :inviterUuid', { - inviterUuid: query.inviterUuid, + } else if (query.senderUuid) { + queryBuilder.where('shared_vault_invite.sender_uuid = :senderUuid', { + senderUuid: query.senderUuid, }) } diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Service/CreateInviteDTO.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Service/CreateInviteDTO.ts index b9c47663c..b79ecee72 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Service/CreateInviteDTO.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Service/CreateInviteDTO.ts @@ -1,10 +1,10 @@ import { SharedVaultUserPermission } from '../../SharedVaultUser/Model/SharedVaultUserPermission' export type CreateInviteDTO = { - originatorUuid: string - sharedVaultUuid: string userUuid: string - inviterPublicKey: string - encryptedVaultKeyContent: string + sharedVaultUuid: string + senderUuid: string + senderPublicKey: string + encryptedMessage: string permissions: SharedVaultUserPermission } diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Service/SharedVaultInviteService.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Service/SharedVaultInviteService.ts index fa568a424..a40e8e675 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Service/SharedVaultInviteService.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Service/SharedVaultInviteService.ts @@ -21,7 +21,7 @@ export class SharedVaultInviteService implements SharedVaultInviteServiceInterfa async createInvite(dto: CreateInviteDTO): Promise { const sharedVault = await this.sharedVaultRepository.findByUuid(dto.sharedVaultUuid) - if (!sharedVault || sharedVault.userUuid !== dto.originatorUuid) { + if (!sharedVault || sharedVault.userUuid !== dto.senderUuid) { return null } @@ -31,9 +31,9 @@ export class SharedVaultInviteService implements SharedVaultInviteServiceInterfa uuid: uuidv4(), user_uuid: dto.userUuid, shared_vault_uuid: dto.sharedVaultUuid, - inviter_uuid: dto.originatorUuid, - sender_public_key: dto.inviterPublicKey, - encrypted_message: dto.encryptedVaultKeyContent, + sender_uuid: dto.senderUuid, + sender_public_key: dto.senderPublicKey, + encrypted_message: dto.encryptedMessage, permissions: dto.permissions, created_at_timestamp: timestamp, updated_at_timestamp: timestamp, @@ -44,12 +44,12 @@ export class SharedVaultInviteService implements SharedVaultInviteServiceInterfa async updateInvite(dto: UpdateInviteDTO): Promise { const sharedVaultInvite = await this.sharedVaultInviteRepository.findByUuid(dto.inviteUuid) - if (!sharedVaultInvite || sharedVaultInvite.inviterUuid !== dto.originatorUuid) { + if (!sharedVaultInvite || sharedVaultInvite.senderUuid !== dto.senderUuid) { return null } - sharedVaultInvite.inviterPublicKey = dto.inviterPublicKey - sharedVaultInvite.encryptedVaultKeyContent = dto.encryptedVaultKeyContent + sharedVaultInvite.senderPublicKey = dto.senderPublicKey + sharedVaultInvite.encryptedMessage = dto.encryptedMessage if (dto.permissions) { sharedVaultInvite.permissions = dto.permissions } @@ -64,7 +64,7 @@ export class SharedVaultInviteService implements SharedVaultInviteServiceInterfa getOutboundInvitesForUser(dto: { userUuid: string }): Promise { return this.sharedVaultInviteRepository.findAll({ - inviterUuid: dto.userUuid, + senderUuid: dto.userUuid, }) } @@ -145,7 +145,7 @@ export class SharedVaultInviteService implements SharedVaultInviteServiceInterfa return false } - const isAuthorized = invite.inviterUuid === dto.originatorUuid || invite.userUuid === dto.originatorUuid + const isAuthorized = invite.senderUuid === dto.originatorUuid || invite.userUuid === dto.originatorUuid if (!isAuthorized) { return false } diff --git a/packages/syncing-server/src/Domain/SharedVaultInvite/Service/UpdateInviteDTO.ts b/packages/syncing-server/src/Domain/SharedVaultInvite/Service/UpdateInviteDTO.ts index 75e2b9524..844b72d2a 100644 --- a/packages/syncing-server/src/Domain/SharedVaultInvite/Service/UpdateInviteDTO.ts +++ b/packages/syncing-server/src/Domain/SharedVaultInvite/Service/UpdateInviteDTO.ts @@ -1,9 +1,9 @@ import { SharedVaultUserPermission } from '../../SharedVaultUser/Model/SharedVaultUserPermission' export type UpdateInviteDTO = { - originatorUuid: string inviteUuid: string - inviterPublicKey: string - encryptedVaultKeyContent: string + senderUuid: string + senderPublicKey: string + encryptedMessage: string permissions?: SharedVaultUserPermission } diff --git a/packages/syncing-server/src/Domain/UseCase/SyncItems.ts b/packages/syncing-server/src/Domain/UseCase/SyncItems.ts index 2185e1549..886416108 100644 --- a/packages/syncing-server/src/Domain/UseCase/SyncItems.ts +++ b/packages/syncing-server/src/Domain/UseCase/SyncItems.ts @@ -1,4 +1,3 @@ -import { ContactServiceInterface } from './../Contact/Service/ContactServiceInterface' import { Item } from '../Item/Item' import { ItemConflict } from '../Item/ItemConflict' import { ItemServiceInterface } from '../Item/ItemServiceInterface' @@ -8,13 +7,14 @@ import { UseCaseInterface } from './UseCaseInterface' import { SharedVaultInviteServiceInterface } from '../SharedVaultInvite/Service/SharedVaultInviteServiceInterface' import { SharedVaultServiceInterface } from '../SharedVault/Service/SharedVaultServiceInterface' import { UserEventServiceInterface } from '../UserEvent/Service/UserEventServiceInterface' +import { AsymmetricMessageServiceInterface } from '../AsymmetricMessage/Service/AsymmetricMessageServiceInterface' export class SyncItems implements UseCaseInterface { constructor( private itemService: ItemServiceInterface, private sharedVaultService: SharedVaultServiceInterface, private sharedVaultInviteService: SharedVaultInviteServiceInterface, - private contactService: ContactServiceInterface, + private asymmetricMessageService: AsymmetricMessageServiceInterface, private userEventService: UserEventServiceInterface, ) {} @@ -58,7 +58,7 @@ export class SyncItems implements UseCaseInterface { lastSyncTime, }) - const contacts = await this.contactService.getUserContacts({ + const asymmetricMessages = await this.asymmetricMessageService.getMessagesForUser({ userUuid: dto.userUuid, lastSyncTime: lastSyncTime, }) @@ -77,7 +77,7 @@ export class SyncItems implements UseCaseInterface { sharedVaults, sharedVaultInvites, userEvents, - contacts, + asymmetricMessages, } return syncResponse diff --git a/packages/syncing-server/src/Domain/UseCase/SyncItemsResponse.ts b/packages/syncing-server/src/Domain/UseCase/SyncItemsResponse.ts index d941f032b..f9eaccaab 100644 --- a/packages/syncing-server/src/Domain/UseCase/SyncItemsResponse.ts +++ b/packages/syncing-server/src/Domain/UseCase/SyncItemsResponse.ts @@ -1,5 +1,5 @@ +import { AsymmetricMessage } from './../AsymmetricMessage/Model/AsymmetricMessage' import { SharedVaultInvite } from '../SharedVaultInvite/Model/SharedVaultInvite' -import { Contact } from '../Contact/Model/Contact' import { Item } from '../Item/Item' import { ItemConflict } from '../Item/ItemConflict' import { SharedVault } from '../SharedVault/Model/SharedVault' @@ -12,7 +12,7 @@ export type SyncItemsResponse = { sharedVaults: Array sharedVaultInvites: Array userEvents: Array - contacts: Array + asymmetricMessages: Array syncToken: string cursorToken?: string } diff --git a/packages/syncing-server/src/Projection/AsymmetricMessageProjection.ts b/packages/syncing-server/src/Projection/AsymmetricMessageProjection.ts new file mode 100644 index 000000000..3cddb425d --- /dev/null +++ b/packages/syncing-server/src/Projection/AsymmetricMessageProjection.ts @@ -0,0 +1,9 @@ +export type AsymmetricMessageProjection = { + uuid: string + user_uuid: string + sender_uuid: string + sender_public_key: string + encrypted_message: string + created_at_timestamp: number + updated_at_timestamp: number +} diff --git a/packages/syncing-server/src/Projection/AsymmetricMessageProjector.ts b/packages/syncing-server/src/Projection/AsymmetricMessageProjector.ts new file mode 100644 index 000000000..2ed2730ea --- /dev/null +++ b/packages/syncing-server/src/Projection/AsymmetricMessageProjector.ts @@ -0,0 +1,30 @@ +import { AsymmetricMessage } from '../Domain/AsymmetricMessage/Model/AsymmetricMessage' +import { ProjectorInterface } from './ProjectorInterface' +import { AsymmetricMessageProjection } from './AsymmetricMessageProjection' + +export class AsymmetricMessageProjector implements ProjectorInterface { + projectSimple(_asymmetricMessage: AsymmetricMessage): AsymmetricMessageProjection { + throw Error('not implemented') + } + + projectCustom(_projectionType: string, asymmetricMessage: AsymmetricMessage): AsymmetricMessageProjection { + const fullProjection = this.projectFull(asymmetricMessage) + + return { + ...fullProjection, + user_uuid: asymmetricMessage.userUuid, + } + } + + projectFull(asymmetricMessage: AsymmetricMessage): AsymmetricMessageProjection { + return { + uuid: asymmetricMessage.uuid, + user_uuid: asymmetricMessage.userUuid, + sender_uuid: asymmetricMessage.senderUuid, + sender_public_key: asymmetricMessage.senderPublicKey, + encrypted_message: asymmetricMessage.encryptedMessage, + created_at_timestamp: asymmetricMessage.createdAtTimestamp, + updated_at_timestamp: asymmetricMessage.updatedAtTimestamp, + } + } +} diff --git a/packages/syncing-server/src/Projection/SharedVaultInviteProjection.ts b/packages/syncing-server/src/Projection/SharedVaultInviteProjection.ts index 4d9321d02..9a7257264 100644 --- a/packages/syncing-server/src/Projection/SharedVaultInviteProjection.ts +++ b/packages/syncing-server/src/Projection/SharedVaultInviteProjection.ts @@ -2,7 +2,7 @@ export type SharedVaultInviteProjection = { uuid: string shared_vault_uuid: string user_uuid: string - inviter_uuid: string + sender_uuid: string sender_public_key: string encrypted_message: string permissions: string diff --git a/packages/syncing-server/src/Projection/SharedVaultInviteProjector.ts b/packages/syncing-server/src/Projection/SharedVaultInviteProjector.ts index 681d6021f..63cd1a3b4 100644 --- a/packages/syncing-server/src/Projection/SharedVaultInviteProjector.ts +++ b/packages/syncing-server/src/Projection/SharedVaultInviteProjector.ts @@ -21,9 +21,9 @@ export class SharedVaultInviteProjector implements ProjectorInterface