update project with new architecture
This commit is contained in:
89
app/middlewares/checkHeaders.js
Executable file
89
app/middlewares/checkHeaders.js
Executable file
@@ -0,0 +1,89 @@
|
||||
const path = require( 'path' );
|
||||
const config = require( '../tribes/townconf.js' );
|
||||
|
||||
const checkHeaders = ( req, res, next ) => {
|
||||
/**
|
||||
* @apiDefine apxHeader
|
||||
* @apiGroup Middleware
|
||||
* @apiDescription Header is mandatory to access apxtrib see tribes/townconf.json.exposedHeaders
|
||||
* A turn around can be done with a simple get params has to be sent in the get url. Usefull to send simple get without header like ?xworkon=tribeName&xlang=en... priority is given to headers
|
||||
* For performance, tokens are store globaly in req.app.locals.tokens={xpaganid:xauth}
|
||||
* if xlang is not in config.languagesAvailable
|
||||
*
|
||||
* @apiHeader {string} xauth Pagans unique jwt token store in local town Pagans data or "noauth"
|
||||
* @apiHeader {string} xpaganid Pagans unique Pagan id in uuid format or "nouuid"
|
||||
* @apiHeader {string} xlang the 2 letter langage it request the api (if not exist the 2 first letter of Accept-Language header ) if lang does not exist in the town then en is set (as it always exist in en).
|
||||
* @apiHeader {string} xtribe Tribes id where Pagan belong to
|
||||
* @apiHeader {string} xworkon Tribes on which pagansId want and have accessright to work on.
|
||||
* @apiHeader {string} xapp Name of app that send the request (tribesId:websiteName) cpaganid have to have accessright on this app}
|
||||
*
|
||||
* @apiError missingexposedHeaders it miss an exposedHeaders
|
||||
*
|
||||
* @apiErrorExample {json} Error-Response:
|
||||
* HTTP/1/1 404 Not Found
|
||||
* {
|
||||
* status:404,
|
||||
* info:"|middleware|missingheaders",
|
||||
* moreinfo: xpaganid xauth
|
||||
* }
|
||||
*
|
||||
* @apiHeaderExample {json} Header-Exemple:
|
||||
* {
|
||||
* xtribe:"apache",
|
||||
* xpaganid:"12123211222",
|
||||
* xworkon:"sioux",
|
||||
* xauth:"",
|
||||
* xlang:"en",
|
||||
* xapp:""
|
||||
* }
|
||||
*/
|
||||
req.session = {};
|
||||
const header = {};
|
||||
if (!req.header('xlang') && req.header('Content-Language')) req.params.xlang=req.header('Content-Language');
|
||||
let missingheader = [];
|
||||
for( const h of config.exposedHeaders ) {
|
||||
//console.log( h, req.header( h ) )
|
||||
if( req.params[ h ] ) {
|
||||
header[ h ] = req.params[ h ]
|
||||
} else if( req.header( h ) ) {
|
||||
header[ h ] = req.header( h )
|
||||
} else {
|
||||
missingheade.push(h);
|
||||
}
|
||||
};
|
||||
//console.log( 'header', header )
|
||||
// store in session the header information
|
||||
req.session.header = header;
|
||||
// Each header have to be declared
|
||||
if( missingheader != "" ) {
|
||||
// bad request
|
||||
return res.status( 400 )
|
||||
.json( {
|
||||
ref:"headers"
|
||||
info: "missingheader",
|
||||
moreinfo: missingheader
|
||||
} );
|
||||
};
|
||||
//console.log( req.app.locals.tribeids )
|
||||
if( !req.app.locals.tribeids.includes( header.xtribe ) ) {
|
||||
return res.status( 400 )
|
||||
.json( {
|
||||
ref:"headers"
|
||||
info: 'tribeiddoesnotexist',
|
||||
moreinfo: header.xtribe
|
||||
} );
|
||||
}
|
||||
if( !req.app.locals.tribeids.includes( header.xworkon ) ) {
|
||||
return res.status( 400 )
|
||||
.send( {
|
||||
info: [ 'workondoesnotexist' ],
|
||||
ref: 'headers',
|
||||
moreinfo:header.xworkon
|
||||
} );
|
||||
}
|
||||
if( !config.languages.includes( header.xlang ) ) {
|
||||
header.xlang="en";
|
||||
}
|
||||
next();
|
||||
};
|
||||
module.exports = checkHeaders;
|
42
app/middlewares/hasAccessrighton.js
Executable file
42
app/middlewares/hasAccessrighton.js
Executable file
@@ -0,0 +1,42 @@
|
||||
const fs = require( 'fs-extra' );
|
||||
const glob = require( 'glob' );
|
||||
const path = require( 'path' );
|
||||
|
||||
const config = require( '../tribes/townconf.js' );
|
||||
|
||||
const hasAccessrighton = ( object, action, ownby ) => {
|
||||
/*
|
||||
@action (mandatory) : CRUDO
|
||||
@object (mandatory)= name of a folder object in /tribeid space can be a tree for example objects/items
|
||||
@ownby (option) = list des uuid propriétaire
|
||||
return next() if all action exist in req.app.local.tokens[UUID].ACCESSRIGHTS.data[object]
|
||||
OR if last action ="O" and uuid exist in ownBy
|
||||
Careffull if you have many action CRO let O at the end this will force req.right at true if the owner try an action on this object
|
||||
*/
|
||||
return ( req, res, next ) => {
|
||||
//console.log( 'err.stack hasAccessrights', err.statck )
|
||||
//console.log( `test accessright on object:${object} for ${req.session.header.xworkon}:`, req.app.locals.tokens[ req.session.header.xpaganid ].ACCESSRIGHTS.data[ req.session.header.xworkon ] )
|
||||
req.right = false;
|
||||
if( req.app.locals.tokens[ req.session.header.xpaganid ].ACCESSRIGHTS.data[ req.session.header.xworkon ] && req.app.locals.tokens[ req.session.header.xpaganid ].ACCESSRIGHTS.data[ req.session.header.xworkon ][ object ] ) {
|
||||
req.right = true;
|
||||
[ ...action ].forEach( a => {
|
||||
if( a == "O" && ownby && ownby.includes( req.session.header.xpaganid ) ) {
|
||||
req.right = true;
|
||||
} else {
|
||||
req.right = req.right && req.app.locals.tokens[ req.session.header.xpaganid ].ACCESSRIGHTS.data[ req.session.header.xworkon ][ object ].includes( a )
|
||||
}
|
||||
} )
|
||||
}
|
||||
//console.log( 'Access data autorise? ', req.right )
|
||||
if( !req.right ) {
|
||||
return res.status( 403 )
|
||||
.json( {
|
||||
info:'forbiddenAccessright',
|
||||
ref: 'headers',
|
||||
moreinfo: {xpaganid:req.session.header.xpaganid,object:object, xworkon:req.session.header.xworkon, action:action}
|
||||
} )
|
||||
}
|
||||
next();
|
||||
}
|
||||
}
|
||||
module.exports = hasAccessrighton;
|
115
app/middlewares/isAuthenticated.js
Executable file
115
app/middlewares/isAuthenticated.js
Executable file
@@ -0,0 +1,115 @@
|
||||
const jwt = require( 'jwt-simple' );
|
||||
const jsonfile = require( 'jsonfile' );
|
||||
const fs = require( 'fs-extra' );
|
||||
const moment = require( 'moment' );
|
||||
const glob = require( 'glob' );
|
||||
//const path = require( 'path' );
|
||||
// Check if package is installed or not to pickup the right config file
|
||||
//const src = '..'; // ( __dirname.indexOf( '/node_modules/' ) > -1 ) ? '../../..' : '..';
|
||||
//const config = require( path.normalize( `${__dirname}/${src}/config.js` ) );
|
||||
const config = require( '../tribes/townconf.js' );
|
||||
|
||||
const isAuthenticated = ( req, res, next ) => {
|
||||
/*
|
||||
check if authenticated with valid token
|
||||
if not => set req.session.header.xauth=1
|
||||
if yes => set for xWorkon
|
||||
req.session.header.accessrights={
|
||||
app:{'tribeid:website':[liste of menu]},
|
||||
data:{ "sitewebsrc": "RWCDO",
|
||||
"contacts": "RWCDO"}}
|
||||
Liste of menu is linked with the app tht h
|
||||
ave to be consistent with accessrights.data
|
||||
data, list of object accessright Read Write Create Delete Owner
|
||||
a xuuid can read any objet if R
|
||||
if O wner means that it can only read write its object create by himself
|
||||
*/
|
||||
console.log( 'isAuthenticated()?' );
|
||||
//console.log( 'req.app.locals.tokens', req.app.locals.tokens )
|
||||
//console.log( 'req.session.header', req.session.header );
|
||||
// Check if token exist or not
|
||||
req.session.header.accessrights = { app: "", data: {} }
|
||||
if( req.session.header.xpaganid == config.devnoauthxuuid && req.session.header.xauth == config.devnoauthxauth ) {
|
||||
console.log( 'isAuthenticated yes: carrefull using a bypass password give you accessrights={}' );
|
||||
} else if( req.session.header.xpaganid == "1" || !req.app.locals.tokens[ req.session.header.xpaganid ] ) {
|
||||
console.log( `isAuthenticated no : uuid=1 (value=${req.session.header.xpaganid}) or locals.tokens[uuid] empty ` );
|
||||
console.log( 'req.app.locals.tokens de xpaganid', req.app.locals.tokens[ req.session.header.xpaganid ] );
|
||||
console.log( 'list key uuid de req.app.locals.tokens', Object.keys( req.app.locals.tokens ) )
|
||||
req.session.header.xauth = "1"
|
||||
} else if( req.app.locals.tokens[ req.session.header.xpaganid ].TOKEN !== req.session.header.xauth ) {
|
||||
// console.log(req.session.header.xuuid);
|
||||
// console.log(req.session.header.xauth);
|
||||
// update tokens from file in case recently logged
|
||||
try {
|
||||
console.log( 'token not in list of token (req.app.locals.tokens) try to refresh from file' );
|
||||
req.app.locals.tokens = fs.readJsonSync( `${config.tmp}/tokens.json` );
|
||||
} catch ( err ) {
|
||||
console.log( `check isAuthenticated issue in reading ${config.tmp}/tokens.json` );
|
||||
}
|
||||
if( req.app.locals.tokens[ req.session.header.xpaganid ].TOKEN !== req.session.header.xauth ) {
|
||||
// if still does not exist then out
|
||||
console.log( 'isAuthenticated no, token outdated' );
|
||||
req.session.header.xauth = "1"
|
||||
req.session.header.xpaganid = "1"
|
||||
}
|
||||
}
|
||||
if( req.session.header.xauth == "1" ) {
|
||||
//return res.status( 403 )
|
||||
return res.status( 403 )
|
||||
.json( {
|
||||
info: [ 'forbiddenAccess' ],
|
||||
model: 'Pagans',
|
||||
moreinfo: 'isAuthenticated faill'
|
||||
} )
|
||||
} else {
|
||||
console.log( 'isAuthenticated yes' );
|
||||
if( req.app.locals.tokens[ req.session.header.xpaganid ] ) {
|
||||
//console.log( `accessright pour ${req.session.header.xpaganid}`, req.app.locals.tokens[ req.session.header.xpaganid ].ACCESSRIGHTS );
|
||||
//set header.accessrights from tokens.json
|
||||
req.session.header.accessrights = req.app.locals.tokens[ req.session.header.xpaganid ].ACCESSRIGHTS
|
||||
} else {
|
||||
// case of bypass no accessright available
|
||||
req.session.header.accessrights = {}
|
||||
}
|
||||
// Once per day, clean old token
|
||||
const currentday = moment()
|
||||
.date();
|
||||
console.log( 'test si menagedone' + currentday, !fs.existsSync( `${config.tmp}/menagedone${currentday}` ) )
|
||||
if( !fs.existsSync( `${config.tmp}/menagedone${currentday}` ) ) {
|
||||
glob.sync( `${config.tmp}/menagedone*` )
|
||||
.forEach( f => {
|
||||
fs.remove( f, ( err ) => {
|
||||
if( err ) {
|
||||
console.log( 'err remove menagedone', err )
|
||||
}
|
||||
} )
|
||||
} );
|
||||
glob.sync( `${config.tmp}/mdcreator*.log` )
|
||||
.forEach( f => {
|
||||
fs.remove( f, ( err ) => {
|
||||
if( err ) {
|
||||
console.log( 'err remove mdcreator log', err )
|
||||
}
|
||||
} )
|
||||
} );
|
||||
const newtokens = {};
|
||||
for( const k of Object.keys( req.app.locals.tokens ) ) {
|
||||
try {
|
||||
const decodedToken = jwt.decode( req.app.locals.tokens[ k ].TOKEN, config.jwtSecret );
|
||||
//console.log( moment( decodedToken.expiration ), moment() )
|
||||
//console.log( moment( decodedToken.expiration ) >= moment() )
|
||||
if( moment( decodedToken.expiration ) >= moment() ) {
|
||||
newtokens[ k ] = req.app.locals.tokens[ k ];
|
||||
}
|
||||
} catch ( err ) {
|
||||
console.log( "Check isAuthenticated cleaning token ", err );
|
||||
}
|
||||
};
|
||||
req.app.locals.tokens = newtokens;
|
||||
fs.outputJsonSync( `${config.tmp}/tokens.json`, newtokens );
|
||||
fs.writeFileSync( `${config.tmp}/menagedone${currentday}`, 'fichier semaphore to clean data each day can be deleted with no consequence', 'utf-8' );
|
||||
}
|
||||
next();
|
||||
}
|
||||
};
|
||||
module.exports = isAuthenticated;
|
6
app/middlewares/lg/headers_en.json
Normal file
6
app/middlewares/lg/headers_en.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"missingheader":"This header miss to have a valid request: {{#moreinfo}} {{.}} {{/moreinfo}}",
|
||||
"tribeiddoesnotexist":"Header xtribe: {{moreinfo}} does not exist",
|
||||
"workondoesnotexist":"Header xworkon: {{moreinfo}} does not exist",
|
||||
"forbiddenAccessright":"Pagan {{moreinfo.xpaganid}} has not access right to act {{moreinfo.action}} onto object {{moreinfo.object}} for tribe {{moreinfo.xworkon}}"
|
||||
}
|
Reference in New Issue
Block a user