import * as express from "express"; import * as bodyparser from "body-parser"; import { authRoute } from "../security/token"; import { userFromSession } from "../utils/user"; import { IUser, IUserDBModel } from "../models/user"; import { LRequest } from "../types/express"; import { Db } from "mongodb"; const userRouter = express.Router(); userRouter.use(authRoute); userRouter.use(bodyparser.json()); // Return the user object if the user is still authenticated userRouter.get("/me", async (req: LRequest, res) => { const { db, token } = req; const session = await db.collection("sessions").findOne({ token, }); if (session !== null) { const user = await db.collection("users").findOne({ username: session.username }); // Copy and strip unneeded attributes let copy = Object.assign({}, user, { sessionToken: token, }); delete copy._id; delete copy.hash; delete copy.salt; res.send({ error: "0", data: copy, }); } else { res.send({ error: "404", data: {}, }); } }); // Removes the user's session userRouter.get("/logout", async (req: LRequest, res) => { // Try to remove the session const { db, token } = req; await db.collection("sessions").findOneAndDelete({ token, }); res.send({ error: "0", data: {}, }); }); // TODO: This should be shared with the frontend, to remove code duplication export enum VocabType { NOMEN = 0, VERB = 1, ADJEKTIV = 2, ADVERB = 3, }; // Gets the user's review queue userRouter.get("/queue", async (req: LRequest, res) => { // TODO: if (user) const { token, db } = req; const user = await userFromSession(token, db); // Fetch all vocab ids from the vocabulary collection const vocabRaw = await db.collection("vocabulary").find({ id: { $in: user.queue }, }, { // TODO: Make this configurable? limit: 20, }).toArray(); // Remove unneeded data const vocab = vocabRaw.map(el => { let tmp = Object.assign({}, el); delete tmp._id; return tmp; }); res.send({ error: "0", data: { queue: vocab, }, }); }); // Get ot set the last review results userRouter.get("/lastReview", async (req: LRequest, res) => { // TODO: if(user) const { token, db } = req; const user = await userFromSession(token, db); res.send({ error: "0", data: user.lastReview, }); }); userRouter.post("/lastReview", async (req: LRequest, res) => { // TODO: Check if we get the correct data // TODO: if(user) const { token, db } = req; const user = await userFromSession(token, db); // TODO: Error handling await db.collection("users").updateOne({ username: user.username, }, { $set: { lastReview: req.body.meta, }, }); res.send({ error: "0", data: {}, }); }); // Returns the next level (level + 1) or the current level, if no higher level // can be found async function getNextLevel(token: string, db: Db): Promise<any> { // TODO: if(user) const user = await userFromSession(token, db); const { lastLevel } = user; // Try to find a level, which level is lastLevel + 1 const level = await db.collection("levels").findOne({ level: lastLevel + 1, }); if (level) { return level; } else { // TODO: Send different data, so that the Client can say "Hey, no more levels" return await db.collection("levels").findOne({ level: lastLevel }); } } // Get the next level userRouter.get("/nextLevel", async (req: LRequest, res) => { const level = await getNextLevel(req.token, req.db); res.send({ error: "0", data: level, }); }); // Mark a level as done userRouter.post("/level/:id", async (req, res) => { console.log("STUB(post): /user/level/:id"); // TODO: Stub res.send({ error: "0", data: {}, }); }); // Get the data needed for the dashboard userRouter.get("/dashboard", async (req: LRequest, res) => { const { db, token } = req; // Get the user // TODO: if (user) const user = await userFromSession(token, db); const { classId } = user; // Fetch the top ten of the class const rawTopTen = await db.collection("users").find({ classId, }, { sort: { score: -1, }, limit: 10, }).toArray(); let nr = 1; const topTen = rawTopTen.map((user: IUser) => { return { username: user.username, score: user.score, // TODO: Calculate on the client? level: 1, nr: nr++, }; }); const nextLevel = await getNextLevel(token, db); res.send({ error: "200", data: { nextLevel, topTen, lastReview: user.lastReview, }, }); }); export default userRouter;