112 lines
2.8 KiB
TypeScript
112 lines
2.8 KiB
TypeScript
import { Type, type FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox'
|
|
import config from '../../config.ts'
|
|
import knex from '../../lib/knex.ts'
|
|
import emitter from '../../lib/emitter.ts'
|
|
import sendMail from '../../lib/send_mail.ts'
|
|
import Queries from '../../services/invites/queries.ts'
|
|
import inviteEmailTemplate from '../../templates/emails/invite.ts'
|
|
|
|
import { RoleSchema } from './roles.ts'
|
|
|
|
export const InviteSchema = Type.Object({
|
|
id: Type.Number(),
|
|
email: Type.String({ format: 'email' }),
|
|
token: Type.String(),
|
|
roles: Type.Array(RoleSchema),
|
|
createdAt: Type.String(),
|
|
createdById: Type.Number(),
|
|
createdBy: Type.Object({}),
|
|
consumedAt: [Type.String(), Type.Null()],
|
|
consumedById: [Type.Number(), Type.Null()],
|
|
consumedBy: [Type.Object({}), Type.Null()],
|
|
})
|
|
|
|
const invitesPlugin: FastifyPluginCallbackTypebox = (fastify, _option, done) => {
|
|
const queries = Queries({ emitter, knex })
|
|
|
|
fastify.addHook('onRequest', fastify.auth)
|
|
|
|
fastify.route({
|
|
url: '/',
|
|
method: 'GET',
|
|
schema: {
|
|
querystring: InviteSchema,
|
|
response: {
|
|
200: InviteSchema,
|
|
},
|
|
},
|
|
handler(request) {
|
|
return queries.find(request.query)
|
|
},
|
|
})
|
|
|
|
fastify.route({
|
|
url: '/',
|
|
method: 'POST',
|
|
schema: {
|
|
body: {
|
|
type: Type.Object({
|
|
email: Type.String({ format: 'email' }),
|
|
roles: Type.Array(Type.Number()),
|
|
}),
|
|
properties: {
|
|
email: { type: 'string' },
|
|
roles: { type: 'array', items: { type: 'integer' } },
|
|
},
|
|
required: ['email', 'roles'],
|
|
},
|
|
response: { 201: InviteSchema },
|
|
},
|
|
async handler(request, reply) {
|
|
const trx = await knex.transaction()
|
|
|
|
const invite = await queries.create(
|
|
{
|
|
...request.body,
|
|
createdById: request.session.userId,
|
|
},
|
|
trx,
|
|
)
|
|
|
|
try {
|
|
const link = `${new URL(config.auth.paths.register, config.site.url)}?email=${invite.email}&token=${invite.token}`
|
|
|
|
await sendMail({
|
|
to: invite.email,
|
|
subject: `Invite to ${config.site.title} Admin`,
|
|
html: await inviteEmailTemplate({ link }).text(),
|
|
})
|
|
|
|
await trx.commit()
|
|
|
|
return reply.header('Location', `${request.url}/${invite.id}`).status(201).send(invite)
|
|
} catch (err) {
|
|
await trx.rollback()
|
|
|
|
throw err
|
|
}
|
|
},
|
|
})
|
|
|
|
fastify.route({
|
|
url: '/:id',
|
|
method: 'DELETE',
|
|
schema: {
|
|
params: Type.Object({
|
|
id: Type.Number(),
|
|
}),
|
|
response: {
|
|
204: {},
|
|
404: {},
|
|
},
|
|
},
|
|
handler(request, reply) {
|
|
return queries.removeById(request.params.id).then((count) => reply.status(count > 0 ? 204 : 404).send())
|
|
},
|
|
})
|
|
|
|
done()
|
|
}
|
|
|
|
export default invitesPlugin
|