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
|
||||
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/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": {
|
||||
"version": "3.4.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
|
||||
@ -66,6 +75,17 @@
|
||||
"integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==",
|
||||
"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": {
|
||||
"version": "10.9.4",
|
||||
"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": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
|
||||
@ -2815,6 +2840,12 @@
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
@ -2955,6 +2986,40 @@
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
@ -3532,6 +3597,22 @@
|
||||
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
|
||||
"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": {
|
||||
"version": "2.0.0",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "0.4.7",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
|
||||
@ -3647,8 +3737,7 @@
|
||||
"semver": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
|
||||
"integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.16.2",
|
||||
@ -3896,6 +3985,15 @@
|
||||
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
|
||||
"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": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
||||
|
@ -21,11 +21,13 @@
|
||||
"dependencies": {
|
||||
"body-parser": "1.18.3",
|
||||
"cors": "^2.8.4",
|
||||
"express": "4.16.3"
|
||||
"express": "4.16.3",
|
||||
"mongodb": "^3.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.4",
|
||||
"@types/express": "4.16.0",
|
||||
"@types/mongodb": "^3.1.9",
|
||||
"ts-loader": "^5.1.1",
|
||||
"typescript": "3.0.3",
|
||||
"webpack": "^4.19.1",
|
||||
|
@ -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: {},
|
||||
|
@ -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");
|
||||
});
|
||||
})();
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
};
|
||||
|
@ -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",
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
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"
|
||||
|
||||
services:
|
||||
# db:
|
||||
# image: mongo:4.1.3-xenial
|
||||
# expose:
|
||||
# - "27017"
|
||||
# networks:
|
||||
# backend:
|
||||
# ipv4_address: 128.1.0.2
|
||||
db:
|
||||
image: mongo:4.1.3-xenial
|
||||
expose:
|
||||
- "27017"
|
||||
networks:
|
||||
backend:
|
||||
ipv4_address: 128.1.0.2
|
||||
|
||||
backend:
|
||||
image: lateinicus/server
|
||||
expose:
|
||||
- "8080"
|
||||
# depends_on:
|
||||
# - db
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
backend:
|
||||
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?
|
||||
export default class Application extends React.Component<IProps> {
|
||||
componentDidMount() {
|
||||
// TODO: Ask the server if our session is still valid
|
||||
// TODO: When asking the server if our session is still valid, a spinner
|
||||
// should be shown
|
||||
if (getSessionToken(window) !== null) {
|
||||
// TODO: We still need to fetch the user data
|
||||
this.props.setAuthenticated(true);
|
||||
const token = getSessionToken(window);
|
||||
if (token !== null && !this.props.authenticated) {
|
||||
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[]> => {
|
||||
return new Promise((res, rej) => {
|
||||
fetch(`${BACKEND_URL}/api/levels`, {
|
||||
|
@ -68,7 +68,6 @@ const initialState: IState = {
|
||||
didLogin: false,
|
||||
|
||||
// Is the user authenticated?
|
||||
// TODO: Set this to false
|
||||
authenticated: false,
|
||||
|
||||
user: {
|
||||
|
Reference in New Issue
Block a user