Reorganised some routing logic. Added separate views for SPAs and reorganised static folders to be globally accessible, so that the separate views can access the right folder. Language can be permanently changed for account.

This commit is contained in:
Daniel Ledda
2020-05-24 11:33:25 +02:00
parent 83844588df
commit 3a7e7de3d4
17 changed files with 1447 additions and 3537 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
node_modules
dist
static/semantic
static/frontend
static/game

2
.idea/modules.xml generated
View File

@@ -3,7 +3,7 @@
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/kadi_backend.iml" filepath="$PROJECT_DIR$/.idea/kadi_backend.iml" />
<module fileurl="file://$PROJECT_DIR$/../kadi_frontend/.idea/kniffel.iml" filepath="$PROJECT_DIR$/../kadi_frontend/.idea/kniffel.iml" />
<module fileurl="file://$PROJECT_DIR$/../kadi_frontend/.idea/kadi_frontendä.iml" filepath="$PROJECT_DIR$/../kadi_frontend/.idea/kadi_frontendä.iml" />
<module fileurl="file://$PROJECT_DIR$/../kadi_game/.idea/kadi_game.iml" filepath="$PROJECT_DIR$/../kadi_game/.idea/kadi_game.iml" />
<module fileurl="file://$PROJECT_DIR$/../../../.idea/www.iml" filepath="$PROJECT_DIR$/../../../.idea/www.iml" />
</modules>

4815
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,9 @@
"express-session": "^1.17.1",
"mongoose": "^5.9.11",
"passport": "^0.4.1",
"passport-local": "^1.0.0"
"passport-local": "^1.0.0",
"diff": ">=3.5.0",
"lodash.template": ">=4.5.0"
},
"devDependencies": {
"@types/bcrypt": "^3.0.0",

View File

@@ -1,14 +1,17 @@
import passport from "passport";
import DbUser, {IDbUser, IDbUserDoc} from "../models/dbUser";
import {IDbUserDoc} from "../models/dbUser";
import {RequestHandler} from "express";
import SavedGame from "../models/savedGame";
export const whoAmI: RequestHandler = async (req, res) => {
if (req.isAuthenticated()) {
const user = req.user as IDbUserDoc;
res.json({loggedIn: true, username: user.username});
res.json({loggedIn: true, username: user.username, lang: user.lang});
}
else {
res.json({loggedIn: false});
}
};
export const changeLang: RequestHandler = async (req, res) => {
const user = (req.user as IDbUserDoc);
user.changeLang(req.body.lang);
};

View File

@@ -7,6 +7,7 @@ export const listGames: RequestHandler = async (req, res) => {
const user = (req.user as IDbUserDoc);
const dbUser = await DbUser.findById(user._id, {"savedGames.game": 1, "savedGames.createdAt": 1});
if (dbUser) {
console.log(dbUser.savedGames);
res.json({games: dbUser.savedGames});
}
else {
@@ -16,25 +17,5 @@ export const listGames: RequestHandler = async (req, res) => {
export const saveGame: RequestHandler = async (req, res) => {
const user = (req.user as IDbUserDoc);
const handleError = (err: string) => {
res.send({error: true, message: err});
};
DbUser.findById(user, (err, user) => {
if (err) {
handleError(err);
}
else if (user) {
const newGame = new SavedGame();
newGame.game = req.body;
user.savedGames.push(newGame);
user.save((err) => {
if (err) {
return handleError(err);
}
else {
res.send("Thanks for submitting your game, " + user.username + "!");
}
})
}
});
await user.addGame(req.body);
};

5
src/enums.ts Normal file
View File

@@ -0,0 +1,5 @@
export enum SupportedLang {
gb = "gb",
de = "de",
it = "it",
}

View File

@@ -5,7 +5,6 @@ import Settings from "./server-config.json";
import flash from "express-flash";
import passport from "passport";
import session from "express-session";
import * as path from "path";
import MainRouter from "./routers/mainRouter";
// MongoDB Setup
@@ -23,6 +22,7 @@ const app = express();
app.use(express.json());
app.set("port", process.env.PORT || 3000);
app.set("view-engine", "ejs");
app.set("views", "views");
app.use(express.urlencoded({ extended: false}));
app.use(flash());
app.use(session({
@@ -39,7 +39,11 @@ app.locals = {
initialisePassport();
app.use(passport.initialize());
app.use(passport.session());
app.use((req, res, next) => {
console.log(req.originalUrl);
next();
});
app.use(Settings.serverRoot + "/static", express.static("static"));
app.use(Settings.serverRoot, MainRouter);
const server = app.listen(app.get("port"), () => {

View File

@@ -1,8 +1,9 @@
import mongoose from "mongoose";
import Player, {IPlayer, IPlayerDoc, PlayerSchema} from "./player";
import {AccountStats, AccountStatsSchema, IAccountStats, IAccountStatsDoc} from "./stats";
import {ISavedGame, ISavedGameDoc, SavedGameSchema} from "./savedGame";
import SavedGame, {ISavedGame, ISavedGameDoc, SavedGameSchema} from "./savedGame";
import bcrypt from "bcrypt";
import {SupportedLang} from "../enums";
export class CredentialsTakenError extends Error {
public emailExists: boolean;
@@ -19,6 +20,7 @@ export interface IDbUser {
username: string;
email: string;
password: string;
lang?: SupportedLang;
friends?: IDbUser[];
player?: IPlayer;
guests?: IPlayer[];
@@ -30,11 +32,14 @@ export interface IDbUserDoc extends mongoose.Document {
username: string;
email: string;
password: string;
lang: SupportedLang;
friends: IDbUserDoc[];
player: IPlayerDoc;
guests: IPlayerDoc[];
accountStats: IAccountStatsDoc;
savedGames: ISavedGameDoc[];
changeLang(lang: SupportedLang): void;
addGame(game: any): Promise<string | null>;
}
export interface IDbUserModel extends mongoose.Model<IDbUserDoc> {
@@ -49,11 +54,12 @@ export const DbUserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
friends: {type: [mongoose.Schema.Types.ObjectId], required: true, default: []},
lang: { type: String, required: true },
friends: {type: [mongoose.Schema.Types.ObjectId], default: []},
player: {type: PlayerSchema, required: true, unique: true},
guests: {type: [PlayerSchema], required: true, default: []},
accountStats: {type: AccountStatsSchema, required: true, default: () => ({}) },
savedGames: {type: [SavedGameSchema], required: true, default: []},
guests: {type: [PlayerSchema], default: []},
accountStats: {type: AccountStatsSchema, default: () => ({}) },
savedGames: {type: [SavedGameSchema], default: []},
});
DbUserSchema.statics.findByEmail = async function (emailQuery: string) {
@@ -63,11 +69,12 @@ DbUserSchema.statics.findByEmail = async function (emailQuery: string) {
DbUserSchema.statics.addNewUser = async function (user: IDbUser) {
const player = new Player( { nick: user.username });
return this.create({
username: user.username,
email: user.email,
password: user.password,
player
});
username: user.username,
email: user.email,
password: user.password,
lang: SupportedLang.gb,
player
});
};
DbUserSchema.statics.registerUser = async function (username: string, email: string, password: string) {
@@ -90,5 +97,19 @@ DbUserSchema.statics.userWithUsernameExists = async function (username: string)
return this.exists({username});
};
DbUserSchema.methods.addGame = function (game: any): void {
const newGame = new SavedGame();
newGame.game = game;
DbUser.updateOne(this, {$push: {savedGames: newGame}}, (err) => {
console.log(err);
});
};
DbUserSchema.methods.changeLang = function (lang: SupportedLang): void {
if (lang in SupportedLang) {
DbUser.updateOne(this, {lang: lang});
}
};
const DbUser = mongoose.model<IDbUserDoc, IDbUserModel>("DbUser", DbUserSchema);
export default DbUser;

View File

@@ -45,7 +45,7 @@ export const initialisePassport = () => {
done(null, user._id)
});
passport.deserializeUser(async (id: string, done) => {
const user: IDbUserDoc | null = await DbUser.findById(id);
const user: IDbUserDoc | null = await DbUser.findById(id, {username: 1, password: 1, lang: 1, email: 1});
done(null, user);
});
};

View File

@@ -1,11 +1,12 @@
import express from "express";
import {requireAuthenticated, requireNotAuthenticated} from "../passport-config";
import {requireAuthenticated} from "../passport-config";
import * as stats from "../controllers/statsController";
import * as dbUser from "../controllers/dbUserController"
const router = express.Router();
router.get("/user", dbUser.whoAmI);
router.post("/changeLang", requireAuthenticated, dbUser.changeLang);
router.get("/games", requireAuthenticated, stats.listGames);
router.post("/savegame", requireAuthenticated, stats.saveGame);

View File

@@ -1,23 +1,25 @@
import express from "express";
import {requireAuthenticated, requireNotAuthenticated} from "../passport-config";
import {requireAuthenticated} from "../passport-config";
import routers from "./routers";
import {IDbUser} from "../models/dbUser";
import * as path from "path";
const router = express.Router();
router.use("/account", routers.signup);
router.use("/api", routers.api);
router.use("/game/static", express.static(path.join(__dirname, "../game/static")));
router.use("/static", express.static(path.join(__dirname, "../frontend/static")));
router.use("/static", express.static("static"));
// General Endpoints
router.get("/game", requireAuthenticated, (req, res) => {
res.sendFile(path.join(__dirname + "/../game/index.html"));
res.render("gameIndex.ejs", {
username: (req.user as IDbUser).username,
rootUrl: req.app.locals.rootUrl
});
});
router.get("", requireAuthenticated, (req, res) => {
res.sendFile(path.join(__dirname + "/../frontend/index.html"), {username: (req.user as IDbUser).username});
router.get("/**", requireAuthenticated, (req, res) => {
res.render("frontendIndex.ejs", {
username: (req.user as IDbUser).username,
rootUrl: req.app.locals.rootUrl
});
});
export default router;

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

22
views/frontendIndex.ejs Executable file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href=<%= rootUrl + "/static/favicon.ico" %> />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Score dice games with K A D I"
/>
<link rel="manifest" href=<%= rootUrl + "/static/frontend/manifest.json" %> />
<title>K A D I - Digital Dice</title>
</head>
<body>
<div id="root"></div>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<script src=<%= rootUrl + "/static/frontend/bundle.js" %>></script>
</body>
</html>

22
views/gameIndex.ejs Executable file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href=<%= rootUrl + "/static/favicon.ico" %> />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Score dice games with K A D I"
/>
<link rel="manifest" href=<%= rootUrl + "/static/game/manifest.json" %> />
<title>K A D I - Digital Dice</title>
</head>
<body>
<div id="root"></div>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<script src=<%= rootUrl + "/static/game/bundle.js" %>></script>
</body>
</html>

View File

@@ -1,6 +1,7 @@
<!doctype html>
<html>
<head>
<link rel="icon" href="<%= rootUrl %>/static/favicon.ico" />
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

View File

@@ -1,6 +1,7 @@
<!doctype html>
<html>
<head>
<link rel="icon" href="<%= rootUrl %>/static/favicon.ico" />
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">