loopback4-authorization
Version:
ARC authorization extension for loopback-next applications.
108 lines • 5.01 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.CasbinAuthorizationProvider = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@loopback/core");
const rest_1 = require("@loopback/rest");
const casbin = tslib_1.__importStar(require("casbin"));
const keys_1 = require("../keys");
let CasbinAuthorizationProvider = class CasbinAuthorizationProvider {
constructor(getCasbinMetadata, getCasbinEnforcerConfig, allowAlwaysPath) {
this.getCasbinMetadata = getCasbinMetadata;
this.getCasbinEnforcerConfig = getCasbinEnforcerConfig;
this.allowAlwaysPath = allowAlwaysPath;
}
value() {
return (response, resource, request) => this.action(response, resource, request);
}
async action(user, resource, request) {
var _a;
let authDecision = false;
try {
// fetch decorator metadata
const metadata = await this.getCasbinMetadata();
if (request && this.checkIfAllowedAlways(request)) {
return true;
}
if (((_a = metadata === null || metadata === void 0 ? void 0 : metadata.permissions) === null || _a === void 0 ? void 0 : _a.indexOf('*')) === 0) {
// Return immediately with true, if allowed to all
// This is for publicly open routes only
return true;
}
if (!(metadata === null || metadata === void 0 ? void 0 : metadata.resource)) {
if (!metadata) {
return false;
}
throw new rest_1.HttpErrors.Unauthorized(`Resource parameter is missing in the decorator.`);
}
if (!user.id) {
throw new rest_1.HttpErrors.Unauthorized(`User not found.`);
}
const subject = this.getUserName(`${user.id}`);
const desiredPermissions = this.getDesiredPermissions(metadata);
// Fetch casbin config by invoking casbin-config-getter-provider
const casbinConfig = await this.getCasbinEnforcerConfig(user, metadata.resource, metadata.isCasbinPolicy);
let enforcer;
// If casbin config policy format is being used, create enforcer
if (metadata.isCasbinPolicy) {
enforcer = await casbin.newEnforcer(casbinConfig.model, casbinConfig.policy);
}
// In case casbin policy is coming via provider, use that to initialise enforcer
else if (casbinConfig.allowedRes) {
const policy = this.createCasbinPolicy(casbinConfig.allowedRes, subject);
const stringAdapter = new casbin.StringAdapter(policy);
enforcer = new casbin.Enforcer();
await enforcer.initWithModelAndAdapter(casbinConfig.model, stringAdapter);
}
else {
return false;
}
// Use casbin enforce method to get authorization decision
for (const permission of desiredPermissions) {
const decision = await enforcer.enforce(subject, resource, permission);
authDecision = authDecision || decision;
}
}
catch (err) {
throw new rest_1.HttpErrors.Unauthorized(err.message);
}
return authDecision;
}
// Generate the user name according to the naming convention
// in casbin policy
// A user's name would be `u${ id }`
getUserName(id) {
return `u${id}`;
}
getDesiredPermissions(metadata) {
if (metadata.permissions && metadata.permissions.length > 0) {
return metadata.permissions;
}
else {
throw new rest_1.HttpErrors.Unauthorized(`Permissions are missing in the decorator.`);
}
}
// Create casbin policy for user based on ResourcePermission data provided by extension client
createCasbinPolicy(resPermObj, subject) {
let result = '';
resPermObj.forEach(resPerm => {
const policy = `p, ${subject}, ${resPerm.resource}, ${resPerm.permission}
`;
result += policy;
});
return result;
}
checkIfAllowedAlways(req) {
let allowed = false;
allowed = !!this.allowAlwaysPath.find(path => req.path.indexOf(path) === 0);
return allowed;
}
};
exports.CasbinAuthorizationProvider = CasbinAuthorizationProvider;
exports.CasbinAuthorizationProvider = CasbinAuthorizationProvider = tslib_1.__decorate([
tslib_1.__param(0, core_1.inject.getter(keys_1.AuthorizationBindings.METADATA)),
tslib_1.__param(1, (0, core_1.inject)(keys_1.AuthorizationBindings.CASBIN_ENFORCER_CONFIG_GETTER)),
tslib_1.__param(2, (0, core_1.inject)(keys_1.AuthorizationBindings.PATHS_TO_ALLOW_ALWAYS)),
tslib_1.__metadata("design:paramtypes", [Function, Function, Array])
], CasbinAuthorizationProvider);
//# sourceMappingURL=casbin-authorization-action.provider.js.map
;