From eaa659f3c6578a4b8f5eac58e64a3dcce7cda1cb Mon Sep 17 00:00:00 2001 From: William Petit Date: Wed, 28 Nov 2018 14:47:09 +0100 Subject: [PATCH] CESI - Exo Microbloggr Solution - Authentification fonctionnelle --- .../docker-compose.yml | 70 ++++++++++- .../services/gateway/Dockerfile | 2 +- .../services/gateway/microbloggr.conf | 4 + .../services/home_page/.dockerignore | 2 +- .../services/home_page/{app => }/.gitignore | 0 .../services/home_page/Dockerfile | 5 +- .../services/home_page/package-lock.json | 69 ++++++++++ .../services/home_page/{app => }/package.json | 2 + .../services/home_page/{app => src}/server.js | 12 +- .../home_page/{app => src}/views/index.ejs | 4 + .../services/login_page/.dockerignore | 2 +- .../services/login_page/{app => }/.gitignore | 0 .../services/login_page/Dockerfile | 5 +- .../services/login_page/app/server.js | 91 -------------- .../services/login_page/package-lock.json | 118 ++++++++++++++++++ .../login_page/{app => }/package.json | 2 + .../services/login_page/src/server.js | 83 ++++++++++++ .../login_page/{app => src}/views/index.ejs | 0 .../services/logout/.dockerignore | 1 + .../services/logout/.gitignore | 1 + .../services/{sessions => logout}/Dockerfile | 5 +- .../services/logout/package.json | 17 +++ .../services/logout/src/server.js | 25 ++++ .../services/sessions/.dockerignore | 1 - .../services/sessions/app/server.js | 102 --------------- .../services/users/.dockerignore | 1 + .../services/users/.gitignore | 1 + .../services/users/Dockerfile | 11 ++ .../{sessions/app => users}/package.json | 7 +- .../services/users/src/server.js | 44 +++++++ .../services/users/src/users.js | 17 +++ 31 files changed, 491 insertions(+), 213 deletions(-) rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/{app => }/.gitignore (100%) create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/package-lock.json rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/{app => }/package.json (87%) rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/{app => src}/server.js (61%) rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/{app => src}/views/index.ejs (54%) rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/{app => }/.gitignore (100%) delete mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/server.js create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/package-lock.json rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/{app => }/package.json (88%) create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/src/server.js rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/{app => src}/views/index.ejs (100%) create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.dockerignore create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.gitignore rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/{sessions => logout}/Dockerfile (55%) create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/package.json create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/src/server.js delete mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/.dockerignore delete mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/app/server.js create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.dockerignore create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.gitignore create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/Dockerfile rename cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/{sessions/app => users}/package.json (70%) create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/server.js create mode 100644 cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/users.js diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/docker-compose.yml b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/docker-compose.yml index f06faff..10ee182 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/docker-compose.yml +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/docker-compose.yml @@ -1,14 +1,76 @@ -version: '2' +version: '2.2' services: + gateway: build: - context: containers/gateway + context: services/gateway + args: + - HTTP_PROXY=${HTTP_PROXY} + - HTTPS_PROXY=${HTTPS_PROXY} + - http_proxy=${HTTP_PROXY} + - https_proxy=${HTTP_PROXY} + links: + - home_page + - login_page + - logout ports: - 8080:80 home_page: build: - context: containers/home_page + context: services/home_page + args: + - HTTP_PROXY=${HTTP_PROXY} + - HTTPS_PROXY=${HTTPS_PROXY} + - http_proxy=${HTTP_PROXY} + - https_proxy=${HTTP_PROXY} + environment: + SESSION_SECRET: "absolutly_not_secret" + links: + - redis + volumes: + - ./services/home_page/src:/app/src:ro + login_page: build: - context: containers/login_page + context: services/login_page + args: + - HTTP_PROXY=${HTTP_PROXY} + - HTTPS_PROXY=${HTTPS_PROXY} + - http_proxy=${HTTP_PROXY} + - https_proxy=${HTTP_PROXY} + links: + - users + - redis + volumes: + - ./services/login_page/src:/app/src:ro + environment: + SESSION_SECRET: "absolutly_not_secret" + + + logout: + build: + context: services/logout + args: + - HTTP_PROXY=${HTTP_PROXY} + - HTTPS_PROXY=${HTTPS_PROXY} + - http_proxy=${HTTP_PROXY} + - https_proxy=${HTTP_PROXY} + volumes: + - ./services/logout/src:/app/src:ro + environment: + SESSION_SECRET: "absolutly_not_secret" + + users: + build: + context: services/users + args: + - HTTP_PROXY=${HTTP_PROXY} + - HTTPS_PROXY=${HTTPS_PROXY} + - http_proxy=${HTTP_PROXY} + - https_proxy=${HTTP_PROXY} + volumes: + - ./services/users/src:/app/src:ro + + redis: + image: redis:5.0-alpine diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/Dockerfile b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/Dockerfile index 997772f..3497f82 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/Dockerfile +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.2 +FROM alpine:3.7 RUN apk add --no-cache nginx COPY microbloggr.conf /etc/nginx/microbloggr.conf diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/microbloggr.conf b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/microbloggr.conf index f289811..4cc7b10 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/microbloggr.conf +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/gateway/microbloggr.conf @@ -28,6 +28,10 @@ http { proxy_pass http://login_page:8080/; } + location /logout { + proxy_pass http://logout:8080/; + } + # location /profile { # proxy_pass http://profile_page:8080/; # } diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/.dockerignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/.dockerignore index 4e4a23e..07e6e47 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/.dockerignore +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/.dockerignore @@ -1 +1 @@ -/app/node_modules +/node_modules diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/.gitignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/.gitignore similarity index 100% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/.gitignore rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/.gitignore diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/Dockerfile b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/Dockerfile index 9cdaec8..f76262d 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/Dockerfile +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/Dockerfile @@ -2,9 +2,10 @@ FROM alpine:3.7 RUN apk add --no-cache nodejs -COPY app /app +COPY ./ /app WORKDIR /app RUN npm install --production +RUN npm install -g nodemon -CMD ["node", "server.js"] +CMD ["nodemon", "src/server.js"] diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/package-lock.json b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/package-lock.json new file mode 100644 index 0000000..61f85a2 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/package-lock.json @@ -0,0 +1,69 @@ +{ + "name": "login_page", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "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" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "requires": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "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" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "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==" + } + } +} diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/package.json b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/package.json similarity index 87% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/package.json rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/package.json index 85dc18f..6b3533a 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/package.json +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/package.json @@ -12,6 +12,8 @@ "ejs": "^2.5.7", "express": "^4.16.2", "express-session": "^1.15.6", + "connect-redis": "^3.4.0", + "morgan": "^1.9.1", "request": "^2.83.0", "request-promise-native": "^1.0.5" } diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/server.js b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/src/server.js similarity index 61% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/server.js rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/src/server.js index 66d6580..f8f1bfe 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/server.js +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/src/server.js @@ -1,11 +1,17 @@ const express = require('express'); const session = require('express-session'); +var RedisStore = require('connect-redis')(session); const app = express(); +const morgan = require('morgan'); app.set('view engine', 'ejs'); +app.set('views', __dirname + '/views'); +app.use(morgan('combined')); app.use(session({ - secret: 'AbsolutlyNotSecret', // Ce secret doit être partagé par tous les microservices *_page + store: new RedisStore({host: 'redis'}), + secret: process.env.SESSION_SECRET, // Ce secret doit être partagé par tous les microservices *_page + cookie: { maxAge: 60000 }, resave: false, saveUninitialized: true, })); @@ -20,10 +26,10 @@ app.get('/', (req, res) => { // On vérifie si un utilisateur a été associé à la session HTTP if (req.session.user) { // Si oui, on affichage la page d'accueil - return res.render('index'); + return res.render('index', { user: req.session.user }); } else { // Si non, on redirige l'utilisateur vers la page de login - return res.redirect(301, '/login'); + return res.redirect(302, '/login'); } }); diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/views/index.ejs b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/src/views/index.ejs similarity index 54% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/views/index.ejs rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/src/views/index.ejs index 2bb1ef3..457091f 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/app/views/index.ejs +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/home_page/src/views/index.ejs @@ -4,6 +4,10 @@ +
+ Bienvenue <%= user.username; %> ! + Se déconnecter +
diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/.dockerignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/.dockerignore index 4e4a23e..07e6e47 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/.dockerignore +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/.dockerignore @@ -1 +1 @@ -/app/node_modules +/node_modules diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/.gitignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/.gitignore similarity index 100% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/.gitignore rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/.gitignore diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/Dockerfile b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/Dockerfile index 9cdaec8..f76262d 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/Dockerfile +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/Dockerfile @@ -2,9 +2,10 @@ FROM alpine:3.7 RUN apk add --no-cache nodejs -COPY app /app +COPY ./ /app WORKDIR /app RUN npm install --production +RUN npm install -g nodemon -CMD ["node", "server.js"] +CMD ["nodemon", "src/server.js"] diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/server.js b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/server.js deleted file mode 100644 index d929560..0000000 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/server.js +++ /dev/null @@ -1,91 +0,0 @@ -const express = require('express'); -const app = express(); -const session = require('express-session'); -const bodyParser = require('body-parser'); -const request = require('request-promise-native'); - -app.set('view engine', 'ejs'); - -app.use(session({ - secret: 'AbsolutlyNotSecret', // Ce secret doit être partagé par tous les microservices *_page - resave: false, - saveUninitialized: true, -})); - -// On utilise le module "body-parser" -// pour faciliter la désérialisation des données -// du formulaire -app.use(bodyParser.urlencoded({extended: false})); - -// GET / -// Affiche la page de login -app.get('/', (req, res) => { - res.render('index', { error: null }); -}); - - -// POST / -// Récupère les données du formulaire de login -app.post('/', (req, res) => { - - const form = req.body; - - // Si le formulaire ne contient pas les données attendues - // on renvoie un code HTTP 400 pour indiquer une requête invalide. - if(!form.username || !form.password) { - return res.render('index', { error: 'Identifiant ou mot de passe manquant.'}); - } - - // On interroge le microservices "users" - // pour récupérer l'utilisateur associé à l'identifiant - // fourni dans le formulaire - findUserByName(form.username) - .then(user => { - - // Si l'utilisateur n'existe pas, on affiche un message d'erreur - if(!user) { - return res.render('index', { error: 'Identifiant invalide !'}); - } - - // Si le mot de passe de l'utilisateur correspond à celui enregistré sur le - // microservice "users", on attache l'identifiant de l'utilisateur à la session - // HTTP puis on le redirige sur la page d'accueil - if(user.password === form.password) { - req.session.user = user; - return res.redirect(302, '/'); - } else { - // Sinon, on affiche un message d'erreur - return res.render('index', { error: 'Mot de passe invalide !'}); - } - - }) - .catch(err => { - // Une erreur s'est produite en essayant de contacter le microservices "users" - // On affiche un message d'erreur à l'utilisateur - return res.render('index', { - error: 'Une erreur s\'est produite pendant le processus d\'authentification.' - }); - }) - ; - -}); - -app.listen(8080, () => console.log('listening on port 8080')); - -// Récupère un utilisateur via son identifiant -// sur le microservice "users" -function findUserByName(username) { - return request({ - uri: `http://users:8080/users/${username}`, - json: true - }) - .catch(err => { - // Si le microservice "users" répond avec un code HTTP 404 - // c'est que l'utilisateur n'existe pas - if (err.response.statusCode === 404) { - return null; - } - throw err; - }) - ; -} diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/package-lock.json b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/package-lock.json new file mode 100644 index 0000000..58b8bb7 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/package-lock.json @@ -0,0 +1,118 @@ +{ + "name": "login_page", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "connect-redis": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-3.4.0.tgz", + "integrity": "sha512-YKPSO9tLwzUr8jzhsGMdSJUxevWrDt0ggXRcTMb+mtnJ/vWGlWV7RC4VUMgqvZv3uTGDFye8Bf7d6No0oSVkOQ==", + "requires": { + "debug": "^4.0.1", + "redis": "^2.8.0" + }, + "dependencies": { + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "requires": { + "ms": "^2.1.1" + } + }, + "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==" + } + } + }, + "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" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "requires": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "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" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "requires": { + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" + } + }, + "redis-commands": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", + "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==" + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" + }, + "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==" + } + } +} diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/package.json b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/package.json similarity index 88% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/package.json rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/package.json index 954d211..aa3aceb 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/package.json +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/package.json @@ -10,9 +10,11 @@ "license": "ISC", "dependencies": { "body-parser": "^1.18.2", + "connect-redis": "^3.4.0", "ejs": "^2.5.7", "express": "^4.16.2", "express-session": "^1.15.6", + "morgan": "^1.9.1", "request": "^2.83.0", "request-promise-native": "^1.0.5" } diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/src/server.js b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/src/server.js new file mode 100644 index 0000000..9d34f0c --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/src/server.js @@ -0,0 +1,83 @@ +const express = require('express'); +const app = express(); +const session = require('express-session'); +var RedisStore = require('connect-redis')(session); +const bodyParser = require('body-parser'); +const request = require('request-promise-native'); +const morgan = require('morgan'); + +app.set('view engine', 'ejs'); +app.set('views', __dirname + '/views'); + +app.use(morgan('combined')); +app.use(session({ + store: new RedisStore({host: 'redis'}), + secret: process.env.SESSION_SECRET, // Ce secret doit être partagé par tous les microservices *_page + cookie: { maxAge: 60000 }, + resave: false, + saveUninitialized: true, +})); + +// On utilise le module "body-parser" +// pour faciliter la désérialisation des données +// du formulaire +app.use(bodyParser.urlencoded({extended: false})); + +// GET / +// Affiche la page de login +app.get('/', (req, res) => { + res.render('index', { error: null }); +}); + +// POST / +// Récupère les données du formulaire de login +app.post('/', (req, res) => { + + const form = req.body; + + // Si le formulaire ne contient pas les données attendues + // on renvoie un code HTTP 400 pour indiquer une requête invalide. + if(!form.username || !form.password) { + return res.render('index', { error: 'Identifiant ou mot de passe manquant.'}); + } + + // On interroge le microservices "users" + // pour récupérer l'utilisateur associé à l'identifiant + // fourni dans le formulaire + authenticateUser(form.username, form.password) + .then(result => { + + // Si l'utilisateur n'existe pas, on affiche un message d'erreur + if(!result.ok) { + return res.render('index', { error: result.error }); + } + + // Si le microservice "users" renvoie "ok", alors cela signifie + // que le mot de passe est valide + req.session.user = result.user; + return res.redirect(303, '/'); + + }) + .catch(err => { + console.error(err); + return res.end(500).send(err.message); + }) + ; + +}); + +app.listen(8080, () => console.log('listening on port 8080')); + +// Authentifie un utilisateur via son couple identifiant/mot de passe +// sur le microservice "users" +function authenticateUser(username, password) { + return request({ + uri: `http://users:8080/auth`, + method: 'POST', + body: { + username, password + }, + json: true + }) + ; +} diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/views/index.ejs b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/src/views/index.ejs similarity index 100% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/app/views/index.ejs rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/login_page/src/views/index.ejs diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.dockerignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.dockerignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.dockerignore @@ -0,0 +1 @@ +/node_modules diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.gitignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.gitignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/Dockerfile b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/Dockerfile similarity index 55% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/Dockerfile rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/Dockerfile index 9cdaec8..f76262d 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/Dockerfile +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/Dockerfile @@ -2,9 +2,10 @@ FROM alpine:3.7 RUN apk add --no-cache nodejs -COPY app /app +COPY ./ /app WORKDIR /app RUN npm install --production +RUN npm install -g nodemon -CMD ["node", "server.js"] +CMD ["nodemon", "src/server.js"] diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/package.json b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/package.json new file mode 100644 index 0000000..0fff541 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/package.json @@ -0,0 +1,17 @@ +{ + "name": "logout", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "connect-redis": "^3.4.0", + "express-session": "^1.15.6", + "express": "^4.16.2", + "morgan": "^1.9.1" + } +} diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/src/server.js b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/src/server.js new file mode 100644 index 0000000..e63a4d6 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/logout/src/server.js @@ -0,0 +1,25 @@ +const express = require('express'); +const app = express(); +const session = require('express-session'); +var RedisStore = require('connect-redis')(session); +const morgan = require('morgan'); + +app.use(morgan('combined')); +app.use(session({ + store: new RedisStore({host: 'redis'}), + secret: process.env.SESSION_SECRET, // Ce secret doit être partagé par tous les microservices accédant à la session + cookie: { maxAge: 60000 }, + resave: false, + saveUninitialized: true, +})); + +// GET / +app.get('/', (req, res) => { + req.session.destroy(err => { + if (err) return res.status(500).send(err.stack); + return res.status(303).redirect("/"); + }); +}); + +app.listen(8080, () => console.log('listening on port 8080')); + diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/.dockerignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/.dockerignore deleted file mode 100644 index 4e4a23e..0000000 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -/app/node_modules diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/app/server.js b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/app/server.js deleted file mode 100644 index b19bb11..0000000 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/app/server.js +++ /dev/null @@ -1,102 +0,0 @@ -const express = require('express'); -const bodyParser = require('body-parser'); -const app = express(); - -const sessions = {}; -let sessionCounter = 0; - -// On utilise le middleware "body-parser" -// pour désérialiser automatiquement -// les objets JSON potentiellement -// fournis par les requêtes -app.use(bodyParser.json()); - -// GET /sessions -// Permet de récupérer la liste des sessions en cours -app.get('/sessions', (req, res) => { - res.json(sessions); -}); - - -// GET /sessions/:id -// Permet de récupérer une session via son identifiant -app.get('/sessions/:id', (req, res) => { - - // On récupère l'identifiant de session - // depuis l'URL - const sessionId = req.params.id; - - // On vérifie que la session existe. - // Si ce n'est pas le cas, on retourne un code - // HTTP 404 pour indiquer que la ressource - // n'existe pas - if (!sessions.hasOwnProperty(sessionId)) { - return res.status(404).end('Not found.'); - } - - // On retourne la session sérialisée en JSON - return res.json(sessions[sessionId]); - -}) - -// POST /sessions -// Body: {"user": } -// Permet de créer une nouvelle session pour l'utilisateur donné -app.post('/sessions', (req, res) => { - - const payload = req.body; - - // On valide la présence de l'attribut "user" - // sur les données fournies. - // Si il n'est pas présent, on retourne un code HTTP - // 400 pour indiquer que la requête est invalide. - if (!payload.user) { - return res.status(400).end('Bad request.'); - } - - // On créait une nouvelle session - const sess = { - user: payload.user, - id: getSessionId(), - }; - - // On la "stocke" dans notre registre - sessions[session.id] = sess; - - // On retourne la session - // nouvellement créée - res.json(sess); - -}) - - -// DELETE /sessions/:id -// Permet de supprimer une session dans le registre via son identifiant -app.delete('/sessions/:id', (req, res) => { - - // On récupère l'identifiant de session - // depuis l'URL - const sessionId = req.params.id; - - // On vérifie que la session existe. - // Si ce n'est pas le cas, on retourne un code - // HTTP 404 pour indiquer que la ressource - // n'existe pas - if (!sessions.hasOwnProperty(sessionId)) { - return res.status(404).end('Not found.'); - } - - delete sessions[sessionId]; - - // On retourne un code HTTP 204 pour indiquer que l'opération - // s'est déroulée correctement mais qu'aucun "contenu" n'est disponible - return res.status(204); - -}); - - -app.listen(8080, () => console.log('listening on port 8080')); - -function getSessionId() { - return `${Date.now()}-${sessionCounter++}`; -} diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.dockerignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.dockerignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.dockerignore @@ -0,0 +1 @@ +/node_modules diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.gitignore b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.gitignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/Dockerfile b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/Dockerfile new file mode 100644 index 0000000..f76262d --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/Dockerfile @@ -0,0 +1,11 @@ +FROM alpine:3.7 + +RUN apk add --no-cache nodejs + +COPY ./ /app +WORKDIR /app + +RUN npm install --production +RUN npm install -g nodemon + +CMD ["nodemon", "src/server.js"] diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/app/package.json b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/package.json similarity index 70% rename from cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/app/package.json rename to cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/package.json index dfb2c2e..c863015 100644 --- a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/sessions/app/package.json +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/package.json @@ -1,8 +1,8 @@ { - "name": "sessions", + "name": "users", "version": "1.0.0", "description": "", - "main": "server.js", + "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "body-parser": "^1.18.2", - "express": "^4.16.2" + "express": "^4.16.2", + "morgan": "^1.9.1" } } diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/server.js b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/server.js new file mode 100644 index 0000000..62664c9 --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/server.js @@ -0,0 +1,44 @@ +const express = require('express'); +const app = express(); +const bodyParser = require('body-parser'); +const morgan = require('morgan'); +const users = require('./users'); + +app.use(morgan('combined')); + +// On utilise le module "body-parser" +// pour faciliter la désérialisation des données +// des appels à l'API +app.use(bodyParser.json()); + +// POST /auth +// Effectue une authentification pour un couple d'identifiants donné +app.post('/auth', (req, res) => { + + const credentials = req.body; + + if(!credentials.username || !credentials.password) { + return res.status(200).send({ + ok: false, + error: "Identifiants invalides.", + }); + } + + const user = users[credentials.username]; + + if (!user || user.password !== credentials.password) { + return res.status(200).send({ + ok: false, + error: "Identifiants invalides.", + }); + } + + return res.status(200).send({ + ok: true, + user, + }); + +}); + +app.listen(8080, () => console.log('listening on port 8080')); + diff --git a/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/users.js b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/users.js new file mode 100644 index 0000000..7051f5f --- /dev/null +++ b/cesi/architecture_n_tiers/ressources/exercices/ex_microbloggr_solution/services/users/src/users.js @@ -0,0 +1,17 @@ +// Liste des utilisateurs définie statiquement +// Dans une situation réelle, ces comptes seraient stockés +// en BDD et les mots de passe hachés/salés. +module.exports = { + admin: { + username: 'admin', + password: 'admin' + }, + user1: { + username: 'user1', + password: 'user1' + }, + user2: { + username: 'user2', + password: 'user2' + } +}; \ No newline at end of file