feat: Implement the /user/me endpoint
This commit is contained in:
parent
2e93fc954d
commit
65070b1f5b
@ -3,4 +3,7 @@ FROM drop:alpine
|
|||||||
RUN apk add --no-cache nodejs
|
RUN apk add --no-cache nodejs
|
||||||
ADD bundle.js /home/cuser/bundle.js
|
ADD bundle.js /home/cuser/bundle.js
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/drop", "/usr/bin/node", "/home/cuser/bundle.js"]
|
ADD wait-for /usr/local/bin/wait-for
|
||||||
|
RUN chmod +rx /usr/local/bin/wait-for
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/drop", "/usr/local/bin/wait-for", "128.1.0.2:27017", "--", "/usr/bin/node", "/home/cuser/bundle.js"]
|
||||||
|
23
backend/db.md
Normal file
23
backend/db.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# User
|
||||||
|
`column`: users
|
||||||
|
`
|
||||||
|
{
|
||||||
|
username: string,
|
||||||
|
salt: string,
|
||||||
|
hash: string,
|
||||||
|
uid: number,
|
||||||
|
showWelcome: boolean,
|
||||||
|
classId: string,
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
# Sessions
|
||||||
|
column: sessions
|
||||||
|
|
||||||
|
`
|
||||||
|
{
|
||||||
|
username: string,
|
||||||
|
session: string,
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
102
backend/package-lock.json
generated
102
backend/package-lock.json
generated
@ -14,6 +14,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/bson": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/bson/-/bson-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-j+UcCWI+FsbI5/FQP/Kj2CXyplWAz39ktHFkXk84h7dNblKRSoNJs95PZFRd96NQGqsPEPgeclqnznWZr14ZDA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/connect": {
|
"@types/connect": {
|
||||||
"version": "3.4.32",
|
"version": "3.4.32",
|
||||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
|
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
|
||||||
@ -66,6 +75,17 @@
|
|||||||
"integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==",
|
"integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/mongodb": {
|
||||||
|
"version": "3.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.1.9.tgz",
|
||||||
|
"integrity": "sha512-3vv3ad/AmiXz/MI/dKVzJNo1FFx/PYp6wlgzbKPPnOnTXnNWKxV9pI/sfReI/7ji0OtxSWByW0LWCNEClyy/vA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/bson": "*",
|
||||||
|
"@types/events": "*",
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "10.9.4",
|
"version": "10.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.4.tgz",
|
||||||
@ -678,6 +698,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bson": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA=="
|
||||||
|
},
|
||||||
"buffer": {
|
"buffer": {
|
||||||
"version": "4.9.1",
|
"version": "4.9.1",
|
||||||
"resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
|
"resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
|
||||||
@ -2815,6 +2840,12 @@
|
|||||||
"readable-stream": "^2.0.1"
|
"readable-stream": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"memory-pager": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Mf9OHV/Y7h6YWDxTzX/b4ZZ4oh9NSXblQL8dtPCOomOtZciEHxePR78+uHFLLlsk01A6jVHhHsQZZ/WcIPpnzg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"merge-descriptors": {
|
"merge-descriptors": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||||
@ -2955,6 +2986,40 @@
|
|||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mongodb": {
|
||||||
|
"version": "3.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.1.6.tgz",
|
||||||
|
"integrity": "sha512-E5QJuXQoMlT7KyCYqNNMfAkhfQD79AT4F8Xd+6x37OX+8BL17GyXyWvfm6wuyx4wnzCCPoCSLeMeUN2S7dU9yw==",
|
||||||
|
"requires": {
|
||||||
|
"mongodb-core": "3.1.5",
|
||||||
|
"safe-buffer": "^5.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mongodb-core": {
|
||||||
|
"version": "3.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.5.tgz",
|
||||||
|
"integrity": "sha512-emT/tM4ZBinqd6RZok+EzDdtN4LjYJIckv71qQVOEFmvXgT5cperZegVmTgox/1cx4XQu6LJ5ZuIwipP/eKdQg==",
|
||||||
|
"requires": {
|
||||||
|
"bson": "^1.1.0",
|
||||||
|
"require_optional": "^1.0.1",
|
||||||
|
"safe-buffer": "^5.1.2",
|
||||||
|
"saslprep": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
@ -3532,6 +3597,22 @@
|
|||||||
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
|
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"require_optional": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
|
||||||
|
"requires": {
|
||||||
|
"resolve-from": "^2.0.0",
|
||||||
|
"semver": "^5.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"resolve-from": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"resolve-cwd": {
|
"resolve-cwd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
|
||||||
@ -3634,6 +3715,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"saslprep": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"sparse-bitfield": "^3.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"schema-utils": {
|
"schema-utils": {
|
||||||
"version": "0.4.7",
|
"version": "0.4.7",
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
|
||||||
@ -3647,8 +3737,7 @@
|
|||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.5.1",
|
"version": "5.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
|
||||||
"integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
|
"integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"send": {
|
"send": {
|
||||||
"version": "0.16.2",
|
"version": "0.16.2",
|
||||||
@ -3896,6 +3985,15 @@
|
|||||||
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
|
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"sparse-bitfield": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
||||||
|
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"memory-pager": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"split-string": {
|
"split-string": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
||||||
|
@ -21,11 +21,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "1.18.3",
|
"body-parser": "1.18.3",
|
||||||
"cors": "^2.8.4",
|
"cors": "^2.8.4",
|
||||||
"express": "4.16.3"
|
"express": "4.16.3",
|
||||||
|
"mongodb": "^3.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/cors": "^2.8.4",
|
"@types/cors": "^2.8.4",
|
||||||
"@types/express": "4.16.0",
|
"@types/express": "4.16.0",
|
||||||
|
"@types/mongodb": "^3.1.9",
|
||||||
"ts-loader": "^5.1.1",
|
"ts-loader": "^5.1.1",
|
||||||
"typescript": "3.0.3",
|
"typescript": "3.0.3",
|
||||||
"webpack": "^4.19.1",
|
"webpack": "^4.19.1",
|
||||||
|
@ -4,27 +4,39 @@ import * as bodyparser from "body-parser";
|
|||||||
import { authRoute } from "../security/token";
|
import { authRoute } from "../security/token";
|
||||||
|
|
||||||
const userRouter = express.Router();
|
const userRouter = express.Router();
|
||||||
userRouter.use(bodyparser.json());
|
|
||||||
userRouter.use(authRoute);
|
userRouter.use(authRoute);
|
||||||
|
userRouter.use(bodyparser.json());
|
||||||
|
|
||||||
// Return the user object if the user is still authenticated
|
// Return the user object if the user is still authenticated
|
||||||
userRouter.get("/get", async (req, res) => {
|
userRouter.get("/me", async (req, res) => {
|
||||||
console.log("STUB: /user/get");
|
//@ts-ignore
|
||||||
|
const { db, token } = req;
|
||||||
|
|
||||||
// TODO: Stub
|
const session = await db.collection("sessions").findOne({ token, });
|
||||||
res.send({
|
if (session !== null) {
|
||||||
error: "0",
|
const user = await db.collection("users").findOne({ username: session.username });
|
||||||
data: {
|
|
||||||
test: 0,
|
// 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
|
// Removes the user's session
|
||||||
userRouter.get("/logout", async (req, res) => {
|
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({
|
res.send({
|
||||||
error: "0",
|
error: "0",
|
||||||
data: {},
|
data: {},
|
||||||
|
@ -12,88 +12,94 @@ import LevelRouter from "./api/level";
|
|||||||
const baseRouter = express.Router();
|
const baseRouter = express.Router();
|
||||||
const authRouter = express.Router();
|
const authRouter = express.Router();
|
||||||
|
|
||||||
authRouter.use(bodyparser.json());
|
import { MongoClient } from "mongodb";
|
||||||
authRouter.use(async (req, res, next) => {
|
const assert = require('assert');
|
||||||
const token = req.get("Token");
|
|
||||||
if (token) {
|
(async function() {
|
||||||
// Check if were authenticated
|
// Connection URL
|
||||||
const auth = await isAuthenticated(token);
|
const url = 'mongodb://128.1.0.2:27017/myproject';
|
||||||
if (auth)
|
// Database Name
|
||||||
next();
|
const dbName = 'myproject';
|
||||||
else
|
let client: MongoClient;
|
||||||
res.send({
|
|
||||||
error: "401",
|
try {
|
||||||
data: {},
|
// Use connect method to connect to the Server
|
||||||
});
|
client = await MongoClient.connect(url);
|
||||||
} else {
|
console.log("Connected to MongoDB");
|
||||||
res.send({
|
} catch (err) {
|
||||||
error: "401",
|
console.log(err.stack);
|
||||||
data: {},
|
assert(1, 2);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
const app = express();
|
const db = client.db(dbName);
|
||||||
app.use(bodyparser.json());
|
console.log("Connected to the database");
|
||||||
// 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());
|
|
||||||
|
|
||||||
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({
|
const app = express();
|
||||||
error: "0",
|
app.use(bodyparser.json());
|
||||||
data: {
|
app.options("*", cors());
|
||||||
levels,
|
|
||||||
},
|
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.use("/api/level", LevelRouter);
|
||||||
app.get("/api/health", (req, res) => {
|
app.use("/api/class", ClassRouter);
|
||||||
res.send({
|
app.use("/api/user", UserRouter);
|
||||||
error: "0",
|
app.get("/api/levels", async (req, res) => {
|
||||||
data: {
|
const levels = [{
|
||||||
msg: "lol",
|
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,
|
||||||
app.post("/api/login", async (req, res) => {
|
}, {
|
||||||
const { body } = req;
|
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({
|
res.send({
|
||||||
error: "400",
|
error: "0",
|
||||||
data: {
|
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
|
// Try to log the user in
|
||||||
const userData = await performLogin(body.username, body.password)
|
try {
|
||||||
.catch((err) => {
|
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);
|
console.log("Could not resolve login promise!", err);
|
||||||
|
|
||||||
// If anything was wrong, just tell the client
|
// 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",
|
msg: "Username or password is wrong",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
res.send({
|
|
||||||
error: "0",
|
|
||||||
data: userData,
|
|
||||||
});
|
});
|
||||||
});
|
const server = app.listen(8080, () => {
|
||||||
app.listen(8080, () => {
|
console.log("Starting on port 8080");
|
||||||
console.log("Starting on port 8080");
|
});
|
||||||
});
|
})();
|
||||||
|
|
||||||
|
@ -1,30 +1,45 @@
|
|||||||
import { pbkdf2Sync } from "crypto";
|
import { pbkdf2Sync, randomBytes } from "crypto";
|
||||||
|
|
||||||
|
import { Db } from "mongodb";
|
||||||
|
|
||||||
import { IUser } from "shared/user";
|
import { IUser } from "shared/user";
|
||||||
|
|
||||||
export function isAuthenticated(token: string): Promise<boolean> {
|
export async function isAuthenticated(token: string, db: Db): Promise<boolean> {
|
||||||
return new Promise((res, rej) => {
|
// See if we can find a session with that token
|
||||||
// TODO
|
const session = await db.collection("sessions").findOne({ token, });
|
||||||
res(true);
|
return session !== null;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function performLogin(username: string, password: string): Promise<IUser | {}> {
|
export async function performLogin(username: string, password: string, db: Db): Promise<IUser> {
|
||||||
return new Promise((res, rej) => {
|
const user = await db.collection("users").findOne({
|
||||||
// Hash the password
|
username,
|
||||||
// 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",
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -6,18 +6,26 @@ export async function authRoute(req: Request, res: Response, next: () => void) {
|
|||||||
const token = req.get("Token");
|
const token = req.get("Token");
|
||||||
if (token) {
|
if (token) {
|
||||||
// Check if were authenticated
|
// Check if were authenticated
|
||||||
const auth = await isAuthenticated(token);
|
//@ts-ignore
|
||||||
if (auth)
|
const auth = await isAuthenticated(token, req.db);
|
||||||
|
if (auth) {
|
||||||
|
//@ts-ignore
|
||||||
|
req.token = token;
|
||||||
next();
|
next();
|
||||||
else
|
} else {
|
||||||
res.send({
|
res.send({
|
||||||
error: "401",
|
error: "403",
|
||||||
data: {},
|
data: {
|
||||||
|
msg: "Session Token not found!",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
res.send({
|
res.send({
|
||||||
error: "401",
|
error: "403",
|
||||||
data: {},
|
data: {
|
||||||
|
msg: "No Session Token specified",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
79
backend/wait-for
Normal file
79
backend/wait-for
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
TIMEOUT=15
|
||||||
|
QUIET=0
|
||||||
|
|
||||||
|
echoerr() {
|
||||||
|
if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
exitcode="$1"
|
||||||
|
cat << USAGE >&2
|
||||||
|
Usage:
|
||||||
|
$cmdname host:port [-t timeout] [-- command args]
|
||||||
|
-q | --quiet Do not output any status messages
|
||||||
|
-t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout
|
||||||
|
-- COMMAND ARGS Execute command with args after the test finishes
|
||||||
|
USAGE
|
||||||
|
exit "$exitcode"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for() {
|
||||||
|
for i in `seq $TIMEOUT` ; do
|
||||||
|
nc -z "$HOST" "$PORT" > /dev/null 2>&1
|
||||||
|
|
||||||
|
result=$?
|
||||||
|
if [ $result -eq 0 ] ; then
|
||||||
|
if [ $# -gt 0 ] ; then
|
||||||
|
exec "$@"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "Operation timed out" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
*:* )
|
||||||
|
HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
|
||||||
|
PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
-q | --quiet)
|
||||||
|
QUIET=1
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
-t)
|
||||||
|
TIMEOUT="$2"
|
||||||
|
if [ "$TIMEOUT" = "" ]; then break; fi
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--timeout=*)
|
||||||
|
TIMEOUT="${1#*=}"
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--help)
|
||||||
|
usage 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echoerr "Unknown argument: $1"
|
||||||
|
usage 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$HOST" = "" -o "$PORT" = "" ]; then
|
||||||
|
echoerr "Error: you need to provide a host and port to test."
|
||||||
|
usage 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
wait_for "$@"
|
18
compose.yml
18
compose.yml
@ -1,20 +1,20 @@
|
|||||||
version: "3.6"
|
version: "3.6"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# db:
|
db:
|
||||||
# image: mongo:4.1.3-xenial
|
image: mongo:4.1.3-xenial
|
||||||
# expose:
|
expose:
|
||||||
# - "27017"
|
- "27017"
|
||||||
# networks:
|
networks:
|
||||||
# backend:
|
backend:
|
||||||
# ipv4_address: 128.1.0.2
|
ipv4_address: 128.1.0.2
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: lateinicus/server
|
image: lateinicus/server
|
||||||
expose:
|
expose:
|
||||||
- "8080"
|
- "8080"
|
||||||
# depends_on:
|
depends_on:
|
||||||
# - db
|
- db
|
||||||
networks:
|
networks:
|
||||||
backend:
|
backend:
|
||||||
ipv4_address: 128.1.0.3
|
ipv4_address: 128.1.0.3
|
||||||
|
1
frontend/index.html
Normal file
1
frontend/index.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<!DOCTYPE html><html> <head> <title>Lateinicus</title> <meta charset="UTF-8"> <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"> <link rel="stylesheet" href="/app/src.33f51c10.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500"> <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin=""></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin=""></script> </head> <body> <div id="app"></div> <script src="/app/src.02f6e325.js"></script> </body> </html>
|
6
frontend/shit.sh
Normal file
6
frontend/shit.sh
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
rm -rf dist/
|
||||||
|
|
||||||
|
./node_modules/.bin/parcel build --out-dir dist/app src/index.html
|
||||||
|
chmod 705 dist dist/app
|
||||||
|
chmod 604 dist/app/*
|
@ -36,15 +36,37 @@ interface IProps {
|
|||||||
// TODO: Replace the sessionStorage with localStorage?
|
// TODO: Replace the sessionStorage with localStorage?
|
||||||
export default class Application extends React.Component<IProps> {
|
export default class Application extends React.Component<IProps> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// TODO: Ask the server if our session is still valid
|
|
||||||
// TODO: When asking the server if our session is still valid, a spinner
|
// TODO: When asking the server if our session is still valid, a spinner
|
||||||
// should be shown
|
// should be shown
|
||||||
if (getSessionToken(window) !== null) {
|
const token = getSessionToken(window);
|
||||||
// TODO: We still need to fetch the user data
|
if (token !== null && !this.props.authenticated) {
|
||||||
this.props.setAuthenticated(true);
|
this.checkAuthStatus(token).then(user => {
|
||||||
|
this.props.setUser(user);
|
||||||
|
this.props.setAuthenticated(true);
|
||||||
|
}).catch(err => {
|
||||||
|
this.props.setAuthenticated(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAuthStatus = (token: string): Promise<IUser> => {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
fetch(`${BACKEND_URL}/api/user/me`, {
|
||||||
|
headers: new Headers({
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Token": token,
|
||||||
|
}),
|
||||||
|
}).then(resp => resp.json(), err => rej(err))
|
||||||
|
.then(data => {
|
||||||
|
if (data.error === "0") {
|
||||||
|
res(data.data);
|
||||||
|
} else {
|
||||||
|
rej(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getLevels = (): Promise<ILevel[]> => {
|
getLevels = (): Promise<ILevel[]> => {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
fetch(`${BACKEND_URL}/api/levels`, {
|
fetch(`${BACKEND_URL}/api/levels`, {
|
||||||
|
@ -68,7 +68,6 @@ const initialState: IState = {
|
|||||||
didLogin: false,
|
didLogin: false,
|
||||||
|
|
||||||
// Is the user authenticated?
|
// Is the user authenticated?
|
||||||
// TODO: Set this to false
|
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
|
|
||||||
user: {
|
user: {
|
||||||
|
Reference in New Issue
Block a user