From 165c26af3ff29f9bbd91b5408903264a90fd55d2 Mon Sep 17 00:00:00 2001 From: Daniel Soares Date: Fri, 24 Dec 2021 11:48:37 -0300 Subject: [PATCH] refactor: api routes --- package.json | 2 - prisma/seed.ts | 1 + src/api/auth/index.ts | 33 ---- src/api/auth/refreshToken.ts | 47 ----- src/api/data/getData.ts | 16 -- src/api/data/updateData.ts | 23 --- src/api/index.ts | 13 -- src/api/users/checkUsername.ts | 13 -- src/api/users/createUser.ts | 50 ----- src/api/users/deleteUser.ts | 26 --- src/api/users/getUserById.ts | 23 --- src/api/users/getUsers.ts | 20 -- src/api/users/me.ts | 23 --- src/api/users/updateUser.ts | 67 ------- src/components/Dash/Button/styles.ts | 17 +- .../Dash/DescriptionInput/index.tsx | 5 +- src/components/Dash/FontsSelect/index.tsx | 25 ++- .../Dash/NameInput/DataSettings/index.tsx | 39 ++-- src/components/Dash/NameInput/index.tsx | 4 +- .../Dash/SaveChangesAlert/index.tsx | 72 +++++--- .../Dash/SaveChangesAlert/styles.ts | 2 + .../Dash/UserSettings/EditUserModal/index.tsx | 4 +- src/components/Dash/index.tsx | 20 +- src/components/Dash/styles.ts | 1 + src/components/Home/index.tsx | 2 +- src/components/Textarea/index.tsx | 16 ++ src/components/Textarea/styles.ts | 32 ++++ src/constants/auth.ts | 5 +- src/constants/fonts.ts | 21 ++- .../auth.middleware.ts} | 3 +- src/modules/auth/auth.controller.ts | 21 +++ src/modules/auth/auth.service.ts | 96 ++++++++++ src/modules/data/data.controller.ts | 19 ++ src/modules/data/data.service.ts | 29 +++ src/modules/users/users.controller.ts | 59 ++++++ src/modules/users/users.service.ts | 171 ++++++++++++++++++ src/pages/_app.tsx | 4 +- src/pages/_document.tsx | 29 ++- src/pages/api/[[...handler]].ts | 40 ++-- src/styles/global.ts | 2 +- src/types/next.d.ts | 4 +- src/utils/createSession.ts | 29 --- 42 files changed, 622 insertions(+), 506 deletions(-) delete mode 100644 src/api/auth/index.ts delete mode 100644 src/api/auth/refreshToken.ts delete mode 100644 src/api/data/getData.ts delete mode 100644 src/api/data/updateData.ts delete mode 100644 src/api/index.ts delete mode 100644 src/api/users/checkUsername.ts delete mode 100644 src/api/users/createUser.ts delete mode 100644 src/api/users/deleteUser.ts delete mode 100644 src/api/users/getUserById.ts delete mode 100644 src/api/users/getUsers.ts delete mode 100644 src/api/users/me.ts delete mode 100644 src/api/users/updateUser.ts create mode 100644 src/components/Textarea/index.tsx create mode 100644 src/components/Textarea/styles.ts rename src/{utils/authMiddleware.ts => middlewares/auth.middleware.ts} (93%) create mode 100644 src/modules/auth/auth.controller.ts create mode 100644 src/modules/auth/auth.service.ts create mode 100644 src/modules/data/data.controller.ts create mode 100644 src/modules/data/data.service.ts create mode 100644 src/modules/users/users.controller.ts create mode 100644 src/modules/users/users.service.ts delete mode 100644 src/utils/createSession.ts diff --git a/package.json b/package.json index 29bd8ed..d352f23 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,7 @@ "next-connect": "0.11.0", "nookies": "2.5.2", "polished": "4.1.3", - "rc-slider": "9.7.5", "react": "17.0.2", - "react-collapsible": "2.8.4", "react-color": "2.19.3", "react-dom": "17.0.2", "react-hot-toast": "^2.1.1", diff --git a/prisma/seed.ts b/prisma/seed.ts index 1dcbed1..4fe5990 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -87,6 +87,7 @@ async function main() { await prisma.user.create({ data: { + id: 1, username: USERNAME, password: hashSync(PASSWORD, 10), lang: 'en', diff --git a/src/api/auth/index.ts b/src/api/auth/index.ts deleted file mode 100644 index 2e1332d..0000000 --- a/src/api/auth/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { compare } from 'bcryptjs' - -import { prisma } from 'services/prisma' -import { createSession } from 'utils/createSession' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function auth(req: NextApiRequest, res: NextApiResponse) { - const { username, password } = req.body - - if (!username || !password) { - throw new ExceptionError('Username and password are required') - } - - const user = await prisma.user.findUnique({ - where: { username } - }) - - if (!user) { - throw new ExceptionError('Credentials are invalid', 401) - } - - const isValidPassword = await compare(password, user.password) - - if (!isValidPassword) { - throw new ExceptionError('Credentials are invalid', 401) - } - - const { accessToken, refreshToken } = await createSession(user) - - res.status(200).json({ accessToken, refreshToken }) -} diff --git a/src/api/auth/refreshToken.ts b/src/api/auth/refreshToken.ts deleted file mode 100644 index cd2100b..0000000 --- a/src/api/auth/refreshToken.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { prisma } from 'services/prisma' -import { createSession } from 'utils/createSession' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function refreshToken(req: NextApiRequest, res: NextApiResponse) { - const { refreshToken } = req.body - - if (!refreshToken) { - throw new ExceptionError('Refresh Token required') - } - - const session = await prisma.session.findUnique({ - where: { id: refreshToken } - }) - - if (!session) { - throw new ExceptionError('Refresh Token are invalid', 401) - } - - const isSessionExpired = new Date(session.expiresAt) < new Date() - - if (isSessionExpired) { - await prisma.session.delete({ - where: { id: refreshToken } - }) - - throw new ExceptionError('Refresh Token are expired', 401) - } - - const user = await prisma.user.findUnique({ - where: { id: session.userId } - }) - - if (!user) { - throw new ExceptionError('User not found', 401) - } - - const tokens = await createSession(user) - - await prisma.session.delete({ - where: { id: refreshToken } - }) - - res.status(200).json({ accessToken: tokens.accessToken, refreshToken: tokens.refreshToken }) -} diff --git a/src/api/data/getData.ts b/src/api/data/getData.ts deleted file mode 100644 index b5eafef..0000000 --- a/src/api/data/getData.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function getData(_req: NextApiRequest, res: NextApiResponse) { - const response = await prisma.data.findUnique({ - where: { id: 1 } - }) - - if (!response) { - throw new ExceptionError('No data found') - } - - res.status(200).json(response?.data) -} diff --git a/src/api/data/updateData.ts b/src/api/data/updateData.ts deleted file mode 100644 index b81a4f1..0000000 --- a/src/api/data/updateData.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function updateData(req: NextApiRequest, res: NextApiResponse) { - const { data } = req.body - - if (!data) { - throw new ExceptionError('No data provided') - } - - try { - const response = await prisma.data.update({ - where: { id: 1 }, - data: { data: JSON.stringify(req.body.data) } - }) - - res.status(200).json(response) - } catch (err: any) { - throw new ExceptionError(err) - } -} diff --git a/src/api/index.ts b/src/api/index.ts deleted file mode 100644 index 824402b..0000000 --- a/src/api/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export { auth } from './auth' -export { refreshToken } from './auth/refreshToken' - -export { getData } from './data/getData' -export { updateData } from './data/updateData' - -export { checkUsername } from './users/checkUsername' -export { createUser } from './users/createUser' -export { deleteUser } from './users/deleteUser' -export { getUserById } from './users/getUserById' -export { getUsers } from './users/getUsers' -export { me } from './users/me' -export { updateUser } from './users/updateUser' diff --git a/src/api/users/checkUsername.ts b/src/api/users/checkUsername.ts deleted file mode 100644 index a33860e..0000000 --- a/src/api/users/checkUsername.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { prisma } from 'services/prisma' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function checkUsername(req: NextApiRequest, res: NextApiResponse) { - const { username } = req.body - - const isTaken = await prisma.user.findUnique({ - where: { username: username.toLowerCase().trim() } - }) - - res.status(200).json({ isTaken: !!isTaken }) -} diff --git a/src/api/users/createUser.ts b/src/api/users/createUser.ts deleted file mode 100644 index 24059db..0000000 --- a/src/api/users/createUser.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { hashSync } from 'bcryptjs' - -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function createUser(req: NextApiRequest, res: NextApiResponse) { - const { username, password, role } = req.body - const normalizedUsername = username.toLowerCase().trim() - - 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') - } - - if (req.userRole !== 'ADMIN') { - throw new ExceptionError('Only admins can create users') - } - - const usernameExists = await prisma.user.findUnique({ - where: { username: normalizedUsername } - }) - - if (usernameExists) { - throw new ExceptionError('Username already exists') - } - - try { - const response = await prisma.user.create({ - data: { - username: normalizedUsername, - password: hashSync(password, 10), - role: role ? role : 'EDITOR' - }, - select: { - id: true, - username: true, - role: true - } - }) - - res.status(200).json(response) - } catch (err: any) { - throw new ExceptionError(err) - } -} diff --git a/src/api/users/deleteUser.ts b/src/api/users/deleteUser.ts deleted file mode 100644 index 674c283..0000000 --- a/src/api/users/deleteUser.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function deleteUser(req: NextApiRequest, res: NextApiResponse) { - const { id } = req.params - - if (id === '1') { - throw new ExceptionError('Cannot delete admin', 403) - } - - if (req.userRole !== 'ADMIN') { - throw new ExceptionError('Only admins can delete other users') - } - - try { - await prisma.user.delete({ - where: { id: +id } - }) - - res.status(204).end() - } catch (err: any) { - throw new ExceptionError(err) - } -} diff --git a/src/api/users/getUserById.ts b/src/api/users/getUserById.ts deleted file mode 100644 index deff7bb..0000000 --- a/src/api/users/getUserById.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function getUserById(req: NextApiRequest, res: NextApiResponse) { - const { id } = req.params - - 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) -} diff --git a/src/api/users/getUsers.ts b/src/api/users/getUsers.ts deleted file mode 100644 index 9716616..0000000 --- a/src/api/users/getUsers.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function getUsers(_req: NextApiRequest, res: NextApiResponse) { - 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) -} diff --git a/src/api/users/me.ts b/src/api/users/me.ts deleted file mode 100644 index 3c1b63b..0000000 --- a/src/api/users/me.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function me(req: NextApiRequest, res: NextApiResponse) { - const { userId } = req - const response = await prisma.user.findUnique({ - where: { id: +userId }, - select: { - id: true, - username: true, - lang: true, - role: true - } - }) - - if (!response) { - throw new ExceptionError('User not found', 404) - } - - res.status(200).json(response) -} diff --git a/src/api/users/updateUser.ts b/src/api/users/updateUser.ts deleted file mode 100644 index eef7f12..0000000 --- a/src/api/users/updateUser.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { compare, hashSync } from 'bcryptjs' - -import { prisma } from 'services/prisma' -import { ExceptionError } from 'utils/error' - -import type { NextApiRequest, NextApiResponse } from 'next' - -export async function updateUser(req: NextApiRequest, res: NextApiResponse) { - const { id } = req.params - const { oldPassword, password, role } = req.body - const user = await prisma.user.findUnique({ - where: { id: +id } - }) - - let updatedUser = {} - - if (!user) { - throw new ExceptionError('No user found', 404) - } - - // if (req.userRole !== 'ADMIN' || req.userId !== id) { - // throw new ExceptionError('Only admins can update other users') - // } - - if (oldPassword && password) { - const isValidPassword = await compare(oldPassword, user.password) - - if (!isValidPassword) { - throw new ExceptionError('Password does not match') - } - - updatedUser = { password: hashSync(password, 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 (role !== 'EDITOR' && user.role === 'EDITOR') { - throw new ExceptionError('Cannot change role', 403) - } - - updatedUser = { ...updatedUser, role } - } - - try { - const response = await prisma.user.update({ - where: { id: +id }, - data: updatedUser, - select: { - id: true, - username: true, - lang: true, - role: true - } - }) - - res.status(200).json(response) - } catch (err: any) { - throw new ExceptionError(err) - } -} diff --git a/src/components/Dash/Button/styles.ts b/src/components/Dash/Button/styles.ts index 258c28f..3b73c28 100644 --- a/src/components/Dash/Button/styles.ts +++ b/src/components/Dash/Button/styles.ts @@ -10,27 +10,28 @@ type ButtonProps = { } export const Button = styled(BaseButton)` - background: #0284c7; - border-color: #0284c7; + background: #000; + border-color: #000; border-width: 1px; + border-radius: 4px; &:hover { transform: translateY(0); - background: ${({ outlined }) => (outlined ? '#0284c7' : darken(0.1, '#0284c7'))}; - border-color: ${({ outlined }) => (outlined ? '#0284c7' : darken(0.1, '#0284c7'))}; + background: ${({ outlined }) => (outlined ? '#000' : lighten(0.3, '#000'))}; + border-color: ${({ outlined }) => (outlined ? '#000' : lighten(0.3, '#000'))}; } &:active { - background: ${({ outlined }) => (outlined ? '#0284c7' : darken(0.2, '#0284c7'))}; - border-color: ${({ outlined }) => (outlined ? '#0284c7' : darken(0.2, '#0284c7'))}; + background: ${({ outlined }) => (outlined ? '#000' : lighten(0.4, '#000'))}; + border-color: ${({ outlined }) => (outlined ? '#000' : lighten(0.4, '#000'))}; } ${({ outlined }) => outlined && ` - color: #0284c7; + color: #000; background: transparent; - border-color: #0284c7; + border-color: #000; &:hover { color: #f8fafc; diff --git a/src/components/Dash/DescriptionInput/index.tsx b/src/components/Dash/DescriptionInput/index.tsx index 4eebe0f..e187aa1 100644 --- a/src/components/Dash/DescriptionInput/index.tsx +++ b/src/components/Dash/DescriptionInput/index.tsx @@ -1,11 +1,12 @@ +import { Textarea } from 'components/Textarea' import { useData } from 'hooks/useData' export function DescriptionInput() { const { data, setData } = useData() return ( -