Skip to content

Commit

Permalink
Merge pull request #17 from Divyateja04/adminfunction1
Browse files Browse the repository at this point in the history
Adminfunction1
  • Loading branch information
thenicekat authored Mar 31, 2024
2 parents bdd1002 + 01ca947 commit adfeba3
Show file tree
Hide file tree
Showing 10 changed files with 495 additions and 171 deletions.
296 changes: 130 additions & 166 deletions backend/package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
"author": "",
"license": "ISC",
"dependencies": {
"@prisma/client": "^5.9.1",
"@prisma/client": "^5.10.2",
"@types/express-session": "^1.17.10",
"axios": "^1.6.7",
"connect-mongodb-session": "^5.0.0",
"connect-mongodb-session": "^2.2.0",
"connect-redis": "^7.1.1",
"cors": "^2.8.5",
"dotenv": "^16.4.1",
Expand All @@ -33,7 +33,7 @@
"jest": "^29.7.0",
"jest-mock-extended": "^3.0.5",
"nodemon": "^3.0.3",
"prisma": "^5.9.1",
"prisma": "^5.10.2",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
Expand Down
1 change: 1 addition & 0 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ model User {
isPublic Boolean @default(false)
posts Post[]
requests Request[]
role String @default("user")
}

model Request {
Expand Down
2 changes: 2 additions & 0 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { gauthRouter } from './routes/gauth.route'
import { userRouter } from './routes/user.route'
import { validateMiddleware } from './middleware/auth.middleware';
import { requestsRouter } from './routes/requests.route';
import { adminRouter } from './routes/admin.route';

const app: Express = express()

Expand Down Expand Up @@ -76,6 +77,7 @@ app.use('/hello', helloRouter)
app.use('/post', postsRouter)
app.use('/request', requestsRouter)
app.use('/user', userRouter)
app.use('/admin', adminRouter);


// Start the server
Expand Down
94 changes: 94 additions & 0 deletions backend/src/routes/admin.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Router } from "express";
import { HttpCodes } from "../types/HttpCodes";
import { CustomResponse } from "../types/CustomResponse";
import { getAllUsers, promoteUser,demoteUser } from "../service/admin.service";
import prisma from '../db'
export const adminRouter = Router();

adminRouter.get("/home", async(req,res)=>{
let currUserEmail = req.session.email;
let currUser;
try {
currUser = await prisma.user.findUnique({
where: {
email: currUserEmail
},
});
}catch(error){
console.log(error);
}

if(currUser?.role==="admin"){
const appUsers = await getAllUsers();

if (appUsers.error) {
const response: CustomResponse = {
error: true,
message: "Error retrieving users",
data: null
}
return res.status(HttpCodes.INTERNAL_SERVER_ERROR).json(response);
}

if (typeof appUsers.data != "string") {
// const normalUsers = appUsers?.data?.filter((u: any) => u.role !== 'admin');

const response: CustomResponse = {
error: false,
message: "All users retrieved successfully",
data: appUsers.data
}

return res.status(HttpCodes.OK).json(response);
} else {
return res.status(HttpCodes.INTERNAL_SERVER_ERROR).json(appUsers.data);
}
}else{
return res.status(HttpCodes.UNAUTHORIZED);
}
})

adminRouter.put("/promote/:user", async(req, res) => {
const userId = req.params.user;
const pro = await promoteUser(userId);

if(pro.error){
const response: CustomResponse = {
error: true,
message: "Error retrieving users",
data: null
}
return res.status(HttpCodes.INTERNAL_SERVER_ERROR).json(response);
}else{
const response: CustomResponse = {
error: false,
message: "selected user is now an admin",
data: pro
}

return res.status(HttpCodes.OK).json(response);
}
})


adminRouter.put("/demote/:user", async(req, res) => {
const userId = req.params.user;
const pro = await demoteUser(userId);

if(pro.error){
const response: CustomResponse = {
error: true,
message: "Error retrieving users",
data: null
}
return res.status(HttpCodes.INTERNAL_SERVER_ERROR).json(response);
}else{
const response: CustomResponse = {
error: false,
message: "selected user is demoted from admin role to user only role",
data: pro
}

return res.status(HttpCodes.OK).json(response);
}
})
12 changes: 11 additions & 1 deletion backend/src/routes/gauth.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { logger } from "../utils/logger";
import { FRONTEND_URL } from "../constants";

export const gauthRouter = Router();
// function isuser(obj: any): obj is {
// return obj && typeof obj === 'object' && 'role' in obj;
// }

gauthRouter.get("/", async (req, res) => {
const appUser = await googleOAuthHandler(req);

logger.info("Setting session data: " + req.session.email);

if (appUser.error) {
Expand All @@ -20,8 +22,16 @@ gauthRouter.get("/", async (req, res) => {
res.redirect(FRONTEND_URL + '/user/create');
return;
} else {
if(appUser.data){
if(typeof appUser.data !=='string' && appUser.data.role ==="admin"){
logger.info("Admin login");
res.redirect(FRONTEND_URL+'/admin/home');
return;
}
}else{
logger.info("User already exists");
res.redirect(FRONTEND_URL);
return;
}
}
});
66 changes: 66 additions & 0 deletions backend/src/service/admin.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { User } from '@prisma/client'
import { CustomReturn } from '../types/CustomReturn'
import prisma from '../db'
import { logger } from '../utils/logger'

export const getAllUsers = async (): Promise<CustomReturn<User[]>> => {
try {
let allUsers: User[] = await prisma.user.findMany();
return {
error: false,
data: allUsers
}
}
catch (error) {
return {
error: true,
data: "Some error occurred while fetching the users"
}
}
}

export const promoteUser = async(userId: string): Promise<CustomReturn<User>> => {
try{
const updatedUser = await prisma.user.update({
where: { email: userId },
data: { role: 'admin' } // Assuming 'role' is the field representing user roles
});

return {
error: false,
data: updatedUser
}
} catch(err: any) {
logger.error(JSON.stringify({
location: "promoteUser",
message: err.toString()
}));
return {
error: true,
data: "Some error occurred while promoting user to admin role"
}
}
}

export const demoteUser = async(userId: string): Promise<CustomReturn<User>> => {
try{
const updatedUser = await prisma.user.update({
where: { email: userId },
data: { role: 'user' } // Assuming 'role' is the field representing user roles
});

return {
error: false,
data: updatedUser
}
} catch(err: any) {
logger.error(JSON.stringify({
location: "demoteUser",
message: err.toString()
}));
return {
error: true,
data: "Some error occurred while demoting admin to user role"
}
}
}
100 changes: 100 additions & 0 deletions backend/tests/admin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { describe, expect } from "@jest/globals";
import { prismaMock } from "./_mockdb";
import { User } from ".prisma/client";
import { getAllUsers, promoteUser, demoteUser } from "../src/service/admin.service";

const user: User = {
id: "1",
name: "ben",
email : "[email protected]",
phoneNumber : "9898989898",
karmaPoints: 0,
role: "admin"
}

const a: User = {
id: "2",
name: "ben",
email : "[email protected]",
phoneNumber : "9898989898",
karmaPoints: 0,
role: "admin"
}

const na: User = {
id: "2",
name: "ben",
email : "[email protected]",
phoneNumber : "9898989898",
karmaPoints: 0,
role: "user"
}


describe("Get all users", () => {
it("should get all users", () => {
prismaMock.user.findMany.mockResolvedValue([user]);

expect(getAllUsers()).resolves.toEqual({
error: false,
data: [user]
});
});

it("should catch any error occurred", () => {
prismaMock.user.findMany.mockRejectedValue(new Error("Some error occurred"));

expect(getAllUsers()).resolves.toEqual({
error: true,
data: "Some error occurred while fetching the users"
});
});
})

describe("promote user to admin", () => {
it("should promote user to admin role", () => {
prismaMock.user.findUnique.mockResolvedValue(na);
prismaMock.user.update.mockResolvedValue(a);

expect(promoteUser(na.email)).resolves.toEqual({
error: false,
data: a
})
})

it("should return error if any error occured", () => {
prismaMock.user.findUnique.mockResolvedValue(na);
prismaMock.user.update.mockResolvedValue(a);

prismaMock.post.create.mockRejectedValue(new Error("Some error occurred"));

expect(promoteUser(na.email)).resolves.toEqual({
error: true,
data: "Some error occurred while promoting user to admin role"
})
})
})

describe("demote admin to user", () => {
it("should demote admin to user", () => {
prismaMock.user.findUnique.mockResolvedValue(a);
prismaMock.user.update.mockResolvedValue(na);

expect(demoteUser(a.email)).resolves.toEqual({
error: false,
data: na
})
})

it("should return error if any error occured", () => {
prismaMock.user.findUnique.mockResolvedValue(a);
prismaMock.user.update.mockResolvedValue(na);

prismaMock.post.create.mockRejectedValue(new Error("Some error occurred"));

expect(demoteUser(a.email)).resolves.toEqual({
error: true,
data: "Some error occurred while demoting admin to user role"
})
})
})
Loading

0 comments on commit adfeba3

Please sign in to comment.