Merge pull request #19 from gparant/Setup-web-socket-connection
Setup web-socket connection
This commit is contained in:
commit
dc1a92f086
@ -21,9 +21,13 @@
|
|||||||
"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/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",
|
||||||
"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",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
|
@ -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}));
|
||||||
|
28
back/src/Controller/AuthenticateController.ts
Normal file
28
back/src/Controller/AuthenticateController.ts
Normal 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});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,36 +1,80 @@
|
|||||||
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";
|
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";
|
||||||
|
import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||||
|
|
||||||
export class IoSocketController{
|
export class IoSocketController{
|
||||||
Io: socketIO.Server;
|
Io: socketIO.Server;
|
||||||
constructor(server : http.Server) {
|
constructor(server : http.Server) {
|
||||||
this.Io = socketIO(server);
|
this.Io = socketIO(server);
|
||||||
|
|
||||||
|
// 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'));
|
||||||
|
}
|
||||||
|
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();
|
this.ioConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
ioConnection() {
|
ioConnection() {
|
||||||
this.Io.on('connection', (socket: Socket) => {
|
this.Io.on('connection', (socket: Socket) => {
|
||||||
//TODO check token access
|
|
||||||
|
|
||||||
/*join-rom event permit to join one room.
|
/*join-rom event permit to join one room.
|
||||||
message :
|
message :
|
||||||
userId : user identification
|
userId : user identification
|
||||||
roomId: room identification
|
roomId: room identification
|
||||||
positionXUser: user x position map
|
position: position of user in map
|
||||||
positionYUser: user y position on 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 = this.hydrateMessageReceive(message);
|
||||||
|
if(messageUserPosition instanceof Error){
|
||||||
|
return socket.emit("message-error", JSON.stringify({message: messageUserPosition.message}))
|
||||||
|
}
|
||||||
|
//join user in room
|
||||||
|
socket.join(messageUserPosition.roomId);
|
||||||
// sending to all clients in room except sender
|
// 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 = this.hydrateMessageReceive(message);
|
||||||
|
if(messageUserPosition instanceof Error){
|
||||||
|
return socket.emit("message-error", JSON.stringify({message: messageUserPosition.message}));
|
||||||
|
}
|
||||||
// sending to all clients in room except sender
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Hydrate and manage error
|
||||||
|
hydrateMessageReceive(message : string) : MessageUserPosition | Error{
|
||||||
|
try {
|
||||||
|
return new MessageUserPosition(message);
|
||||||
|
}catch (err) {
|
||||||
|
//TODO log error
|
||||||
|
return new Error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
5
back/src/Enum/EnvironmentVariable.ts
Normal file
5
back/src/Enum/EnvironmentVariable.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY";
|
||||||
|
|
||||||
|
export {
|
||||||
|
SECRET_KEY
|
||||||
|
}
|
7
back/src/Model/Websocket/ExSocketInterface.ts
Normal file
7
back/src/Model/Websocket/ExSocketInterface.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import {Socket} from "socket.io";
|
||||||
|
import {PointInterface} from "./PointInterface";
|
||||||
|
|
||||||
|
export interface ExSocketInterface extends Socket {
|
||||||
|
token: object;
|
||||||
|
position: PointInterface;
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,33 @@
|
|||||||
import {Message} from "./Message";
|
import {Message} from "./Message";
|
||||||
|
import {PointInterface} from "./PointInterface";
|
||||||
|
|
||||||
|
export class Point implements PointInterface{
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
|
||||||
|
constructor(x : number, y : number) {
|
||||||
|
if(!x || !y){
|
||||||
|
throw Error("position x and y cannot be null");
|
||||||
|
}
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJson(){
|
||||||
|
return {
|
||||||
|
x : this.x,
|
||||||
|
y: this.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MessageUserPosition extends Message{
|
export class MessageUserPosition extends Message{
|
||||||
positionXUser: string;
|
position: PointInterface
|
||||||
positionYUser: string;
|
|
||||||
|
|
||||||
constructor(message: string) {
|
constructor(message: string) {
|
||||||
super(message);
|
super(message);
|
||||||
let data = JSON.parse(message);
|
let data = JSON.parse(message);
|
||||||
this.positionXUser = data.positionXUser;
|
this.position = new Point(data.position.x, data.position.y);
|
||||||
this.positionYUser = data.positionYUser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
@ -16,8 +35,7 @@ export class MessageUserPosition extends Message{
|
|||||||
Object.assign(
|
Object.assign(
|
||||||
super.toJson(),
|
super.toJson(),
|
||||||
{
|
{
|
||||||
positionXUser: this.positionXUser,
|
position: this.position.toJson()
|
||||||
positionYUser: this.positionYUser
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
5
back/src/Model/Websocket/PointInterface.ts
Normal file
5
back/src/Model/Websocket/PointInterface.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface PointInterface {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
toJson() : object;
|
||||||
|
}
|
@ -43,8 +43,8 @@
|
|||||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||||
"paths": {
|
"paths": {
|
||||||
"@Controller/*": ["src/Controller/*"],
|
"_Controller/*": ["src/Controller/*"],
|
||||||
"@Model/*": ["src/Model/*"]
|
"_Model/*": ["src/Model/*"]
|
||||||
}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
}, /* 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. */
|
// "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. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
|
106
back/yarn.lock
106
back/yarn.lock
@ -66,11 +66,25 @@
|
|||||||
"@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"
|
||||||
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
|
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@*":
|
"@types/mime@*":
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
|
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
|
||||||
@ -317,6 +331,11 @@ brace-expansion@^1.1.7:
|
|||||||
balanced-match "^1.0.0"
|
balanced-match "^1.0.0"
|
||||||
concat-map "0.0.1"
|
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:
|
buffer-from@^1.0.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
@ -546,6 +565,13 @@ dynamic-dedupe@^0.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
xtend "^4.0.0"
|
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:
|
ee-first@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||||
@ -967,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"
|
||||||
@ -1126,6 +1157,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"
|
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
||||||
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
|
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:
|
levn@^0.3.0, levn@~0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
|
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
|
||||||
@ -1145,6 +1209,41 @@ load-json-file@^1.0.0:
|
|||||||
pinkie-promise "^2.0.0"
|
pinkie-promise "^2.0.0"
|
||||||
strip-bom "^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:
|
lodash@^4.17.14, lodash@^4.17.15:
|
||||||
version "4.17.15"
|
version "4.17.15"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||||
@ -1568,12 +1667,17 @@ safe-buffer@5.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
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":
|
"safer-buffer@>= 2.1.2 < 3":
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
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"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
|
@ -29,6 +29,7 @@ services:
|
|||||||
command: yarn dev
|
command: yarn dev
|
||||||
environment:
|
environment:
|
||||||
STARTUP_COMMAND_1: yarn install
|
STARTUP_COMMAND_1: yarn install
|
||||||
|
SECRET_KEY: yourSecretKey
|
||||||
volumes:
|
volumes:
|
||||||
- ./back:/usr/src/app
|
- ./back:/usr/src/app
|
||||||
labels:
|
labels:
|
||||||
|
Loading…
Reference in New Issue
Block a user