| 1 | let router = require("express").Router(); |
| 2 | const access = require("../utils/access"); |
| 3 | const UserModel = require("../models/user"); |
| 4 | const EvaluationModel = require("../models/evaluation"); |
| 5 | const CourseModel = require("../models/course"); |
| 6 | |
| 7 | // Actual pages (least specific last) |
| 8 | |
| 9 | // List initials and count evaluations |
| 10 | router.get("/", (req,res) => { |
| 11 | UserModel.getAll( (err,userArray) => { |
| 12 | if (!!err) |
| 13 | return res.json(err); |
| 14 | res.render("index", { |
| 15 | title: "home", |
| 16 | userArray: userArray, |
| 17 | }); |
| 18 | }); |
| 19 | }); |
| 20 | |
| 21 | // Login screen |
| 22 | router.get("/login", access.unlogged, (req,res) => { |
| 23 | res.render("login", { |
| 24 | title: "login", |
| 25 | }); |
| 26 | }); |
| 27 | |
| 28 | // Redirection screens when possible cheating attempt detected in exam |
| 29 | router.get("/enablejs", (req,res) => { |
| 30 | res.render("enablejs", { |
| 31 | title: "JS disabled", |
| 32 | }); |
| 33 | }); |
| 34 | |
| 35 | router.get("/fullscreen", (req,res) => { |
| 36 | res.render("fullscreen", { |
| 37 | title: "Not in fullscreen", |
| 38 | }); |
| 39 | }); |
| 40 | |
| 41 | router.get("/noblur", (req,res) => { |
| 42 | res.render("noblur", { |
| 43 | title: "Lost focus", |
| 44 | }); |
| 45 | }); |
| 46 | |
| 47 | // List courses of some user (should be [a-z]+[0-9]* but fails...) |
| 48 | router.get("/:initials([a-z0-9]+)", (req,res) => { |
| 49 | let initials = req.params["initials"]; |
| 50 | CourseModel.getByInitials(initials, (err,courseArray) => { |
| 51 | if (!!err) |
| 52 | return res.json(err); |
| 53 | access.getUser(req, res, (err2,user) => { |
| 54 | const isTeacher = !!user && user.initials == initials; |
| 55 | // Strip students from courses if not course admin (TODO: not required in any case) |
| 56 | if (!isTeacher) |
| 57 | { |
| 58 | courseArray.forEach( c => { |
| 59 | delete c["students"]; |
| 60 | }); |
| 61 | } |
| 62 | res.render("course-list", { |
| 63 | title: initials + " courses", |
| 64 | courseArray: courseArray, |
| 65 | teacher: isTeacher, |
| 66 | initials: initials, |
| 67 | }); |
| 68 | }); |
| 69 | }); |
| 70 | }); |
| 71 | |
| 72 | // Detailed content of one course |
| 73 | router.get("/:initials([a-z0-9]+)/:courseCode([a-z0-9._-]+)", (req,res) => { |
| 74 | let initials = req.params["initials"]; |
| 75 | let code = req.params["courseCode"]; |
| 76 | CourseModel.getByRefs(initials, code, (err,course) => { |
| 77 | access.checkRequest(res, err, course, "Course not found", () => { |
| 78 | EvaluationModel.getByCourse(course._id, (err2,evaluationArray) => { |
| 79 | if (!!err) |
| 80 | return res.json(err); |
| 81 | access.getUser(req, res, (err2,user) => { |
| 82 | const isTeacher = !!user && user.initials == initials; |
| 83 | // Strip students from course if not course admin |
| 84 | if (!isTeacher) |
| 85 | delete course["students"]; |
| 86 | res.render("course", { |
| 87 | title: "course " + initials + "/" + code, |
| 88 | course: course, |
| 89 | evaluationArray: evaluationArray, |
| 90 | teacher: isTeacher, |
| 91 | initials: initials, |
| 92 | }); |
| 93 | }); |
| 94 | }); |
| 95 | }); |
| 96 | }); |
| 97 | }); |
| 98 | |
| 99 | // Grading students answers: --> after identification (password), always send secret with requests |
| 100 | router.get("/:initials([a-z0-9]+)/:courseCode([a-z0-9._-]+)/grade", (req,res) => { |
| 101 | let initials = req.params["initials"]; |
| 102 | let code = req.params["courseCode"]; |
| 103 | // TODO: if (main) teacher, also send secret, saving one request |
| 104 | res.render("grade", { |
| 105 | title: "grade exams " + code + "/" + name, |
| 106 | initials: initials, |
| 107 | courseCode: code, |
| 108 | }); |
| 109 | }); |
| 110 | |
| 111 | // Display evaluation (exam or open status) |
| 112 | router.get("/:initials([a-z0-9]+)/:courseCode([a-z0-9._-]+)/:evaluationName([a-z0-9._-]+)", (req,res) => { |
| 113 | let initials = req.params["initials"]; |
| 114 | let code = req.params["courseCode"]; |
| 115 | let name = req.params["evaluationName"]; |
| 116 | EvaluationModel.getByRefs(initials, code, name, (err,evaluation) => { |
| 117 | access.checkRequest(res, err, evaluation, "Evaluation not found", () => { |
| 118 | if (!evaluation.active) |
| 119 | return res.json({errmsg: "Evaluation is idle"}); |
| 120 | delete evaluation["papers"]; //always remove recorded students answers |
| 121 | if (evaluation.mode == "exam") |
| 122 | { |
| 123 | if (!!req.headers['user-agent'].match(/(SpecialAgent|HeadlessChrome|PhantomJS)/)) |
| 124 | { |
| 125 | // Basic headless browser detection |
| 126 | return res.json({errmsg: "Headless browser detected"}); |
| 127 | } |
| 128 | // Strip questions if exam mode (stepwise process) |
| 129 | delete evaluation["questions"]; |
| 130 | } |
| 131 | res.render("evaluation", { |
| 132 | title: "evaluation " + initials + "/" + code + "/" + name, |
| 133 | evaluation: evaluation, |
| 134 | }); |
| 135 | }); |
| 136 | }); |
| 137 | }); |
| 138 | |
| 139 | // Monitor: --> after identification (password), always send secret with requests |
| 140 | router.get("/:initials([a-z0-9]+)/:courseCode([a-z0-9._-]+)/:evaluationName([a-z0-9._-]+)/monitor", (req,res) => { |
| 141 | let initials = req.params["initials"]; |
| 142 | let code = req.params["courseCode"]; |
| 143 | let name = req.params["evaluationName"]; |
| 144 | // TODO: if (main) teacher, also send secret, saving one request |
| 145 | res.render("monitor", { |
| 146 | title: "monitor evaluation " + code + "/" + name, |
| 147 | initials: initials, |
| 148 | courseCode: code, |
| 149 | examName: name, |
| 150 | }); |
| 151 | }); |
| 152 | |
| 153 | module.exports = router; |