From ba47d8b1d483ffd65879ece10859f4e06fc5a8db Mon Sep 17 00:00:00 2001 From: gparant Date: Sat, 4 Apr 2020 14:05:18 +0200 Subject: [PATCH 1/5] Setup web-socket connection - Add authentification socket.io with jwt token --- back/package.json | 2 + back/src/Controller/IoSocketController.ts | 21 ++++- back/src/Model/Websocket/ExSocketInterface.ts | 5 + back/yarn.lock | 94 ++++++++++++++++++- docker-compose.yaml | 1 + 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 back/src/Model/Websocket/ExSocketInterface.ts diff --git a/back/package.json b/back/package.json index b86e21c8..af3c8a7a 100644 --- a/back/package.json +++ b/back/package.json @@ -21,9 +21,11 @@ "homepage": "https://github.com/thecodingmachine/workadventure#readme", "dependencies": { "@types/express": "^4.17.4", + "@types/jsonwebtoken": "^8.3.8", "@types/socket.io": "^2.1.4", "body-parser": "^1.19.0", "express": "^4.17.1", + "jsonwebtoken": "^8.5.1", "socket.io": "^2.3.0", "ts-node-dev": "^1.0.0-pre.44", "typescript": "^3.8.3" diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 7317ceb7..abc5210f 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -2,18 +2,35 @@ import socketIO = require('socket.io'); import {Socket} from "socket.io"; import * as http from "http"; import {MessageUserPosition} from "@Model/Websocket/MessageUserPosition"; +import {ExSocketInterface} from "@Model/Websocket/ExSocketInterface"; +import Jwt, {JsonWebTokenError} from "jsonwebtoken"; + +const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY"; export class IoSocketController{ Io: socketIO.Server; constructor(server : http.Server) { this.Io = socketIO(server); + + //authentication with token. it will be decodes and stock in socket. + this.Io.use( (socket: Socket, next) => { + if (!socket.handshake.query || !socket.handshake.query.token) { + return next(new Error('Authentication error')); + } + Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: object) => { + if (err) { + return next(new Error('Authentication error')); + } + (socket as ExSocketInterface).token = tokenDecoded; + next(); + }); + }); + this.ioConnection(); } ioConnection() { this.Io.on('connection', (socket: Socket) => { - //TODO check token access - /*join-rom event permit to join one room. message : userId : user identification diff --git a/back/src/Model/Websocket/ExSocketInterface.ts b/back/src/Model/Websocket/ExSocketInterface.ts new file mode 100644 index 00000000..6adcb477 --- /dev/null +++ b/back/src/Model/Websocket/ExSocketInterface.ts @@ -0,0 +1,5 @@ +import {Socket} from "socket.io"; + +export interface ExSocketInterface extends Socket { + token: object; +} \ No newline at end of file diff --git a/back/yarn.lock b/back/yarn.lock index e2c5879c..c7946b00 100644 --- a/back/yarn.lock +++ b/back/yarn.lock @@ -71,6 +71,13 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/jsonwebtoken@^8.3.8": + version "8.3.8" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.3.8.tgz#b27c9156dde2049ae03e56528a53ef5a8294aa82" + integrity sha512-g2ke5+AR/RKYpQxd+HJ2yisLHGuOV0uourOcPtKlcT5Zqv4wFg9vKhFpXEztN4H/6Y6RSUKioz/2PTFPP30CTA== + dependencies: + "@types/node" "*" + "@types/mime@*": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" @@ -317,6 +324,11 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -546,6 +558,13 @@ dynamic-dedupe@^0.3.0: dependencies: xtend "^4.0.0" +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1126,6 +1145,39 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +jsonwebtoken@^8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^5.6.0" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -1145,6 +1197,41 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + lodash@^4.17.14, lodash@^4.17.15: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -1568,12 +1655,17 @@ safe-buffer@5.1.2: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@^5.0.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -"semver@2 || 3 || 4 || 5", semver@^5.5.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== diff --git a/docker-compose.yaml b/docker-compose.yaml index 86923563..a23a5204 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -29,6 +29,7 @@ services: command: yarn dev environment: STARTUP_COMMAND_1: yarn install + SECRET_KEY: yourSecretKey volumes: - ./back:/usr/src/app labels: From e8da727cae4037ec9b13326ae2f2bf754f52cfbc Mon Sep 17 00:00:00 2001 From: gparant Date: Sat, 4 Apr 2020 16:25:03 +0200 Subject: [PATCH 2/5] Refactor and fix error hydration message socket io - Position message send will be on format : message : userId : user identification roomId: room identification position: position of user in map x: user x position on map y: user y position on map - Create Point object and interface to have position x and y of user in map. --- back/src/Controller/IoSocketController.ts | 28 +++++++++++++------ back/src/Model/Websocket/ExSocketInterface.ts | 2 ++ .../Model/Websocket/MessageUserPosition.ts | 27 ++++++++++++++---- back/src/Model/Websocket/PointInterface.ts | 5 ++++ back/tsconfig.json | 4 +-- 5 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 back/src/Model/Websocket/PointInterface.ts diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index abc5210f..fba029b7 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -1,8 +1,8 @@ import socketIO = require('socket.io'); import {Socket} from "socket.io"; import * as http from "http"; -import {MessageUserPosition} from "@Model/Websocket/MessageUserPosition"; -import {ExSocketInterface} from "@Model/Websocket/ExSocketInterface"; +import {MessageUserPosition} from "../Model/Websocket/MessageUserPosition"; //TODO fix to use "_Model/.." +import {ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix to use "_Model/.." import Jwt, {JsonWebTokenError} from "jsonwebtoken"; const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY"; @@ -35,19 +35,29 @@ export class IoSocketController{ message : userId : user identification roomId: room identification - positionXUser: user x position map - positionYUser: user y position on map + position: position of user in map + x: user x position on map + y: user y position on map */ - socket.on('join-room', (message : MessageUserPosition) => { - socket.join(message.roomId); + socket.on('join-room', (message : string) => { + let messageUserPosition = new MessageUserPosition(message); + socket.join(messageUserPosition.roomId); // sending to all clients in room except sender - socket.to(message.roomId).emit('join-room', message.toString()); + this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); + socket.to(messageUserPosition.roomId).emit('join-room', messageUserPosition.toString()); }); - socket.on('user-position', (message : MessageUserPosition) => { + socket.on('user-position', (message : string) => { + let messageUserPosition = new MessageUserPosition(message); // sending to all clients in room except sender - socket.to(message.roomId).emit('join-room', message.toString()); + this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); + socket.to(messageUserPosition.roomId).emit('join-room', messageUserPosition.toString()); }); }); } + + //permit to save user position in socket + saveUserPosition(socket : ExSocketInterface, message : MessageUserPosition){ + socket.position = message.position; + } } \ No newline at end of file diff --git a/back/src/Model/Websocket/ExSocketInterface.ts b/back/src/Model/Websocket/ExSocketInterface.ts index 6adcb477..51df9258 100644 --- a/back/src/Model/Websocket/ExSocketInterface.ts +++ b/back/src/Model/Websocket/ExSocketInterface.ts @@ -1,5 +1,7 @@ import {Socket} from "socket.io"; +import {PointInterface} from "./PointInterface"; export interface ExSocketInterface extends Socket { token: object; + position: PointInterface; } \ No newline at end of file diff --git a/back/src/Model/Websocket/MessageUserPosition.ts b/back/src/Model/Websocket/MessageUserPosition.ts index b37b5089..663ce71d 100644 --- a/back/src/Model/Websocket/MessageUserPosition.ts +++ b/back/src/Model/Websocket/MessageUserPosition.ts @@ -1,14 +1,30 @@ import {Message} from "./Message"; +import {PointInterface} from "./PointInterface"; + +export class Point implements PointInterface{ + x: number; + y: number; + + constructor(x : number, y : number) { + this.x = x; + this.y = y; + } + + toJson(){ + return { + x : this.x, + y: this.y + } + } +} export class MessageUserPosition extends Message{ - positionXUser: string; - positionYUser: string; + position: PointInterface constructor(message: string) { super(message); let data = JSON.parse(message); - this.positionXUser = data.positionXUser; - this.positionYUser = data.positionYUser; + this.position = new Point(data.position.x, data.position.y); } toString() { @@ -16,8 +32,7 @@ export class MessageUserPosition extends Message{ Object.assign( super.toJson(), { - positionXUser: this.positionXUser, - positionYUser: this.positionYUser + position: this.position.toJson() }) ); } diff --git a/back/src/Model/Websocket/PointInterface.ts b/back/src/Model/Websocket/PointInterface.ts new file mode 100644 index 00000000..7f2ab39a --- /dev/null +++ b/back/src/Model/Websocket/PointInterface.ts @@ -0,0 +1,5 @@ +export interface PointInterface { + x: number; + y: number; + toJson() : object; +} \ No newline at end of file diff --git a/back/tsconfig.json b/back/tsconfig.json index d208ee64..2fefad63 100644 --- a/back/tsconfig.json +++ b/back/tsconfig.json @@ -43,8 +43,8 @@ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ "baseUrl": ".", /* Base directory to resolve non-absolute module names. */ "paths": { - "@Controller/*": ["src/Controller/*"], - "@Model/*": ["src/Model/*"] + "_Controller/*": ["src/Controller/*"], + "_Model/*": ["src/Model/*"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ From 53e1600e6798a2e44072810fd0d2705fa399032a Mon Sep 17 00:00:00 2001 From: gparant Date: Sat, 4 Apr 2020 17:22:02 +0200 Subject: [PATCH 3/5] 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" From f04d1342b5ed668f1cc1d80ab9130e1e4b9fcb6a Mon Sep 17 00:00:00 2001 From: gparant Date: Sat, 4 Apr 2020 17:56:43 +0200 Subject: [PATCH 4/5] Refactor error message --- back/src/Controller/IoSocketController.ts | 12 ++++++------ back/src/Model/Websocket/MessageUserPosition.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 109fda6a..5dbacdac 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -41,8 +41,8 @@ export class IoSocketController{ socket.on('join-room', (message : string) => { let messageUserPosition = this.hydrateMessageReceive(message); - if(!messageUserPosition){ - return socket.emit("message-error", JSON.stringify({message: "Error format message"})) + if(messageUserPosition instanceof Error){ + return socket.emit("message-error", JSON.stringify({message: messageUserPosition.message})) } //join user in room socket.join(messageUserPosition.roomId); @@ -53,8 +53,8 @@ export class IoSocketController{ socket.on('user-position', (message : string) => { let messageUserPosition = this.hydrateMessageReceive(message); - if(!messageUserPosition){ - return socket.emit("message-error", JSON.stringify({message: "Error format message"})); + if(messageUserPosition instanceof Error){ + return socket.emit("message-error", JSON.stringify({message: messageUserPosition.message})); } // sending to all clients in room except sender this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); @@ -69,12 +69,12 @@ export class IoSocketController{ } //Hydrate and manage error - hydrateMessageReceive(message : string) : MessageUserPosition | null{ + hydrateMessageReceive(message : string) : MessageUserPosition | Error{ try { return new MessageUserPosition(message); }catch (err) { //TODO log error - return null; + return new Error(err); } } } \ No newline at end of file diff --git a/back/src/Model/Websocket/MessageUserPosition.ts b/back/src/Model/Websocket/MessageUserPosition.ts index 60e76ab7..731d60ff 100644 --- a/back/src/Model/Websocket/MessageUserPosition.ts +++ b/back/src/Model/Websocket/MessageUserPosition.ts @@ -7,7 +7,7 @@ export class Point implements PointInterface{ constructor(x : number, y : number) { if(!x || !y){ - throw Error("x and y cannot be null"); + throw Error("position x and y cannot be null"); } this.x = x; this.y = y; From d064aca525b6092da34437b7b9214a210c391620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sat, 4 Apr 2020 22:35:20 +0200 Subject: [PATCH 5/5] Fixing typo in comment --- back/src/Controller/IoSocketController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 5dbacdac..3907436b 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -11,7 +11,7 @@ export class IoSocketController{ constructor(server : http.Server) { this.Io = socketIO(server); - //authentication with token. it will be decodes and stock in socket. + // Authentication with token. it will be decoded and stored in the socket. this.Io.use( (socket: Socket, next) => { if (!socket.handshake.query || !socket.handshake.query.token) { return next(new Error('Authentication error')); @@ -77,4 +77,4 @@ export class IoSocketController{ return new Error(err); } } -} \ No newline at end of file +}