chore(server): notifications IoC 5 - newStreamAccessRequestHandlerFactory

This commit is contained in:
Kristaps Fabians Geikins
2024-09-13 13:27:46 +03:00
parent e322b1b59f
commit ad2278a79b
@@ -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<ReturnType<typeof validateMessage>>
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<ReturnType<typeof validateMessageFactory>>
>
function buildEmailTemplateHtml(
state: ValidatedMessageState
@@ -106,22 +118,42 @@ function buildEmailTemplateParams(state: ValidatedMessageState): EmailTemplatePa
}
}
const handler: NotificationHandler<NewStreamAccessRequestMessage> = 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<NewStreamAccessRequestMessage> =>
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<NewStreamAccessRequestMessage> = (...args) => {
const newStreamAccessRequestHandler = newStreamAccessRequestHandlerFactory({
getServerInfo,
renderEmail,
sendEmail,
getUser,
getStream,
getPendingAccessRequest: getPendingAccessRequestFactory({ db })
})
return newStreamAccessRequestHandler(...args)
}
export default handler