@brandazm/dynamic-permissions
Version:
A flexible and powerful permissions management system for NestJS applications with built-in security features
139 lines • 6.31 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SecurityMiddleware = void 0;
const common_1 = require("@nestjs/common");
const helmet_1 = __importDefault(require("helmet"));
const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
const config_service_1 = require("../services/config.service");
let SecurityMiddleware = class SecurityMiddleware {
constructor(configService) {
this.configService = configService;
this.config = this.configService.getSecurityConfig();
if (this.config.helmet.enabled) {
this.helmetMiddleware = (0, helmet_1.default)({
contentSecurityPolicy: this.config.helmet.contentSecurityPolicy,
crossOriginEmbedderPolicy: this.config.helmet.crossOriginEmbedderPolicy,
crossOriginOpenerPolicy: this.config.helmet.crossOriginOpenerPolicy,
crossOriginResourcePolicy: this.config.helmet.crossOriginResourcePolicy
? { policy: 'same-site' }
: false,
dnsPrefetchControl: this.config.helmet.dnsPrefetchControl,
frameguard: this.config.helmet.frameguard ? { action: 'deny' } : false,
hidePoweredBy: this.config.helmet.hidePoweredBy,
hsts: this.config.helmet.hsts
? {
maxAge: 31536000,
includeSubDomains: true,
preload: true,
}
: false,
ieNoOpen: this.config.helmet.ieNoOpen,
noSniff: this.config.helmet.noSniff,
referrerPolicy: this.config.helmet.referrerPolicy
? { policy: 'strict-origin-when-cross-origin' }
: false,
xssFilter: this.config.helmet.xssFilter,
});
}
if (this.config.rateLimit.enabled) {
this.rateLimiter = (0, express_rate_limit_1.default)({
windowMs: this.config.rateLimit.windowMs,
max: this.config.rateLimit.max,
message: 'Too many requests from this IP, please try again later',
standardHeaders: true,
legacyHeaders: false,
});
}
}
use(req, res, next) {
const chain = [];
if (this.config.helmet.enabled) {
chain.push((req, res, next) => {
this.helmetMiddleware(req, res, next);
});
}
if (this.config.rateLimit.enabled) {
chain.push((req, res, next) => {
this.rateLimiter(req, res, next);
});
}
if (this.config.cors.enabled) {
chain.push((req, res, next) => {
const origin = req.headers.origin;
if (origin && this.isAllowedOrigin(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Methods', this.config.cors.allowedMethods.join(','));
res.setHeader('Access-Control-Allow-Headers', this.config.cors.allowedHeaders.join(','));
res.setHeader('Access-Control-Expose-Headers', this.config.cors.exposedHeaders.join(','));
if (this.config.cors.credentials) {
res.setHeader('Access-Control-Allow-Credentials', 'true');
}
}
next();
});
}
if (this.config.requestValidation.validateContentType) {
chain.push((req, res, next) => {
try {
this.validateRequest(req);
next();
}
catch (error) {
next(error);
}
});
}
const executeChain = (index) => {
if (index < chain.length) {
chain[index](req, res, (error) => {
if (error) {
next(error);
}
else {
executeChain(index + 1);
}
});
}
else {
next();
}
};
executeChain(0);
}
validateRequest(req) {
if (this.config.requestValidation.requireJsonContent) {
if (['POST', 'PUT', 'PATCH'].includes(req.method)) {
const contentType = req.headers['content-type'];
if (!contentType || !contentType.includes('application/json')) {
throw new Error('Invalid Content-Type. Expected application/json');
}
}
}
const contentLength = parseInt(req.headers['content-length'] || '0', 10);
if (contentLength > this.config.requestValidation.maxBodySize) {
throw new Error('Request body too large');
}
}
isAllowedOrigin(origin) {
return (this.config.cors.allowedOrigins.includes(origin) ||
this.config.cors.allowedOrigins.includes('*'));
}
};
exports.SecurityMiddleware = SecurityMiddleware;
exports.SecurityMiddleware = SecurityMiddleware = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [config_service_1.ConfigService])
], SecurityMiddleware);
//# sourceMappingURL=security.middleware.js.map