From 53e1600e6798a2e44072810fd0d2705fa399032a Mon Sep 17 00:00:00 2001 From: gparant Date: Sat, 4 Apr 2020 17:22:02 +0200 Subject: [PATCH] Add authenticate - Create new controller authenticate with login root.. - Update and manage error message socket io. - Create enum for environment variables --- back/package.json | 2 ++ back/src/App.ts | 10 ++++++- back/src/Controller/AuthenticateController.ts | 28 ++++++++++++++++++ back/src/Controller/IoSocketController.ts | 29 +++++++++++++++---- back/src/Enum/EnvironmentVariable.ts | 5 ++++ back/src/Model/Websocket/Message.ts | 3 ++ .../Model/Websocket/MessageUserPosition.ts | 3 ++ back/yarn.lock | 12 ++++++++ 8 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 back/src/Controller/AuthenticateController.ts create mode 100644 back/src/Enum/EnvironmentVariable.ts diff --git a/back/package.json b/back/package.json index af3c8a7a..97d28968 100644 --- a/back/package.json +++ b/back/package.json @@ -21,10 +21,12 @@ "homepage": "https://github.com/thecodingmachine/workadventure#readme", "dependencies": { "@types/express": "^4.17.4", + "@types/http-status-codes": "^1.2.0", "@types/jsonwebtoken": "^8.3.8", "@types/socket.io": "^2.1.4", "body-parser": "^1.19.0", "express": "^4.17.1", + "http-status-codes": "^1.4.0", "jsonwebtoken": "^8.5.1", "socket.io": "^2.3.0", "ts-node-dev": "^1.0.0-pre.44", diff --git a/back/src/App.ts b/back/src/App.ts index f0d391b7..e46f4cb3 100644 --- a/back/src/App.ts +++ b/back/src/App.ts @@ -1,5 +1,6 @@ // lib/app.ts -import {IoSocketController} from "./Controller/IoSocketController"; +import {IoSocketController} from "./Controller/IoSocketController"; //TODO fix impot by "_Controller/..." +import {AuthenticateController} from "./Controller/AuthenticateController"; //TODO fix impot by "_Controller/..." import express from "express"; import {Application} from 'express'; import bodyParser = require('body-parser'); @@ -9,14 +10,21 @@ class App { public app: Application; public server: http.Server; public ioSocketController: IoSocketController; + public authenticateController: AuthenticateController; constructor() { this.app = express(); + + //config server http this.config(); this.server = http.createServer(this.app); + + //create controllers this.ioSocketController = new IoSocketController(this.server); + this.authenticateController = new AuthenticateController(this.app); } + // TODO add session user private config(): void { this.app.use(bodyParser.json()); this.app.use(bodyParser.urlencoded({extended: false})); diff --git a/back/src/Controller/AuthenticateController.ts b/back/src/Controller/AuthenticateController.ts new file mode 100644 index 00000000..01985b6a --- /dev/null +++ b/back/src/Controller/AuthenticateController.ts @@ -0,0 +1,28 @@ +import {Application, Request, Response} from "express"; +import Jwt, {JsonWebTokenError} from "jsonwebtoken"; +import {BAD_REQUEST, OK} from "http-status-codes"; +import {SECRET_KEY} from "../Enum/EnvironmentVariable"; + +export class AuthenticateController{ + App : Application; + + constructor(App : Application) { + this.App = App; + this.login(); + } + + //permit to login on application. Return token to connect on Websocket IO. + login(){ + this.App.post("/login", (req: Request, res: Response) => { + let param = req.body; + if(!param.email){ + return res.status(BAD_REQUEST).send({ + message: "email parameter is empty" + }); + } + //TODO check user email for The Coding Machine game + let token = Jwt.sign({email: param.email}, SECRET_KEY, {expiresIn: '24h'}); + return res.status(OK).send({token: token}); + }); + } +} \ No newline at end of file diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index fba029b7..109fda6a 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -1,11 +1,10 @@ import socketIO = require('socket.io'); import {Socket} from "socket.io"; import * as http from "http"; -import {MessageUserPosition} from "../Model/Websocket/MessageUserPosition"; //TODO fix to use "_Model/.." -import {ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix to use "_Model/.." +import {MessageUserPosition} from "../Model/Websocket/MessageUserPosition"; //TODO fix import by "_Model/.." +import {ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix import by "_Model/.." import Jwt, {JsonWebTokenError} from "jsonwebtoken"; - -const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY"; +import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..." export class IoSocketController{ Io: socketIO.Server; @@ -39,8 +38,13 @@ export class IoSocketController{ x: user x position on map y: user y position on map */ + socket.on('join-room', (message : string) => { - let messageUserPosition = new MessageUserPosition(message); + let messageUserPosition = this.hydrateMessageReceive(message); + if(!messageUserPosition){ + return socket.emit("message-error", JSON.stringify({message: "Error format message"})) + } + //join user in room socket.join(messageUserPosition.roomId); // sending to all clients in room except sender this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); @@ -48,7 +52,10 @@ export class IoSocketController{ }); socket.on('user-position', (message : string) => { - let messageUserPosition = new MessageUserPosition(message); + let messageUserPosition = this.hydrateMessageReceive(message); + if(!messageUserPosition){ + return socket.emit("message-error", JSON.stringify({message: "Error format message"})); + } // sending to all clients in room except sender this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); socket.to(messageUserPosition.roomId).emit('join-room', messageUserPosition.toString()); @@ -60,4 +67,14 @@ export class IoSocketController{ saveUserPosition(socket : ExSocketInterface, message : MessageUserPosition){ socket.position = message.position; } + + //Hydrate and manage error + hydrateMessageReceive(message : string) : MessageUserPosition | null{ + try { + return new MessageUserPosition(message); + }catch (err) { + //TODO log error + return null; + } + } } \ No newline at end of file diff --git a/back/src/Enum/EnvironmentVariable.ts b/back/src/Enum/EnvironmentVariable.ts new file mode 100644 index 00000000..27f56d78 --- /dev/null +++ b/back/src/Enum/EnvironmentVariable.ts @@ -0,0 +1,5 @@ +const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY"; + +export { + SECRET_KEY +} \ No newline at end of file diff --git a/back/src/Model/Websocket/Message.ts b/back/src/Model/Websocket/Message.ts index 4fc340a6..3a53163f 100644 --- a/back/src/Model/Websocket/Message.ts +++ b/back/src/Model/Websocket/Message.ts @@ -4,6 +4,9 @@ export class Message { constructor(message: string) { let data = JSON.parse(message); + if(!data.userId || !data.roomId){ + throw Error("userId and roomId cannot be null"); + } this.userId = data.userId; this.roomId = data.roomId; } diff --git a/back/src/Model/Websocket/MessageUserPosition.ts b/back/src/Model/Websocket/MessageUserPosition.ts index 663ce71d..60e76ab7 100644 --- a/back/src/Model/Websocket/MessageUserPosition.ts +++ b/back/src/Model/Websocket/MessageUserPosition.ts @@ -6,6 +6,9 @@ export class Point implements PointInterface{ y: number; constructor(x : number, y : number) { + if(!x || !y){ + throw Error("x and y cannot be null"); + } this.x = x; this.y = y; } diff --git a/back/yarn.lock b/back/yarn.lock index c7946b00..7ba7fbdc 100644 --- a/back/yarn.lock +++ b/back/yarn.lock @@ -66,6 +66,13 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/http-status-codes@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/http-status-codes/-/http-status-codes-1.2.0.tgz#6e5244835aaf7164dd306f1d4d2dfdbb2159d909" + integrity sha512-vjpjevMaxtrtdrrV/TQNIFT7mKL8nvIKG7G/LjMDZdVvqRxRg5SNfGkeuSaowVc0rbK8xDA2d/Etunyb5GyzzA== + dependencies: + http-status-codes "*" + "@types/json-schema@^7.0.3": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" @@ -986,6 +993,11 @@ http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http-status-codes@*, http-status-codes@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-1.4.0.tgz#6e4c15d16ff3a9e2df03b89f3a55e1aae05fb477" + integrity sha512-JrT3ua+WgH8zBD3HEJYbeEgnuQaAnUeRRko/YojPAJjGmIfGD3KPU/asLdsLwKjfxOmQe5nXMQ0pt/7MyapVbQ== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"