integration of authentication

This commit is contained in:
Cyril Rouillon 2024-08-06 17:44:28 +02:00
parent 0c7fc6fdf7
commit ee932a2339
13 changed files with 153 additions and 84 deletions

View File

@ -1,4 +1,4 @@
module.exports = { const config = {
db: { db: {
connectionString: "mongodb://db:27017", connectionString: "mongodb://db:27017",
dbName: "jucundus", dbName: "jucundus",
@ -19,5 +19,11 @@ module.exports = {
jwtOptions: { jwtOptions: {
issuer: "jucundus.com", issuer: "jucundus.com",
audience: "yoursite", audience: "yoursite",
},
agent :{
ApiAgentURL: 'http://host.docker.internal:3020/api',
token: '861v48gr4YTHJTUre0reg40g8e6r8r64eggv1r4e6g4r81PKREVJ8g6reg46r8eg416reST6ger84g14er86e',
} }
}; };
module.exports = { config };

View File

@ -185,6 +185,16 @@ exports.current = asyncHandler(async (req, res, next) => {
}); });
exports.agentConnected = asyncHandler(async (req, res, next) => {
try{
res.status(200).send("OK");
}catch(err){
console.log(err);
return res.status(500).send(err);
}
});
exports.getAllUsers = asyncHandler(async (req, res, next) => { exports.getAllUsers = asyncHandler(async (req, res, next) => {
try{ try{
const userDb = await UserDb.init(); const userDb = await UserDb.init();

View File

@ -1,33 +1,53 @@
const passport = require('passport');
function Admited(acceptedRoles){
return (req, res, next) => {
// if Unconnected accepted
if (acceptedRoles.includes('Unconnected') || acceptedRoles.length == 0){
next();
}
function checkIsConcernedUserOrAdmin(req, res, next) { passport.authenticate('jwt', { session: false }, (err, user, info) => {
const user = req.user; // User is set by Passport
const userIdParam = req.params.id; if (err) {
// An error occurred, return a JSON error response
return res.status(500).json({ error: "An error occurred" });
}
if (!user) {
// User not authenticated, return a JSON error response
console.log('User not authenticated');
return res.status(401).json({ error: "User not authenticated" });
}
// User authenticated, attach user to request and proceed
req.user = user;
if (user.isAdmin === true || user._id === userIdParam) { // Determine the user's role
next(); let userRoles = [];
} else { if (user.isAdmin) {
res.status(403).json({ error: 'Forbidden' }); userRoles.push('Admin');
}
if (user.isAgent) {
userRoles.push('Agent')
}
if (user._id.toString() === req.params.id) {
userRoles.push('ConcernedUser')
}
if (user) {
userRoles.push('NormalUser')
}
// Check if any of the user's roles are in the list of accepted roles
const isAuthorized = userRoles.some(role => acceptedRoles.includes(role));
// Check if the user's role is in the list of accepted roles
if (isAuthorized) {
next(); // User's role is accepted, proceed to the next middleware/controller
} else {
res.status(403).json({ error: 'Forbidden' }); // User's role is not accepted, return 403 Forbidden
}
})(req, res, next);
} }
} }
module.exports = { Admited };
function checkIsAdmin(req, res, next) {
const user = req.user; // User is set by Passport
if (user.isAdmin === true) {
next();
} else {
res.status(403).json({ error: 'Forbidden' });
}
}
function checkIsAgent(req, res, next) {
const user = req.user; // User is set by Passport
if (user.isAgent === true) {
next();
} else {
res.status(403).json({ error: 'Forbidden' });
}
}
module.exports = { checkIsConcernedUserOrAdmin, checkIsAgent, checkIsAdmin };

View File

@ -2,7 +2,7 @@ var passport = require('passport');
var LocalStrategy = require('passport-local'); var LocalStrategy = require('passport-local');
var crypto = require('crypto'); var crypto = require('crypto');
const router = require('express').Router() const router = require('express').Router()
const config = require("../config.js"); const {config} = require("../config.js");
const keys = require("../.Keys.js"); const keys = require("../.Keys.js");
/* Configure password authentication strategy. /* Configure password authentication strategy.
@ -98,13 +98,17 @@ router.post('/authenticate', async function(req, res) {
if (err) { return res.status(500).json({message: err.message}); } if (err) { return res.status(500).json({message: err.message}); }
if (!user) { return res.status(401).json({message: 'Incorrect email or password.'}); } if (!user) { return res.status(401).json({message: 'Incorrect email or password.'}); }
console.log('/authenticate: '+user.username);
// User found, generate a JWT for the user // User found, generate a JWT for the user
var token = jwt.sign({ sub: user._id, email: user.email }, opts.secretOrKey, { var token = jwt.sign({ sub: user._id, email: user.email }, opts.secretOrKey, {
issuer: opts.issuer, issuer: opts.issuer,
audience: opts.audience, audience: opts.audience,
expiresIn: 86400 * 30 // 30 days expiresIn: 86400 * 30 // 30 days
}); });
console.log('Token: '+token);
res.json({ token: token }); res.json({ token: token });
//return res.status(500).json({message: 'Incorrect email or password.'}) //return res.status(500).json({message: 'Incorrect email or password.'})
})(req, res); })(req, res);

View File

@ -1,9 +1,8 @@
const controllers = require('../controllers/favorite') const controllers = require('../controllers/favorite')
const router = require('express').Router() const router = require('express').Router()
const passport = require('passport'); const { Admited } = require('../middleware/authMiddleware')
const { checkIsConcernedUserOrAdmin } = require('../middleware/authMiddleware')
router.post('/save/', passport.authenticate('jwt', { session: false }), controllers.save) router.post('/save/', Admited(['NormalUser']), controllers.save)
router.get('/getAll/', passport.authenticate('jwt', { session: false }), controllers.getAll) router.get('/getAll/', Admited(['NormalUser']), controllers.getAll)
module.exports = router module.exports = router

View File

@ -1,21 +1,20 @@
const controllers = require('../controllers/lot') const controllers = require('../controllers/lot')
const router = require('express').Router() const router = require('express').Router()
const passport = require('passport'); const { Admited } = require('../middleware/authMiddleware')
const { checkIsAgent, checkIsAdmin } = require('../middleware/authMiddleware')
router.get('/getInfos/:url', passport.authenticate('jwt', { session: false }), controllers.getInfos) router.get('/getInfos/:url', Admited(['NormalUser']), controllers.getInfos)
router.get('/getPictures/:url', passport.authenticate('jwt', { session: false }), controllers.getPictures) router.get('/getPictures/:url', Admited(['NormalUser']), controllers.getPictures)
router.get('/getLotsBySale/:id', passport.authenticate('jwt', { session: false }), controllers.getLotsBySale) router.get('/getLotsBySale/:id', Admited(['NormalUser']), controllers.getLotsBySale)
// DB // DB
router.get('/lot/:id', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.get) router.get('/lot/:id', Admited(['Admin']), controllers.get)
router.post('/lot/', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.post) router.post('/lot/', Admited(['Admin']), controllers.post)
router.put('/lot/:id', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.put) router.put('/lot/:id', Admited(['Admin']), controllers.put)
router.delete('/lot/:id', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.delete) router.delete('/lot/:id', Admited(['Admin']), controllers.delete)
// Live Data // Live Data
router.post('/NextItem/', checkIsAgent, controllers.NextItem) router.post('/NextItem/', Admited(['Agent', 'Admin']), controllers.NextItem)
router.post('/AuctionedItem/', checkIsAgent, controllers.AuctionedItem) router.post('/AuctionedItem/', Admited(['Agent', 'Admin']), controllers.AuctionedItem)
router.post('/Bid/', checkIsAgent, controllers.Bid) router.post('/Bid/', Admited(['Agent', 'Admin']), controllers.Bid)
module.exports = router module.exports = router

View File

@ -1,24 +1,24 @@
const controllers = require('../controllers/sale') const controllers = require('../controllers/sale')
const passport = require('passport');
const router = require('express').Router() const router = require('express').Router()
const { Admited } = require('../middleware/authMiddleware')
// AuctionAgent // AuctionAgent
router.get('/getSaleInfos/:url', controllers.getSaleInfos) router.get('/getSaleInfos/:url', Admited(['NormalUser']), controllers.getSaleInfos)
router.get('/prepareSale/:id', controllers.prepareSale) router.get('/prepareSale/:id', Admited(['NormalUser']), controllers.prepareSale)
router.get('/followSale/:id', controllers.followSale) router.get('/followSale/:id', Admited(['NormalUser']), controllers.followSale)
// DB // DB
router.get('/sale/:id', controllers.get) router.get('/sale/:id', Admited(['Admin']), controllers.get)
router.post('/sale/', controllers.post) router.post('/sale/', Admited(['Admin']), controllers.post)
router.put('/sale/:id', controllers.put) router.put('/sale/:id', Admited(['Admin', 'Agent']), controllers.put)
router.delete('/sale/:id', controllers.delete) router.delete('/sale/:id', Admited(['Admin']), controllers.delete)
//router.get('/getAll/', controllers.getAll)
router.get('/getAll/', passport.authenticate('jwt', { session: false }), controllers.getAll); router.get('/getAll/', Admited(['Admin']), controllers.getAll);
router.get('/getByUrl/:url', controllers.getByUrl) router.get('/getByUrl/:url', Admited(['Agent', 'Admin']), controllers.getByUrl)
router.get('/postProcessing/:id', controllers.postProcessing) router.get('/postProcessing/:id', Admited(['Admin']), controllers.postProcessing)
router.get('/SaleStatXsl/:id', controllers.SaleStatXsl) router.get('/SaleStatXsl/:id', Admited(['Admin']), controllers.SaleStatXsl)
module.exports = router module.exports = router

View File

@ -1,15 +1,15 @@
const controllers = require('../controllers/user') const controllers = require('../controllers/user')
const passport = require('passport');
const router = require('express').Router() const router = require('express').Router()
const { checkIsConcernedUserOrAdmin, checkIsAdmin } = require('../middleware/authMiddleware') const { Admited } = require('../middleware/authMiddleware')
// DB // DB
router.get('/user/:id', passport.authenticate('jwt', { session: false }), checkIsConcernedUserOrAdmin, controllers.get); router.get('/user/:id', Admited(['Admin', 'ConcernedUser']), controllers.get);
router.post('/user/', controllers.post) router.post('/user/', Admited(['Unconnected']), controllers.post)
router.put('/user/:id', passport.authenticate('jwt', { session: false }), checkIsConcernedUserOrAdmin, controllers.put) router.put('/user/:id', Admited(['Admin', 'ConcernedUser']), controllers.put)
router.delete('/user/:id', passport.authenticate('jwt', { session: false }), checkIsConcernedUserOrAdmin, controllers.delete) router.delete('/user/:id', Admited(['Admin', 'ConcernedUser']), controllers.delete)
router.get('/current', passport.authenticate('jwt', { session: false }), controllers.current) router.get('/current', Admited(['NormalUser']), controllers.current)
router.get('/getAllUsers', passport.authenticate('jwt', { session: false }), checkIsAdmin, controllers.getAllUsers) router.get('/agentConnected', Admited(['Agent']), controllers.agentConnected)
router.get('/getAllUsers', Admited(['Admin']), controllers.getAllUsers)
module.exports = router module.exports = router

View File

@ -4,20 +4,39 @@ const lotDb = new LotDb();
const { SaleDb } = require("./saleDb"); const { SaleDb } = require("./saleDb");
const saleDb = new SaleDb(); const saleDb = new SaleDb();
const moment = require('moment-timezone'); const moment = require('moment-timezone');
const { config } = require("../config.js");
const Agent = class const Agent = class
{ {
constructor() constructor()
{ {
this.ApiAgentURL = "http://host.docker.internal:3020/api"; this.ApiAgentURL = config.agent.ApiAgentURL;
this.token = config.agent.token;
}
async request(url, method){
return new Promise((resolve, reject) => {
fetch(url,{
method: method,
headers: {
'authorization': this.token
}
})
.then(response => response.json())
.then(data => {
resolve(data);
})
.catch(error => {
reject(error);
});
});
} }
async getSaleInfos(url) async getSaleInfos(url)
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
url = encodeURIComponent(url); url = encodeURIComponent(url);
fetch(this.ApiAgentURL+'/sale/getSaleInfos/'+url) this.request(this.ApiAgentURL+'/sale/getSaleInfos/'+url, 'GET')
.then(response => response.json())
.then(data => { .then(data => {
resolve(data); resolve(data);
}) })
@ -40,9 +59,7 @@ const Agent = class
let url = Sale.url let url = Sale.url
url = encodeURIComponent(url); url = encodeURIComponent(url);
this.request(this.ApiAgentURL+'/sale/getLotList/'+url, 'GET')
fetch(this.ApiAgentURL+'/sale/getLotList/'+url)
.then(response => response.json())
.then( async data => { .then( async data => {
for (let lot of data) { for (let lot of data) {
@ -68,9 +85,7 @@ const Agent = class
let url = Sale.url let url = Sale.url
url = encodeURIComponent(url); url = encodeURIComponent(url);
this.request(this.ApiAgentURL+'/sale/followSale/'+url, 'GET')
fetch(this.ApiAgentURL+'/sale/followSale/'+url)
.then(response => response.json())
.then(async data => { .then(async data => {
// set the Sale status to following // set the Sale status to following

View File

@ -1,5 +1,5 @@
const MongoClient = require("mongodb").MongoClient; const MongoClient = require("mongodb").MongoClient;
const config = require("../config.js"); const {config} = require("../config.js");
const connectionString = config.db.connectionString; const connectionString = config.db.connectionString;
const client = new MongoClient(connectionString); const client = new MongoClient(connectionString);

View File

@ -61,7 +61,13 @@
<ng-container matColumnDef="plateform"> <ng-container matColumnDef="plateform">
<th mat-header-cell *matHeaderCellDef> Plateforme </th> <th mat-header-cell *matHeaderCellDef> Plateforme </th>
<td mat-cell *matCellDef="let element"> {{element.platform}} </td> <td mat-cell *matCellDef="let element"> {{element.platform}} </td>
</ng-container> </ng-container>
<!-- Status Column -->
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef> Status </th>
<td mat-cell *matCellDef="let element"> {{element.status}} </td>
</ng-container>
<!-- Action Column --> <!-- Action Column -->
<ng-container matColumnDef="action"> <ng-container matColumnDef="action">
@ -80,7 +86,7 @@
</ng-container> </ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns; trackBy: trackByElementId"></tr>
</table> </table>
</div> </div>
@ -120,6 +126,12 @@
<td mat-cell *matCellDef="let element"> {{element.platform}} </td> <td mat-cell *matCellDef="let element"> {{element.platform}} </td>
</ng-container> </ng-container>
<!-- Status Column -->
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef> Status </th>
<td mat-cell *matCellDef="let element"> {{element.status}} </td>
</ng-container>
<!-- PostProcessing Column --> <!-- PostProcessing Column -->
<ng-container matColumnDef="postProcessing"> <ng-container matColumnDef="postProcessing">
<th mat-header-cell *matHeaderCellDef> Post Processing </th> <th mat-header-cell *matHeaderCellDef> Post Processing </th>
@ -137,7 +149,7 @@
</ng-container> </ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumnsOld"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumnsOld"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumnsOld;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumnsOld; trackBy: trackByElementId"></tr>
</table> </table>
</div> </div>

View File

@ -20,8 +20,8 @@ export class SalesPageComponent implements OnInit,OnDestroy {
url: string = ''; url: string = '';
refreshSalesId: any; refreshSalesId: any;
displayedColumns: string[] = ['title', 'date', 'house', 'plateform', 'action']; displayedColumns: string[] = ['title', 'date', 'house', 'plateform', 'status', 'action'];
displayedColumnsOld: string[] = ['title', 'date', 'house', 'plateform', 'postProcessing', 'delete']; displayedColumnsOld: string[] = ['title', 'date', 'house', 'plateform', 'status', 'postProcessing', 'delete'];
futureSales = [] futureSales = []
pastSales = [] pastSales = []
@ -62,6 +62,10 @@ export class SalesPageComponent implements OnInit,OnDestroy {
.sort((a: any, b: any) => moment(a.date).isAfter(b.date) ? 1 : -1); .sort((a: any, b: any) => moment(a.date).isAfter(b.date) ? 1 : -1);
}); });
} }
trackByElementId(index: number, element: any): string {
return element._id;
}
ngOnInit(): void { ngOnInit(): void {
this.titleService.setTitle('Jucundus - Sales'); this.titleService.setTitle('Jucundus - Sales');

View File

@ -16,7 +16,7 @@ services:
- ./backend:/backend - ./backend:/backend
ports: ports:
- "3000:3000" - "3000:3000"
- "9229:9229" - "9228:9229"
command: ["npm", "run", "dev"] command: ["npm", "run", "dev"]
depends_on: depends_on:
- db - db