141 lines
3.4 KiB
TypeScript
141 lines
3.4 KiB
TypeScript
import type { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox'
|
|
import bcrypt from 'bcrypt'
|
|
import { CreateUserPayloadSchema, LoginPayloadSchema, UserSchema } from '../plugins/schemas/auth.ts'
|
|
import { TypeboxRef } from '../utils/typebox-ref.ts'
|
|
|
|
const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
|
|
fastify.post(
|
|
'/auth/register',
|
|
{
|
|
schema: {
|
|
summary: 'Register',
|
|
tags: ['Auth'],
|
|
operationId: 'auth.register',
|
|
body: TypeboxRef(CreateUserPayloadSchema),
|
|
response: {
|
|
200: TypeboxRef(UserSchema),
|
|
},
|
|
},
|
|
config: {
|
|
skipAuth: true,
|
|
},
|
|
},
|
|
async (req, reply) => {
|
|
const hashed = await bcrypt.hash(req.body.password, 10)
|
|
const user = await fastify.prisma.user.create({
|
|
data: {
|
|
username: req.body.username,
|
|
password: hashed,
|
|
displayName: req.body.username,
|
|
UserPreferences: {
|
|
create: {},
|
|
},
|
|
},
|
|
})
|
|
|
|
const session = await fastify.lucia.createSession(user.username, {})
|
|
const cookie = fastify.lucia.createSessionCookie(session.id)
|
|
|
|
reply.setCookie(cookie.name, cookie.value, cookie.attributes)
|
|
|
|
return {
|
|
username: user.username,
|
|
displayName: user.username,
|
|
createdAt: user.createdAt.toISOString(),
|
|
}
|
|
},
|
|
)
|
|
|
|
fastify.post(
|
|
'/auth/login',
|
|
{
|
|
schema: {
|
|
summary: 'Login',
|
|
tags: ['Auth'],
|
|
operationId: 'auth.login',
|
|
body: TypeboxRef(LoginPayloadSchema),
|
|
response: {
|
|
200: TypeboxRef(UserSchema),
|
|
},
|
|
},
|
|
config: {
|
|
skipAuth: true,
|
|
},
|
|
},
|
|
async (req, reply) => {
|
|
const user = await fastify.prisma.user.findFirst({
|
|
where: { username: req.body.username },
|
|
select: {
|
|
username: true,
|
|
displayName: true,
|
|
createdAt: true,
|
|
password: true,
|
|
},
|
|
})
|
|
|
|
if (!user) {
|
|
return reply.notFound('Incorrect username or password')
|
|
}
|
|
|
|
const validPassword = await bcrypt.compare(req.body.password, user.password)
|
|
if (!validPassword) {
|
|
return reply.notFound('Incorrect username or password')
|
|
}
|
|
|
|
const session = await fastify.lucia.createSession(user.username, {})
|
|
const cookie = fastify.lucia.createSessionCookie(session.id)
|
|
|
|
reply.setCookie(cookie.name, cookie.value, cookie.attributes)
|
|
|
|
return {
|
|
...user,
|
|
createdAt: user.createdAt.toISOString(),
|
|
}
|
|
},
|
|
)
|
|
|
|
fastify.get(
|
|
'/auth/me',
|
|
{
|
|
schema: {
|
|
summary: 'Me',
|
|
tags: ['Auth'],
|
|
operationId: 'auth.me',
|
|
response: {
|
|
200: TypeboxRef(UserSchema),
|
|
},
|
|
},
|
|
},
|
|
async (req) => {
|
|
const user = req.user!
|
|
|
|
return {
|
|
username: user.username,
|
|
displayName: user.displayName,
|
|
createdAt: user.createdAt.toISOString(),
|
|
}
|
|
},
|
|
)
|
|
|
|
fastify.post(
|
|
'/auth/logout',
|
|
{
|
|
schema: {
|
|
summary: 'Logout',
|
|
tags: ['Auth'],
|
|
operationId: 'auth.logout',
|
|
},
|
|
},
|
|
async (req, reply) => {
|
|
if (req.session)
|
|
await fastify.lucia.invalidateSession(req.session.id)
|
|
|
|
const blank = fastify.lucia.createBlankSessionCookie()
|
|
|
|
reply.setCookie(blank.name, blank.value, blank.attributes)
|
|
},
|
|
)
|
|
}
|
|
|
|
export default plugin
|