| 
									
										
										
										
											2023-03-28 07:31:44 +02:00
										 |  |  | const express = require("express"); | 
					
						
							|  |  |  | const app = express(); | 
					
						
							|  |  |  | const cors = require("cors"); | 
					
						
							| 
									
										
										
										
											2023-03-28 16:56:48 +02:00
										 |  |  | const mongoose = require("mongoose"); | 
					
						
							| 
									
										
										
										
											2023-03-28 07:31:44 +02:00
										 |  |  | require("dotenv").config(); | 
					
						
							| 
									
										
										
										
											2017-02-18 20:06:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 07:31:44 +02:00
										 |  |  | const PORT = process.env.PORT || 16749; | 
					
						
							| 
									
										
										
										
											2023-03-28 16:56:48 +02:00
										 |  |  | const MONGODB_URI = process.env.MONGODB_URI || ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | mongoose.connect(MONGODB_URI, { | 
					
						
							|  |  |  |   // @ts-ignore
 | 
					
						
							|  |  |  |   useNewUrlParser: true, | 
					
						
							|  |  |  |   useUnifiedTopology: true, | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const exerciseLogsSchema = new mongoose.Schema({ | 
					
						
							|  |  |  |   username: { type: String, required: true }, | 
					
						
							| 
									
										
										
										
											2023-03-29 05:51:08 +02:00
										 |  |  |   log: [ | 
					
						
							| 
									
										
										
										
											2023-03-28 16:56:48 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |       description: { type: String, required: true }, | 
					
						
							|  |  |  |       duration: { type: Number, required: true }, | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  |       date: { type: Number, required: true }, | 
					
						
							| 
									
										
										
										
											2023-03-28 16:56:48 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  |   ], | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const exerciseLogs = mongoose.model("ExerciseLogs", exerciseLogsSchema); | 
					
						
							| 
									
										
										
										
											2017-02-18 20:06:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 07:31:44 +02:00
										 |  |  | app.use(cors()); | 
					
						
							|  |  |  | app.use(express.static("public")); | 
					
						
							| 
									
										
										
										
											2023-03-28 16:56:48 +02:00
										 |  |  | app.use(express.urlencoded({ extended: false })); | 
					
						
							| 
									
										
										
										
											2023-03-28 07:31:44 +02:00
										 |  |  | app.get("/", (req, res) => { | 
					
						
							|  |  |  |   res.sendFile(__dirname + "/views/index.html"); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2017-02-18 20:06:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 16:56:48 +02:00
										 |  |  | app.post("/api/users", (req, res) => { | 
					
						
							|  |  |  |   const username = req.body.username; | 
					
						
							|  |  |  |   const exerciseLogsModel = new exerciseLogs({ username: username }); | 
					
						
							|  |  |  |   exerciseLogsModel | 
					
						
							|  |  |  |     .save() | 
					
						
							|  |  |  |     .then((user) => { | 
					
						
							|  |  |  |       if (user) return res.json({ username: user.username, _id: user._id }); | 
					
						
							|  |  |  |       res.status(500); | 
					
						
							|  |  |  |       res.json({ error: `Error creating user: ${username}` }); | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     .catch((err) => { | 
					
						
							|  |  |  |       res.status(500); | 
					
						
							|  |  |  |       return res.json({ | 
					
						
							|  |  |  |         error: `Error type 2 while creating user: ${username}`, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 17:34:09 +02:00
										 |  |  | app.get("/api/users", (req, res) => { | 
					
						
							|  |  |  |   exerciseLogs | 
					
						
							|  |  |  |     .find() | 
					
						
							|  |  |  |     .select({ username: true, _id: true }) | 
					
						
							|  |  |  |     .exec() | 
					
						
							|  |  |  |     .then((users) => { | 
					
						
							|  |  |  |       res.json(users); | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     .catch((err) => { | 
					
						
							|  |  |  |       res.sendStatus(500); | 
					
						
							|  |  |  |       res.json({ error: `Error while retrieving users list:\n${err}` }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-29 05:57:58 +02:00
										 |  |  | const getDateInTicks = (date) => { | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  |   // current time in tick if no date specified
 | 
					
						
							|  |  |  |   if (!date) date = new Date().getTime(); | 
					
						
							|  |  |  |   // Convert String to Number if date specified in ticks
 | 
					
						
							|  |  |  |   if (!Number.isNaN(Number(date))) date = Number(date); | 
					
						
							|  |  |  |   // get date ticks from ticks Number or date String
 | 
					
						
							|  |  |  |   date = new Date(date).getTime(); | 
					
						
							|  |  |  |   // date will be NaN if invalid date String is provided
 | 
					
						
							| 
									
										
										
										
											2023-03-29 05:57:58 +02:00
										 |  |  |   return date; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | app.post("/api/users/:_id/exercises", (req, res) => { | 
					
						
							|  |  |  |   const _id = req.params._id; | 
					
						
							|  |  |  |   const description = req.body.description; | 
					
						
							| 
									
										
										
										
											2023-03-29 07:18:16 +02:00
										 |  |  |   const duration = Number(req.body.duration); | 
					
						
							| 
									
										
										
										
											2023-03-29 05:57:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   let date = getDateInTicks(req.body.date); | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  |   if (Number.isNaN(Number(date))) { | 
					
						
							| 
									
										
										
										
											2023-03-29 04:16:23 +02:00
										 |  |  |     res.status(400); | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  |     return res.json({ error: `Input date: '${req.body.date}' is not valid` }); | 
					
						
							| 
									
										
										
										
											2023-03-29 04:16:23 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-29 04:06:13 +02:00
										 |  |  |   exerciseLogs | 
					
						
							| 
									
										
										
										
											2023-03-29 07:25:26 +02:00
										 |  |  |     .findById(_id) | 
					
						
							|  |  |  |     .select({ username: 1 }) | 
					
						
							|  |  |  |     .then((user) => { | 
					
						
							|  |  |  |       if (user) { | 
					
						
							| 
									
										
										
										
											2023-03-29 04:06:13 +02:00
										 |  |  |         exerciseLogs | 
					
						
							|  |  |  |           .updateOne( | 
					
						
							|  |  |  |             { _id: _id }, | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               $push: { | 
					
						
							| 
									
										
										
										
											2023-03-29 05:51:08 +02:00
										 |  |  |                 log: { | 
					
						
							| 
									
										
										
										
											2023-03-29 04:06:13 +02:00
										 |  |  |                   description: description, | 
					
						
							|  |  |  |                   duration: duration, | 
					
						
							|  |  |  |                   date: date, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             { runValidators: true } | 
					
						
							|  |  |  |           ) | 
					
						
							|  |  |  |           .then((excLogs) => { | 
					
						
							|  |  |  |             if (excLogs.modifiedCount) { | 
					
						
							|  |  |  |               res.json({ | 
					
						
							|  |  |  |                 _id: _id, | 
					
						
							| 
									
										
										
										
											2023-03-29 07:25:26 +02:00
										 |  |  |                 username: user.username, | 
					
						
							| 
									
										
										
										
											2023-03-29 04:06:13 +02:00
										 |  |  |                 description: description, | 
					
						
							|  |  |  |                 duration: duration, | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  |                 date: new Date(date).toDateString(), | 
					
						
							| 
									
										
										
										
											2023-03-29 04:06:13 +02:00
										 |  |  |               }); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |               res.json(500); | 
					
						
							|  |  |  |               res.json({ | 
					
						
							|  |  |  |                 error: `Failed to add exercise logs to database:\n${excLogs}`, | 
					
						
							|  |  |  |               }); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }) | 
					
						
							|  |  |  |           .catch((err) => { | 
					
						
							|  |  |  |             res.status(500); | 
					
						
							|  |  |  |             res.json({ | 
					
						
							|  |  |  |               error: `Failed to add exercise logs to database:\n${err}`, | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         res.status(403); | 
					
						
							|  |  |  |         res.json({ error: `No user with id: ${_id} exists` }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     .catch((err) => { | 
					
						
							|  |  |  |       res.status(500); | 
					
						
							|  |  |  |       res.json({ error: "Failed to check user in database" }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-29 04:41:49 +02:00
										 |  |  | app.get("/api/users/:_id/logs", (req, res) => { | 
					
						
							|  |  |  |   const _id = req.params._id; | 
					
						
							| 
									
										
										
										
											2023-03-29 07:02:03 +02:00
										 |  |  |   const limit = req.query.limit | 
					
						
							|  |  |  |     ? Math.trunc(Number(req.query.limit)) | 
					
						
							|  |  |  |     : Number.MAX_SAFE_INTEGER; | 
					
						
							|  |  |  |   if (Number.isNaN(limit)) { | 
					
						
							|  |  |  |     res.status(400); | 
					
						
							|  |  |  |     return res.json({ | 
					
						
							|  |  |  |       error: `Query key 'limit''s value '${req.query.limit}' is not a number`, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const from = req.query.from ? getDateInTicks(req.query.from) : 0; | 
					
						
							|  |  |  |   if (Number.isNaN(from)) { | 
					
						
							|  |  |  |     res.status(400); | 
					
						
							|  |  |  |     return res.json({ | 
					
						
							|  |  |  |       error: `Query key 'from''s value '${req.query.from}' is invalid for date`, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const to = req.query.to | 
					
						
							|  |  |  |     ? getDateInTicks(req.query.to) | 
					
						
							|  |  |  |     : Number.MAX_SAFE_INTEGER; | 
					
						
							|  |  |  |   if (Number.isNaN(to)) { | 
					
						
							|  |  |  |     res.status(400); | 
					
						
							|  |  |  |     return res.json({ | 
					
						
							|  |  |  |       error: `Query key 'to''s value '${req.query.to}' is invalid for date`, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-03-29 04:41:49 +02:00
										 |  |  |   exerciseLogs | 
					
						
							|  |  |  |     .findById(_id) | 
					
						
							| 
									
										
										
										
											2023-03-29 07:02:03 +02:00
										 |  |  |     .select({ "log._id": false, __v: false }) | 
					
						
							| 
									
										
										
										
											2023-03-29 04:41:49 +02:00
										 |  |  |     .then((excLogs) => { | 
					
						
							|  |  |  |       if (excLogs) { | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  |         let excLogsJson = excLogs.toJSON(); | 
					
						
							| 
									
										
										
										
											2023-03-29 07:02:03 +02:00
										 |  |  |         excLogsJson.log = excLogsJson.log.filter( | 
					
						
							|  |  |  |           (log) => log.date >= from && log.date <= to | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         excLogsJson.log.sort((a, b) => a.date - b.date); | 
					
						
							|  |  |  |         excLogsJson.log = excLogsJson.log.slice(0, limit); | 
					
						
							| 
									
										
										
										
											2023-03-29 05:51:08 +02:00
										 |  |  |         excLogsJson.count = excLogsJson.log.length; | 
					
						
							|  |  |  |         excLogsJson.log = excLogsJson.log.map((log) => { | 
					
						
							| 
									
										
										
										
											2023-03-29 05:47:36 +02:00
										 |  |  |           log.date = new Date(log.date).toDateString(); | 
					
						
							|  |  |  |           return log; | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2023-03-29 04:41:49 +02:00
										 |  |  |         return res.json(excLogsJson); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       res.status(400); | 
					
						
							|  |  |  |       res.json({ error: `No user with id: '${_id}' exists` }); | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     .catch((err) => { | 
					
						
							|  |  |  |       res.status(400); | 
					
						
							|  |  |  |       res.json({ error: `Input user id: '${_id}' is malformed` }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 07:31:44 +02:00
										 |  |  | const listener = app.listen(PORT, () => { | 
					
						
							|  |  |  |   console.log("Your app is listening on port " + listener.address().port); | 
					
						
							|  |  |  | }); |