brf/server/plugins/auth.ts
2025-12-18 07:31:37 +01:00

93 lines
2.4 KiB
TypeScript

import type { FastifyPluginCallback, FastifyRequest } from 'fastify'
import fp from 'fastify-plugin'
import UserQueries from '../services/users/queries.ts'
import changePassword from './auth/routes/change_password.ts'
import resetPassword from './auth/routes/reset_password.ts'
import login from './auth/routes/login.ts'
import logout from './auth/routes/logout.ts'
import register from './auth/routes/register.ts'
import verifyEmail from './auth/routes/verify_email.ts'
import knex from '../lib/knex.ts'
import emitter from '../lib/emitter.ts'
import type { User } from '../services/users/types.ts'
const userQueries = UserQueries({ knex, emitter })
const userPromiseSymbol = Symbol('user')
const serialize = (user: User) => Promise.resolve(user.id)
const auth: FastifyPluginCallback<{ prefix?: string }> = (fastify, options, done) => {
const prefix = options.prefix || ''
fastify.decorate('auth', (request, reply, done) => {
if (!request.session.userId) return reply.status(401).send()
done()
})
fastify.decorateRequest(
'login',
function login(user) {
return serialize(user).then((result) => {
this.session.set('userId', result)
return this.session.save().catch(console.error)
})
},
['session'],
)
fastify.decorateRequest(
'logout',
function logout() {
return this.session.destroy()
},
['session'],
)
fastify.decorateRequest('getUser', function getUser(this: FastifyRequest & { [userPromiseSymbol]?: Promise<ANY> }) {
if (!this.session || !this.session.userId) {
return Promise.resolve(null)
} else if (!this[userPromiseSymbol]) {
this[userPromiseSymbol] = userQueries.findById(this.session.userId).catch((err) => {
this.log.error(err)
})
}
return this[userPromiseSymbol]
})
fastify.decorateRequest(
'user',
{
getter() {
return this.getUser()
},
},
['getUser'],
)
fastify.get(`${prefix}/current`, function (request) {
return request.user
})
fastify.post(prefix + '/change-password', changePassword)
fastify.post(prefix + '/reset-password', resetPassword)
fastify.get(prefix + '/verify-email', verifyEmail)
fastify.post(prefix + '/login', login)
fastify.get(prefix + '/logout', logout)
fastify.post(prefix + '/register', register)
fastify.addHook('onClose', () => {
knex.destroy()
})
done()
}
export default fp(auth, {
name: 'auth',
fastify: '5.x',
})