feat: messages controller. (#653)

Co-authored-by: Mo <[email protected]>
This commit is contained in:
Karol Sójko
2023-07-10 14:21:59 +02:00
committed by GitHub
co-authored by Mo
parent cbc024f67a
commit 18d07d431f
5 changed files with 236 additions and 1 deletions
@@ -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
@@ -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 })
}
}
@@ -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)
}
}
@@ -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,
}
}
}
@@ -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
}