UNPKG

typeorm-adapter

Version:

TypeORM adapter for Casbin

354 lines (353 loc) 13.1 kB
"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;