feat: Implement the /user/me endpoint

This commit is contained in:
Alexander Polynomdivision
2018-09-29 14:23:09 +02:00
parent 2e93fc954d
commit 65070b1f5b
14 changed files with 410 additions and 139 deletions

View File

@@ -4,27 +4,39 @@ import * as bodyparser from "body-parser";
import { authRoute } from "../security/token";
const userRouter = express.Router();
userRouter.use(bodyparser.json());
userRouter.use(authRoute);
userRouter.use(bodyparser.json());
// Return the user object if the user is still authenticated
userRouter.get("/get", async (req, res) => {
console.log("STUB: /user/get");
userRouter.get("/me", async (req, res) => {
//@ts-ignore
const { db, token } = req;
// TODO: Stub
res.send({
error: "0",
data: {
test: 0,
},
});
const session = await db.collection("sessions").findOne({ token, });
if (session !== null) {
const user = await db.collection("users").findOne({ username: session.username });
// TODO: Strip salt, hash, _id
res.send({
error: "0",
data: Object.assign({}, user, {
sessionToken: token,
}),
});
} else {
res.send({
error: "404",
data: {},
});
}
});
// Removes the user's session
userRouter.get("/logout", async (req, res) => {
console.log("STUB: /user/logout");
// Try to remove the session
//@ts-ignore
await req.db.collections("sessions").findOneAndDelete({ session: req.get("Token") });
// TODO: Stub
res.send({
error: "0",
data: {},

View File

@@ -12,88 +12,94 @@ import LevelRouter from "./api/level";
const baseRouter = express.Router();
const authRouter = express.Router();
authRouter.use(bodyparser.json());
authRouter.use(async (req, res, next) => {
const token = req.get("Token");
if (token) {
// Check if were authenticated
const auth = await isAuthenticated(token);
if (auth)
next();
else
res.send({
error: "401",
data: {},
});
} else {
res.send({
error: "401",
data: {},
});
import { MongoClient } from "mongodb";
const assert = require('assert');
(async function() {
// Connection URL
const url = 'mongodb://128.1.0.2:27017/myproject';
// Database Name
const dbName = 'myproject';
let client: MongoClient;
try {
// Use connect method to connect to the Server
client = await MongoClient.connect(url);
console.log("Connected to MongoDB");
} catch (err) {
console.log(err.stack);
assert(1, 2);
}
});
const app = express();
app.use(bodyparser.json());
// app.use((req, res, next) => {
// // TODO: Change this to our domain
// res.append("Access-Control-Allow-Origin", "*");
// res.append("Access-Control-Allow-Headers", "Content-Type,Token");
// next();
// });
app.options("*", cors());
const db = client.db(dbName);
console.log("Connected to the database");
app.use("/api/level", LevelRouter);
app.use("/api/class", ClassRouter);
app.use("/api/user", UserRouter);
app.get("/api/levels", async (req, res) => {
const levels = [{
name: "Der Bauer auf dem Feld",
desc: "So fängt alles an: Du bist ein einfacher Bauer und musst dich die Karriereleiter mit deinen freshen Latein-Skills hinaufarbeiten",
level: 1,
done: true,
}, {
name: "???",
desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd",
level: 2,
done: false,
}];
res.send({
error: "0",
data: {
levels,
},
const app = express();
app.use(bodyparser.json());
app.options("*", cors());
app.use((req, res, next) => {
// Every route should have access to the database so that
// we can easily make calls to it
// @ts-ignore
req.db = db;
next();
});
});
app.get("/api/health", (req, res) => {
res.send({
error: "0",
data: {
msg: "lol",
},
});
});
app.post("/api/login", async (req, res) => {
const { body } = req;
app.use("/api/level", LevelRouter);
app.use("/api/class", ClassRouter);
app.use("/api/user", UserRouter);
app.get("/api/levels", async (req, res) => {
const levels = [{
name: "Der Bauer auf dem Feld",
desc: "So fängt alles an: Du bist ein einfacher Bauer und musst dich die Karriereleiter mit deinen freshen Latein-Skills hinaufarbeiten",
level: 1,
done: true,
}, {
name: "???",
desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd",
level: 2,
done: false,
}];
console.log("Stub: /login");
// Check if all arguments were sent
if (!body || !("username" in body) || !("password" in body)) {
res.send({
error: "400",
error: "0",
data: {
msg: "Username or password not specified",
levels,
},
});
});
app.get("/api/health", (req, res) => {
res.send({
error: "0",
data: {
msg: "lol",
},
});
});
app.post("/api/login", async (req, res) => {
// Check if all arguments were sent
const { body } = req;
if (!body || !("username" in body) || !("password" in body)) {
res.send({
error: "400",
data: {
msg: "Username or password not specified",
},
});
return;
}
return;
}
// Try to log the user in
const userData = await performLogin(body.username, body.password)
.catch((err) => {
// Try to log the user in
try {
const userData = await performLogin(body.username, body.password, db);
res.send({
error: "0",
data: userData,
});
} catch (err) {
console.log("Could not resolve login promise!", err);
// If anything was wrong, just tell the client
@@ -103,13 +109,10 @@ app.post("/api/login", async (req, res) => {
msg: "Username or password is wrong",
},
});
});
res.send({
error: "0",
data: userData,
}
});
});
app.listen(8080, () => {
console.log("Starting on port 8080");
});
const server = app.listen(8080, () => {
console.log("Starting on port 8080");
});
})();

View File

@@ -1,30 +1,45 @@
import { pbkdf2Sync } from "crypto";
import { pbkdf2Sync, randomBytes } from "crypto";
import { Db } from "mongodb";
import { IUser } from "shared/user";
export function isAuthenticated(token: string): Promise<boolean> {
return new Promise((res, rej) => {
// TODO
res(true);
});
export async function isAuthenticated(token: string, db: Db): Promise<boolean> {
// See if we can find a session with that token
const session = await db.collection("sessions").findOne({ token, });
return session !== null;
}
export function performLogin(username: string, password: string): Promise<IUser | {}> {
return new Promise((res, rej) => {
// Hash the password
// TODO: Fetch the salt
const salt = "";
const hash = pbkdf2Sync(password, salt, 50000, 512, "sha512").toString("hex");
// TODO: Look up the user, compare hashes and send the returned user
res({
username: "Polynom",
uid: "1",
showWelcome: true,
classId: "test",
score: 4,
sessionToken: "abc123",
});
export async function performLogin(username: string, password: string, db: Db): Promise<IUser> {
const user = await db.collection("users").findOne({
username,
});
// Hash the password
const hash = pbkdf2Sync(password, user.salt, 50000, 512, "sha512").toString("hex");
if (hash === user.hash) {
// Create a session
const sessionToken = randomBytes(20).toString("hex");
// Store the token
await db.collection("sessions").insertOne({
username: user.username,
token: sessionToken,
});
return {
username: user.username,
uid: user.uid,
showWelcome: user.showWelcome,
//@ts-ignore
classId: user.classId,
// TODO: Implement
score: 4,
sessionToken,
};
} else {
// It does not matter what we throw
throw new Error("LOL");
}
};

View File

@@ -6,18 +6,26 @@ export async function authRoute(req: Request, res: Response, next: () => void) {
const token = req.get("Token");
if (token) {
// Check if were authenticated
const auth = await isAuthenticated(token);
if (auth)
//@ts-ignore
const auth = await isAuthenticated(token, req.db);
if (auth) {
//@ts-ignore
req.token = token;
next();
else
} else {
res.send({
error: "401",
data: {},
error: "403",
data: {
msg: "Session Token not found!",
},
});
}
} else {
res.send({
error: "401",
data: {},
error: "403",
data: {
msg: "No Session Token specified",
},
});
}
};