Separate client and server codes. Keep everything in one git repo for simplicity
[vchess.git] / server / routes / problems.js
diff --git a/server/routes/problems.js b/server/routes/problems.js
new file mode 100644 (file)
index 0000000..777543b
--- /dev/null
@@ -0,0 +1,94 @@
+// AJAX methods to get, create, update or delete a problem
+
+let router = require("express").Router();
+const access = require("../utils/access");
+const ProblemModel = require("../models/Problem");
+const sanitizeHtml = require('sanitize-html');
+const MaxNbProblems = 20;
+
+function sanitizeUserInput(fen, instructions, solution)
+{
+       if (!fen.match(/^[a-zA-Z0-9, /-]*$/))
+               return "Bad characters in FEN string";
+       instructions = sanitizeHtml(instructions);
+       solution = sanitizeHtml(solution);
+       if (instructions.length == 0)
+               return "Empty instructions";
+       if (solution.length == 0)
+               return "Empty solution";
+       return {
+               fen: fen,
+               instructions: instructions,
+               solution: solution
+       };
+}
+
+// Get one problem (TODO: vid unused, here for URL de-ambiguification)
+router.get("/problems/:vid([0-9]+)/:id([0-9]+)", access.ajax, (req,res) => {
+       const pid = req.params["id"];
+       ProblemModel.getOne(pid, (err,problem) => {
+               if (!!err)
+                       return res.json(err);
+               return res.json({problem: problem});
+       });
+});
+
+// Fetch N previous or next problems
+router.get("/problems/:vid([0-9]+)", access.ajax, (req,res) => {
+       const vid = req.params["vid"];
+       const directionStr = (req.query.direction == "forward" ? ">" : "<");
+       const lastDt = req.query.last_dt;
+       const type = req.query.type;
+       if (!lastDt.match(/[0-9]+/))
+               return res.json({errmsg: "Bad timestamp"});
+       if (!["others","mine"].includes(type))
+               return res.json({errmsg: "Bad type"});
+       ProblemModel.fetchN(vid, req.userId, type, directionStr, lastDt, MaxNbProblems,
+               (err,problems) => {
+                       if (!!err)
+                               return res.json(err);
+                       return res.json({problems: problems});
+               }
+       );
+});
+
+// Upload a problem (sanitize inputs)
+router.post("/problems/:vid([0-9]+)", access.logged, access.ajax, (req,res) => {
+       const vid = req.params["vid"];
+       const s = sanitizeUserInput(
+               req.body["fen"], req.body["instructions"], req.body["solution"]);
+       if (typeof s === "string")
+               return res.json({errmsg: s});
+  ProblemModel.create(req.userId, vid, s.fen, s.instructions, s.solution,
+               (err,pid) => {
+                       if (!!err)
+                               return res.json(err);
+                       res.json({id: pid["rowid"]});
+               }
+       );
+});
+
+// Update a problem (also sanitize inputs)
+router.put("/problems/:id([0-9]+)", access.logged, access.ajax, (req,res) => {
+       const pid = req.params["id"]; //problem ID
+       const s = sanitizeUserInput(
+               req.body["fen"], req.body["instructions"], req.body["solution"]);
+       if (typeof s === "string")
+               return res.json({errmsg: s});
+       ProblemModel.update(pid, req.userId, s.fen, s.instructions, s.solution,
+               err => {
+                       if (!!err)
+                               return res.json(err);
+                       res.json({});
+               }
+       );
+});
+
+// Delete a problem
+router.delete("/problems/:id([0-9]+)", access.logged, access.ajax, (req,res) => {
+       const pid = req.params["id"]; //problem ID
+  ProblemModel.remove(pid, req.userId);
+       res.json({});
+});
+
+module.exports = router;