diff --git a/backend/db.md b/backend/db.md index b43a24b..0b29c38 100644 --- a/backend/db.md +++ b/backend/db.md @@ -8,6 +8,12 @@ uid: number, showWelcome: boolean, classId: string, + score: number, + + lastReview: { + correct: number, + wrong: number, + } } ` diff --git a/backend/src/api/user.ts b/backend/src/api/user.ts index 52b579a..b1eb385 100644 --- a/backend/src/api/user.ts +++ b/backend/src/api/user.ts @@ -3,6 +3,10 @@ import * as bodyparser from "body-parser"; import { authRoute } from "../security/token"; +import { userFromSession } from "../utils/user"; + +import { IUser } from "../models/user"; + const userRouter = express.Router(); userRouter.use(authRoute); userRouter.use(bodyparser.json()); @@ -16,12 +20,17 @@ userRouter.get("/me", async (req, res) => { if (session !== null) { const user = await db.collection("users").findOne({ username: session.username }); - // TODO: Strip salt, hash, _id + // 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: Object.assign({}, user, { - sessionToken: token, - }), + data: copy, }); } else { res.send({ @@ -127,22 +136,43 @@ userRouter.post("/level/:id", async (req, res) => { // Get the data needed for the dashboard userRouter.get("/dashboard", async (req, res) => { - console.log("STUB(post): /user/dashboard"); + console.log("SEMI-STUB(post): /user/dashboard"); - let users: any[] = []; - let nr = 10; - for (let i = 0; i < 10; i++) - users = users.concat({ - username: `Test User ${i}`, - score: 100 * i, - level: Math.floor(Math.random() * Math.floor(10)), - nr: nr--, - }); + //@ts-ignore + const { db, token } = req; + + // Get the user + const user = await userFromSession(token, db); + // TODO: if (user) + + 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 + level: 1, + nr: nr++, + }; + }); // TODO: Stub res.send({ error: "200", data: { + // TODO: Get this some way nextLevel: { name: "Test level", desc: "Just a test", @@ -150,11 +180,8 @@ userRouter.get("/dashboard", async (req, res) => { done: false, }, - topTen: users, - lastReview: { - correct: 0, - wrong: 0, - }, + topTen, + lastReview: user.lastReview, }, }); }); diff --git a/backend/src/models/user.ts b/backend/src/models/user.ts new file mode 100644 index 0000000..53f01d4 --- /dev/null +++ b/backend/src/models/user.ts @@ -0,0 +1,14 @@ +export interface IUser { + username: string; + uid: string; + showWelcome: boolean; + score: number; + classId: string; + + sessionToken: string; + + lastReview: { + correct: number; + wrong: number; + }; +}; diff --git a/backend/src/security/auth.ts b/backend/src/security/auth.ts index 5ff5594..afe2102 100644 --- a/backend/src/security/auth.ts +++ b/backend/src/security/auth.ts @@ -2,7 +2,7 @@ import { pbkdf2Sync, randomBytes } from "crypto"; import { Db } from "mongodb"; -import { IUser } from "shared/user"; +import { IUser } from "../models/user"; export async function isAuthenticated(token: string, db: Db): Promise { // See if we can find a session with that token @@ -34,6 +34,8 @@ export async function performLogin(username: string, password: string, db: Db): //@ts-ignore classId: user.classId, + lastReview: user.lastReview, + // TODO: Implement score: 4, sessionToken, diff --git a/backend/src/utils/user.ts b/backend/src/utils/user.ts new file mode 100644 index 0000000..557ef16 --- /dev/null +++ b/backend/src/utils/user.ts @@ -0,0 +1,18 @@ +import { Db } from "mongodb"; + +import { IUser } from "../models/user"; + +export async function userFromSession(token: string, db: Db): Promise { + // Get the username + const session = await db.collection("sessions").findOne({ token, }); + if (session) { + const user = await db.collection("users").findOne({ username: session.username }); + if (user) { + return user; + } else { + throw new Error("Failed to find user"); + } + } else { + throw new Error("Failed to find session"); + } +} diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 4131165..6587f73 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -9,10 +9,6 @@ "outDir": "./dist/", - "baseUrl": "./src/", - - "paths": { - "shared/*": ["../../shared/*"] - } + "baseUrl": "./src/" } } diff --git a/backend/webpack.config.js b/backend/webpack.config.js index 471ded4..6c95497 100644 --- a/backend/webpack.config.js +++ b/backend/webpack.config.js @@ -19,10 +19,7 @@ module.exports = env => { ] }, resolve: { - extensions: [".ts", ".js"], - alias: { - shared: path.join(__dirname, "../shared/") - } + extensions: [".ts", ".js"] }, output: { filename: "bundle.js", diff --git a/shared/user.ts b/shared/user.ts deleted file mode 100644 index cc15ea2..0000000 --- a/shared/user.ts +++ /dev/null @@ -1,51 +0,0 @@ -export interface IUser { - username: string; - uid: string; - showWelcome: boolean; - score: number; - - sessionToken: string; -}; - -export interface IUserLevel { - // The numerical representation - level: number; - // The string representation - name: string; - // The user has this level until: score => levelCap - levelCap: number; -}; - -function levelFactory(): (name: string, levelCap: number) => IUserLevel { - let level = 1; - return (name: string, levelCap: number) => { - return { - level: level++, - name, - levelCap, - }; - }; -} -const l = levelFactory(); - -export const UserLevels: IUserLevel[] = [ - l("Sklave", 35), - l("Farmer", 75), - l("Soldat", 120), - l("Gladiator", 170), - l("Zenturio", 220), - l("Prätor", 270), - l("Reiter", 320), - l("General", 370), - l("Konsul", 420), - l("Caesar", 470), -]; - -export function userScoreToLevel(userScore: number): IUserLevel { - // NOTE: The failure level should never be returned - return UserLevels.find((el) => userScore < el.levelCap) || { - level: 0, - name: "Failure", - levelCap: 10000000, - }; -}