93 lines
2.3 KiB
TypeScript
93 lines
2.3 KiB
TypeScript
import type EventEmitter from 'node:events'
|
|
import crypto from 'node:crypto'
|
|
import type { Knex } from 'knex'
|
|
import _ from 'lodash'
|
|
import type { NewInvite } from './types.ts'
|
|
|
|
import RestQueriesFactory from '../../lib/knex_rest_queries.ts'
|
|
|
|
export const columns = [
|
|
'id',
|
|
'email',
|
|
'token',
|
|
'createdAt',
|
|
'createdById',
|
|
'modifiedAt',
|
|
'modifiedById',
|
|
'consumedAt',
|
|
'consumedById',
|
|
]
|
|
|
|
export const Selects = (knex: Knex) => ({
|
|
roles: knex
|
|
.select(knex.raw('json_agg(roles)'))
|
|
.from(
|
|
knex
|
|
.select('id', 'name')
|
|
.from('role')
|
|
.innerJoin('invites_roles', 'role.id', 'invites_roles.role_id')
|
|
.where('invites_roles.invite_id', knex.ref('invite.id'))
|
|
.as('roles'),
|
|
),
|
|
|
|
createdBy: knex
|
|
.select(knex.raw('row_to_json(users)'))
|
|
.from(knex.select('id', 'email').from('user').where('id', knex.ref('invite.created_by_id')).as('users')),
|
|
|
|
consumedBy: knex
|
|
.select(knex.raw('row_to_json(users)'))
|
|
.from(knex.select('id', 'email').from('user').where('id', knex.ref('invite.consumed_by_id')).as('users')),
|
|
})
|
|
|
|
function generateToken(length = 64) {
|
|
return crypto.randomBytes(length / 2).toString('hex')
|
|
}
|
|
|
|
export default ({ knex, emitter }: { knex: Knex; emitter: EventEmitter }) => {
|
|
const queries = RestQueriesFactory({
|
|
emitter,
|
|
knex,
|
|
table: 'invite',
|
|
columns,
|
|
selects: Selects(knex),
|
|
})
|
|
|
|
function consume(id: number, consumedById: number, client = knex) {
|
|
return client('invite')
|
|
.update({ consumed_at: knex.fn.now(), consumed_by_id: consumedById })
|
|
.where('id', id)
|
|
.then((result: ANY) => {
|
|
if (result === 0) throw new Error('No invite was consumed')
|
|
|
|
return !!result
|
|
})
|
|
}
|
|
|
|
async function create(json: NewInvite, client: Knex | Knex.Transaction = knex) {
|
|
const token = generateToken()
|
|
|
|
const trx = client.isTransaction ? (client as Knex.Transaction) : await client.transaction()
|
|
|
|
const invite = await queries.create({ ..._.omit(json, 'roles'), token }, trx)
|
|
|
|
const roles = json.roles.map((role: number) => ({
|
|
invite_id: invite.id,
|
|
role_id: role,
|
|
}))
|
|
|
|
await trx.table('invites_roles').insert(roles)
|
|
|
|
if (trx !== client) {
|
|
await trx.commit()
|
|
}
|
|
|
|
return queries.findById(invite.id, trx)
|
|
}
|
|
|
|
return {
|
|
...queries,
|
|
consume,
|
|
create,
|
|
}
|
|
}
|