Kaballas's picture
initialize project structure with essential configurations and components
56b6519
// Dynamic generation of JWT Secret if not exist (different for each environnment)
var fs = require('fs');
var env = process.env.NODE_ENV || 'dev';
var config = require('../config/config.json');
if (!config[env].jwtSecret) {
config[env].jwtSecret = require('crypto').randomBytes(32).toString('hex');
var configString = JSON.stringify(config, null, 4);
fs.writeFileSync(`${__basedir}/config/config.json`, configString);
}
if (!config[env].jwtRefreshSecret) {
config[env].jwtRefreshSecret = require('crypto')
.randomBytes(32)
.toString('hex');
var configString = JSON.stringify(config, null, 4);
fs.writeFileSync(`${__basedir}/config/config.json`, configString);
}
var jwtSecret = config[env].jwtSecret;
exports.jwtSecret = jwtSecret;
var jwtRefreshSecret = config[env].jwtRefreshSecret;
exports.jwtRefreshSecret = jwtRefreshSecret;
/* ROLES LOGIC
role_name: {
allows: [],
inherits: []
}
allows: allowed permissions to access | use * for all
inherits: inherits other users "allows"
*/
const builtInRoles = {
user: {
allows: [
// Audits
'audits:create',
'audits:read',
'audits:update',
'audits:delete',
// Images
'images:create',
'images:read',
// Clients
'clients:create',
'clients:read',
'clients:update',
'clients:delete',
// Companies
'companies:create',
'companies:read',
'companies:update',
'companies:delete',
// Languages
'languages:read',
// Audit Types
'audit-types:read',
// Vulnerability Types
'vulnerability-types:read',
// Vulnerability Categories
'vulnerability-categories:read',
// Sections Data
'sections:read',
// Templates
'templates:read',
// Users
'users:read',
// Roles
'roles:read',
// Vulnerabilities
'vulnerabilities:read',
'vulnerability-updates:create',
// Custom Fields
'custom-fields:read',
// Settings
'settings:read-public',
// Classify
'classify:all',
// Check CWE Update
'check-update:all',
// Update CWE Model
'update-model:all',
],
},
admin: {
allows: '*',
},
};
try {
var customRoles = require('../config/roles.json');
} catch (error) {
var customRoles = [];
}
var roles = { ...customRoles, ...builtInRoles };
class ACL {
constructor(roles) {
if (typeof roles !== 'object') {
throw new TypeError('Expected an object as input');
}
this.roles = roles;
}
isAllowed(role, permission) {
// Check if role exists
if (!this.roles[role] && !this.roles['user']) {
return false;
}
let $role = this.roles[role] || this.roles['user']; // Default to user role in case of inexistant role
// Check if role is allowed with permission
if (
$role.allows &&
($role.allows === '*' || $role.allows.indexOf(permission) !== -1)
) {
return true;
}
// Check if there is inheritance
if (!$role.inherits || $role.inherits.length < 1) {
return false;
}
// Recursive check childs until true or false
return $role.inherits.some(role => this.isAllowed(role, permission));
}
hasPermission(permission) {
var Response = require('./httpResponse');
var jwt = require('jsonwebtoken');
return (req, res, next) => {
if (!req.cookies['token']) {
Response.Unauthorized(res, 'No token provided');
return;
}
var cookie = req.cookies['token'].split(' ');
if (cookie.length !== 2 || cookie[0] !== 'JWT') {
Response.Unauthorized(res, 'Bad token type');
return;
}
var token = cookie[1];
jwt.verify(token, jwtSecret, (err, decoded) => {
if (err) {
if (err.name === 'TokenExpiredError')
Response.Unauthorized(res, 'Expired token');
else Response.Unauthorized(res, 'Invalid token');
return;
}
if (
permission === 'validtoken' ||
this.isAllowed(decoded.role, permission)
) {
req.decodedToken = decoded;
return next();
} else {
Response.Forbidden(res, 'Insufficient privileges');
return;
}
});
};
}
buildRoles(role) {
var currentRole = this.roles[role] || this.roles['user']; // Default to user role in case of inexistant role
var result = currentRole.allows || [];
if (currentRole.inherits) {
currentRole.inherits.forEach(element => {
result = [...new Set([...result, ...this.buildRoles(element)])];
});
}
return result;
}
getRoles(role) {
var result = this.buildRoles(role);
if (result.includes('*')) return '*';
return result;
}
}
exports.acl = new ACL(roles);