This repository has been archived on 2022-03-12. You can view files and clone it, but cannot push or open issues or pull requests.
Lateinicus/backend/src/main.ts

244 lines
6.5 KiB
TypeScript
Raw Normal View History

2018-10-07 13:41:08 +00:00
import { env, exit } from "process";
import { randomBytes, pbkdf2Sync } from "crypto";
import * as assert from "assert";
2018-09-20 15:38:12 +00:00
import * as express from "express";
2018-09-28 21:33:28 +00:00
import * as cors from "cors";
2018-09-20 15:38:12 +00:00
import * as bodyparser from "body-parser";
import { isAuthenticated, performLogin } from "./security/auth";
import { LRequest } from "./types/express";
2018-09-23 20:17:35 +00:00
import UserRouter from "./api/user";
import LevelRouter from "./api/level";
2018-10-09 14:01:17 +00:00
import { ITrackerDBModel } from "./models/tracker";
2018-09-20 15:38:12 +00:00
const baseRouter = express.Router();
const authRouter = express.Router();
2018-09-29 12:23:09 +00:00
import { MongoClient } from "mongodb";
const user = encodeURIComponent("backend");
const password = encodeURIComponent(env["LATEINICUS_USER_PW"]);
2018-09-29 12:23:09 +00:00
(async function() {
// Database Name
const dbName = 'lateinicus';
// Connection URL
const url = `mongodb://${user}:${password}@128.1.0.2:27017/?authMechanism=SCRAM-SHA-1&authSource=${dbName}`;
2018-09-29 12:23:09 +00:00
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(false);
2018-09-20 15:38:12 +00:00
}
2018-09-29 12:23:09 +00:00
const db = client.db(dbName);
console.log("Connected to the database");
2018-09-20 15:38:12 +00:00
2018-09-29 12:23:09 +00:00
const app = express();
app.use(bodyparser.json());
app.options("*", cors());
app.use((req: LRequest, res, next) => {
2018-09-29 12:23:09 +00:00
// Every route should have access to the database so that
// we can easily make calls to it
req.db = db;
next();
});
app.use("/api/level", LevelRouter);
app.use("/api/user", UserRouter);
2018-10-09 14:01:17 +00:00
app.post("/api/tracker", async (req, res) => {
// Did we get any data
if (!req.body) {
res.send({
error: "403",
data: {
msg: "No request body provided",
},
});
return;
}
// Did we get all arguments?
if (!("session" in req.body) || !("event" in req.body)) {
res.send({
error: "403",
data: {
msg: "Invalid request",
},
});
return;
}
// Insert it into the database
const tracker: ITrackerDBModel = Object.assign({}, req.body, {
timestamp: Date.now(),
});
await db.collection("tracker").insertOne(tracker);
res.send({
error: "200",
data: {},
});
});
2018-09-29 12:23:09 +00:00
app.get("/api/levels", async (req, res) => {
2018-09-29 17:34:22 +00:00
// TODO: if (levels)
const levels = (await db.collection("levels").find({}, {
// The order in which we send the levels is important, so better
// sort them
sort: {
level: 1,
},
})
2018-09-29 17:34:22 +00:00
.toArray())
.map((el) => {
let tmp = Object.assign({}, el);
delete tmp.vocab;
2018-09-29 17:34:22 +00:00
delete tmp._id;
return tmp;
});
2018-09-29 12:23:09 +00:00
res.send({
error: "200",
2018-09-29 12:23:09 +00:00
data: {
levels,
},
});
});
2018-10-07 13:41:08 +00:00
app.post("/api/register", async (req, res) => {
// Check if any data was sent
if (!req.body) {
res.send({
error: "403",
data: {
msg: `No data sent`,
},
});
return;
}
// Check if we have all we need
const params = ["username", "password", "classId"];
for (let param of params) {
if (!(param in req.body)) {
res.send({
error: "403",
data: {
msg: `${param} not specified!`,
},
});
return;
}
}
const { username, password, classId } = req.body;
2018-10-08 09:22:13 +00:00
// Check if the registration is open for the class Id
// NOTE: This to prevent people from spamming the database
2018-10-08 09:22:13 +00:00
const classes = env["LATEINICUS_CLASSES"].split(",");
if (classes.indexOf(classId) === -1) {
2018-10-08 09:22:13 +00:00
res.send({
error: "403",
data: {
msg: "Class does not exist",
},
});
return;
}
2018-10-07 13:41:08 +00:00
// Check if the user already exists
const checkUser = await db.collection("users").findOne({
username,
});
if (checkUser) {
res.send({
error: "403",
data: {
msg: "User already exists",
},
});
return;
}
const salt = randomBytes(30).toString("hex");
const hash = pbkdf2Sync(password, salt, 50000, 512, "sha512").toString("hex");
const user = {
username,
salt,
hash,
classId,
score: 0,
showWelcome: true,
lastReview: {
correct: 0,
wrong: 0,
},
lastLevel: 0,
levels: [] as number[],
vocabMetadata: {},
};
await db.collection("users").insertOne(user);
res.send({
error: "200",
data: {},
});
});
2018-09-29 12:23:09 +00:00
app.get("/api/health", (req, res) => {
2018-09-20 15:38:12 +00:00
res.send({
error: "200",
2018-09-20 15:38:12 +00:00
data: {
2018-09-29 12:23:09 +00:00
msg: "lol",
2018-09-20 15:38:12 +00:00
},
});
2018-09-29 12:23:09 +00:00
});
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",
},
});
2018-09-20 15:38:12 +00:00
2018-09-29 12:23:09 +00:00
return;
}
2018-09-20 15:38:12 +00:00
2018-09-29 12:23:09 +00:00
// Try to log the user in
try {
const userData = await performLogin(body.username, body.password, db);
res.send({
error: "200",
2018-09-29 12:23:09 +00:00
data: userData,
});
} catch (err) {
console.log("Could not resolve login promise!", err);
2018-09-20 15:38:12 +00:00
// If anything was wrong, just tell the client
res.send({
error: "1",
data: {
msg: "Username or password is wrong",
},
});
2018-09-29 12:23:09 +00:00
}
});
const server = app.listen(8080, () => {
console.log("Starting on port 8080");
2018-09-20 15:38:12 +00:00
});
2018-09-29 12:23:09 +00:00
})();