typeorm-adapter
Version:
TypeORM adapter for Casbin
354 lines (353 loc) • 13.1 kB
JavaScript
"use strict";
// Copyright 2018 The Casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the 'License');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const casbin_1 = require("casbin");
const casbinRule_1 = require("./casbinRule");
const typeorm_1 = require("typeorm");
const casbinMongoRule_1 = require("./casbinMongoRule");
/**
* TypeORMAdapter represents the TypeORM filtered adapter for policy storage.
*/
class TypeORMAdapter {
constructor(option, adapterConfig) {
this.filtered = false;
this.adapterConfig = adapterConfig;
if (option.connection) {
this.typeorm = option.connection;
this.option = this.typeorm.options;
}
else {
this.option = option;
}
}
isFiltered() {
return this.filtered;
}
/**
* newAdapter is the constructor.
* @param option typeorm connection option
* @param adapterConfig additional configuration options for the adapter
*/
static newAdapter(option, adapterConfig) {
return __awaiter(this, void 0, void 0, function* () {
let a;
const defaults = {
synchronize: true,
name: 'node-casbin-official',
};
if (option.connection) {
a = new TypeORMAdapter(option, adapterConfig);
}
else {
const options = option;
const entities = {
entities: [
TypeORMAdapter.getCasbinRuleType(options.type, adapterConfig),
],
};
const configuration = Object.assign(defaults, options);
a = new TypeORMAdapter(Object.assign(configuration, entities), adapterConfig);
}
yield a.open();
return a;
});
}
open() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.typeorm) {
this.typeorm = new typeorm_1.DataSource(this.option);
}
if (!this.typeorm.isInitialized) {
yield this.typeorm.initialize();
}
});
}
close() {
return __awaiter(this, void 0, void 0, function* () {
if (this.typeorm.isInitialized) {
yield this.typeorm.destroy();
}
});
}
clearTable() {
return __awaiter(this, void 0, void 0, function* () {
yield this.getRepository().clear();
});
}
loadPolicyLine(line, model) {
const result = line.ptype +
', ' +
[line.v0, line.v1, line.v2, line.v3, line.v4, line.v5, line.v6]
.filter((n) => n)
.map((n) => `"${n}"`)
.join(', ');
casbin_1.Helper.loadPolicyLine(result, model);
}
/**
* loadPolicy loads all policy rules from the storage.
*/
loadPolicy(model) {
return __awaiter(this, void 0, void 0, function* () {
const lines = yield this.getRepository().find();
for (const line of lines) {
this.loadPolicyLine(line, model);
}
});
}
// Loading policies based on filter condition
loadFilteredPolicy(model, filter) {
return __awaiter(this, void 0, void 0, function* () {
const filteredLines = yield this.getRepository().find({ where: filter });
for (const line of filteredLines) {
this.loadPolicyLine(line, model);
}
this.filtered = true;
});
}
savePolicyLine(ptype, rule) {
const line = new (this.getCasbinRuleConstructor())();
line.ptype = ptype;
if (rule.length > 0) {
line.v0 = rule[0];
}
if (rule.length > 1) {
line.v1 = rule[1];
}
if (rule.length > 2) {
line.v2 = rule[2];
}
if (rule.length > 3) {
line.v3 = rule[3];
}
if (rule.length > 4) {
line.v4 = rule[4];
}
if (rule.length > 5) {
line.v5 = rule[5];
}
if (rule.length > 6) {
line.v6 = rule[6];
}
return line;
}
/**
* savePolicy saves all policy rules to the storage.
*/
savePolicy(model) {
return __awaiter(this, void 0, void 0, function* () {
yield this.clearTable();
let astMap = model.model.get('p');
const lines = [];
// @ts-ignore
for (const [ptype, ast] of astMap) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
lines.push(line);
}
}
astMap = model.model.get('g');
if (astMap) {
// @ts-ignore
for (const [ptype, ast] of astMap) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
lines.push(line);
}
}
}
const queryRunner = this.typeorm.createQueryRunner();
yield queryRunner.connect();
yield queryRunner.startTransaction();
try {
yield queryRunner.manager.save(lines);
yield queryRunner.commitTransaction();
}
catch (err) {
yield queryRunner.rollbackTransaction();
throw err;
}
finally {
yield queryRunner.release();
}
return true;
});
}
/**
* addPolicy adds a policy rule to the storage.
*/
addPolicy(sec, ptype, rule) {
return __awaiter(this, void 0, void 0, function* () {
const line = this.savePolicyLine(ptype, rule);
yield this.getRepository().save(line);
});
}
/**
* addPolicies adds policy rules to the storage.
*/
addPolicies(sec, ptype, rules) {
return __awaiter(this, void 0, void 0, function* () {
const lines = [];
for (const rule of rules) {
const line = this.savePolicyLine(ptype, rule);
lines.push(line);
}
const queryRunner = this.typeorm.createQueryRunner();
yield queryRunner.connect();
yield queryRunner.startTransaction();
try {
yield queryRunner.manager.save(lines);
yield queryRunner.commitTransaction();
}
catch (err) {
yield queryRunner.rollbackTransaction();
throw err;
}
finally {
yield queryRunner.release();
}
});
}
updatePolicy(sec, ptype, oldRule, newRule) {
return __awaiter(this, void 0, void 0, function* () {
const { v0, v1, v2, v3, v4, v5, v6 } = this.savePolicyLine(ptype, oldRule);
const newLine = this.savePolicyLine(ptype, newRule);
const foundLine = yield this.getRepository().findOneOrFail({
where: {
ptype,
v0,
v1,
v2,
v3,
v4,
v5,
v6,
},
});
yield this.getRepository().save(Object.assign(foundLine, newLine));
});
}
/**
* removePolicy removes a policy rule from the storage.
*/
removePolicy(sec, ptype, rule) {
return __awaiter(this, void 0, void 0, function* () {
const line = this.savePolicyLine(ptype, rule);
yield this.getRepository().delete(Object.assign({}, line));
});
}
/**
* removePolicies removes policy rules from the storage.
*/
removePolicies(sec, ptype, rules) {
return __awaiter(this, void 0, void 0, function* () {
const queryRunner = this.typeorm.createQueryRunner();
const type = TypeORMAdapter.getCasbinRuleType(this.option.type, this.adapterConfig);
yield queryRunner.connect();
yield queryRunner.startTransaction();
try {
for (const rule of rules) {
const line = this.savePolicyLine(ptype, rule);
yield queryRunner.manager.delete(type, line);
}
yield queryRunner.commitTransaction();
}
catch (err) {
yield queryRunner.rollbackTransaction();
throw err;
}
finally {
yield queryRunner.release();
}
});
}
/**
* removeFilteredPolicy removes policy rules that match the filter from the storage.
*/
removeFilteredPolicy(sec, ptype, fieldIndex, ...fieldValues) {
return __awaiter(this, void 0, void 0, function* () {
const line = new (this.getCasbinRuleConstructor())();
if (ptype) {
line.ptype = ptype;
}
if (fieldIndex <= 0 && 0 < fieldIndex + fieldValues.length) {
if (fieldValues[0 - fieldIndex]) {
line.v0 = fieldValues[0 - fieldIndex];
}
}
if (fieldIndex <= 1 && 1 < fieldIndex + fieldValues.length) {
if (fieldValues[1 - fieldIndex]) {
line.v1 = fieldValues[1 - fieldIndex];
}
}
if (fieldIndex <= 2 && 2 < fieldIndex + fieldValues.length) {
if (fieldValues[2 - fieldIndex]) {
line.v2 = fieldValues[2 - fieldIndex];
}
}
if (fieldIndex <= 3 && 3 < fieldIndex + fieldValues.length) {
if (fieldValues[3 - fieldIndex]) {
line.v3 = fieldValues[3 - fieldIndex];
}
}
if (fieldIndex <= 4 && 4 < fieldIndex + fieldValues.length) {
if (fieldValues[4 - fieldIndex]) {
line.v4 = fieldValues[4 - fieldIndex];
}
}
if (fieldIndex <= 5 && 5 < fieldIndex + fieldValues.length) {
if (fieldValues[5 - fieldIndex]) {
line.v5 = fieldValues[5 - fieldIndex];
}
}
if (fieldIndex <= 6 && 6 < fieldIndex + fieldValues.length) {
if (fieldValues[6 - fieldIndex]) {
line.v6 = fieldValues[6 - fieldIndex];
}
}
yield this.getRepository().delete(Object.assign({}, line));
});
}
getCasbinRuleConstructor() {
return TypeORMAdapter.getCasbinRuleType(this.option.type, this.adapterConfig);
}
/**
* Returns either a {@link CasbinRule} or a {@link CasbinMongoRule}, depending on the type. If passed a custom entity through the adapter config it will use that entity type.
* This switch is required as the normal {@link CasbinRule} does not work when using MongoDB as a backend (due to a missing ObjectId field).
* @param type
* @param adapterConfig
*/
static getCasbinRuleType(type, adapterConfig) {
if (adapterConfig === null || adapterConfig === void 0 ? void 0 : adapterConfig.customCasbinRuleEntity) {
return adapterConfig.customCasbinRuleEntity;
}
if (type === 'mongodb') {
return casbinMongoRule_1.CasbinMongoRule;
}
return casbinRule_1.CasbinRule;
}
getRepository() {
return this.typeorm.getRepository(this.getCasbinRuleConstructor());
}
}
exports.default = TypeORMAdapter;