Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion server/controllers/contestCon.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const manageViolations = async (req, res) => {
} catch (error) {
res.status(500).json({ message: 'Server error', error: error.message });
}
};No
};

module.exports = {
startContest,
Expand Down
64 changes: 64 additions & 0 deletions server/controllers/contestController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const Contest = require('../models/Contest');


const createContest = async (req, res) => {
try {
const contest = new Contest(req.body);
await contest.save();
res.status(201).json({ message: 'Contest created successfully', contest });
} catch (error) {
res.status(500).json({ message: 'Error creating contest', error: error.message });
}
};

const getAllContests = async (req, res) => {
try {
const contests = await Contest.find().populate('questions');
res.json(contests);
} catch (error) {
res.status(500).json({ message: 'Error fetching contests', error: error.message });
}
};


const getContestById = async (req, res) => {
try {
const contest = await Contest.findById(req.params.id).populate('questions');
if (!contest) {
return res.status(404).json({ message: 'Contest not found' });
}
res.json(contest);
} catch (error) {
res.status(500).json({ message: 'Error fetching contest', error: error.message });
}
};


const updateContest = async (req, res) => {
try {
const updated = await Contest.findByIdAndUpdate(req.params.id, req.body, { new: true });
if (!updated) return res.status(404).json({ message: 'Contest not found' });
res.json({ message: 'Contest updated', updated });
} catch (error) {
res.status(500).json({ message: 'Error updating contest', error: error.message });
}
};


const deleteContest = async (req, res) => {
try {
const deleted = await Contest.findByIdAndDelete(req.params.id);
if (!deleted) return res.status(404).json({ message: 'Contest not found' });
res.json({ message: 'Contest deleted successfully' });
} catch (error) {
res.status(500).json({ message: 'Error deleting contest', error: error.message });
}
};

module.exports = {
createContest,
getAllContests,
getContestById,
updateContest,
deleteContest,
};
24 changes: 24 additions & 0 deletions server/controllers/leaderboardCon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const testAns = require('../helpers/testAns');
// Example loop over user answers
const evaluateMCQSubmissions = (userSubmissions, questions) => {
const results = [];

for (let i = 0; i < questions.length; i++) {
const userAnswer = userSubmissions[i]; // e.g., 'A'
const correctAnswer = questions[i].correctOption; // e.g., 'B'
const marks = questions[i].marks || 1;

const result = testAns({
submitted: userAnswer,
correct: correctAnswer,
marks: marks
});

results.push({
questionId: questions[i]._id,
...result
});
}

return results;
};
23 changes: 23 additions & 0 deletions server/helpers/testAns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@


/**
* Evaluate a multiple-choice question answer
*
* @param {Object} params
* @param {string} params.submitted - User's submitted answer (e.g., "A", "B")
* @param {string} params.correct - Correct answer (e.g., "B")
* @param {number} params.marks - Marks awarded for a correct answer
*
* @returns {Object} result - Includes correctness, score, and result string
*/
const testAns = ({ submitted, correct, marks }) => {
const isCorrect = submitted === correct;

return {
correct: isCorrect,
score: isCorrect ? marks : 0,
result: isCorrect ? 'Correct' : 'Wrong',
};
};

module.exports = testAns;
27 changes: 27 additions & 0 deletions server/middlewares/isAdmin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const User = require('../models/User');
const isAdmin = async (req, res, next) => {
try {
const clerkUserId = req.auth?.userId;

if (!clerkUserId) {
return res.status(401).json({ message: 'Unauthorized: No Clerk user ID found' });
}

const user = await User.findOne({ clerkId: clerkUserId });

if (!user) {
return res.status(404).json({ message: 'User not found in database' });
}

if (user.role !== 'admin') {
return res.status(403).json({ message: 'Forbidden: Admin access only' });
}

next(); // User is verified admin → continue
} catch (error) {
console.error('isAdmin Middleware Error:', error);
res.status(500).json({ message: 'Internal Server Error' });
}
};

module.exports = isAdmin;
25 changes: 25 additions & 0 deletions server/routes/AdminRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const express = require('express');
const router = express.Router();

const { requireAuth } = require('../middlewares/auth');
const isAdmin = require('../middlewares/isAdmin');

const { startContest, manageViolations } = require('../controllers/contestCon');

const {
createContest,
updateContest,
deleteContest,
} = require('../controllers/contestController');

router.use(requireAuth, isAdmin);

router.post('/contests/:id/start', startContest);
router.post('/contests/:id/violation', manageViolations);

// Add more routes like create/update/delete contests/questions here
router.post('/contests', isAdmin, createContest);
router.put('/contests/:id', isAdmin, updateContest);
router.delete('/contests/:id', isAdmin, deleteContest);

module.exports = router;
12 changes: 12 additions & 0 deletions server/routes/ContestRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const express = require('express');
const router = express.Router();
const {
getAllContests,
getContestById,
} = require('../controllers/contestController');

// Public routes
router.get('/contests', getAllContests);
router.get('/contests/:id', getContestById);

module.exports = router;