From ad2278a79b11f0a67882bffe6fca036a444292db Mon Sep 17 00:00:00 2001 From: Kristaps Fabians Geikins Date: Fri, 13 Sep 2024 13:27:46 +0300 Subject: [PATCH] chore(server): notifications IoC 5 - newStreamAccessRequestHandlerFactory --- .../handlers/newStreamAccessRequest.ts | 136 +++++++++++------- 1 file changed, 84 insertions(+), 52 deletions(-) diff --git a/packages/server/modules/notifications/services/handlers/newStreamAccessRequest.ts b/packages/server/modules/notifications/services/handlers/newStreamAccessRequest.ts index 63c040d33..9daba03ed 100644 --- a/packages/server/modules/notifications/services/handlers/newStreamAccessRequest.ts +++ b/packages/server/modules/notifications/services/handlers/newStreamAccessRequest.ts @@ -21,47 +21,59 @@ import { } from '@/modules/emails/services/emailRendering' import { getServerInfo } from '@/modules/core/services/generic' import { db } from '@/db/knex' +import { GetPendingAccessRequest } from '@/modules/accessrequests/domain/operations' -async function validateMessage(msg: NewStreamAccessRequestMessage) { - const { - targetUserId, - data: { requestId } - } = msg - - const [request, user] = await Promise.all([ - getPendingAccessRequestFactory({ db })(requestId, AccessRequestType.Stream), - getUser(targetUserId) - ]) - - if (!request) - throw new NotificationValidationError('Nonexistant stream access request') - if (!user) throw new NotificationValidationError('Nonexistant user') - - const [streamWithRole, requester] = await Promise.all([ - getStream({ - streamId: request.resourceId, - userId: targetUserId - }), - getUser(request.requesterId) - ]) - - if (!streamWithRole) throw new NotificationValidationError('Nonexistant stream') - if (streamWithRole.role !== Roles.Stream.Owner) - throw new NotificationValidationError( - 'Only stream owners can receive notifications about stream access requests' - ) - if (!requester) - throw new NotificationValidationError('User who made the request no longer exists') - - return { - request, - stream: streamWithRole, - targetUser: user, - requester - } +type ValidateMessageDeps = { + getPendingAccessRequest: GetPendingAccessRequest + getUser: typeof getUser + getStream: typeof getStream } -type ValidatedMessageState = Awaited> +const validateMessageFactory = + (deps: ValidateMessageDeps) => async (msg: NewStreamAccessRequestMessage) => { + const { + targetUserId, + data: { requestId } + } = msg + + const [request, user] = await Promise.all([ + deps.getPendingAccessRequest(requestId, AccessRequestType.Stream), + deps.getUser(targetUserId) + ]) + + if (!request) + throw new NotificationValidationError('Nonexistant stream access request') + if (!user) throw new NotificationValidationError('Nonexistant user') + + const [streamWithRole, requester] = await Promise.all([ + deps.getStream({ + streamId: request.resourceId, + userId: targetUserId + }), + deps.getUser(request.requesterId) + ]) + + if (!streamWithRole) throw new NotificationValidationError('Nonexistant stream') + if (streamWithRole.role !== Roles.Stream.Owner) + throw new NotificationValidationError( + 'Only stream owners can receive notifications about stream access requests' + ) + if (!requester) + throw new NotificationValidationError( + 'User who made the request no longer exists' + ) + + return { + request, + stream: streamWithRole, + targetUser: user, + requester + } + } + +type ValidatedMessageState = Awaited< + ReturnType> +> function buildEmailTemplateHtml( state: ValidatedMessageState @@ -106,22 +118,42 @@ function buildEmailTemplateParams(state: ValidatedMessageState): EmailTemplatePa } } -const handler: NotificationHandler = async (msg) => { - const state = await validateMessage(msg) - const htmlTemplateParams = buildEmailTemplateParams(state) - const serverInfo = await getServerInfo() - const { html, text } = await renderEmail( - htmlTemplateParams, - serverInfo, - state.targetUser - ) +const newStreamAccessRequestHandlerFactory = + ( + deps: { + getServerInfo: typeof getServerInfo + renderEmail: typeof renderEmail + sendEmail: typeof sendEmail + } & ValidateMessageDeps + ): NotificationHandler => + async (msg) => { + const state = await validateMessageFactory(deps)(msg) + const htmlTemplateParams = buildEmailTemplateParams(state) + const serverInfo = await deps.getServerInfo() + const { html, text } = await deps.renderEmail( + htmlTemplateParams, + serverInfo, + state.targetUser + ) - await sendEmail({ - to: state.targetUser.email, - text, - html, - subject: 'A user requested access to your project' + await deps.sendEmail({ + to: state.targetUser.email, + text, + html, + subject: 'A user requested access to your project' + }) + } + +const handler: NotificationHandler = (...args) => { + const newStreamAccessRequestHandler = newStreamAccessRequestHandlerFactory({ + getServerInfo, + renderEmail, + sendEmail, + getUser, + getStream, + getPendingAccessRequest: getPendingAccessRequestFactory({ db }) }) + return newStreamAccessRequestHandler(...args) } export default handler