mirror of
https://github.com/dsoaress/link-free.git
synced 2026-08-18 23:46:04 +01:00
feat: add user and session
This commit is contained in:
144
src/pages/api/users/[id].ts
Normal file
144
src/pages/api/users/[id].ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { Prisma } from '@prisma/client'
|
||||
import { compare, hashSync } from 'bcryptjs'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import nc from 'next-connect'
|
||||
|
||||
import { prisma } from '../../../services/prisma'
|
||||
import { ExceptionError } from '../../../utils/error'
|
||||
|
||||
const handler = nc<NextApiRequest, NextApiResponse>({
|
||||
onNoMatch: (_req, res) => {
|
||||
res.status(404).json({ error: 'Not found' })
|
||||
},
|
||||
onError: (err, _req, res) => {
|
||||
if (err instanceof ExceptionError) {
|
||||
res.status(err.status).json({
|
||||
status: err.status,
|
||||
error: err.message
|
||||
})
|
||||
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
res.status(400).json({
|
||||
status: 400,
|
||||
error: err.message
|
||||
})
|
||||
} else {
|
||||
res.status(500).json({
|
||||
status: 500,
|
||||
error: err.message
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.get(async (req, res) => {
|
||||
const { id } = req.query
|
||||
|
||||
if (!id) {
|
||||
throw new ExceptionError('No id provided')
|
||||
}
|
||||
|
||||
const response = await prisma.user.findUnique({
|
||||
where: { id: +id },
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
role: true
|
||||
}
|
||||
})
|
||||
|
||||
if (!response) {
|
||||
throw new ExceptionError('No data found', 404)
|
||||
}
|
||||
|
||||
res.status(200).json(response)
|
||||
})
|
||||
|
||||
.patch(async (req, res) => {
|
||||
const { id } = req.query
|
||||
const { username, password, newPassword, role } = req.body
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: +id }
|
||||
})
|
||||
|
||||
let updatedUser = {}
|
||||
|
||||
if (!user) {
|
||||
throw new ExceptionError('No user found', 404)
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
throw new ExceptionError('No id provided')
|
||||
}
|
||||
|
||||
if (username) {
|
||||
const usernameExists = await prisma.user.findUnique({
|
||||
where: { username }
|
||||
})
|
||||
|
||||
if (usernameExists && usernameExists.id !== +id) {
|
||||
throw new ExceptionError('Username already exists')
|
||||
}
|
||||
|
||||
updatedUser = { ...updatedUser, username }
|
||||
}
|
||||
|
||||
if (password && newPassword) {
|
||||
const isValidPassword = await compare(password, user.password)
|
||||
|
||||
if (!isValidPassword) {
|
||||
throw new ExceptionError('Password does not match')
|
||||
}
|
||||
|
||||
updatedUser = { password: hashSync(newPassword, 10) }
|
||||
}
|
||||
|
||||
if (role) {
|
||||
if (!['ADMIN', 'EDITOR'].includes(role)) {
|
||||
throw new ExceptionError('Role must be either ADMIN or EDITOR')
|
||||
}
|
||||
|
||||
if (user.role === 'ADMIN' && role === 'EDITOR') {
|
||||
throw new ExceptionError('Cannot downgrade admin role', 403)
|
||||
}
|
||||
|
||||
if (user.role === 'EDITOR') {
|
||||
throw new ExceptionError('Cannot change role', 403)
|
||||
}
|
||||
|
||||
updatedUser = { ...updatedUser, role }
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await prisma.data.update({
|
||||
where: { id: +id },
|
||||
data: { ...updatedUser }
|
||||
})
|
||||
|
||||
res.status(200).json(response)
|
||||
} catch (err: any) {
|
||||
throw new ExceptionError(err)
|
||||
}
|
||||
})
|
||||
|
||||
.delete(async (req, res) => {
|
||||
const { id } = req.query
|
||||
|
||||
if (!id) {
|
||||
throw new ExceptionError('No id provided')
|
||||
}
|
||||
|
||||
if (id === '1') {
|
||||
throw new ExceptionError('Cannot delete admin', 403)
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.data.delete({
|
||||
where: { id: +id }
|
||||
})
|
||||
|
||||
res.status(204).end()
|
||||
} catch (err: any) {
|
||||
throw new ExceptionError(err)
|
||||
}
|
||||
})
|
||||
|
||||
export default handler
|
||||
84
src/pages/api/users/index.ts
Normal file
84
src/pages/api/users/index.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Prisma } from '@prisma/client'
|
||||
import { hashSync } from 'bcryptjs'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import nc from 'next-connect'
|
||||
|
||||
import { prisma } from '../../../services/prisma'
|
||||
import { ExceptionError } from '../../../utils/error'
|
||||
|
||||
const handler = nc<NextApiRequest, NextApiResponse>({
|
||||
onNoMatch: (_req, res) => {
|
||||
res.status(404).json({ error: 'Not found' })
|
||||
},
|
||||
onError: (err, _req, res) => {
|
||||
if (err instanceof ExceptionError) {
|
||||
res.status(err.status).json({
|
||||
status: err.status,
|
||||
error: err.message
|
||||
})
|
||||
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
res.status(400).json({
|
||||
status: 400,
|
||||
error: err.message
|
||||
})
|
||||
} else {
|
||||
res.status(500).json({
|
||||
status: 500,
|
||||
error: err.message
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.get(async (_req, res) => {
|
||||
const response = await prisma.user.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
role: true
|
||||
}
|
||||
})
|
||||
|
||||
if (!response) {
|
||||
throw new ExceptionError('No data found')
|
||||
}
|
||||
|
||||
res.status(200).json(response)
|
||||
})
|
||||
|
||||
.post(async (req, res) => {
|
||||
const { username, password, role } = req.body
|
||||
|
||||
if (!username || !password) {
|
||||
throw new ExceptionError('Username and password are required')
|
||||
}
|
||||
|
||||
if (!['ADMIN', 'EDITOR'].includes(role)) {
|
||||
throw new ExceptionError('Role must be either ADMIN or EDITOR')
|
||||
}
|
||||
|
||||
// TODO implement role validation
|
||||
|
||||
const usernameExists = await prisma.user.findUnique({
|
||||
where: { username }
|
||||
})
|
||||
|
||||
if (usernameExists) {
|
||||
throw new ExceptionError('Username already exists')
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
password: hashSync(password, 10),
|
||||
role: role ? role : 'EDITOR'
|
||||
}
|
||||
})
|
||||
|
||||
res.status(200).json(response)
|
||||
} catch (err: any) {
|
||||
throw new ExceptionError(err)
|
||||
}
|
||||
})
|
||||
|
||||
export default handler
|
||||
Reference in New Issue
Block a user