CESI - Exo Microbloggr Solution - Authentification fonctionnelle
This commit is contained in:
parent
68ccdca3a4
commit
eaa659f3c6
@ -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
|
||||
|
@ -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
|
||||
|
@ -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/;
|
||||
# }
|
||||
|
@ -1 +1 @@
|
||||
/app/node_modules
|
||||
/node_modules
|
||||
|
@ -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"]
|
||||
|
@ -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=="
|
||||
}
|
||||
}
|
||||
}
|
@ -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"
|
||||
}
|
@ -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');
|
||||
}
|
||||
|
||||
});
|
@ -4,6 +4,10 @@
|
||||
<nav class="main">
|
||||
<h1 class="brand">MicroBloggr</div>
|
||||
</nav>
|
||||
<div class="content">
|
||||
Bienvenue <%= user.username; %> !
|
||||
<a href="/logout">Se déconnecter</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1 +1 @@
|
||||
/app/node_modules
|
||||
/node_modules
|
||||
|
@ -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"]
|
||||
|
@ -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;
|
||||
})
|
||||
;
|
||||
}
|
@ -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=="
|
||||
}
|
||||
}
|
||||
}
|
@ -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"
|
||||
}
|
@ -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
|
||||
})
|
||||
;
|
||||
}
|
@ -0,0 +1 @@
|
||||
/node_modules
|
@ -0,0 +1 @@
|
||||
/node_modules
|
@ -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"]
|
@ -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"
|
||||
}
|
||||
}
|
@ -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'));
|
||||
|
@ -1 +0,0 @@
|
||||
/app/node_modules
|
@ -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": <user_id> }
|
||||
// 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++}`;
|
||||
}
|
@ -0,0 +1 @@
|
||||
/node_modules
|
@ -0,0 +1 @@
|
||||
/node_modules
|
@ -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"]
|
@ -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"
|
||||
}
|
||||
}
|
@ -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'));
|
||||
|
@ -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'
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user