Skip to content

Commit

Permalink
remove admin feature works
Browse files Browse the repository at this point in the history
  • Loading branch information
qiandrewj committed May 5, 2024
1 parent 5a469df commit 2366269
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 15 deletions.
10 changes: 3 additions & 7 deletions client/src/modules/Admin/Components/Admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,6 @@ export const Admin = () => {
</button>
<div className = "PendingReviews">
{pendingReviews.map((review: Review) => {
if (review.reported !== 1) {
return (
<UpdateReview
key={review._id}
Expand All @@ -393,14 +392,12 @@ export const Admin = () => {
/>
)
}
return null
})}
)}
</div>
<h1>Reported Reviews</h1>
<div className= "ReportedReviews">
{reportedReviews.map((review: Review) => {
//create a new class "button" that will set the selected class to this class when it is clicked.
if (review.reported === 1) {
return (
<UpdateReview
key={review._id}
Expand All @@ -410,9 +407,8 @@ export const Admin = () => {
unReportHandler={unReportReview}
/>
)
}
return null
})}
}
)}
</div>
</div>
</div>
Expand Down
15 changes: 14 additions & 1 deletion client/src/modules/Admin/Components/AdminUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,23 @@ import axios from 'axios'

type Props = {
user: any
token: string
removeHandler: (arg1: any) => any
}

const AdminUser = ({user}: Props) => {
const AdminUser = ({user, token, removeHandler}: Props) => {


return (
<div>
{user.firstName} {user.lastName}, {user.netId}
<button
onClick={() => removeHandler(user)}
>
Remove
</button>
</div>
)
}

export default AdminUser
47 changes: 45 additions & 2 deletions client/src/modules/Admin/Components/ManageAdminModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,47 @@ import React, { useEffect, useState } from 'react'
import axios from 'axios'
import styles from '../Styles/ManageAdminModal.module.css'

import { Student } from 'common'
import AdminUser from './AdminUser'

type Props = {
open: boolean
setOpen: (open: boolean) => void
token: string
}

const ManageAdminModal = ({token, open, setOpen}: Props) => {

const [admins, setAdmins] = useState<Student[]>([])

useEffect(() => {
axios
.post('/api/getAdmins', {token: token})
.then((response) => {
const result = response.data.result
if (response.status === 200) {
setAdmins(result)
} else {
console.log('Error at getAdmins')
}
})
}, [token])

function removeAdmin(user: Student) {
axios
.post('/api/removeAdmin', {
userId: user._id,
token: token
})
.then((response) => {
if (response.status === 200) {
const updatedAdmins = admins.filter((admin: Student) => {
return admin && admin._id !== user._id
})
setAdmins(updatedAdmins)
}
}).catch((e) => console.log(`Unable to remove admin ${e}`))
}

function closeModal() {
setOpen(false)
}
Expand All @@ -21,7 +54,17 @@ const ManageAdminModal = ({token, open, setOpen}: Props) => {
return (
<div className={styles.modalbg}>
<div className={styles.modal}>
Test
<h2>Administrators</h2>

{admins.map((admin) => {
return (
<AdminUser
user={admin}
token={token}
removeHandler={removeAdmin}
/>
)
})}
<button
onClick={closeModal}
>
Expand Down
50 changes: 48 additions & 2 deletions server/src/admin/admin.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import {
findStudentById,
updateCourseMetrics,
findReviewCounts,
createCourseCSV
createCourseCSV,
findAdminUsers,
removeAdminPrivilege,
grantAdminPrivilege
} from './admin.data-access';
import {
AdminAddSemesterType,
Expand All @@ -17,6 +20,7 @@ import {
ReportReviewRequestType,
UpdateCourseMetrics,
VerifyAdminType,
VerifyManageAdminType
} from './admin.type';

import {
Expand Down Expand Up @@ -144,7 +148,7 @@ export const getPendingReviews = async ({ auth }: VerifyAdminType) => {
};

/**
* Gets all reviews that are pending and reported (visible only to admin).
* Gets all reviews that are reported (visible only to admin).
*
* @param {Auth} auth: Object that represents the authentication of a request being passed in.
* @returns all reported review objects if operation was successful, null otherwise
Expand All @@ -158,6 +162,12 @@ export const getReportedReviews = async ({ auth }: VerifyAdminType) => {
return null;
};

/**
* Counts all reviews that are approved, pending, and reported.
*
* @param {Auth} auth: Object that represents the authentication of a request being passed in.
* @returns all counts if operation was successful, null otherwise
*/
export const getReviewCounts = async ({ auth }: VerifyAdminType) => {
const userIsAdmin = await verifyTokenAdmin({ auth });
if (userIsAdmin) {
Expand All @@ -166,6 +176,12 @@ export const getReviewCounts = async ({ auth }: VerifyAdminType) => {
}
}

/**
* Gets CSV text string of all reviews that are approved, sorted by class.
*
* @param {Auth} auth: Object that represents the authentication of a request being passed in.
* @returns CSV text if operation was successful, null otherwise
*/
export const getCourseCSV = async ({ auth }: VerifyAdminType) => {
const userIsAdmin = await verifyTokenAdmin({ auth });
if (userIsAdmin) {
Expand All @@ -174,6 +190,36 @@ export const getCourseCSV = async ({ auth }: VerifyAdminType) => {
}
}

/**
* Gets all users with admin privilege.
*
* @param {Auth} auth: Object that represents the authentication of a request being passed in.
* @returns all admin users if operation was successful, null otherwise
*/
export const getAdminUsers = async ({ auth }: VerifyAdminType) => {
const userIsAdmin = await verifyTokenAdmin({ auth });
if (userIsAdmin) {
const admins = await findAdminUsers();
return admins;
}
}

/**
* Removes a user's admin privilege by id. Assumes that the user is already in the
* database because they are retrieved into the ManageAdminModal
*
* @param {Auth} auth: Object that represents the authentication of a request being passed in.
* @param {string} id: String identifying the user in the
* @returns all admin users if operation was successful, null otherwise
*/
export const removeAdmin = async ({auth, id}: VerifyManageAdminType) => {
const userIsAdmin = await verifyTokenAdmin({ auth });
if (userIsAdmin) {
const res = await removeAdminPrivilege(id);
return res;
}
}

/**
* Updated all professors in the database by scraping through the Cornell course API.
*
Expand Down
8 changes: 5 additions & 3 deletions server/src/admin/admin.data-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,17 @@ export const updateReviewVisibility = async (
* Admin users have privilege "admin" and everyone else has privilege "regular"
*/

export const getAdminUsers = async () => {
export const findAdminUsers = async () => {
const adminUsers = await Students.find({ privilege: 'admin' }).exec()
return adminUsers
}

export const removeAdminPrivilege = async (id: string) => {
await Students.updateOne({ _id: id }, { $set: {privilege: 'regular'} }).exec()
const res = await Students.updateOne({ _id: id }, { $set: {privilege: 'regular'} }).exec()
return res
}

export const grantAdminPrivilege = async (id: string) => {
await Students.updateOne({ _id: id }, { $set: {privilege: 'admin'} }).exec()
const res = await Students.updateOne({ _id: id }, { $set: {privilege: 'admin'} }).exec()
return res
}
45 changes: 45 additions & 0 deletions server/src/admin/admin.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Auth } from '../auth/auth';
import {
AdminReviewRequestType,
AdminRequestType,
AdminUserRequestType,
RaffleWinnerRequestType,
AdminAddSemesterRequestType,
ReportReviewRequestType,
Expand All @@ -21,6 +22,8 @@ import {
addNewSemDb,
verifyTokenAdmin,
reportReview,
getAdminUsers,
removeAdmin,
} from './admin.controller';

export const adminRouter = express.Router();
Expand Down Expand Up @@ -176,6 +179,48 @@ adminRouter.post('/getCourseCSV', async (req, res) => {
}
})

adminRouter.post('/getAdmins', async (req, res) => {
try {
const { token }: AdminRequestType = req.body;
const auth = new Auth({ token });
const admins = await getAdminUsers({ auth });
if (admins === null) {
return res.status(400).json({
error: `User is not an admin.`
})
}

return res.status(200).json({
message: 'Retrieved admin users',
result: admins
})

} catch (err) {
return res.status(500).json({ error: `Internal Server Error: ${err}`});
}
})

adminRouter.post('/removeAdmin', async (req, res) => {
const {token, userId}: AdminUserRequestType = req.body;

try {
const auth = new Auth({ token });
const result = await removeAdmin({ auth: auth, id: userId})

if (result) {
return res.status(200).json({
message: `Remove admin privilege from user with id ${userId}`
});
}

return res.status(400).json({
error: 'User is not an admin.'
})
} catch (err) {
return res.status(500).json({ error: `Internal Server Error: ${err}`})
}
})

adminRouter.post('/addNewSemester', async (req, res) => {
const { semester, token }: AdminAddSemesterRequestType = req.body;
try {
Expand Down
10 changes: 10 additions & 0 deletions server/src/admin/admin.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export interface AdminReviewRequestType {
review: AdminReviewType;
}

export interface AdminUserRequestType {
token: string;
userId: string;
}

interface AdminReviewType {
_id: string;
reported: number;
Expand All @@ -28,6 +33,11 @@ export interface VerifyAdminType {
auth: Auth;
}

export interface VerifyManageAdminType {
auth: Auth;
id: string;
}

export interface RaffleWinnerRequestType {
startDate: string;
}
Expand Down

0 comments on commit 2366269

Please sign in to comment.