Add authenticate

- Create new controller authenticate with login root..
 - Update and manage error message socket io.
 - Create enum for environment variables
This commit is contained in:
gparant 2020-04-04 17:22:02 +02:00
parent e8da727cae
commit 53e1600e67
8 changed files with 85 additions and 7 deletions

View File

@ -21,10 +21,12 @@
"homepage": "https://github.com/thecodingmachine/workadventure#readme", "homepage": "https://github.com/thecodingmachine/workadventure#readme",
"dependencies": { "dependencies": {
"@types/express": "^4.17.4", "@types/express": "^4.17.4",
"@types/http-status-codes": "^1.2.0",
"@types/jsonwebtoken": "^8.3.8", "@types/jsonwebtoken": "^8.3.8",
"@types/socket.io": "^2.1.4", "@types/socket.io": "^2.1.4",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"express": "^4.17.1", "express": "^4.17.1",
"http-status-codes": "^1.4.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"socket.io": "^2.3.0", "socket.io": "^2.3.0",
"ts-node-dev": "^1.0.0-pre.44", "ts-node-dev": "^1.0.0-pre.44",

View File

@ -1,5 +1,6 @@
// lib/app.ts // 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 express from "express";
import {Application} from 'express'; import {Application} from 'express';
import bodyParser = require('body-parser'); import bodyParser = require('body-parser');
@ -9,14 +10,21 @@ class App {
public app: Application; public app: Application;
public server: http.Server; public server: http.Server;
public ioSocketController: IoSocketController; public ioSocketController: IoSocketController;
public authenticateController: AuthenticateController;
constructor() { constructor() {
this.app = express(); this.app = express();
//config server http
this.config(); this.config();
this.server = http.createServer(this.app); this.server = http.createServer(this.app);
//create controllers
this.ioSocketController = new IoSocketController(this.server); this.ioSocketController = new IoSocketController(this.server);
this.authenticateController = new AuthenticateController(this.app);
} }
// TODO add session user
private config(): void { private config(): void {
this.app.use(bodyParser.json()); this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded({extended: false})); this.app.use(bodyParser.urlencoded({extended: false}));

View File

@ -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});
});
}
}

View File

@ -1,11 +1,10 @@
import socketIO = require('socket.io'); import socketIO = require('socket.io');
import {Socket} from "socket.io"; import {Socket} from "socket.io";
import * as http from "http"; import * as http from "http";
import {MessageUserPosition} from "../Model/Websocket/MessageUserPosition"; //TODO fix to use "_Model/.." import {MessageUserPosition} from "../Model/Websocket/MessageUserPosition"; //TODO fix import by "_Model/.."
import {ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix to use "_Model/.." import {ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix import by "_Model/.."
import Jwt, {JsonWebTokenError} from "jsonwebtoken"; import Jwt, {JsonWebTokenError} from "jsonwebtoken";
import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY";
export class IoSocketController{ export class IoSocketController{
Io: socketIO.Server; Io: socketIO.Server;
@ -39,8 +38,13 @@ export class IoSocketController{
x: user x position on map x: user x position on map
y: user y position on map y: user y position on map
*/ */
socket.on('join-room', (message : string) => { 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); socket.join(messageUserPosition.roomId);
// sending to all clients in room except sender // sending to all clients in room except sender
this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); this.saveUserPosition((socket as ExSocketInterface), messageUserPosition);
@ -48,7 +52,10 @@ export class IoSocketController{
}); });
socket.on('user-position', (message : string) => { 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 // sending to all clients in room except sender
this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); this.saveUserPosition((socket as ExSocketInterface), messageUserPosition);
socket.to(messageUserPosition.roomId).emit('join-room', messageUserPosition.toString()); socket.to(messageUserPosition.roomId).emit('join-room', messageUserPosition.toString());
@ -60,4 +67,14 @@ export class IoSocketController{
saveUserPosition(socket : ExSocketInterface, message : MessageUserPosition){ saveUserPosition(socket : ExSocketInterface, message : MessageUserPosition){
socket.position = message.position; 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;
}
}
} }

View File

@ -0,0 +1,5 @@
const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY";
export {
SECRET_KEY
}

View File

@ -4,6 +4,9 @@ export class Message {
constructor(message: string) { constructor(message: string) {
let data = JSON.parse(message); let data = JSON.parse(message);
if(!data.userId || !data.roomId){
throw Error("userId and roomId cannot be null");
}
this.userId = data.userId; this.userId = data.userId;
this.roomId = data.roomId; this.roomId = data.roomId;
} }

View File

@ -6,6 +6,9 @@ export class Point implements PointInterface{
y: number; y: number;
constructor(x : number, y : number) { constructor(x : number, y : number) {
if(!x || !y){
throw Error("x and y cannot be null");
}
this.x = x; this.x = x;
this.y = y; this.y = y;
} }

View File

@ -66,6 +66,13 @@
"@types/qs" "*" "@types/qs" "*"
"@types/serve-static" "*" "@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": "@types/json-schema@^7.0.3":
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" 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" statuses ">= 1.5.0 < 2"
toidentifier "1.0.0" 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: iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24" version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"