From 8cf65202243efc2e3157ae13feeff9efd2fab029 Mon Sep 17 00:00:00 2001 From: vankhaiphan Date: Fri, 28 May 2021 01:01:00 +0200 Subject: [PATCH 01/12] add auth-service not verified with Dockerfile --- backend/service-authentication/auth.js | 44 ++++++++++ backend/service-authentication/checkLogin.js | 18 ++++ backend/service-authentication/config.js | 15 ++++ .../service-authentication/keys/jwtRS256.key | 27 ++++++ .../keys/jwtRS256.key.pub | 9 ++ .../service-authentication/keys/jwtRS256.sh | 5 ++ backend/service-authentication/message.js | 13 +++ .../service-authentication/mongodbConnect.js | 18 ++++ .../service-authentication/mongodbQueries.js | 16 ++++ backend/service-authentication/package.json | 19 ++++ backend/service-authentication/server.js | 32 +++++++ backend/service-authentication/sessionJWT.js | 88 +++++++++++++++++++ 12 files changed, 304 insertions(+) create mode 100644 backend/service-authentication/auth.js create mode 100644 backend/service-authentication/checkLogin.js create mode 100644 backend/service-authentication/config.js create mode 100644 backend/service-authentication/keys/jwtRS256.key create mode 100644 backend/service-authentication/keys/jwtRS256.key.pub create mode 100644 backend/service-authentication/keys/jwtRS256.sh create mode 100644 backend/service-authentication/message.js create mode 100644 backend/service-authentication/mongodbConnect.js create mode 100644 backend/service-authentication/mongodbQueries.js create mode 100644 backend/service-authentication/package.json create mode 100644 backend/service-authentication/server.js create mode 100644 backend/service-authentication/sessionJWT.js diff --git a/backend/service-authentication/auth.js b/backend/service-authentication/auth.js new file mode 100644 index 0000000..a5a5487 --- /dev/null +++ b/backend/service-authentication/auth.js @@ -0,0 +1,44 @@ +const sessionJwt = require ('./sessionJWT'); +const queries = require('./mongodbQueries'); + +// ici, on récupère le contenu du cookie de session JWT. +// celui-ci contient le userId mais également des informations +// concernant sa date d'expiration. +function getSession (req) { + return sessionJwt.decodeSessionCookie(req); +} +module.exports.getSession = getSession; + +// cette fonction ajoute le cookie de session au headers du +// message qui sera renvoyé à Angular. Si le cookie actuel +// est "vieux", on en recrée ici un nouveau. +function setSessionCookie (req, res, session) { + sessionJwt.createSessionCookie(req, res, session); +} +module.exports.setSessionCookie = setSessionCookie; + +// fonction pour récupérer le userId provenant du cookie +// de session. Si ce dernier n'existe pas, on renvoie +// l'ID -1. +function getUserId(session) { + if (typeof session.userId === 'undefined') return -1; + return session.userId; +} +module.exports.getUserId = getUserId; + +async function authenticate(req, res) { + const login = req.body.login; + const password = req.body.password; + + const userList = await queries.checkLoginQuery(login, password); + if (userList !== undefined && userList[0] !== undefined && userList[0].idUtilisateur > 0){ + setSessionCookie (req, res, { userId: userList[0].idUtilisateur }); + // return userList[0].idUtilisateur; + return getUserId(getSession(req)); + } else { + setSessionCookie (req, res, {userId: -1}); + return -1; + } + +} +module.exports.authenticate = authenticate; diff --git a/backend/service-authentication/checkLogin.js b/backend/service-authentication/checkLogin.js new file mode 100644 index 0000000..e8a1dce --- /dev/null +++ b/backend/service-authentication/checkLogin.js @@ -0,0 +1,18 @@ +const {sendError, sendMessage} = require ("./message"); +const auth = require ('./auth'); + +async function checkLogin (req,res) { + if (typeof req.body.login === 'undefined') + return sendError(res, 'Vous n\'avez pas envoyé le champ login'); + if (typeof req.body.password === 'undefined') + return sendError(res, 'Vous n\'avez pas envoyé le champ password'); + + const result = await auth.authenticate(req, res); + if (result){ + return sendMessage(res, result); + } + else{ + return sendError(res, 'Invalid username or password'); + } +} +module.exports = checkLogin; diff --git a/backend/service-authentication/config.js b/backend/service-authentication/config.js new file mode 100644 index 0000000..ad36165 --- /dev/null +++ b/backend/service-authentication/config.js @@ -0,0 +1,15 @@ +const config = { + // paramètres de connexion à la base de données + mongodbDatabase: 'chat', + mongodbHost: 'mongodb://localhost:27017/', + charset: 'utf8', + mongodbLogin: '', + mongodbPassword: '', + + // les noms des tables + mongodbUtilisateurs: 'users' +}; +module.exports = config; + + + diff --git a/backend/service-authentication/keys/jwtRS256.key b/backend/service-authentication/keys/jwtRS256.key new file mode 100644 index 0000000..d8fc20c --- /dev/null +++ b/backend/service-authentication/keys/jwtRS256.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAvtgwBVQ26VNO1XD+PTZDdZJdWXufontRZIO/ev7OkvH8qM6g +mZDJOZQRrbaMI2w3jGr/x1uDhIaafRtyRsQ9Jdjb2GVjQc9deiNMfeEvA1YJZjiC +LDy4igtmitPup3WrG+xb9asNAuQUtn1bXKM/3ecVxIKq6j/wh1578ra9WGpcTZjx ++1u+3LjviWehb9Gwu8FOIPBu9bcIf48JZLr3Zq/0Fv0Atw7gTJBDAb2B9Zsjxc59 +oKKyWguRQG6COUaxZ/Lsyczv0FIFFsfAKzuihqfI+EsVGJ1nsFBH3gAdeUW2RX7/ +z+7cmR305sf3cdN7kcK8ZwgrG7/lnszSUf79uQIDAQABAoIBAAKKDdmETVa9bQca +Acf+uNcPo35VTsJysZqMxjd0vHroDVyRo0Fn08WYWsPc8fBmuDZ+FfkpFo7k25le +jB607btbL1Gpx7BQegXuAk6KeH2q32Uky1abWDk9/ZdLSpmfzy8H7hFOvVWUg1IK +SPTqlyb0tC1xL6T+RM0ITM3l8I8ElWHKzhs5H9jLlhOng0sW9RbLjWtBRXPp48tB +YFhx/wuSNpTOVGZAKpWVMaCgOizeL0yT6t+z/QL7Pvq3IhlcFMLz5K6f6/mZ+ODV +W/TpbwC7ll204vmgHsYY6tdpDAKqZK0ayPxm018QCCtCsYawDyk2HjYYnytXSsNu +UNPt+KECgYEA6WkKd5Nh8K0m9LVL3Gpbep9MKTqGgBVo8z4UV6iSDQdCBUSU8cFi +2ntsyAh0PCvQHxvn/DwqCcKafbFQMX+S1jpkZsoqA0OUjYRxQYOEn1iIGJdspzYl +cv2637p3Aza6x75eFLOZvFa3C1rCFQxJHvAYolN/FnhBx9D3QnaDydsCgYEA0VCJ +z4kVFm35poBEAVJOO3fdmFUvAn3bFhgI5zfzC/e4dPs9beiWo9XmpeOapu9D7F3M +1OFITUw1yQBoDtG5Gt/cIp39wdPNLfDM3kgv/djQGa/EZO1NkDrk/AGDZqyzDTUV +vGB/d8dGQdP9buiZFcy9D3HSsNVD9RP547+mfPsCgYEAywfa2f6yr/b+LthQ368I +WdadGjPVcS6udv+mFEYGnRyWGhz47n4IbgH0st9ftENsKtNMbQUskAbd+b22Awh0 +grKSSTNLbkFnw93T4mfzgeQxpip5kc2wr6Dz387D3WDLAhqenaVIciJ/4HmW31Yr +eKTi2LiGkNYUaipkGkUbCAcCgYEAmHvCmWT07s0ZJLmmUQwjn+D3lqTfxUHoW9UQ +j1jL/3jscJQisTHSo/IMv+bqYBhH9CZ1NNQVdvJA8HgSVlFkNvbECJfuJ8jjXUdi +B8Cw7Y2INF4+hYP2kE7HR+rWTfMb0VBN0FjAI4MRZJ1JsAVUmHP5ewnhgh8rDZwK +3GZepAcCgYEA1LwjdqCg3LJzXVSJ6gWwNNB9gRX2bb2l7iMHxaTEyRFvJFW7cuL9 +Y7iCKw+9EpGqSZesIHk1V+TCj77nXKpsyO+/tmiyyeqa1DT+AvvG+IgB0aJto7kU +f2oxn02dX9hN51tRhHZ6PDV/43GnJ3ltaXLBhCxq/MQZFXztYkUd6Z0= +-----END RSA PRIVATE KEY----- diff --git a/backend/service-authentication/keys/jwtRS256.key.pub b/backend/service-authentication/keys/jwtRS256.key.pub new file mode 100644 index 0000000..e316812 --- /dev/null +++ b/backend/service-authentication/keys/jwtRS256.key.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvtgwBVQ26VNO1XD+PTZD +dZJdWXufontRZIO/ev7OkvH8qM6gmZDJOZQRrbaMI2w3jGr/x1uDhIaafRtyRsQ9 +Jdjb2GVjQc9deiNMfeEvA1YJZjiCLDy4igtmitPup3WrG+xb9asNAuQUtn1bXKM/ +3ecVxIKq6j/wh1578ra9WGpcTZjx+1u+3LjviWehb9Gwu8FOIPBu9bcIf48JZLr3 +Zq/0Fv0Atw7gTJBDAb2B9Zsjxc59oKKyWguRQG6COUaxZ/Lsyczv0FIFFsfAKzui +hqfI+EsVGJ1nsFBH3gAdeUW2RX7/z+7cmR305sf3cdN7kcK8ZwgrG7/lnszSUf79 +uQIDAQAB +-----END PUBLIC KEY----- diff --git a/backend/service-authentication/keys/jwtRS256.sh b/backend/service-authentication/keys/jwtRS256.sh new file mode 100644 index 0000000..0fe22a2 --- /dev/null +++ b/backend/service-authentication/keys/jwtRS256.sh @@ -0,0 +1,5 @@ +ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key +# Don't add passphrase +openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub +cat jwtRS256.key +cat jwtRS256.key.pub \ No newline at end of file diff --git a/backend/service-authentication/message.js b/backend/service-authentication/message.js new file mode 100644 index 0000000..05714bc --- /dev/null +++ b/backend/service-authentication/message.js @@ -0,0 +1,13 @@ +// renvoie un message au format JSON. On a besoin de passer en paramètre +// res, la réponse que l'on envoie au client (Angular). Le paramètre +// data est un objet JavaScript. Globalement, cette fonction est +// équivalente au "echo json_encode(data);" que vous utilisiez en PHP +function sendMessage (res, data) { + res.json ({ status: 'ok', data: data }); +} + +function sendError (res, reason) { + res.json ({ status: 'error', data: {reason: reason }}); +} + +module.exports = { sendMessage, sendError }; diff --git a/backend/service-authentication/mongodbConnect.js b/backend/service-authentication/mongodbConnect.js new file mode 100644 index 0000000..004ee4e --- /dev/null +++ b/backend/service-authentication/mongodbConnect.js @@ -0,0 +1,18 @@ +const config = require('./config'); +const MongoClient = require( 'mongodb' ).MongoClient; +const uri = config.mongodbHost; +let db; + +module.exports = { + connectToServer: function( callback ) { + MongoClient.connect( uri, { useNewUrlParser: true, useUnifiedTopology: true }, function( err, client ) { + db = client.db(config.mongodbDatabase); + return callback( err ); + }); + }, + + getDB: function() { + return db; + } +}; + diff --git a/backend/service-authentication/mongodbQueries.js b/backend/service-authentication/mongodbQueries.js new file mode 100644 index 0000000..62bb37a --- /dev/null +++ b/backend/service-authentication/mongodbQueries.js @@ -0,0 +1,16 @@ +const config = require('./config'); +const mongoDB = require ('./mongodbConnect').getDB(); + +function checkLoginQuery(login, password){ + // SELECT idUtilisateurs + // FROM utilisateurs + // WHERE login = ? AND password = ?; + return new Promise((resolve, reject) => { + resolve(mongoDB.collection(config.mongodbUtilisateurs).find( + {login: login, password: password}, + {projection: {idUtilisateur: 1, _id: 0}}).toArray()); + }); +} +module.exports.checkLoginQuery = checkLoginQuery; + + diff --git a/backend/service-authentication/package.json b/backend/service-authentication/package.json new file mode 100644 index 0000000..c98b345 --- /dev/null +++ b/backend/service-authentication/package.json @@ -0,0 +1,19 @@ +{ + "name": "service-authentication", + "version": "1.0.0", + "description": "", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Van Khai PHAN", + "license": "ISC", + "dependencies": { + "body-parser": "^1.19.0", + "cookie-parser": "^1.4.5", + "cors": "^2.8.5", + "express": "^4.17.1", + "jsonwebtoken": "^8.5.1", + "mongodb": "^3.6.9" + } +} diff --git a/backend/service-authentication/server.js b/backend/service-authentication/server.js new file mode 100644 index 0000000..b5eb59d --- /dev/null +++ b/backend/service-authentication/server.js @@ -0,0 +1,32 @@ +const express = require('express'); +const app = express(); +const port = process.env.PORT || 3000; + +const cookieParser = require('cookie-parser'); +app.use(cookieParser()); + +const bodyParser = require('body-parser'); +app.use(bodyParser.urlencoded({extended:true})); +app.use(bodyParser.json()); + +const cors = require('cors'); +app.use(cors({origin: 'http://127.0.0.1:4200', credentials: true})); + +const mongoConnect = require('./mongodbConnect'); + +mongoConnect.connectToServer(function( err, client ) { + if (err) + console.log(err); + + const checkLogin = require('./checkLogin'); + + app.post('/checkLogin', (req, res) => { + checkLogin(req,res); + }); + + app.listen(port, () => { + console.log (`listening on port ${port}`); + }); +}); + + diff --git a/backend/service-authentication/sessionJWT.js b/backend/service-authentication/sessionJWT.js new file mode 100644 index 0000000..90133d1 --- /dev/null +++ b/backend/service-authentication/sessionJWT.js @@ -0,0 +1,88 @@ +const sessionJWT = require ('jsonwebtoken'); +const fs = require ('fs'); + +// renvoie un nouveau token JWT +function createSessionJWT (userId) { + // ci-dessous, on met en place le cookie de session JWT : + // 1/ on recupere notre clef privee + const RSA_PRIVATE_KEY = fs.readFileSync('./keys/jwtRS256.key'); + + // 2/ on signe un token JWT. Le payload est l'identifiant de + // l'utilisateur ainsi qu'une date d'expiration à mi-parcours : + // on récupérra ultérieurement ces informations, qui permettront + // de savoir si le token est valide ou non et de connaître l'ID + // de l'utilisateur. Dans le token, le champ exp indique la date + // de validité du token (pas besoin de se relogguer tant que la + // date actuelle est inférieure à exp) et le champ midExp indique + // à partir de quel moment on doit recréer un nouveau cookie de + // session. + const jwtToken = sessionJWT.sign( + { + userId: userId, + midExp: Math.floor(Date.now() / 1000) + 1800 // validité: 30mn + }, + RSA_PRIVATE_KEY, + { + algorithm: 'RS256', + expiresIn: '1h' // champ exp: validité 1h + }); + + return jwtToken; +} + + +// crée un cookie de session JWT (Si le JWT de la requête est encore valide, +// on l'utilise, sinon on en recrée un nouveau) +function createSessionCookie(req, res, payload) { + // on regarde si le payload contient les champs userId et midExp. Si c'est le + // cas, c'est qu'on a reçu dans la request un cookie. On va donc vérifier si + // ce cookie est encore valide ou non : si la date actuelle est inférieure à + // midExp, alors le cookie est encore valide et on peut le renvoyer. Sinon, + // on doit recalculer un nouveau cookie. + let jwtToken = ''; + if ((typeof payload.userId !== 'undefined') && + (typeof payload.midExp !== 'undefined') && + (Math.floor(Date.now() / 1000) <= payload.midExp)) { + jwtToken = req.cookies.SESSIONID; + } + else { + // on crée un nouveau cookie + jwtToken = createSessionJWT(payload.userId); + } + + // on renvoie le cookie au client + // on met le secure à false afin de pouvoir utiliser http plutôt que https + res.cookie('SESSIONID', jwtToken, {httpOnly:true, secure:false}); +} +module.exports.createSessionCookie = createSessionCookie; + + +// décode un cookie de session et renvoie les informations contenues dans ce +// cookie, notamment le userId. Si le cookie n'existe pas, la fonction renvoie +// juste un objet avec un userId égal à -1. +function decodeSessionCookie(req) { + // si l'on n'a pas de cookie de session, on renvoie une session avec vide, + // avec juste un userId à -1 + console.log(req.cookies); + if (typeof req.cookies.SESSIONID === 'undefined') { + return { userId: -1 }; + } + const sessionid = req.cookies.SESSIONID; + + // on lit la clef publique + const RSA_PUBLIC_KEY = fs.readFileSync('./keys/jwtRS256.key.pub'); + + // on récupère les données du cookie + try { + const token = sessionJWT.verify( + sessionid, + RSA_PUBLIC_KEY, + {algorithms: ['RS256']}); + return token; + } + catch (err) { + return {userId: -1}; + } +} +module.exports.decodeSessionCookie = decodeSessionCookie; + From 157c0e13a77de82455cf5df11278ba05c7c1ad98 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:01:50 +0200 Subject: [PATCH 02/12] Docker added --- backend/service-authentication/Dockerfile | 4 +- .../service-authentication/mongodbConnect.js | 2 + docker-compose.yml | 101 +++++++----------- 3 files changed, 39 insertions(+), 68 deletions(-) diff --git a/backend/service-authentication/Dockerfile b/backend/service-authentication/Dockerfile index 77f61f6..b0b4790 100644 --- a/backend/service-authentication/Dockerfile +++ b/backend/service-authentication/Dockerfile @@ -1,8 +1,6 @@ -# syntax=docker/dockerfile:1 FROM node:current-slim -ENV NODE_ENV=production WORKDIR /app-authentication COPY ["package.json", "package-lock.json*", "./"] -RUN npm install --production +RUN npm install --NODE_ENV COPY . . CMD [ "node", "server.js" ] \ No newline at end of file diff --git a/backend/service-authentication/mongodbConnect.js b/backend/service-authentication/mongodbConnect.js index 004ee4e..dde6462 100644 --- a/backend/service-authentication/mongodbConnect.js +++ b/backend/service-authentication/mongodbConnect.js @@ -6,7 +6,9 @@ let db; module.exports = { connectToServer: function( callback ) { MongoClient.connect( uri, { useNewUrlParser: true, useUnifiedTopology: true }, function( err, client ) { + console.log(client.isConnected()); db = client.db(config.mongodbDatabase); + return callback( err ); }); }, diff --git a/docker-compose.yml b/docker-compose.yml index bb3d7fc..4912f89 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,82 +1,53 @@ -version: '3.7' -networks: - net: +version: '3.8' services: - frontend: - image: frontend - environment: - SERVICE_ADRESS: frontend - SERVICE_PORT: 4200 - ports: - - 4200:4200 - networks: - - net - service-authentication: - image: service-authentication + build: backend/service-authentication + command: node server.js + volumes: + - backend/service-authentication + - backend/service-authentication/node_modules + ports: + - 3001:3000 + depends_on: + - mongodb-authentication environment: - SERVICE_ADRESS: service-authentication - SERVICE_PORT: 3000 - ports: - - 3000:3000 - networks: - - net + NODE_ENV: development service-message: - image: service-message + build: backend/service-message + command: node server.js + volumes: + - backend/service-message + - backend/service-message/node_modules + ports: + - 3000:3000 + depends_on: + - mongodb-message environment: - SERVICE_ADRESS: service-message - SERVICE_PORT: 3000 - ports: - - 3001:3000 - networks: - - net - service-notification: - image: service-notification - environment: - SERVICE_ADRESS: service-notification - SERVICE_PORT: 3000 - ports: - - 3002:3000 - networks: - - net - - service-privateroom: - image: service-privateroom - environment: - SERVICE_ADRESS: service-privateroom - SERVICE_PORT: 3000 - ports: - - 3003:3000 - networks: - - net + NODE_ENV: development mongodb-authentication: image: mongo - networks: - - net + container_name: mongodb-authentication + environment: + - PUID=1001 + - PGID=1001 + volumes: + - ./backend/service-authentication/database:/data/db ports: - - 27017:27017 + - 27017:27017 + restart: unless-stopped mongodb-message: image: mongo - networks: - - net + container_name: mongodb-message + environment: + - PUID=1000 + - PGID=1000 + volumes: + - ./backend/service-message/database:/data/db ports: - 27020:27017 - - mongodb-notification: - image: mongo - networks: - - net - ports: - - 27021:27017 - - mongodb-privateroom: - image: mongo - networks: - - net - ports: - - 27022:27017 \ No newline at end of file + restart: unless-stopped \ No newline at end of file From 72d9179ddd267281efbb9a4d67d63424a0019e85 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:02:52 +0200 Subject: [PATCH 03/12] Docker added --- backend/service-authentication/mongodbConnect.js | 2 +- backend/service-message/Dockerfile | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/service-authentication/mongodbConnect.js b/backend/service-authentication/mongodbConnect.js index dde6462..3c6db28 100644 --- a/backend/service-authentication/mongodbConnect.js +++ b/backend/service-authentication/mongodbConnect.js @@ -6,7 +6,7 @@ let db; module.exports = { connectToServer: function( callback ) { MongoClient.connect( uri, { useNewUrlParser: true, useUnifiedTopology: true }, function( err, client ) { - console.log(client.isConnected()); + console.log('mongodb-authentication-checkConnection'+client.isConnected()); db = client.db(config.mongodbDatabase); return callback( err ); diff --git a/backend/service-message/Dockerfile b/backend/service-message/Dockerfile index 8e92ff6..78cf074 100644 --- a/backend/service-message/Dockerfile +++ b/backend/service-message/Dockerfile @@ -1,8 +1,6 @@ -# syntax=docker/dockerfile:1 FROM node:current-slim -ENV NODE_ENV=production WORKDIR /app-message COPY ["package.json", "package-lock.json*", "./"] -RUN npm install --production +RUN npm install --NODE_ENV COPY . . CMD [ "node", "server.js" ] \ No newline at end of file From 652679126323cf2352cc98b629137ae6ae0ff7c2 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:03:55 +0200 Subject: [PATCH 04/12] Message and Docker added --- backend/service-message/auth.js | 26 + backend/service-message/config.js | 13 + backend/service-message/message.js | 13 + backend/service-message/mongodb-message.js | 34 + backend/service-message/package-lock.json | 849 +++++++++++++++++++++ backend/service-message/package.json | 22 + backend/service-message/server.js | 81 ++ backend/service-message/sessionJWT.js | 87 +++ 8 files changed, 1125 insertions(+) create mode 100644 backend/service-message/auth.js create mode 100644 backend/service-message/config.js create mode 100644 backend/service-message/message.js create mode 100644 backend/service-message/mongodb-message.js create mode 100644 backend/service-message/package-lock.json create mode 100644 backend/service-message/package.json create mode 100644 backend/service-message/server.js create mode 100644 backend/service-message/sessionJWT.js diff --git a/backend/service-message/auth.js b/backend/service-message/auth.js new file mode 100644 index 0000000..d198a41 --- /dev/null +++ b/backend/service-message/auth.js @@ -0,0 +1,26 @@ +const sessionJwt = require ('./sessionJWT'); + +// ici, on récupère le contenu du cookie de session JWT. +// celui-ci contient le userId mais également des informations +// concernant sa date d'expiration. +function getSession (req) { + return sessionJwt.decodeSessionCookie(req); +} +module.exports.getSession = getSession; + +// cette fonction ajoute le cookie de session au headers du +// message qui sera renvoyé à Angular. Si le cookie actuel +// est "vieux", on en recrée ici un nouveau. +function setSessionCookie (req, res, session) { + sessionJwt.createSessionCookie(req, res, session); +} +module.exports.setSessionCookie = setSessionCookie; + +// fonction pour récupérer le userId provenant du cookie +// de session. Si ce dernier n'existe pas, on renvoie +// l'ID -1. +function getUsername(session) { + if (typeof session.username === 'undefined') return -1; + return session.username; +} +module.exports.getUsername = getUsername; diff --git a/backend/service-message/config.js b/backend/service-message/config.js new file mode 100644 index 0000000..fb37e42 --- /dev/null +++ b/backend/service-message/config.js @@ -0,0 +1,13 @@ +const config = { + mongodbDatabase: 'chat', + mongodbHost: 'mongodb://localhost:27020/', + charset: 'utf8', + mongodbLogin: '', + mongodbPassword: '', + + mongodbMessages: 'messages' +}; +module.exports = config; + + + diff --git a/backend/service-message/message.js b/backend/service-message/message.js new file mode 100644 index 0000000..05714bc --- /dev/null +++ b/backend/service-message/message.js @@ -0,0 +1,13 @@ +// renvoie un message au format JSON. On a besoin de passer en paramètre +// res, la réponse que l'on envoie au client (Angular). Le paramètre +// data est un objet JavaScript. Globalement, cette fonction est +// équivalente au "echo json_encode(data);" que vous utilisiez en PHP +function sendMessage (res, data) { + res.json ({ status: 'ok', data: data }); +} + +function sendError (res, reason) { + res.json ({ status: 'error', data: {reason: reason }}); +} + +module.exports = { sendMessage, sendError }; diff --git a/backend/service-message/mongodb-message.js b/backend/service-message/mongodb-message.js new file mode 100644 index 0000000..df441f8 --- /dev/null +++ b/backend/service-message/mongodb-message.js @@ -0,0 +1,34 @@ +const config = require('./config'); +const mongoose = require( 'mongoose' ); +const url = config.mongodbHost; + +mongoose.connect(url,({useNewUrlParser: true, useUnifiedTopology: true})); +console.log(mongoose.connection.readyState); + +const schemaMessage = mongoose.Schema({ + username:{ + type: String, + required: true + }, + date:{ + type: Date, + required: true + }, + channel:{ + type: String, + required: true + }, + message:{ + type: String, + required: true + } +}); + +const messages = mongoose.model(config.mongodbMessages, schemaMessage); + +// messages.find({},(err, messages) => { +// if(err) throw err; +// console.log(messages); +// }); + +module.exports = messages; diff --git a/backend/service-message/package-lock.json b/backend/service-message/package-lock.json new file mode 100644 index 0000000..bf9c4b6 --- /dev/null +++ b/backend/service-message/package-lock.json @@ -0,0 +1,849 @@ +{ + "name": "service-message", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/bson": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz", + "integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==", + "requires": { + "@types/node": "*" + } + }, + "@types/component-emitter": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", + "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" + }, + "@types/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==" + }, + "@types/cors": { + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", + "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==" + }, + "@types/mongodb": { + "version": "3.6.16", + "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.16.tgz", + "integrity": "sha512-D3tM0iRUet3TiIMAdvovxAIRG9gYqFd4j7visGwmPNdQj8Fq/uFFfRxyGCgEwVXAs0NnJPMI/QGVTADxDwhmSQ==", + "requires": { + "@types/bson": "*", + "@types/node": "*" + } + }, + "@types/node": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz", + "integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" + }, + "bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bson": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "denque": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", + "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "engine.io": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-5.1.1.tgz", + "integrity": "sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w==", + "requires": { + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~4.0.0", + "ws": "~7.4.2" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "engine.io-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", + "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", + "requires": { + "base64-arraybuffer": "0.1.4" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "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" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "kareem": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", + "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + }, + "mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "requires": { + "mime-db": "1.47.0" + } + }, + "mongodb": { + "version": "3.6.8", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.8.tgz", + "integrity": "sha512-sDjJvI73WjON1vapcbyBD3Ao9/VN3TKYY8/QX9EPbs22KaCSrQ5rXo5ZZd44tWJ3wl3FlnrFZ+KyUtNH6+1ZPQ==", + "requires": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "optional-require": "^1.0.3", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, + "mongoose": { + "version": "5.12.11", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.12.11.tgz", + "integrity": "sha512-16TVqYhHQdZNR8RTis/8iiTPy+nJPq0UhKyBFTucLLU3PWcDLY2gAGv6aOk0LygTNhEfgNnENgUUHhjVqTuh8w==", + "requires": { + "@types/mongodb": "^3.5.27", + "bson": "^1.1.4", + "kareem": "2.3.2", + "mongodb": "3.6.8", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.8.3", + "mquery": "3.2.5", + "ms": "2.1.2", + "regexp-clone": "1.0.0", + "safe-buffer": "5.2.1", + "sift": "13.5.2", + "sliced": "1.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + }, + "mpath": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz", + "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==" + }, + "mquery": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", + "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", + "requires": { + "bluebird": "3.5.1", + "debug": "3.1.0", + "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", + "sliced": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "optional-require": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", + "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regexp-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "sift": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", + "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "socket.io": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.2.tgz", + "integrity": "sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w==", + "requires": { + "@types/cookie": "^0.4.0", + "@types/cors": "^2.8.8", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.1", + "engine.io": "~5.1.0", + "socket.io-adapter": "~2.3.0", + "socket.io-parser": "~4.0.3" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "socket.io-adapter": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz", + "integrity": "sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw==" + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" + } + } +} diff --git a/backend/service-message/package.json b/backend/service-message/package.json new file mode 100644 index 0000000..051c9ee --- /dev/null +++ b/backend/service-message/package.json @@ -0,0 +1,22 @@ +{ + "name": "service-message", + "version": "1.0.0", + "description": "", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "body-parser": "^1.19.0", + "cookie-parser": "^1.4.5", + "cors": "^2.8.5", + "express": "^4.17.1", + "fs": "0.0.1-security", + "jsonwebtoken": "^8.5.1", + "mongoose": "^5.12.11", + "socket.io": "^4.1.2" + } +} diff --git a/backend/service-message/server.js b/backend/service-message/server.js new file mode 100644 index 0000000..c6cf276 --- /dev/null +++ b/backend/service-message/server.js @@ -0,0 +1,81 @@ +const express = require('express'); +const http = require('http'); +const { Server } = require("socket.io"); +const cors = require ('cors'); +const cookieParser = require('cookie-parser'); +const auth = require ('./auth'); +const bodyParser = require ('body-parser'); +const {sendError, sendMessage} = require ('./message'); +const messages = require('./mongodb-message'); + +const app = express(); +const server = http.createServer(app); +const io = new Server(server); +const port = process.env.PORT || 3000; + +app.use(bodyParser.json()); +app.use(cors({origin: 'http://127.0.0.1:4200', credentials: true})); +app.use(cookieParser()); + + +app.get('/', (req, res) => { + const session = auth.getSession(req); + const getUsername = auth.getUsername(session); + if (getUsername === -1) { + //sendError(res, 'not authenticated'); + } + //auth.setSessionCookie(req, res, session); + res.sendFile(__dirname + '/index.html'); + +}); + +io.on('connection',socket => { + let users = {} + + socket.on('user', (userData) => { + console.log(`${getUsername} joined the chat.`); + users[socket.id] = getUsername; + messages.find({},(err, res) => { + if(err) throw err; + if(res.length > 0){ + const savedChat = res; + socket.emit('general',savedChat); + } + }); + }); + + socket.on('general',function(data){ + socket.broadcast.emit('general',data); + + const username = data.username; + const date = Date.now(); + const channel = 'general'; + const message = data.message; + + messages.insertMany([{ + username: username, + date: date, + channel: channel, + message: message + } + ]).then(function(){ + console.log(data, "inserted"); + }).catch(function(error){ + console.log("error",error); + }); + + }); + + socket.on('typing',(user)=>{ + socket.broadcast.emit('notifyTyping',user) + }) + + socket.on("disconnect", function() { + console.log(`${socket.id} left the chat.`); + }); + +}); + +server.listen(port, () => { + console.log('listening on *:3000'); +}); \ No newline at end of file diff --git a/backend/service-message/sessionJWT.js b/backend/service-message/sessionJWT.js new file mode 100644 index 0000000..7372845 --- /dev/null +++ b/backend/service-message/sessionJWT.js @@ -0,0 +1,87 @@ +const sessionJWT = require ('jsonwebtoken'); +const fs = require ('fs'); + +// renvoie un nouveau token JWT +function createSessionJWT (userId) { + // ci-dessous, on met en place le cookie de session JWT : + // 1/ on recupere notre clef privee + const RSA_PRIVATE_KEY = fs.readFileSync('./keys/jwtRS256.key'); + + // 2/ on signe un token JWT. Le payload est l'identifiant de + // l'utilisateur ainsi qu'une date d'expiration à mi-parcours : + // on récupérra ultérieurement ces informations, qui permettront + // de savoir si le token est valide ou non et de connaître l'ID + // de l'utilisateur. Dans le token, le champ exp indique la date + // de validité du token (pas besoin de se relogguer tant que la + // date actuelle est inférieure à exp) et le champ midExp indique + // à partir de quel moment on doit recréer un nouveau cookie de + // session. + const jwtToken = sessionJWT.sign( + { + userId: userId, + midExp: Math.floor(Date.now() / 1000) + 1800 // validité: 30mn + }, + RSA_PRIVATE_KEY, + { + algorithm: 'RS256', + expiresIn: '1h' // champ exp: validité 1h + }); + + return jwtToken; +} + + +// crée un cookie de session JWT (Si le JWT de la requête est encore valide, +// on l'utilise, sinon on en recrée un nouveau) +function createSessionCookie(req, res, payload) { + // on regarde si le payload contient les champs userId et midExp. Si c'est le + // cas, c'est qu'on a reçu dans la request un cookie. On va donc vérifier si + // ce cookie est encore valide ou non : si la date actuelle est inférieure à + // midExp, alors le cookie est encore valide et on peut le renvoyer. Sinon, + // on doit recalculer un nouveau cookie. + let jwtToken = ''; + if ((typeof payload.userId !== 'undefined') && + (typeof payload.midExp !== 'undefined') && + (Math.floor(Date.now() / 1000) <= payload.midExp)) { + jwtToken = req.cookies.SESSIONID; + } + else { + // on crée un nouveau cookie + jwtToken = createSessionJWT(payload.userId); + } + + // on renvoie le cookie au client + // on met le secure à false afin de pouvoir utiliser http plutôt que https + res.cookie('SESSIONID', jwtToken, {httpOnly:true, secure:false}); +} +module.exports.createSessionCookie = createSessionCookie; + + +// décode un cookie de session et renvoie les informations contenues dans ce +// cookie, notamment le userId. Si le cookie n'existe pas, la fonction renvoie +// juste un objet avec un userId égal à -1. +function decodeSessionCookie(req) { + // si l'on n'a pas de cookie de session, on renvoie une session avec vide, + // avec juste un userId à -1 + if (typeof req.cookies.SESSIONID === 'undefined') { + return { userId: -1 }; + } + const sessionid = req.cookies.SESSIONID; + + // on lit la clef publique + const RSA_PUBLIC_KEY = fs.readFileSync('./keys/jwtRS256.key.pub'); + + // on récupère les données du cookie + try { + const token = sessionJWT.verify( + sessionid, + RSA_PUBLIC_KEY, + {algorithms: ['RS256']}); + return token; + } + catch (err) { + return {userId: -1}; + } +} +module.exports.decodeSessionCookie = decodeSessionCookie; + From 9521494addb54ce14f16bbd2ba76b90347a7b82b Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:51:51 +0200 Subject: [PATCH 05/12] Add expose port --- backend/service-authentication/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/service-authentication/Dockerfile b/backend/service-authentication/Dockerfile index b0b4790..198444f 100644 --- a/backend/service-authentication/Dockerfile +++ b/backend/service-authentication/Dockerfile @@ -1,6 +1,7 @@ FROM node:current-slim WORKDIR /app-authentication COPY ["package.json", "package-lock.json*", "./"] -RUN npm install --NODE_ENV +RUN npm install COPY . . +EXPOSE 3000 CMD [ "node", "server.js" ] \ No newline at end of file From 502de9b05a8bfc2a89d9124e402e006aa51b1c37 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:52:05 +0200 Subject: [PATCH 06/12] Add check client --- backend/service-authentication/mongodbConnect.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/service-authentication/mongodbConnect.js b/backend/service-authentication/mongodbConnect.js index 3c6db28..57643a1 100644 --- a/backend/service-authentication/mongodbConnect.js +++ b/backend/service-authentication/mongodbConnect.js @@ -6,7 +6,9 @@ let db; module.exports = { connectToServer: function( callback ) { MongoClient.connect( uri, { useNewUrlParser: true, useUnifiedTopology: true }, function( err, client ) { - console.log('mongodb-authentication-checkConnection'+client.isConnected()); + if(err) throw err; + console.log('mongodb-authentication-checkConnection'+client===undefined); + if (client !== undefined) console.log(client.isConnected()); db = client.db(config.mongodbDatabase); return callback( err ); From e787258999e2015644d0f31bcb9fa09403a47eb4 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:52:35 +0200 Subject: [PATCH 07/12] Debug response --- backend/service-authentication/auth.js | 8 ++++---- backend/service-authentication/checkLogin.js | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/backend/service-authentication/auth.js b/backend/service-authentication/auth.js index a5a5487..a0a184f 100644 --- a/backend/service-authentication/auth.js +++ b/backend/service-authentication/auth.js @@ -32,11 +32,11 @@ async function authenticate(req, res) { const userList = await queries.checkLoginQuery(login, password); if (userList !== undefined && userList[0] !== undefined && userList[0].idUtilisateur > 0){ - setSessionCookie (req, res, { userId: userList[0].idUtilisateur }); - // return userList[0].idUtilisateur; - return getUserId(getSession(req)); + console.log("check"); + setSessionCookie (req, res, { username: login}); + return userList[0].idUtilisateur; } else { - setSessionCookie (req, res, {userId: -1}); + setSessionCookie (req, res, {username: -1}); return -1; } diff --git a/backend/service-authentication/checkLogin.js b/backend/service-authentication/checkLogin.js index e8a1dce..3de2160 100644 --- a/backend/service-authentication/checkLogin.js +++ b/backend/service-authentication/checkLogin.js @@ -8,8 +8,11 @@ async function checkLogin (req,res) { return sendError(res, 'Vous n\'avez pas envoyé le champ password'); const result = await auth.authenticate(req, res); - if (result){ - return sendMessage(res, result); + if (result > 0){ + return sendMessage(res, { + id: result, + username: req.body.login + }); } else{ return sendError(res, 'Invalid username or password'); From f5020bd378ce90372ac8094252fb1f082e74f0bd Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:52:42 +0200 Subject: [PATCH 08/12] Add expose port --- backend/service-message/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/service-message/Dockerfile b/backend/service-message/Dockerfile index 78cf074..ff0de4c 100644 --- a/backend/service-message/Dockerfile +++ b/backend/service-message/Dockerfile @@ -3,4 +3,5 @@ WORKDIR /app-message COPY ["package.json", "package-lock.json*", "./"] RUN npm install --NODE_ENV COPY . . +EXPOSE 3000 CMD [ "node", "server.js" ] \ No newline at end of file From ae936d9817ad1777ecb32fec98144ccfc8115481 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:53:16 +0200 Subject: [PATCH 09/12] Add links & container_name --- docker-compose.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4912f89..3854e79 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,51 +3,49 @@ version: '3.8' services: service-authentication: + container_name: service-authentication build: backend/service-authentication command: node server.js volumes: - backend/service-authentication - backend/service-authentication/node_modules ports: - - 3001:3000 + - 3000:3000 depends_on: - mongodb-authentication + links: + - mongodb-authentication environment: NODE_ENV: development service-message: + container_name: service-message build: backend/service-message command: node server.js volumes: - backend/service-message - backend/service-message/node_modules ports: - - 3000:3000 + - 3001:3000 depends_on: - mongodb-message + links: + - mongodb-message environment: NODE_ENV: development mongodb-authentication: image: mongo container_name: mongodb-authentication - environment: - - PUID=1001 - - PGID=1001 volumes: - ./backend/service-authentication/database:/data/db ports: - 27017:27017 - restart: unless-stopped mongodb-message: image: mongo container_name: mongodb-message - environment: - - PUID=1000 - - PGID=1000 volumes: - ./backend/service-message/database:/data/db ports: - - 27020:27017 - restart: unless-stopped \ No newline at end of file + - 27020:27017 \ No newline at end of file From 7dd198c42ca42d393263826cee1009aa5dfa741a Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:53:31 +0200 Subject: [PATCH 10/12] Change host for the docker compose --- backend/service-message/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/service-message/config.js b/backend/service-message/config.js index fb37e42..612edc0 100644 --- a/backend/service-message/config.js +++ b/backend/service-message/config.js @@ -1,6 +1,6 @@ const config = { mongodbDatabase: 'chat', - mongodbHost: 'mongodb://localhost:27020/', + mongodbHost: 'mongodb://mongodb-message:27020/', charset: 'utf8', mongodbLogin: '', mongodbPassword: '', From da20cd22128670019659f94a9bcbd5912484eac5 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:56:33 +0200 Subject: [PATCH 11/12] Expose port remove because of conflict --- backend/service-authentication/Dockerfile | 1 - backend/service-message/Dockerfile | 1 - 2 files changed, 2 deletions(-) diff --git a/backend/service-authentication/Dockerfile b/backend/service-authentication/Dockerfile index 198444f..94cb3f1 100644 --- a/backend/service-authentication/Dockerfile +++ b/backend/service-authentication/Dockerfile @@ -3,5 +3,4 @@ WORKDIR /app-authentication COPY ["package.json", "package-lock.json*", "./"] RUN npm install COPY . . -EXPOSE 3000 CMD [ "node", "server.js" ] \ No newline at end of file diff --git a/backend/service-message/Dockerfile b/backend/service-message/Dockerfile index ff0de4c..78cf074 100644 --- a/backend/service-message/Dockerfile +++ b/backend/service-message/Dockerfile @@ -3,5 +3,4 @@ WORKDIR /app-message COPY ["package.json", "package-lock.json*", "./"] RUN npm install --NODE_ENV COPY . . -EXPOSE 3000 CMD [ "node", "server.js" ] \ No newline at end of file From 52f13387c1b43f12ba336b2508a0f833084a43b4 Mon Sep 17 00:00:00 2001 From: NyxiumYuuki Date: Fri, 28 May 2021 08:56:52 +0200 Subject: [PATCH 12/12] Host changed to service name for the docker compose --- backend/service-authentication/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/service-authentication/config.js b/backend/service-authentication/config.js index ad36165..4e951d0 100644 --- a/backend/service-authentication/config.js +++ b/backend/service-authentication/config.js @@ -1,7 +1,7 @@ const config = { // paramètres de connexion à la base de données mongodbDatabase: 'chat', - mongodbHost: 'mongodb://localhost:27017/', + mongodbHost: 'mongodb://mongodb-authentication:27017/', charset: 'utf8', mongodbLogin: '', mongodbPassword: '',