feat: add user and session

This commit is contained in:
Daniel Soares
2021-12-15 14:05:27 -03:00
parent 5df44ceddc
commit e071c0a19b
11 changed files with 577 additions and 9 deletions

144
src/pages/api/users/[id].ts Normal file
View 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

View 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