import express from "express"; import { requireAuthenticated } from "../middleware/authority.js"; import { needDatabase } from "../middleware/database.js"; import matchModel from "../schemas/matchModel.js"; import sportModel from "../schemas/sportModel.js"; import userModel from "../schemas/userModel.js"; const MatchController = express.Router(); MatchController.get("/search/:sport", needDatabase, async (req, res) => { try { let sport = sportModel.findByName(req.params.sport); let query = matchModel.find({ sport: sport._id }); query.where("when").gte(Date.now); // We don't want to return any results of matches that have already occurred. if (req.session.userId) query.where("publicity").gte(1).where("friends").in(req.session.userId); if (req.query.within) query.where("location").within({ center: req.query.location.split(","), radius: req.query.within }); if (req.query.minDifficulty) query.where("difficulty").gte(req.query.minDifficulty); if (req.query.maxDifficulty) query.where("difficulty").lte(req.query.maxDifficulty); if (req.query.beforeDate) query.where("when").lte(req.query.beforeDate); let queryResults = await query; res.send({ results: queryResults }); } catch (error) { console.error(error); res.status(500).send("Internal server error."); } }); MatchController.get("/recent/:limit?", needDatabase, async (req, res) => { try { let user = null; if (req.session.userId) { user = await userModel.findById(req.session.userId); } let limit = parseInt(req.params.limit); if (!req.params.limit) limit = 10; if (isNaN(limit)) { console.log(typeof (limit)); res.status(400).send("Limit parameter is not a number."); return; } if (isNaN(limit)) { res.status(400).send("Limit parameter not a number."); return; } if (limit > 50) { res.status(400).send("Limit greater than maximum limit of 50."); return; } let recent = null; if (user) { await user.populate("participatingMatches").populate("participatingMatches.members.$"); recent = user.participatingMatches.slice(-limit); } else { recent = await matchModel.find().where("publicity").gte(2).limit(limit).sort({ createDate: -1 }).populate("members.$"); } await recent; // Populates all references. res.status(200).send({ recent: recent }); } catch (error) { console.error(error); res.status(500).send("Internal server error."); // TODO: Check and improve error handling. } }); MatchController.post("/", needDatabase, requireAuthenticated, async (req, res) => { try { const userId = req.session.userId; const user = await userModel.findById(userId); const match = new matchModel({ title: req.body.title, when: req.body.when, public: req.body.public, location: req.body.location, creator: userId, difficulty: req.body.difficulty, sport: await sportModel.findByName(req.body.sport), participants: [user._id] }); await match.save(); user.createdMatches.push(match._id); user.participatingMatches.push(match._id); await user.save(); res.status(201).send({ createdMatch: match }); } catch (error) { console.error(error); res.status(500).send("Internal server error."); // TODO: Develop the error handling. } }); MatchController.patch("/:id", needDatabase, requireAuthenticated, async (req, res) => { try { const match = await matchModel.findById(req.params.id); if (!match) { res.status(400).send("Invalid match ID provided."); return; } if (req.user._id !== match.creator && req.user.accessLevel < 3) { res.status(401).send("Not authorized."); return; } if (req.body._id) { res.status(400).send("Cannot change ID of match."); return; } if (req.body.creator) { res.status(400).send("Cannot change creator of match."); return; } await match.updateOne(req.body); res.status(200).send({ updatedMatch: match }); } catch (error) { res.status(200).send("Internal server error."); } }); MatchController.delete("/:id", needDatabase, requireAuthenticated, async (req, res) => { try { const match = await matchModel.findById(req.params.id); if (!match) { res.status(400).send("Invalid match ID provided."); return; } if (req.user._id !== match.creator && req.user.accessLevel < 3) { res.status(401).send("Not authorized."); return; } await match.deleteOne(); res.status(200).send("Deleted."); } catch (error) { console.error(error); res.status(500).send("Internal server error"); } }); MatchController.get("/:id", needDatabase, async (req, res) => { try { if (!req.params.id) { res.status(404).send("Id must be provided to retrieve match"); return; } const match = await matchModel.findById(req.params.id).populate("sport"); if (match) { res.status(200).send({ match: match }); } else { res.status(404).send("Could not find match with ID: " + req.params.id); } } catch (error) { console.error(error); res.status(500).send("Internal server error."); // TODO: Improve the error handling. } }); MatchController.get("/join/:id", needDatabase, requireAuthenticated, async (req, res) => { try { const match = await matchModel.findById(req.params.id); const user = req.user; if (!match) { res.status(400).send("Invalid match ID provided."); return; } if (user.participatingMatches.includes(match._id)) { res.status(400).send("Already participating in match."); return; } match.participants.push(user._id); user.participatingMatches.push(match._id); await match.save(); await user.save(); res.status(200).send("Joined."); } catch (error) { console.error(error); res.status(500).send("Internal server error."); } }); MatchController.get("/leave/:id", needDatabase, requireAuthenticated, async (req, res) => { try { const match = await matchModel.findById(req.params.id); const user = req.user; if (!match) { res.status(400).send("Invalid match ID provided."); return; } if (!user.participatingMatches.includes(match._id)) { res.status(400).send("Not part of match."); return; } const userIndex = match.participants.indexOf(user._id); match.participants.splice(userIndex, 1); await match.save(); const matchIndex = user.participatingMatches.indexOf(match._id); user.participatingMatches.splice(matchIndex, 1); await user.save(); res.status(200).send("Left match."); } catch (error) { console.error(error); res.status(500).send("Internal server error."); } }); export default MatchController;