Explorar o código

feat: messages controller. (#653)

Co-authored-by: Mo <mo@standardnotes.com>
Karol Sójko hai 1 ano
pai
achega
18d07d431f

+ 7 - 1
packages/syncing-server/src/Bootstrap/Types.ts

@@ -52,7 +52,11 @@ const TYPES = {
   Sync_DeleteSharedVaultInvitesSentByUser: Symbol.for('Sync_DeleteSharedVaultInvitesSentByUser'),
   Sync_GetSharedVaultInvitesSentByUser: Symbol.for('Sync_GetSharedVaultInvitesSentByUser'),
   Sync_GetSharedVaultInvitesSentToUser: Symbol.for('Sync_GetSharedVaultInvitesSentToUser'),
-  Sync_SharedVaultInviteHttpMapper: Symbol.for('Sync_SharedVaultInviteHttpMapper'),
+  Sync_GetMessagesSentToUser: Symbol.for('Sync_GetMessagesSentToUser'),
+  Sync_GetMessagesSentByUser: Symbol.for('Sync_GetMessagesSentByUser'),
+  Sync_SendMessageToUser: Symbol.for('Sync_SendMessageToUser'),
+  Sync_DeleteAllMessagesSentToUser: Symbol.for('Sync_DeleteAllMessagesSentToUser'),
+  Sync_DeleteMessage: Symbol.for('Sync_DeleteMessage'),
   // Handlers
   Sync_AccountDeletionRequestedEventHandler: Symbol.for('Sync_AccountDeletionRequestedEventHandler'),
   Sync_DuplicateItemSyncedEventHandler: Symbol.for('Sync_DuplicateItemSyncedEventHandler'),
@@ -86,6 +90,8 @@ const TYPES = {
   // Mapping
   Sync_SharedVaultHttpMapper: Symbol.for('Sync_SharedVaultHttpMapper'),
   Sync_SharedVaultUserHttpMapper: Symbol.for('Sync_SharedVaultUserHttpMapper'),
+  Sync_SharedVaultInviteHttpMapper: Symbol.for('Sync_SharedVaultInviteHttpMapper'),
+  Sync_MessageHttpMapper: Symbol.for('Sync_MessageHttpMapper'),
 }
 
 export default TYPES

+ 138 - 0
packages/syncing-server/src/Infra/InversifyExpressUtils/HomeServer/HomeServerMessagesController.ts

@@ -0,0 +1,138 @@
+import { Request, Response } from 'express'
+import { BaseHttpController, results } from 'inversify-express-utils'
+import { HttpStatusCode } from '@standardnotes/responses'
+import { ControllerContainerInterface, MapperInterface } from '@standardnotes/domain-core'
+import { GetMessagesSentToUser } from '../../../Domain/UseCase/Messaging/GetMessagesSentToUser/GetMessagesSentToUser'
+import { MessageHttpRepresentation } from '../../../Mapping/Http/MessageHttpRepresentation'
+import { Message } from '../../../Domain/Message/Message'
+import { SendMessageToUser } from '../../../Domain/UseCase/Messaging/SendMessageToUser/SendMessageToUser'
+import { DeleteAllMessagesSentToUser } from '../../../Domain/UseCase/Messaging/DeleteAllMessagesSentToUser/DeleteAllMessagesSentToUser'
+import { DeleteMessage } from '../../../Domain/UseCase/Messaging/DeleteMessage/DeleteMessage'
+import { GetMessagesSentByUser } from '../../../Domain/UseCase/Messaging/GetMessagesSentByUser/GetMessagesSentByUser'
+
+export class HomeServerMessagesController extends BaseHttpController {
+  constructor(
+    protected getMessageSentToUserUseCase: GetMessagesSentToUser,
+    protected getMessagesSentByUserUseCase: GetMessagesSentByUser,
+    protected sendMessageToUserUseCase: SendMessageToUser,
+    protected deleteMessagesSentToUserUseCase: DeleteAllMessagesSentToUser,
+    protected deleteMessageUseCase: DeleteMessage,
+    protected messageHttpMapper: MapperInterface<Message, MessageHttpRepresentation>,
+    private controllerContainer?: ControllerContainerInterface,
+  ) {
+    super()
+
+    if (this.controllerContainer !== undefined) {
+      this.controllerContainer.register('sync.messages.get-received', this.getMessages.bind(this))
+      this.controllerContainer.register('sync.messages.get-sent', this.getMessagesSent.bind(this))
+      this.controllerContainer.register('sync.messages.send', this.sendMessage.bind(this))
+      this.controllerContainer.register('sync.messages.delete-all', this.deleteMessagesSentToUser.bind(this))
+      this.controllerContainer.register('sync.messages.delete', this.deleteMessage.bind(this))
+    }
+  }
+
+  async getMessages(_request: Request, response: Response): Promise<results.JsonResult> {
+    const result = await this.getMessageSentToUserUseCase.execute({
+      recipientUuid: response.locals.user.uuid,
+    })
+
+    if (result.isFailed()) {
+      return this.json(
+        {
+          error: {
+            message: result.getError(),
+          },
+        },
+        HttpStatusCode.BadRequest,
+      )
+    }
+
+    return this.json({
+      messages: result.getValue().map((message) => this.messageHttpMapper.toProjection(message)),
+    })
+  }
+
+  async getMessagesSent(_request: Request, response: Response): Promise<results.JsonResult> {
+    const result = await this.getMessagesSentByUserUseCase.execute({
+      senderUuid: response.locals.user.uuid,
+    })
+
+    if (result.isFailed()) {
+      return this.json(
+        {
+          error: {
+            message: result.getError(),
+          },
+        },
+        HttpStatusCode.BadRequest,
+      )
+    }
+
+    return this.json({
+      messages: result.getValue().map((message) => this.messageHttpMapper.toProjection(message)),
+    })
+  }
+
+  async sendMessage(request: Request, response: Response): Promise<results.JsonResult> {
+    const result = await this.sendMessageToUserUseCase.execute({
+      senderUuid: response.locals.user.uuid,
+      recipientUuid: request.body.recipient_uuid,
+      encryptedMessage: request.body.encrypted_message,
+      replaceabilityIdentifier: request.body.replaceability_identifier,
+    })
+
+    if (result.isFailed()) {
+      return this.json(
+        {
+          error: {
+            message: result.getError(),
+          },
+        },
+        HttpStatusCode.BadRequest,
+      )
+    }
+
+    return this.json({
+      message: this.messageHttpMapper.toProjection(result.getValue()),
+    })
+  }
+
+  async deleteMessagesSentToUser(_request: Request, response: Response): Promise<results.JsonResult> {
+    const result = await this.deleteMessagesSentToUserUseCase.execute({
+      recipientUuid: response.locals.user.uuid,
+    })
+
+    if (result.isFailed()) {
+      return this.json(
+        {
+          error: {
+            message: result.getError(),
+          },
+        },
+        HttpStatusCode.BadRequest,
+      )
+    }
+
+    return this.json({ success: true })
+  }
+
+  async deleteMessage(request: Request, response: Response): Promise<results.JsonResult> {
+    const result = await this.deleteMessageUseCase.execute({
+      messageUuid: request.params.messageUuid,
+      originatorUuid: response.locals.user.uuid,
+    })
+
+    if (result.isFailed()) {
+      return this.json(
+        {
+          error: {
+            message: result.getError(),
+          },
+        },
+        HttpStatusCode.BadRequest,
+      )
+    }
+
+    return this.json({ success: true })
+  }
+}

+ 62 - 0
packages/syncing-server/src/Infra/InversifyExpressUtils/InversifyExpressMessagesController.ts

@@ -0,0 +1,62 @@
+import { controller, httpDelete, httpGet, httpPost, results } from 'inversify-express-utils'
+import { inject } from 'inversify'
+import { MapperInterface } from '@standardnotes/domain-core'
+import { Request, Response } from 'express'
+
+import TYPES from '../../Bootstrap/Types'
+import { HomeServerMessagesController } from './HomeServer/HomeServerMessagesController'
+import { GetMessagesSentToUser } from '../../Domain/UseCase/Messaging/GetMessagesSentToUser/GetMessagesSentToUser'
+import { DeleteAllMessagesSentToUser } from '../../Domain/UseCase/Messaging/DeleteAllMessagesSentToUser/DeleteAllMessagesSentToUser'
+import { DeleteMessage } from '../../Domain/UseCase/Messaging/DeleteMessage/DeleteMessage'
+import { SendMessageToUser } from '../../Domain/UseCase/Messaging/SendMessageToUser/SendMessageToUser'
+import { MessageHttpRepresentation } from '../../Mapping/Http/MessageHttpRepresentation'
+import { Message } from '../../Domain/Message/Message'
+import { GetMessagesSentByUser } from '../../Domain/UseCase/Messaging/GetMessagesSentByUser/GetMessagesSentByUser'
+
+@controller('/messages', TYPES.Sync_AuthMiddleware)
+export class InversifyExpressMessagesController extends HomeServerMessagesController {
+  constructor(
+    @inject(TYPES.Sync_GetMessagesSentToUser) override getMessageSentToUserUseCase: GetMessagesSentToUser,
+    @inject(TYPES.Sync_GetMessagesSentByUser) override getMessagesSentByUserUseCase: GetMessagesSentByUser,
+    @inject(TYPES.Sync_SendMessageToUser) override sendMessageToUserUseCase: SendMessageToUser,
+    @inject(TYPES.Sync_DeleteAllMessagesSentToUser)
+    override deleteMessagesSentToUserUseCase: DeleteAllMessagesSentToUser,
+    @inject(TYPES.Sync_DeleteMessage) override deleteMessageUseCase: DeleteMessage,
+    @inject(TYPES.Sync_MessageHttpMapper)
+    override messageHttpMapper: MapperInterface<Message, MessageHttpRepresentation>,
+  ) {
+    super(
+      getMessageSentToUserUseCase,
+      getMessagesSentByUserUseCase,
+      sendMessageToUserUseCase,
+      deleteMessagesSentToUserUseCase,
+      deleteMessageUseCase,
+      messageHttpMapper,
+    )
+  }
+
+  @httpGet('/')
+  override async getMessages(_request: Request, response: Response): Promise<results.JsonResult> {
+    return super.getMessages(_request, response)
+  }
+
+  @httpGet('/outbound')
+  override async getMessagesSent(_request: Request, response: Response): Promise<results.JsonResult> {
+    return super.getMessagesSent(_request, response)
+  }
+
+  @httpPost('/')
+  override async sendMessage(request: Request, response: Response): Promise<results.JsonResult> {
+    return super.sendMessage(request, response)
+  }
+
+  @httpDelete('/inbound')
+  override async deleteMessagesSentToUser(_request: Request, response: Response): Promise<results.JsonResult> {
+    return super.deleteMessagesSentToUser(_request, response)
+  }
+
+  @httpDelete('/:messageUuid')
+  override async deleteMessage(request: Request, response: Response): Promise<results.JsonResult> {
+    return super.deleteMessage(request, response)
+  }
+}

+ 21 - 0
packages/syncing-server/src/Mapping/Http/MessageHttpMapper.ts

@@ -0,0 +1,21 @@
+import { MapperInterface } from '@standardnotes/domain-core'
+
+import { Message } from '../../Domain/Message/Message'
+import { MessageHttpRepresentation } from './MessageHttpRepresentation'
+
+export class MessageHttpMapper implements MapperInterface<Message, MessageHttpRepresentation> {
+  toDomain(_projection: MessageHttpRepresentation): Message {
+    throw new Error('Mapping from http representation to domain is not implemented.')
+  }
+
+  toProjection(domain: Message): MessageHttpRepresentation {
+    return {
+      uuid: domain.id.toString(),
+      recipient_uuid: domain.props.recipientUuid.value,
+      sender_uuid: domain.props.senderUuid.value,
+      encrypted_message: domain.props.encryptedMessage,
+      created_at_timestamp: domain.props.timestamps.createdAt,
+      updated_at_timestamp: domain.props.timestamps.updatedAt,
+    }
+  }
+}

+ 8 - 0
packages/syncing-server/src/Mapping/Http/MessageHttpRepresentation.ts

@@ -0,0 +1,8 @@
+export interface MessageHttpRepresentation {
+  uuid: string
+  recipient_uuid: string
+  sender_uuid: string
+  encrypted_message: string
+  created_at_timestamp: number
+  updated_at_timestamp: number
+}