diff --git a/src/api/index.ts b/src/api/index.ts index 3dda0c8..44fb8ca 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -2,11 +2,13 @@ import { Router } from 'express'; import posts from './posts'; import auth from './auth'; import me from './me'; +import users from './users'; const api = Router(); api.use('/posts', posts); api.use('/auth', auth); api.use('/me', me); +api.use('/users', users); export default api; diff --git a/src/api/users/index.ts b/src/api/users/index.ts new file mode 100644 index 0000000..8c3ebe7 --- /dev/null +++ b/src/api/users/index.ts @@ -0,0 +1,31 @@ +import Roles from "./roles"; +import { NextFunction, Request, Response, Router } from 'express'; +import { verifyToken } from "@/controller/AuthController"; + +const users = Router(); + +const getToken = (req: Request): string | undefined => { + const token: string | undefined = req.headers.authorization?.substring(7); // remove 'Bearer ' from token + return token; +}; + +const checkAuth = (req: Request, res: Response, next: NextFunction) => { + const token = getToken(req); + if (token === undefined) { + return res.status(401).send({ error: 'No token provided' }); + } + return verifyToken(token) + .then((decodedToken: number) => { + req.userId = decodedToken; + next(); + }) + .catch((error) => { + return res.status(401).send({ error }); + }); +}; + +users.use(checkAuth); + +users.post('/:id/roles', Roles); + +export default users; \ No newline at end of file diff --git a/src/api/users/roles.ts b/src/api/users/roles.ts new file mode 100644 index 0000000..7fd25fe --- /dev/null +++ b/src/api/users/roles.ts @@ -0,0 +1,20 @@ +import { Request, Response } from "express"; +import { changeUserRoles, getUserById } from "@/controller/UserController"; + +export default async (req: Request, res: Response) => { + try { + const user = await getUserById(req.userId); + if (user?.role !== "ADMIN") { + return res.status(403).send({ error: "Forbidden" }); + } + const id = parseInt(req.params.id); + const role = req.body.role; + const changedUser = await changeUserRoles(id, role); + if (changedUser instanceof Error) { + return res.status(403).send(changedUser.message); + } + return res.status(200).send({ message: "User role changed" }); + } catch (error) { + return res.status(500).send(error); + } +} \ No newline at end of file diff --git a/src/controller/UserController.ts b/src/controller/UserController.ts index ac64c2a..43344d6 100644 --- a/src/controller/UserController.ts +++ b/src/controller/UserController.ts @@ -1,4 +1,4 @@ -import { PrismaClient } from '@prisma/client'; +import { PrismaClient, Role } from '@prisma/client'; import { User } from '@/models/UserModel'; import { exclude } from '@/lib/utils'; @@ -61,4 +61,33 @@ const newUser = async (user: User) => { return newUser; }; +export const changeUserRoles = async (id: number, role: Role) => { + const currentUser = await prisma.user.findUnique({ + where: { + id, + }, + }); + + if (!currentUser) { + return new Error('User not found'); + } + if (currentUser.role === role) { + throw new Error('User already has this role'); + } + + const updatedUser = await prisma.user.update({ + where: { + id, + }, + data: { + role, + }, + }); + + if (!updatedUser) { + return new Error('User not found'); + } + return exclude(updatedUser, 'password'); +}; + export { getUser, newUser, isUserExist, getUserById };