@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
80 lines (77 loc) • 4.36 kB
JavaScript
;
var tslib_es6 = require('../../../external/tslib/tslib.es6.js');
var engine_class = require('./engine.class.js');
var decision_constant = require('../../../constant/class/authorization/metadata/decision.constant.js');
var registry_constant = require('../../../constant/class/authorization/token/registry.constant.js');
var controller_constant = require('../../../constant/decorator/api/controller.constant.js');
var effect_enum = require('../../../enum/class/authorization/effect.enum.js');
var common = require('@nestjs/common');
var resolveDefaultSubject_utility = require('../../../utility/authorization/subject/resolve-default-subject.utility.js');
var logger_utility = require('../../../utility/logger.utility.js');
const authorizationGuardLogger = logger_utility.LoggerUtility.getLogger("ApiAuthorizationGuard");
exports.ApiAuthorizationGuard = class ApiAuthorizationGuard {
policyRegistry;
authorizationEngine;
constructor(policyRegistry, authorizationEngine) {
this.policyRegistry = policyRegistry;
this.authorizationEngine = authorizationEngine;
}
async canActivate(context) {
if (!this.isControllerSecurable(context)) {
authorizationGuardLogger.debug("Controller is not marked as @ApiControllerSecurable, skipping authorization");
return true;
}
const entityConstructor = this.resolveEntityConstructor(context);
if (!entityConstructor) {
authorizationGuardLogger.debug("No entity constructor found in controller metadata, skipping authorization");
return true;
}
const action = this.resolveAction(context);
authorizationGuardLogger.verbose(`Evaluating authorization for entity "${entityConstructor.name}" action "${action}"`);
const policy = await this.policyRegistry.buildAggregatedPolicy(entityConstructor, action);
if (!policy) {
authorizationGuardLogger.debug(`No policy found for entity "${entityConstructor.name}" action "${action}", allowing access`);
return true;
}
authorizationGuardLogger.verbose(`Found policy "${policy.policyId}" with ${policy.rules.length} rules for entity "${entityConstructor.name}" action "${action}"`);
const request = context.switchToHttp().getRequest();
const subject = resolveDefaultSubject_utility.AuthorizationResolveDefaultSubject(request.user);
const decision = await this.authorizationEngine.evaluate({
action,
policy,
resource: undefined,
subject,
});
this.attachDecisionToRequest(request, decision);
if (decision.effect === effect_enum.EAuthorizationEffect.DENY) {
authorizationGuardLogger.warn(`Access denied for entity "${entityConstructor.name}" action "${action}" subject "${subject.id}"`);
throw new common.ForbiddenException("Access denied");
}
authorizationGuardLogger.verbose(`Access granted for entity "${entityConstructor.name}" action "${action}" subject "${subject.id}"`);
return true;
}
attachDecisionToRequest(request, decision) {
request.authorizationDecision = decision;
request[decision_constant.AUTHORIZATION_DECISION_METADATA_CONSTANT.REQUEST_KEY] = decision;
}
isControllerSecurable(context) {
return Boolean(Reflect.getMetadata(controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.SECURABLE_METADATA_KEY, context.getClass()));
}
resolveAction(context) {
const handlerName = context.getHandler().name;
const prefix = controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.RESERVED_METHOD_PREFIX ?? "";
if (handlerName.startsWith(prefix)) {
return handlerName.slice(prefix.length);
}
return handlerName;
}
resolveEntityConstructor(context) {
return Reflect.getMetadata(controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.ENTITY_METADATA_KEY, context.getClass());
}
};
exports.ApiAuthorizationGuard = tslib_es6.__decorate([
common.Injectable(),
tslib_es6.__param(0, common.Inject(registry_constant.AUTHORIZATION_POLICY_REGISTRY_TOKEN)),
tslib_es6.__metadata("design:paramtypes", [Object, engine_class.ApiAuthorizationEngine])
], exports.ApiAuthorizationGuard);
//# sourceMappingURL=guard.class.js.map