From 2cb3604e967df624d972db34c6e4670082bed480 Mon Sep 17 00:00:00 2001 From: Nikhil Trehan Date: Mon, 16 Sep 2024 19:34:57 -0400 Subject: [PATCH 1/2] Added Admin button capability to Edit Users --- backend/models/user.model.js | 6 +- backend/scripts/project_event_delete.js | 66 +++++++++++++++++++ client/src/api/UserApiService.js | 16 +++++ .../src/components/user-admin/EditUsers.jsx | 24 +++++-- client/src/pages/UserAdmin.jsx | 8 +++ client/src/sass/UserAdmin.scss | 6 +- 6 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 backend/scripts/project_event_delete.js diff --git a/backend/models/user.model.js b/backend/models/user.model.js index 1424a3753..715dc9046 100644 --- a/backend/models/user.model.js +++ b/backend/models/user.model.js @@ -36,7 +36,8 @@ const userSchema = mongoose.Schema({ managedProjects: [{ type: String}], // Which projects managed by user. //currentProject: { type: String } // no longer need this as we can get it from Project Team Member table // password: { type: String, required: true } - isActive: { type: Boolean, default: true } + isActive: { type: Boolean, default: true }, + isAdmin: {type: Boolean, default: false} // Signifies if a user is an admin or not }); userSchema.methods.serialize = function () { @@ -67,7 +68,8 @@ userSchema.methods.serialize = function () { githubPublic2FA: this.githubPublic2FA, availability: this.availability, managedProjects: this.managedProjects, - isActive: this.isActive + isActive: this.isActive, + isAdmin: this.isAmdin }; }; diff --git a/backend/scripts/project_event_delete.js b/backend/scripts/project_event_delete.js new file mode 100644 index 000000000..7217023e7 --- /dev/null +++ b/backend/scripts/project_event_delete.js @@ -0,0 +1,66 @@ +const { MongoClient } = require('mongodb'); +// Load config variables +const { DATABASE_URL } = require('../config/database.config'); + +async function deleteProjectsAndEvents() { + // We can pass any db name in the command line + const dbName = process.argv[2]; + + if (!dbName) { + console.error('Please provide a database name as an argument.'); + process.exit(1); + } + + // Strip out the existing db name and parameters from the URL + const baseUrl = DATABASE_URL.split('/').slice(0, -1).join('/'); + + // Construct the new URL by appending the dbName + const url = `${baseUrl}/${dbName}?retryWrites=true&w=majority`; + + const client = new MongoClient(url); + + try { + // Connect the client to the server + await client.connect(); + console.log('Connected to the server'); + const db = client.db(dbName); + + const projectsCount = await db.collection('projects').countDocuments(); + const eventsCount = await db.collection('events').countDocuments(); + + console.log(`Projects in database: ${projectsCount}`); + console.log(`Events in database: ${eventsCount}`); + + // if (projectsCount > 0) { + // // Find all project IDs + // const projectIds = await db.collection('projects').find({}, { projection: { _id: 1 } }).toArray(); + // const projectIdsArray = projectIds.map(project => project._id); + + // // Delete corresponding events + // const deleteEventsResult = await db.collection('events').deleteMany({ project: { $in: projectIdsArray } }); + // console.log(`Deleted ${deleteEventsResult.deletedCount} events.`); + + // // Delete all projects + // const deleteProjectsResult = await db.collection('projects').deleteMany({}); + // console.log(`Deleted ${deleteProjectsResult.deletedCount} projects.`); + // } else { + // console.log('No projects found in the database.'); + // } + + // Verification after deletion + const remainingProjects = await db.collection('projects').countDocuments(); + const remainingEvents = await db.collection('events').countDocuments(); + + console.log(`Projects remaining: ${remainingProjects}`); + console.log(`Events remaining: ${remainingEvents}`); + } catch (err) { + console.error(err); + } finally { + // Close the connection to the MongoDB server + await client.close(); + console.log('Connection closed'); + } +} + +// Run the function +deleteProjectsAndEvents(); diff --git a/client/src/api/UserApiService.js b/client/src/api/UserApiService.js index d0c5506de..a6b16eddf 100644 --- a/client/src/api/UserApiService.js +++ b/client/src/api/UserApiService.js @@ -73,6 +73,22 @@ class UserApiService { alert('server not responding. Please try again.'); } } + + async updateUserDbIsAdmin(userToEdit, isAdmin) { + const url = `${this.baseUserUrl}${userToEdit._id}`; + const requestOptions = { + method: 'PATCH', + headers: this.headers, + body: JSON.stringify({ isAdmin }), + }; + + try { + return await fetch(url, requestOptions); + } catch (err) { + console.error('update is-admin error', err); + alert('server not responding. Please try again.'); + } + } } export default UserApiService; diff --git a/client/src/components/user-admin/EditUsers.jsx b/client/src/components/user-admin/EditUsers.jsx index 1e5f72e93..d5426302c 100644 --- a/client/src/components/user-admin/EditUsers.jsx +++ b/client/src/components/user-admin/EditUsers.jsx @@ -3,10 +3,11 @@ import '../../sass/UserAdmin.scss'; import { FormGroup, FormControlLabel, Switch } from '@mui/material' // child of UserAdmin. Displays form to update users. -const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUserActiveStatus }) => { +const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUserActiveStatus, updateUserAdminStatus }) => { const [userManagedProjects, setUserManagedProjects] = useState([]); // The projects that the selected user is assigned const [projectValue, setProjectValue] = useState(''); // State and handler for form in EditUsers const [isActive, setIsActive] = useState(userToEdit.isActive); + const [isAdmin, setIsAdmin] = useState(userToEdit.isAdmin); // Prepare data for display const userName = `${userToEdit.name?.firstName} ${userToEdit.name?.lastName}`; @@ -64,6 +65,10 @@ const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUse updateUserActiveStatus(userToEdit, !isActive) } + const handleSetIsAdmin = () => { + setIsAdmin(!isAdmin) + updateUserAdminStatus(userToEdit, !isAdmin) + } return (
@@ -74,15 +79,24 @@ const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUse
Email:
{userEmail}
-
-
Is Active:
-
- {isActive.toString()} +
+
Is Active:
+
+ {isActive.toString()} } onClick={() => handleSetIsActive()} />
+
+
Is Admin:
+
+ {isAdmin.toString()} + + } onClick={() => handleSetIsAdmin()} /> + +
+
Projects:
diff --git a/client/src/pages/UserAdmin.jsx b/client/src/pages/UserAdmin.jsx index c540082ff..b501ca5e0 100644 --- a/client/src/pages/UserAdmin.jsx +++ b/client/src/pages/UserAdmin.jsx @@ -37,6 +37,13 @@ const UserAdmin = () => { }, [userApiService, fetchUsers] ) + const updateUserAdminStatus = useCallback( + async (user, isAdmin) => { + await userApiService.updateUserDbIsAdmin(user, isAdmin); + fetchUsers() + }, [userApiService, fetchUsers] + ) + const fetchProjects = useCallback(async () => { const projectRes = await projectApiService.fetchProjects(); setProjects(projectRes); @@ -65,6 +72,7 @@ const UserAdmin = () => { updateUserDb={updateUserDb} backToSearch={backToSearch} updateUserActiveStatus={updateUserActiveStatus} + updateUserAdminStatus={updateUserAdminStatus} /> ); } diff --git a/client/src/sass/UserAdmin.scss b/client/src/sass/UserAdmin.scss index 0d3759edb..adf81a32e 100644 --- a/client/src/sass/UserAdmin.scss +++ b/client/src/sass/UserAdmin.scss @@ -65,18 +65,18 @@ margin-bottom: 8px; } -.user-is-active-column-left { +.user-toggle-column-left { display: flex; flex-direction: column; flex-basis: 15%; } -.active-status { +.toggle-status { margin-right: 15px; width: 25px; } -.is-active-flex { +.toggle-flex { display: flex; align-items: center; } From 739ff757a0de766be544877abb1d6fa8971c5784 Mon Sep 17 00:00:00 2001 From: Nikhil Trehan Date: Mon, 16 Sep 2024 19:52:22 -0400 Subject: [PATCH 2/2] removed extra file --- backend/scripts/project_event_delete.js | 66 ------------------------- 1 file changed, 66 deletions(-) delete mode 100644 backend/scripts/project_event_delete.js diff --git a/backend/scripts/project_event_delete.js b/backend/scripts/project_event_delete.js deleted file mode 100644 index 7217023e7..000000000 --- a/backend/scripts/project_event_delete.js +++ /dev/null @@ -1,66 +0,0 @@ -const { MongoClient } = require('mongodb'); -// Load config variables -const { DATABASE_URL } = require('../config/database.config'); - -async function deleteProjectsAndEvents() { - // We can pass any db name in the command line - const dbName = process.argv[2]; - - if (!dbName) { - console.error('Please provide a database name as an argument.'); - process.exit(1); - } - - // Strip out the existing db name and parameters from the URL - const baseUrl = DATABASE_URL.split('/').slice(0, -1).join('/'); - - // Construct the new URL by appending the dbName - const url = `${baseUrl}/${dbName}?retryWrites=true&w=majority`; - - const client = new MongoClient(url); - - try { - // Connect the client to the server - await client.connect(); - console.log('Connected to the server'); - const db = client.db(dbName); - - const projectsCount = await db.collection('projects').countDocuments(); - const eventsCount = await db.collection('events').countDocuments(); - - console.log(`Projects in database: ${projectsCount}`); - console.log(`Events in database: ${eventsCount}`); - - // if (projectsCount > 0) { - // // Find all project IDs - // const projectIds = await db.collection('projects').find({}, { projection: { _id: 1 } }).toArray(); - // const projectIdsArray = projectIds.map(project => project._id); - - // // Delete corresponding events - // const deleteEventsResult = await db.collection('events').deleteMany({ project: { $in: projectIdsArray } }); - // console.log(`Deleted ${deleteEventsResult.deletedCount} events.`); - - // // Delete all projects - // const deleteProjectsResult = await db.collection('projects').deleteMany({}); - // console.log(`Deleted ${deleteProjectsResult.deletedCount} projects.`); - // } else { - // console.log('No projects found in the database.'); - // } - - // Verification after deletion - const remainingProjects = await db.collection('projects').countDocuments(); - const remainingEvents = await db.collection('events').countDocuments(); - - console.log(`Projects remaining: ${remainingProjects}`); - console.log(`Events remaining: ${remainingEvents}`); - } catch (err) { - console.error(err); - } finally { - // Close the connection to the MongoDB server - await client.close(); - console.log('Connection closed'); - } -} - -// Run the function -deleteProjectsAndEvents();