-
Notifications
You must be signed in to change notification settings - Fork 56
refactor: move route logic into controllers #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| const { Achievement } = require("../models/schema"); | ||
| const { v4: uuidv4 } = require("uuid"); | ||
|
|
||
| // GET unverified achievements by type | ||
| const getUnendorsedAchievements = async (req, res) => { | ||
| const { type } = req.params; | ||
|
|
||
| try { | ||
| const unverifiedAchievements = await Achievement.find({ | ||
| type, | ||
| verified: false, | ||
| }) | ||
| .populate("user_id", "personal_info.name username user_id") | ||
| .populate("event_id", "title description "); | ||
|
|
||
| res.json(unverifiedAchievements); | ||
| } catch (err) { | ||
| console.error(err); | ||
| res | ||
| .status(500) | ||
| .json({ message: "Failed to fetch unverified achievements." }); | ||
| } | ||
| }; | ||
|
|
||
| // PATCH verify achievement by ID | ||
| const verifyAchievement = async (req, res) => { | ||
| const { id } = req.params; | ||
| const { verified_by } = req.body; | ||
|
|
||
| try { | ||
| const achievement = await Achievement.findById(id); | ||
|
|
||
| if (!achievement) { | ||
| return res.status(404).json({ | ||
| message: "Achievement not found.", | ||
| }); | ||
| } | ||
|
|
||
| achievement.verified = true; | ||
| achievement.verified_by = verified_by; | ||
|
|
||
| await achievement.save(); | ||
|
|
||
| res.json({ | ||
| message: "Achievement verified successfully.", | ||
| achievement, | ||
| }); | ||
| } catch (err) { | ||
| console.error(err); | ||
| res.status(500).json({ | ||
| message: "Failed to verify achievement.", | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
| // REJECT (delete) achievement by ID | ||
| const rejectAchievement = async (req, res) => { | ||
| const { id } = req.params; | ||
|
|
||
| try { | ||
| const deletedAchievement = await Achievement.findByIdAndDelete(id); | ||
|
|
||
| if (!deletedAchievement) { | ||
| return res.status(404).json({ | ||
| message: "Achievement not found.", | ||
| }); | ||
| } | ||
|
|
||
| res.json({ | ||
| message: "Achievement rejected and deleted successfully.", | ||
| }); | ||
| } catch (err) { | ||
| console.error("Failed to reject achievement:", err); | ||
|
|
||
| res.status(500).json({ | ||
| message: "Failed to reject achievement.", | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
| // Add achievement | ||
| const addAchievement = async (req, res) => { | ||
| try { | ||
| const { | ||
| title, | ||
| description, | ||
| category, | ||
| type, | ||
| level, | ||
| date_achieved, | ||
| position, | ||
| certificate_url, | ||
| event_id, | ||
| user_id, | ||
| } = req.body; | ||
|
|
||
| if (!title || !category || !date_achieved || !user_id) { | ||
| return res.status(400).json({ | ||
| message: "Missing required fields", | ||
| }); | ||
| } | ||
|
|
||
| const achievement = new Achievement({ | ||
| achievement_id: uuidv4(), | ||
| user_id, | ||
| title, | ||
| description, | ||
| category, | ||
| type, | ||
| level, | ||
| date_achieved, | ||
| position, | ||
| certificate_url, | ||
| event_id: event_id || null, | ||
| }); | ||
|
Comment on lines
+82
to
+115
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Block cross-user achievement creation. Line 94 accepts Suggested fix const addAchievement = async (req, res) => {
try {
const {
@@
- user_id,
+ user_id,
} = req.body;
+
+ const effectiveUserId =
+ req.user.role === "admin" ? user_id : req.user._id; // match the schema field
- if (!title || !category || !date_achieved || !user_id) {
+ if (!title || !category || !date_achieved || !effectiveUserId) {
return res.status(400).json({
message: "Missing required fields",
});
}
@@
const achievement = new Achievement({
achievement_id: uuidv4(),
- user_id,
+ user_id: effectiveUserId,
title,🤖 Prompt for AI Agents |
||
|
|
||
| await achievement.save(); | ||
|
|
||
| return res.status(201).json({ | ||
| message: "Achievement saved successfully", | ||
| achievement, | ||
| }); | ||
| } catch (error) { | ||
| console.error("Error saving achievement:", error); | ||
|
|
||
| return res.status(500).json({ | ||
| message: "Server error", | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
| // Get all user achievements | ||
| const getUserAchievements = async (req, res) => { | ||
| const userId = req.params.userId; | ||
|
|
||
| try { | ||
| const userAchievements = await Achievement.find({ | ||
| user_id: userId, | ||
| }) | ||
| .populate("event_id", "title description") | ||
| .populate( | ||
| "verified_by", | ||
| "personal_info.name username user_id" | ||
| ); | ||
|
|
||
| res.json(userAchievements); | ||
| } catch (err) { | ||
| console.error("Failed to get user Achievements:", err); | ||
|
|
||
| res.status(500).json({ | ||
| message: "Failed to get user Achievements.", | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
| module.exports = { | ||
| getUnendorsedAchievements, | ||
| verifyAchievement, | ||
| rejectAchievement, | ||
| addAchievement, | ||
| getUserAchievements, | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Derive
verified_byfrom the authenticated user, not the request body.Line 28 lets the caller choose
verified_by, so an admin can verify an achievement while attributing it to someone else. That breaks the audit trail. Set this field from the authenticated principal instead of trusting client input.Suggested fix
const verifyAchievement = async (req, res) => { const { id } = req.params; - const { verified_by } = req.body; + const verified_by = req.user._id; // or req.user.user_id, matching the schema try { const achievement = await Achievement.findById(id); @@ achievement.verified = true; achievement.verified_by = verified_by;📝 Committable suggestion
🤖 Prompt for AI Agents