From 3e93ba30ecb6540832f72e39eacb2c52e046fc2e Mon Sep 17 00:00:00 2001 From: Xc Date: Fri, 17 Mar 2023 19:47:57 +0800 Subject: [PATCH 1/4] 2.6.6-dev --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 17a400b..3e068e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oak-domain", - "version": "2.6.5", + "version": "2.6.6", "author": { "name": "XuChang" }, From ee8a2ea772b5b95d35a0d0c490d52dad74a8d97b Mon Sep 17 00:00:00 2001 From: Xc Date: Mon, 20 Mar 2023 10:54:35 +0800 Subject: [PATCH 2/4] =?UTF-8?q?filter=E4=B8=AD=E5=A2=9E=E5=8A=A0=E4=BA=86g?= =?UTF-8?q?etCascadeFilter=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/filter.d.ts | 1 + lib/store/filter.js | 21 ++++++++++++++++++++- src/store/filter.ts | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/store/filter.d.ts b/lib/store/filter.d.ts index 6f7c213..4ae7028 100644 --- a/lib/store/filter.d.ts +++ b/lib/store/filter.d.ts @@ -107,3 +107,4 @@ export declare function makeTreeDescendantFilter | AsyncContext>(entity: T, context: Cxt, contained: ED[T]['Selection']['filter'], filter?: ED[T]['Selection']['filter'], dataCompare?: true): boolean | Promise; export declare function checkFilterRepel | AsyncContext>(entity: T, context: Cxt, filter1: ED[T]['Selection']['filter'], filter2: ED[T]['Selection']['filter'], dataCompare?: true): boolean | Promise; +export declare function getCascadeEntityFilter(filter: NonNullable, attr: keyof NonNullable): ED[keyof ED]['Selection']['filter']; diff --git a/lib/store/filter.js b/lib/store/filter.js index e903de7..91f3c02 100644 --- a/lib/store/filter.js +++ b/lib/store/filter.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.checkFilterRepel = exports.checkFilterContains = exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.repel = exports.contains = exports.judgeValueRelation = exports.combineFilters = exports.unionFilterSegment = exports.addFilterSegment = void 0; +exports.getCascadeEntityFilter = exports.checkFilterRepel = exports.checkFilterContains = exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.repel = exports.contains = exports.judgeValueRelation = exports.combineFilters = exports.unionFilterSegment = exports.addFilterSegment = void 0; var tslib_1 = require("tslib"); var assert_1 = tslib_1.__importDefault(require("assert")); var types_1 = require("../types"); @@ -883,3 +883,22 @@ function checkFilterRepel(entity, context, filter1, filter2, dataCompare) { return false; } exports.checkFilterRepel = checkFilterRepel; +function getCascadeEntityFilter(filter, attr) { + var filters = []; + if (filter[attr]) { + (0, assert_1.default)(typeof filter[attr] === 'object'); + filters.push(filter[attr]); + } + if (filter.$and) { + filter.$and.forEach(function (ele) { + var f2 = getCascadeEntityFilter(ele, attr); + if (f2) { + filters.push(f2); + } + }); + } + if (filters.length > 0) { + return combineFilters(filters); + } +} +exports.getCascadeEntityFilter = getCascadeEntityFilter; diff --git a/src/store/filter.ts b/src/store/filter.ts index 7750bf8..774747c 100644 --- a/src/store/filter.ts +++ b/src/store/filter.ts @@ -947,4 +947,28 @@ export function checkFilterRepel( + filter: NonNullable, + attr: keyof NonNullable +): ED[keyof ED]['Selection']['filter'] { + const filters: ED[keyof ED]['Selection']['filter'][] = []; + if (filter![attr]) { + assert(typeof filter![attr] === 'object'); + filters.push(filter![attr]); + } + if (filter.$and) { + filter.$and.forEach( + (ele: NonNullable) => { + const f2 = getCascadeEntityFilter(ele, attr); + if (f2) { + filters.push(f2) + } + } + ); + } + if (filters.length > 0) { + return combineFilters(filters); + } } \ No newline at end of file From 1328e256f502006d70ef4598a25df87a068d8c78 Mon Sep 17 00:00:00 2001 From: Xc Date: Tue, 21 Mar 2023 20:34:03 +0800 Subject: [PATCH 3/4] =?UTF-8?q?checker=E4=B8=AD=E5=AF=B9relation=E5=92=8Cr?= =?UTF-8?q?ow=E7=B1=BB=E5=9E=8B=E7=9A=84filter=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/checker.js | 47 ++++++++++++++++++++++---------------------- lib/store/filter.js | 1 + src/store/checker.ts | 26 +++++++++++------------- src/store/filter.ts | 1 + 4 files changed, 37 insertions(+), 38 deletions(-) diff --git a/lib/store/checker.js b/lib/store/checker.js index 82716cf..175871c 100644 --- a/lib/store/checker.js +++ b/lib/store/checker.js @@ -102,11 +102,11 @@ function translateCheckerInAsyncContext(checker) { }; } case 'relation': { - var relationFilter_1 = checker.relationFilter, errMsg = checker.errMsg; + var relationFilter_1 = checker.relationFilter, errMsg_2 = checker.errMsg; var fn = (function (_a, context, option) { var operation = _a.operation; return tslib_1.__awaiter(_this, void 0, void 0, function () { - var result, _b; + var result, _b, filter, action; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: @@ -123,15 +123,20 @@ function translateCheckerInAsyncContext(checker) { _c.label = 3; case 3: result = _b; - if (result) { - if (operation.action === 'create') { - console.warn("".concat(entity, "\u5BF9\u8C61\u7684create\u7C7B\u578B\u7684checker\u4E2D\uFF0C\u5B58\u5728\u65E0\u6CD5\u8F6C\u6362\u4E3A\u8868\u8FBE\u5F0F\u5F62\u5F0F\u7684\u60C5\u51B5\uFF0C\u8BF7\u5C3D\u91CF\u4F7F\u7528authDef\u683C\u5F0F\u5B9A\u4E49\u8FD9\u7C7Bchecker")); - } - else { - operation.filter = (0, filter_1.combineFilters)([operation.filter, result]); - } + if (!result) return [3 /*break*/, 5]; + filter = operation.filter, action = operation.action; + if (action === 'create') { + console.warn("".concat(entity, "\u5BF9\u8C61\u7684create\u7C7B\u578B\u7684checker\u4E2D\uFF0C\u5B58\u5728\u65E0\u6CD5\u8F6C\u6362\u4E3A\u8868\u8FBE\u5F0F\u5F62\u5F0F\u7684\u60C5\u51B5\uFF0C\u8BF7\u5C3D\u91CF\u4F7F\u7528authDef\u683C\u5F0F\u5B9A\u4E49\u8FD9\u7C7Bchecker")); + return [2 /*return*/, 0]; } - return [2 /*return*/, 0]; + (0, assert_1.default)(filter); + return [4 /*yield*/, (0, filter_1.checkFilterContains)(entity, context, result, filter, true)]; + case 4: + if (_c.sent()) { + return [2 /*return*/]; + } + throw new Exception_1.OakUserUnpermittedException(errMsg_2); + case 5: return [2 /*return*/, 0]; } }); }); @@ -185,23 +190,17 @@ function translateCheckerInSyncContext(checker) { }; } case 'row': { - var filter_3 = checker.filter, errMsg_2 = checker.errMsg; + var filter_3 = checker.filter, errMsg_3 = checker.errMsg; var fn = function (operation, context, option) { var operationFilter = operation.filter, action = operation.action; var filter2 = typeof filter_3 === 'function' ? filter_3(operation, context, option) : filter_3; (0, assert_1.default)(operationFilter); - if (['select', 'count', 'stat'].includes(action)) { - operation.filter = (0, filter_1.addFilterSegment)(operationFilter, filter2); - return 0; - } - else { - (0, assert_1.default)(!(filter2 instanceof Promise)); - if ((0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter, true)) { - return; - } - var e = new Exception_1.OakRowInconsistencyException(undefined, errMsg_2); - throw e; + (0, assert_1.default)(!(filter2 instanceof Promise)); + if ((0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter, true)) { + return; } + var e = new Exception_1.OakRowInconsistencyException(undefined, errMsg_3); + throw e; }; return { fn: fn, @@ -209,7 +208,7 @@ function translateCheckerInSyncContext(checker) { }; } case 'relation': { - var relationFilter_2 = checker.relationFilter, errMsg_3 = checker.errMsg; + var relationFilter_2 = checker.relationFilter, errMsg_4 = checker.errMsg; var fn = function (operation, context, option) { if (context.isRoot()) { return; @@ -226,7 +225,7 @@ function translateCheckerInSyncContext(checker) { if ((0, filter_1.checkFilterContains)(entity, context, result, filter, true)) { return; } - throw new Exception_1.OakUserUnpermittedException(errMsg_3); + throw new Exception_1.OakUserUnpermittedException(errMsg_4); } }; return { diff --git a/lib/store/filter.js b/lib/store/filter.js index 91f3c02..afe3793 100644 --- a/lib/store/filter.js +++ b/lib/store/filter.js @@ -845,6 +845,7 @@ function checkFilterContains(entity, context, contained, filter, dataCompare) { }]); var count = context.count(entity, { filter: filter2, + count: 1, }, { dontCollect: true, blockTrigger: true, diff --git a/src/store/checker.ts b/src/store/checker.ts index e36a5c4..9fea2c6 100644 --- a/src/store/checker.ts +++ b/src/store/checker.ts @@ -95,12 +95,16 @@ export function translateCheckerInAsyncContext< const result = typeof relationFilter === 'function' ? await relationFilter(operation, context, option) : relationFilter; if (result) { - if (operation.action === 'create') { + const { filter, action } = operation; + if (action === 'create') { console.warn(`${entity as string}对象的create类型的checker中,存在无法转换为表达式形式的情况,请尽量使用authDef格式定义这类checker`); + return 0; } - else { - operation.filter = combineFilters([operation.filter, result as ED[T]['Selection']['filter']]); + assert(filter); + if (await checkFilterContains(entity, context, result, filter, true)) { + return; } + throw new OakUserUnpermittedException(errMsg); } return 0; }) as UpdateTriggerInTxn['fn']; @@ -155,18 +159,12 @@ export function translateCheckerInSyncContext< const { filter: operationFilter, action } = operation; const filter2 = typeof filter === 'function' ? (filter as Function)(operation, context, option) : filter; assert(operationFilter); - if (['select', 'count', 'stat'].includes(action)) { - operation.filter = addFilterSegment(operationFilter, filter2); - return 0; - } - else { - assert(!(filter2 instanceof Promise)); - if (checkFilterContains(entity, context, filter2, operationFilter, true)) { - return; - } - const e = new OakRowInconsistencyException(undefined, errMsg); - throw e; + assert(!(filter2 instanceof Promise)); + if (checkFilterContains(entity, context, filter2, operationFilter, true)) { + return; } + const e = new OakRowInconsistencyException(undefined, errMsg); + throw e; }; return { fn, diff --git a/src/store/filter.ts b/src/store/filter.ts index 774747c..1b5c9d7 100644 --- a/src/store/filter.ts +++ b/src/store/filter.ts @@ -901,6 +901,7 @@ export function checkFilterContains Date: Thu, 23 Mar 2023 14:03:43 +0800 Subject: [PATCH 4/4] =?UTF-8?q?checker=E4=B8=AD=E7=B1=BB=E5=9E=8B=E4=B8=BA?= =?UTF-8?q?relation,row=E7=9A=84=E6=94=AF=E6=8C=81silent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/store/TriggerExecutor.js | 2 +- lib/store/checker.d.ts | 8 +++++++- lib/store/checker.js | 14 ++++++++++++-- src/store/TriggerExecutor.ts | 2 +- src/store/checker.ts | 14 ++++++++++++-- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/lib/store/TriggerExecutor.js b/lib/store/TriggerExecutor.js index 2ad37ef..c6a7e8f 100644 --- a/lib/store/TriggerExecutor.js +++ b/lib/store/TriggerExecutor.js @@ -33,7 +33,7 @@ var TriggerExecutor = /** @class */ (function () { TriggerExecutor.prototype.registerChecker = function (checker) { var entity = checker.entity, action = checker.action, type = checker.type, conditionalFilter = checker.conditionalFilter; var triggerName = "".concat(String(entity)).concat(action, "\u6743\u9650\u68C0\u67E5-").concat(this.counter++); - var _a = (0, checker_1.translateCheckerInAsyncContext)(checker), fn = _a.fn, when = _a.when; + var _a = (0, checker_1.translateCheckerInAsyncContext)(checker, true), fn = _a.fn, when = _a.when; var priority = type === 'data' ? Trigger_1.DATA_CHECKER_DEFAULT_PRIORITY : Trigger_1.CHECKER_DEFAULT_PRIORITY; // checker的默认优先级最低(前面的trigger可能会赋上一些相应的值) var trigger = { checkerType: type, diff --git a/lib/store/checker.d.ts b/lib/store/checker.d.ts index f385b1b..71791d7 100644 --- a/lib/store/checker.d.ts +++ b/lib/store/checker.d.ts @@ -2,7 +2,13 @@ import { AuthDefDict, Checker, EntityDict, OperateOption, SelectOption, StorageS import { EntityDict as BaseEntityDict } from '../base-app-domain'; import { AsyncContext } from "./AsyncRowStore"; import { SyncContext } from './SyncRowStore'; -export declare function translateCheckerInAsyncContext>(checker: Checker): { +/** + * + * @param checker 要翻译的checker + * @param silent 如果silent,则row和relation类型的checker只会把限制条件加到查询上,而不报错(除掉create动作) + * @returns + */ +export declare function translateCheckerInAsyncContext>(checker: Checker, silent?: boolean): { fn: Trigger['fn']; when: 'before' | 'after'; }; diff --git a/lib/store/checker.js b/lib/store/checker.js index 175871c..957b8ff 100644 --- a/lib/store/checker.js +++ b/lib/store/checker.js @@ -11,7 +11,13 @@ var string_1 = require("../utils/string"); var lodash_1 = require("../utils/lodash"); var relation_1 = require("./relation"); var uuid_1 = require("../utils/uuid"); -function translateCheckerInAsyncContext(checker) { +/** + * + * @param checker 要翻译的checker + * @param silent 如果silent,则row和relation类型的checker只会把限制条件加到查询上,而不报错(除掉create动作) + * @returns + */ +function translateCheckerInAsyncContext(checker, silent) { var _this = this; var entity = checker.entity, type = checker.type; var when = 'before'; // 现在create的relation改成提前的expression检查了,原先是先插入再后检查,性能不行,而且select也需要实现前检查 @@ -59,7 +65,7 @@ function translateCheckerInAsyncContext(checker) { _c.label = 3; case 3: filter2 = _b; - if (!['select', 'count', 'stat'].includes(action)) return [3 /*break*/, 4]; + if (!silent) return [3 /*break*/, 4]; operation.filter = (0, filter_1.addFilterSegment)(operationFilter || {}, filter2); return [2 /*return*/, 0]; case 4: return [4 /*yield*/, (0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter || {}, true)]; @@ -129,6 +135,10 @@ function translateCheckerInAsyncContext(checker) { console.warn("".concat(entity, "\u5BF9\u8C61\u7684create\u7C7B\u578B\u7684checker\u4E2D\uFF0C\u5B58\u5728\u65E0\u6CD5\u8F6C\u6362\u4E3A\u8868\u8FBE\u5F0F\u5F62\u5F0F\u7684\u60C5\u51B5\uFF0C\u8BF7\u5C3D\u91CF\u4F7F\u7528authDef\u683C\u5F0F\u5B9A\u4E49\u8FD9\u7C7Bchecker")); return [2 /*return*/, 0]; } + if (silent) { + operation.filter = (0, filter_1.addFilterSegment)(filter || {}, result); + return [2 /*return*/, 0]; + } (0, assert_1.default)(filter); return [4 /*yield*/, (0, filter_1.checkFilterContains)(entity, context, result, filter, true)]; case 4: diff --git a/src/store/TriggerExecutor.ts b/src/store/TriggerExecutor.ts index 3b7c726..c7888c2 100644 --- a/src/store/TriggerExecutor.ts +++ b/src/store/TriggerExecutor.ts @@ -49,7 +49,7 @@ export class TriggerExecutor { registerChecker>(checker: Checker): void { const { entity, action, type, conditionalFilter } = checker; const triggerName = `${String(entity)}${action}权限检查-${this.counter++}`; - const { fn, when } = translateCheckerInAsyncContext(checker); + const { fn, when } = translateCheckerInAsyncContext(checker, true); const priority = type === 'data' ? DATA_CHECKER_DEFAULT_PRIORITY : CHECKER_DEFAULT_PRIORITY; // checker的默认优先级最低(前面的trigger可能会赋上一些相应的值) const trigger = { checkerType: type, diff --git a/src/store/checker.ts b/src/store/checker.ts index 9fea2c6..2b30d91 100644 --- a/src/store/checker.ts +++ b/src/store/checker.ts @@ -14,11 +14,17 @@ import { union, uniq, difference } from '../utils/lodash'; import { judgeRelation } from './relation'; import { generateNewId } from '../utils/uuid'; +/** + * + * @param checker 要翻译的checker + * @param silent 如果silent,则row和relation类型的checker只会把限制条件加到查询上,而不报错(除掉create动作) + * @returns + */ export function translateCheckerInAsyncContext< ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext ->(checker: Checker): { +>(checker: Checker, silent?: boolean): { fn: Trigger['fn']; when: 'before' | 'after'; } { @@ -42,7 +48,7 @@ export function translateCheckerInAsyncContext< const fn = (async ({ operation }, context, option) => { const { filter: operationFilter, action } = operation; const filter2 = typeof filter === 'function' ? await (filter as Function)(operation, context, option) : filter; - if (['select', 'count', 'stat'].includes(action)) { + if (silent) { operation.filter = addFilterSegment(operationFilter || {}, filter2); return 0; } @@ -100,6 +106,10 @@ export function translateCheckerInAsyncContext< console.warn(`${entity as string}对象的create类型的checker中,存在无法转换为表达式形式的情况,请尽量使用authDef格式定义这类checker`); return 0; } + if (silent) { + operation.filter = addFilterSegment(filter || {}, result); + return 0; + } assert(filter); if (await checkFilterContains(entity, context, result, filter, true)) { return;