oak-domain 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -381,19 +381,21 @@ var CascadeStore = /** @class */ (function (_super) {
381
381
  }));
382
382
  var dealWithSubRows = function (subRows) {
383
383
  (0, assert_1.default)(subRows.length <= entityIds.length);
384
- if (context instanceof AsyncRowStore_1.AsyncContext && subRows.length < entityIds.length && !toModi) {
384
+ if (subRows.length < entityIds.length && !toModi) {
385
385
  // 后台不允许数据不一致
386
- throw new types_1.OakRowUnexistedException([{
387
- entity: attr,
388
- selection: {
389
- data: projection2[attr],
390
- filter: {
391
- id: {
392
- $in: entityIds
386
+ if (context instanceof AsyncRowStore_1.AsyncContext || !option.ignoreForeignKeyMiss) {
387
+ throw new types_1.OakRowUnexistedException([{
388
+ entity: attr,
389
+ selection: {
390
+ data: projection2[attr],
391
+ filter: {
392
+ id: {
393
+ $in: entityIds
394
+ },
393
395
  },
394
396
  },
395
- },
396
- }]);
397
+ }]);
398
+ }
397
399
  }
398
400
  result.forEach(function (ele) {
399
401
  var _a, _b;
@@ -470,18 +472,20 @@ var CascadeStore = /** @class */ (function (_super) {
470
472
  var ids = (0, lodash_1.uniq)(result.filter(function (ele) { return !!(ele["".concat(attr, "Id")]); }).map(function (ele) { return ele["".concat(attr, "Id")]; }));
471
473
  var dealWithSubRows = function (subRows) {
472
474
  (0, assert_1.default)(subRows.length <= ids.length);
473
- if (context instanceof AsyncRowStore_1.AsyncContext && subRows.length < ids.length && !toModi) {
474
- throw new types_1.OakRowUnexistedException([{
475
- entity: relation,
476
- selection: {
477
- data: projection2[attr],
478
- filter: {
479
- id: {
480
- $in: ids
475
+ if (subRows.length < ids.length && !toModi) {
476
+ if (context instanceof AsyncRowStore_1.AsyncContext || !option.ignoreForeignKeyMiss) {
477
+ throw new types_1.OakRowUnexistedException([{
478
+ entity: relation,
479
+ selection: {
480
+ data: projection2[attr],
481
+ filter: {
482
+ id: {
483
+ $in: ids
484
+ },
481
485
  },
482
- },
483
- }
484
- }]);
486
+ }
487
+ }]);
488
+ }
485
489
  }
486
490
  result.forEach(function (ele) {
487
491
  var _a, _b, _c;
@@ -40,12 +40,12 @@ export declare class RelationAuth<ED extends EntityDict & BaseEntityDict> {
40
40
  */
41
41
  private destructOperation;
42
42
  /**
43
- * 定位到了当前用户所有可能的actionAuth,对单条actionAuth加以判断,找到可以满足当前操作的actionAuth
43
+ * 对所有满足操作要求的actionAuth加以判断,找到可以满足当前用户身份的actionAuth
44
44
  * @param entity
45
45
  * @param filter
46
46
  * @param actionAuths
47
47
  * @param context
48
- * @return string代表用户获得授权的relationId,空字符串代表通过userId赋权,false代表失败
48
+ * @return
49
49
  */
50
50
  private filterActionAuths;
51
51
  /**
@@ -58,8 +58,15 @@ export declare class RelationAuth<ED extends EntityDict & BaseEntityDict> {
58
58
  */
59
59
  private checkActionAuthInGroup;
60
60
  private checkSelection;
61
+ /**
62
+ * 此函数判定一个结点是否能通过权限检测,同时寻找该结点本身对象上成立的actionAuth,用于本结点子孙结点的快速检测
63
+ * 如果结点因其deduce的对象通过了检测,其被推断对象的actionAuth无法用于更低对象的权限检测
64
+ * @param node
65
+ * @param context
66
+ * @returns
67
+ */
61
68
  private findActionAuthsOnNode;
62
- private checkOperationTree;
69
+ private checkOperationTree2;
63
70
  private checkOperation;
64
71
  /**
65
72
  * 检查一个operation是否能被通过权限测试
@@ -7,7 +7,6 @@ var types_1 = require("../types");
7
7
  var AsyncRowStore_1 = require("./AsyncRowStore");
8
8
  var filter_1 = require("./filter");
9
9
  var relation_1 = require("./relation");
10
- var SyncRowStore_1 = require("./SyncRowStore");
11
10
  var action_1 = require("../actions/action");
12
11
  var lodash_1 = require("../utils/lodash");
13
12
  var env_1 = require("../compiler/env");
@@ -217,10 +216,11 @@ var RelationAuth = /** @class */ (function () {
217
216
  var getRecursiveDeducedFilters_1 = function (deduceEntity, deduceFilter) {
218
217
  var excludeActions = action_1.readOnlyActions.concat([ /* 'create', 'remove' */]);
219
218
  var updateActions = _this.schema[deduceEntity].actions.filter(function (a) { return !excludeActions.includes(a); });
220
- if (!RelationAuth.SPECIAL_ENTITIES.includes(deduceEntity)) {
221
- return _this.getDeducedEntityFilters(deduceEntity, deduceFilter, actions[0] === 'select' ? actions : updateActions, context);
219
+ /* if (!RelationAuth.SPECIAL_ENTITIES.includes(deduceEntity as string)) {
220
+ return this.getDeducedEntityFilters(deduceEntity, deduceFilter, actions[0] === 'select' ? actions : updateActions, context);
222
221
  }
223
- return [];
222
+ return []; */
223
+ return _this.getDeducedEntityFilters(deduceEntity, deduceFilter, actions[0] === 'select' ? actions : updateActions, context);
224
224
  };
225
225
  if (deduceEntity && deduceFilter) {
226
226
  var deducedSelections = getRecursiveDeducedFilters_1(deduceEntity, deduceFilter);
@@ -467,15 +467,15 @@ var RelationAuth = /** @class */ (function () {
467
467
  return destructInner(entity2, (0, lodash_1.cloneDeep)(operation2));
468
468
  };
469
469
  /**
470
- * 定位到了当前用户所有可能的actionAuth,对单条actionAuth加以判断,找到可以满足当前操作的actionAuth
470
+ * 对所有满足操作要求的actionAuth加以判断,找到可以满足当前用户身份的actionAuth
471
471
  * @param entity
472
472
  * @param filter
473
473
  * @param actionAuths
474
474
  * @param context
475
- * @return string代表用户获得授权的relationId,空字符串代表通过userId赋权,false代表失败
475
+ * @return
476
476
  */
477
- RelationAuth.prototype.filterActionAuths = function (entity, filter, actionAuths, context, actions) {
478
- return actionAuths.map(function (ele) {
477
+ RelationAuth.prototype.filterActionAuths = function (entity, filter, actionAuths, context) {
478
+ var result = actionAuths.map(function (ele) {
479
479
  var paths = ele.paths, relation = ele.relation, relationId = ele.relationId;
480
480
  // 在cache中,可能出现relation外键指向的对象为null的情况,要容错
481
481
  if (relationId) {
@@ -532,6 +532,10 @@ var RelationAuth = /** @class */ (function () {
532
532
  return ele;
533
533
  }
534
534
  });
535
+ if (result.find(function (ele) { return ele instanceof Promise; })) {
536
+ return Promise.all(result).then(function (r2) { return r2.filter(function (ele) { return !!ele; }); });
537
+ }
538
+ return result.filter(function (ele) { return !!ele; });
535
539
  };
536
540
  /**
537
541
  * 对于有些特殊的查询(带很多$or的查询,多发生在系统级别),单个actionAuth无法满足,需要共同加以判定
@@ -648,7 +652,7 @@ var RelationAuth = /** @class */ (function () {
648
652
  }
649
653
  ]
650
654
  }
651
- }, { dontCollect: true });
655
+ }, { dontCollect: true, ignoreForeignKeyMiss: true });
652
656
  /**
653
657
  * 返回的结果中,第一层为leafNode,必须全通过,第二层为单个leafNode上的deduce,通过一个就可以
654
658
  * @param result
@@ -690,169 +694,152 @@ var RelationAuth = /** @class */ (function () {
690
694
  }
691
695
  return checkDeducedLeafSelections(deducedLeafSelections);
692
696
  };
697
+ /**
698
+ * 此函数判定一个结点是否能通过权限检测,同时寻找该结点本身对象上成立的actionAuth,用于本结点子孙结点的快速检测
699
+ * 如果结点因其deduce的对象通过了检测,其被推断对象的actionAuth无法用于更低对象的权限检测
700
+ * @param node
701
+ * @param context
702
+ * @returns
703
+ */
693
704
  RelationAuth.prototype.findActionAuthsOnNode = function (node, context) {
694
705
  var _this = this;
695
706
  var entity = node.entity, filter = node.filter, action = node.action, userRelations = node.userRelations;
696
- if (RelationAuth.SPECIAL_ENTITIES.includes(entity)) {
697
- // 特殊对象不用查询
698
- return [];
699
- }
700
707
  var deducedEntityFilters2 = this.getDeducedEntityFilters(entity, filter, [action], context);
708
+ /**
709
+ * 搜索判定是否允许自建对象,自建的条件是 path = '',destEntity === entity
710
+ * @param actionAuths
711
+ * @returns
712
+ */
713
+ var findOwnCreateUserRelation = function (actionAuths) {
714
+ if (userRelations && userRelations.length > 0) {
715
+ (0, assert_1.default)(action === 'create');
716
+ var ars = actionAuths.filter(function (ar) { return !!userRelations.find(function (ur) { return ur.relationId === ar.relationId; }) && ar.paths.includes('') && ar.destEntity === entity; });
717
+ if (ars.length > 0) {
718
+ return ars;
719
+ }
720
+ }
721
+ };
722
+ var actionAuthOnEntities = [];
701
723
  var dealWithDeducedEntityFilters = function (deducedEntityFilters) {
702
- var allEntities = deducedEntityFilters.map(function (ele) { return ele.entity; });
703
- var allActions = (0, lodash_1.uniq)(deducedEntityFilters.map(function (ele) { return ele.actions; }).flat());
704
- var actionAuths = context.select('actionAuth', {
705
- data: {
706
- id: 1,
707
- paths: 1,
708
- destEntity: 1,
709
- deActions: 1,
710
- relation: {
724
+ var specialEntities = deducedEntityFilters.filter(function (ele) { return RelationAuth.SPECIAL_ENTITIES.includes(ele.entity); });
725
+ var unspecicalEntities = deducedEntityFilters.filter(function (ele) { return !RelationAuth.SPECIAL_ENTITIES.includes(ele.entity); });
726
+ var result = [];
727
+ if (specialEntities.length > 0) {
728
+ // 对special对象,直接判定create应该问题不大,否则写起来太烦琐
729
+ result.push.apply(result, tslib_1.__spreadArray([], tslib_1.__read(specialEntities.map(function (ele) { return _this.checkOperateSpecialEntities2(ele.entity, 'create', ele.filter, context); })), false));
730
+ }
731
+ if (unspecicalEntities.length > 0) {
732
+ var allEntities = unspecicalEntities.map(function (ele) { return ele.entity; });
733
+ var allActions = (0, lodash_1.uniq)(unspecicalEntities.map(function (ele) { return ele.actions; }).flat());
734
+ var actionAuths2 = context.select('actionAuth', {
735
+ data: {
711
736
  id: 1,
712
- userRelation$relation: {
713
- $entity: 'userRelation',
714
- data: {
715
- id: 1,
716
- entity: 1,
717
- entityId: 1,
718
- },
719
- filter: {
720
- userId: context.getCurrentUserId(),
737
+ paths: 1,
738
+ destEntity: 1,
739
+ deActions: 1,
740
+ relation: {
741
+ id: 1,
742
+ userRelation$relation: {
743
+ $entity: 'userRelation',
744
+ data: {
745
+ id: 1,
746
+ entity: 1,
747
+ entityId: 1,
748
+ },
749
+ filter: {
750
+ userId: context.getCurrentUserId(),
751
+ },
721
752
  },
722
753
  },
723
754
  },
724
- },
725
- filter: {
726
- destEntity: {
727
- $in: allEntities,
728
- },
729
- deActions: {
730
- $overlaps: allActions,
731
- },
732
- }
733
- }, { dontCollect: true });
734
- var getActionAuths = function (result) {
735
- var aas = [];
736
- result.forEach(function (ele) { return ele.forEach(function (ele2) {
737
- if (!!ele2) {
738
- aas.push(ele2);
739
- }
740
- }); });
741
- return aas;
742
- };
743
- /**
744
- * 搜索判定是否允许自建对象,自建的条件是 path = '',destEntity === entity
745
- * @param actionAuths
746
- * @returns
747
- */
748
- var findOwnCreateUserRelation = function (actionAuths) {
749
- if (userRelations) {
750
- (0, assert_1.default)(action === 'create');
751
- var ars = actionAuths.filter(function (ar) { return !!userRelations.find(function (ur) { return ur.relationId === ar.relationId; }) && ar.paths.includes('') && ar.destEntity === entity; });
752
- if (ars.length > 0) {
753
- return ars;
755
+ filter: {
756
+ destEntity: {
757
+ $in: allEntities,
758
+ },
759
+ deActions: {
760
+ $overlaps: allActions,
761
+ },
754
762
  }
755
- }
756
- };
757
- if (actionAuths instanceof Promise) {
758
- return actionAuths.then(function (ars) {
759
- var created = findOwnCreateUserRelation(ars);
763
+ }, { dontCollect: true, ignoreForeignKeyMiss: true });
764
+ var checkActionAuths_1 = function (actionAuths) {
765
+ var created = findOwnCreateUserRelation(actionAuths);
760
766
  if (created) {
761
- return created;
767
+ actionAuthOnEntities.push.apply(actionAuthOnEntities, tslib_1.__spreadArray([], tslib_1.__read(created), false));
768
+ return true;
762
769
  }
763
- return Promise.all(deducedEntityFilters.map(function (ele) {
764
- var ars2 = ars.filter(function (ele2) { return ele2.destEntity === ele.entity && (0, lodash_1.intersection)(ele2.deActions, ele.actions).length > 0; } // 这里只要overlap就可以了
770
+ var result = deducedEntityFilters.map(function (ele) {
771
+ var ars2 = actionAuths.filter(function (ele2) { return ele2.destEntity === ele.entity && (0, lodash_1.intersection)(ele2.deActions, ele.actions).length > 0; } // 这里只要overlap就可以了
765
772
  );
766
- return Promise.all(_this.filterActionAuths(ele.entity, ele.filter, ars2, context, ele.actions));
767
- })).then(function (result) { return getActionAuths(result); });
773
+ var ars3 = _this.filterActionAuths(ele.entity, ele.filter, ars2, context);
774
+ var checkFilteredArs = function (actionAuths2) {
775
+ if (actionAuths2.length > 0) {
776
+ if (ele.entity === entity) {
777
+ actionAuthOnEntities.push.apply(actionAuthOnEntities, tslib_1.__spreadArray([], tslib_1.__read(actionAuths2), false));
778
+ }
779
+ return true;
780
+ }
781
+ return false;
782
+ };
783
+ if (ars3 instanceof Promise) {
784
+ return ars3.then(function (ars4) { return checkFilteredArs(ars4); });
785
+ }
786
+ return checkFilteredArs(ars3);
787
+ });
788
+ if (result.find(function (ele) { return ele instanceof Promise; })) {
789
+ return Promise.all(result).then(function (r2) { return r2.includes(true); });
790
+ }
791
+ return result.includes(true);
792
+ };
793
+ if (actionAuths2 instanceof Promise) {
794
+ result.push(actionAuths2.then(function (ars2) { return checkActionAuths_1(ars2); }));
795
+ }
796
+ else {
797
+ result.push(checkActionAuths_1(actionAuths2));
798
+ }
799
+ }
800
+ if (result.find(function (ele) { return ele instanceof Promise; })) {
801
+ return Promise.all(result).then(function (r2) {
802
+ // r2中只有一个通过就能通过
803
+ if (r2.includes(true)) {
804
+ return actionAuthOnEntities;
805
+ }
806
+ return false;
768
807
  });
769
808
  }
770
- (0, assert_1.default)(context instanceof SyncRowStore_1.SyncContext);
771
- var created = findOwnCreateUserRelation(actionAuths);
772
- if (created) {
773
- return created;
809
+ if (result.includes(true)) {
810
+ return actionAuthOnEntities;
774
811
  }
775
- return getActionAuths(deducedEntityFilters.map(function (ele) {
776
- var ars2 = actionAuths.filter(function (ele2) { return ele2.destEntity === ele.entity && (0, lodash_1.intersection)(ele2.deActions, ele.actions).length > 0; } // 这里只要overlap就可以了
777
- );
778
- return _this.filterActionAuths(ele.entity, ele.filter, ars2, context, ele.actions);
779
- }));
812
+ return false;
780
813
  };
781
814
  if (deducedEntityFilters2 instanceof Promise) {
782
815
  return deducedEntityFilters2.then(function (def2) { return dealWithDeducedEntityFilters(def2); });
783
816
  }
784
817
  return dealWithDeducedEntityFilters(deducedEntityFilters2);
785
818
  };
786
- RelationAuth.prototype.checkOperationTree = function (tree, context) {
819
+ RelationAuth.prototype.checkOperationTree2 = function (tree, context) {
787
820
  var _this = this;
788
- var actionAuths2 = this.findActionAuthsOnNode(tree, context);
789
- var checkChildNode = function (actionAuths, node) {
790
- var checkChildNodeInner = function (legalAuths) {
791
- // 因为如果children是数组的话,会把数组中所有的action并起来查询,所以在这里还要再确认一次
792
- var realLegalPaths = legalAuths.filter(function (ele) {
793
- if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
794
- return true;
795
- }
796
- // 有一种例外情况,是在tree的根结点findActionAuthsOnNode时,deduce出了另外一个对象的权限,此时肯定可以通过,但不能再使用这条路径对children进行进一步判断了
797
- if (node === tree) {
798
- return true;
799
- }
800
- return false;
801
- });
802
- var checkChildren = function () {
803
- var children = node.children;
804
- var childPath = Object.keys(children);
805
- if (childPath.length === 0) {
806
- return true;
807
- }
808
- var selfLegalPaths = realLegalPaths.filter(function (ele) {
809
- if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
821
+ var checkNode = function (node, actionAuths) {
822
+ var checkChildren = function (legalPaths) {
823
+ var children = node.children;
824
+ var childPath = Object.keys(children);
825
+ if (childPath.length === 0) {
826
+ return true;
827
+ }
828
+ var childResult = childPath.map(function (childPath) {
829
+ var child = children[childPath];
830
+ var childEntity = child instanceof Array ? child[0].entity : child.entity;
831
+ // 这里如果该子结点能deduce到父,则直接通过
832
+ if (_this.authDeduceRelationMap[childEntity]) {
833
+ (0, assert_1.default)(_this.authDeduceRelationMap[childEntity] === 'entity');
834
+ var rel = (0, relation_1.judgeRelation)(_this.schema, childEntity, childPath);
835
+ if (rel === 2) {
810
836
  return true;
811
837
  }
812
- return false;
813
- });
814
- // assert(selfLegalPaths.length > 0, `对象${node.entity as string}的权限检查是用deduce的对象通过的,无法再进一步对子对象加以判断`);
815
- var childResult = childPath.map(function (childPath) {
816
- var child = children[childPath];
817
- var childEntity = child instanceof Array ? child[0].entity : child.entity;
818
- // 这里如果该子结点能deduce到父,则直接通过
819
- if (_this.authDeduceRelationMap[childEntity]) {
820
- (0, assert_1.default)(_this.authDeduceRelationMap[childEntity] === 'entity');
821
- var rel = (0, relation_1.judgeRelation)(_this.schema, childEntity, childPath);
822
- if (rel === 2) {
823
- return true;
824
- }
825
- }
826
- var pathToParent = childPath.endsWith('$entity') ? node.entity : childPath.split('$')[1];
827
- if (child instanceof Array) {
828
- var childActions_1 = child.map(function (ele) { return ele.action; });
829
- var childLegalAuths_1 = selfLegalPaths.map(function (ele) {
830
- var paths = ele.paths, relationId = ele.relationId;
831
- var paths2 = paths.map(function (path) { return path ? "".concat(pathToParent, ".").concat(path) : pathToParent; });
832
- return context.select('actionAuth', {
833
- data: {
834
- id: 1,
835
- },
836
- filter: {
837
- paths: {
838
- $overlaps: paths2,
839
- },
840
- destEntity: childEntity,
841
- deActions: {
842
- $overlaps: childActions_1,
843
- },
844
- relationId: relationId || {
845
- $exists: false,
846
- },
847
- }
848
- }, { dontCollect: true });
849
- }).flat();
850
- if (childLegalAuths_1[0] instanceof Promise) {
851
- return Promise.all(childLegalAuths_1).then(function (clas) { return child.map(function (c) { return checkChildNode(clas, c); }); });
852
- }
853
- return child.map(function (c) { return checkChildNode(childLegalAuths_1, c); });
854
- }
855
- var childLegalAuths = realLegalPaths.map(function (ele) {
838
+ }
839
+ var pathToParent = childPath.endsWith('$entity') ? node.entity : childPath.split('$')[1];
840
+ if (child instanceof Array) {
841
+ var childActions_1 = child.map(function (ele) { return ele.action; });
842
+ var childLegalAuths_1 = legalPaths.map(function (ele) {
856
843
  var paths = ele.paths, relationId = ele.relationId;
857
844
  var paths2 = paths.map(function (path) { return path ? "".concat(pathToParent, ".").concat(path) : pathToParent; });
858
845
  return context.select('actionAuth', {
@@ -865,7 +852,7 @@ var RelationAuth = /** @class */ (function () {
865
852
  },
866
853
  destEntity: childEntity,
867
854
  deActions: {
868
- $overlaps: child.action,
855
+ $overlaps: childActions_1,
869
856
  },
870
857
  relationId: relationId || {
871
858
  $exists: false,
@@ -873,32 +860,224 @@ var RelationAuth = /** @class */ (function () {
873
860
  }
874
861
  }, { dontCollect: true });
875
862
  }).flat();
876
- if (childLegalAuths[0] instanceof Promise) {
877
- return Promise.all(childLegalAuths).then(function (clas) { return checkChildNode(clas.flat(), child); });
863
+ if (childLegalAuths_1[0] instanceof Promise) {
864
+ return Promise.all(childLegalAuths_1).then(function (clas) { return child.map(function (c) { return checkNode(c, clas); }); });
878
865
  }
879
- return checkChildNode(childLegalAuths, child);
866
+ return child.map(function (c) { return checkNode(c, childLegalAuths_1); });
867
+ }
868
+ var childLegalAuths = legalPaths.map(function (ele) {
869
+ var paths = ele.paths, relationId = ele.relationId;
870
+ var paths2 = paths.map(function (path) { return path ? "".concat(pathToParent, ".").concat(path) : pathToParent; });
871
+ return context.select('actionAuth', {
872
+ data: {
873
+ id: 1,
874
+ },
875
+ filter: {
876
+ paths: {
877
+ $overlaps: paths2,
878
+ },
879
+ destEntity: childEntity,
880
+ deActions: {
881
+ $overlaps: child.action,
882
+ },
883
+ relationId: relationId || {
884
+ $exists: false,
885
+ },
886
+ }
887
+ }, { dontCollect: true });
880
888
  }).flat();
889
+ if (childLegalAuths[0] instanceof Promise) {
890
+ return Promise.all(childLegalAuths).then(function (clas) { return checkNode(child, clas.flat()); });
891
+ }
892
+ return checkNode(child, childLegalAuths);
893
+ }).flat();
894
+ if (childResult[0] instanceof Promise) {
895
+ return Promise.all(childResult).then(function (r) { return !r.includes(false); });
896
+ }
897
+ return !childResult.includes(false);
898
+ };
899
+ // 先根据parent传下来的合法auths来搜寻,只需要查找actionAuth,降低开销
900
+ // 这里有可能父结点根据actionAuths能通过,但子结点需要重新搜索父结点上的新actionAuths才能通过吗?应该不存在这种情况。 by Xc 20230824
901
+ if (actionAuths && actionAuths.length > 0) {
902
+ return checkChildren(actionAuths);
903
+ }
904
+ // 没有能根据父亲传下来的actionAuth判定,只能自己找
905
+ var result = _this.findActionAuthsOnNode(node, context);
906
+ var checkResult = function (result2) {
907
+ if (result2 === false) {
908
+ return false;
909
+ }
910
+ // 如果是对user对象操作通过,需要增添一条虚假的的actionAuth
911
+ if (node.entity === 'user') {
912
+ result2.push({
913
+ id: 'temp',
914
+ paths: [''],
915
+ $$createAt$$: 1,
916
+ $$updateAt$$: 1,
917
+ $$seq$$: 'temp',
918
+ destEntity: 'user',
919
+ deActions: [node.action],
920
+ });
921
+ }
922
+ return checkChildren(result2);
923
+ };
924
+ if (result instanceof Promise) {
925
+ return result.then(function (r2) { return checkResult(r2); });
926
+ }
927
+ return checkResult(result);
928
+ };
929
+ return checkNode(tree);
930
+ };
931
+ /* private checkOperationTree<Cxt extends AsyncContext<ED> | SyncContext<ED>>(tree: OperationTree<ED>, context: Cxt) {
932
+ const actionAuths2 = this.findActionAuthsOnNode(tree, context);
933
+
934
+ const checkChildNode = (actionAuths: ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema'][]>, node: OperationTree<ED>): boolean | Promise<boolean> => {
935
+ const checkChildNodeInner = (legalAuths: ED['actionAuth']['Schema'][]) => {
936
+ // 因为如果children是数组的话,会把数组中所有的action并起来查询,所以在这里还要再确认一次
937
+
938
+ const realLegalPaths = legalAuths.filter(
939
+ (ele) => {
940
+ if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
941
+ return true;
942
+ }
943
+ // 有一种例外情况,是在tree的根结点findActionAuthsOnNode时,deduce出了另外一个对象的权限,此时肯定可以通过,但不能再使用这条路径对children进行进一步判断了
944
+ if (node === tree) {
945
+ return true;
946
+ }
947
+ return false;
948
+ }
949
+ );
950
+ const checkChildren = () => {
951
+ const { children } = node;
952
+ const childPath = Object.keys(children);
953
+ if (childPath.length === 0) {
954
+ return true;
955
+ }
956
+
957
+ const selfLegalPaths = realLegalPaths.filter(
958
+ (ele) => {
959
+ if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
960
+ return true;
961
+ }
962
+ return false;
963
+ }
964
+ );
965
+ // assert(selfLegalPaths.length > 0, `对象${node.entity as string}的权限检查是用deduce的对象通过的,无法再进一步对子对象加以判断`);
966
+ const childResult = childPath.map(
967
+ (childPath) => {
968
+ const child = children[childPath];
969
+ const childEntity = child instanceof Array ? child[0].entity : child.entity;
970
+ // 这里如果该子结点能deduce到父,则直接通过
971
+ if (this.authDeduceRelationMap[childEntity]) {
972
+ assert(this.authDeduceRelationMap[childEntity] === 'entity');
973
+ const rel = judgeRelation(this.schema, childEntity, childPath);
974
+ if (rel === 2) {
975
+ return true;
976
+ }
977
+ }
978
+
979
+ const pathToParent = childPath.endsWith('$entity') ? node.entity as string : childPath.split('$')[1];
980
+ if (child instanceof Array) {
981
+ const childActions = child.map(ele => ele.action);
982
+ const childLegalAuths = selfLegalPaths.map(
983
+ (ele) => {
984
+ const { paths, relationId } = ele;
985
+ const paths2 = paths.map(
986
+ (path) => path ? `${pathToParent}.${path}` : pathToParent
987
+ );
988
+ return context.select('actionAuth', {
989
+ data: {
990
+ id: 1,
991
+ },
992
+ filter: {
993
+ paths: {
994
+ $overlaps: paths2,
995
+ },
996
+ destEntity: childEntity as string,
997
+ deActions: {
998
+ $overlaps: childActions,
999
+ },
1000
+ relationId: relationId || {
1001
+ $exists: false,
1002
+ },
1003
+ }
1004
+ }, { dontCollect: true })
1005
+ }
1006
+ ).flat() as ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema']>[];
1007
+ if (childLegalAuths[0] instanceof Promise) {
1008
+ return Promise.all(childLegalAuths).then(
1009
+ (clas) => child.map(
1010
+ (c) => checkChildNode(clas, c)
1011
+ )
1012
+ )
1013
+ }
1014
+ return child.map(
1015
+ (c) => checkChildNode(childLegalAuths as ED['actionAuth']['Schema'][], c)
1016
+ );
1017
+ }
1018
+
1019
+ const childLegalAuths = realLegalPaths.map(
1020
+ (ele) => {
1021
+ const { paths, relationId } = ele;
1022
+ const paths2 = paths.map(
1023
+ (path) => path ? `${pathToParent}.${path}` : pathToParent
1024
+ );
1025
+ return context.select('actionAuth', {
1026
+ data: {
1027
+ id: 1,
1028
+ },
1029
+ filter: {
1030
+ paths: {
1031
+ $overlaps: paths2,
1032
+ },
1033
+ destEntity: childEntity as string,
1034
+ deActions: {
1035
+ $overlaps: child.action,
1036
+ },
1037
+ relationId: relationId || {
1038
+ $exists: false,
1039
+ },
1040
+ }
1041
+ }, { dontCollect: true })
1042
+ }
1043
+ ).flat() as ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema']>[];
1044
+
1045
+ if (childLegalAuths[0] instanceof Promise) {
1046
+ return Promise.all(childLegalAuths).then(
1047
+ (clas) => checkChildNode(clas.flat(), child)
1048
+ );
1049
+ }
1050
+ return checkChildNode(childLegalAuths as ED['actionAuth']['Schema'][], child);
1051
+ }
1052
+ ).flat();
1053
+
881
1054
  if (childResult[0] instanceof Promise) {
882
- return Promise.all(childResult).then(function (r) { return !r.includes(false); });
1055
+ return Promise.all(childResult).then(
1056
+ (r) => !r.includes(false)
1057
+ );
883
1058
  }
884
1059
  return !childResult.includes(false);
885
1060
  };
886
- if (RelationAuth.SPECIAL_ENTITIES.includes(node.entity)) {
1061
+
1062
+ if (RelationAuth.SPECIAL_ENTITIES.includes(node.entity as string)) {
887
1063
  // 特殊entity走特别的路径判断
888
- var result = _this.checkOperateSpecialEntities2(node.entity, node.action, node.filter, context);
1064
+ const result = this.checkOperateSpecialEntities2(node.entity, node.action, node.filter, context);
1065
+
889
1066
  if (result instanceof Promise) {
890
- return result.then(function (r) {
891
- if (r) {
892
- return checkChildren();
1067
+ return result.then(
1068
+ (r) => {
1069
+ if (r) {
1070
+ return checkChildren();
1071
+ }
1072
+ return false;
893
1073
  }
894
- return false;
895
- });
1074
+ );
896
1075
  }
897
1076
  if (result) {
898
1077
  if (node.entity === 'user') {
899
1078
  // 如果当前是对user对象操作,需要加上一个指向它自身的actionAuth,否则剩下的子对象会判定不过
900
1079
  // user的操作权限由应用自己决定,如果user的操作最终过不去,这里放过也没关系
901
- (0, assert_1.default)(node === tree && realLegalPaths.length === 0); // user不可能是非根结点
1080
+ assert(node === tree && realLegalPaths.length === 0); // user不可能是非根结点
902
1081
  realLegalPaths.push({
903
1082
  id: 'temp',
904
1083
  paths: [''],
@@ -916,6 +1095,7 @@ var RelationAuth = /** @class */ (function () {
916
1095
  }
917
1096
  return false;
918
1097
  }
1098
+
919
1099
  if (realLegalPaths.length === 0) {
920
1100
  if (node === tree) {
921
1101
  if (process.env.NODE_ENV === 'development') {
@@ -924,17 +1104,22 @@ var RelationAuth = /** @class */ (function () {
924
1104
  return false;
925
1105
  }
926
1106
  // 如果不是tree的根结点,相对路径上的actionAuth找不到,还可以尝试从自身的filter去重试其它路径
927
- return _this.checkOperationTree(node, context);
1107
+ return this.checkOperationTree(node, context);
928
1108
  }
1109
+
929
1110
  return checkChildren();
930
1111
  };
1112
+
931
1113
  if (actionAuths instanceof Promise) {
932
- return actionAuths.then(function (aars) { return checkChildNodeInner(aars); });
1114
+ return actionAuths.then(
1115
+ (aars) => checkChildNodeInner(aars)
1116
+ );
933
1117
  }
934
1118
  return checkChildNodeInner(actionAuths);
935
1119
  };
1120
+
936
1121
  return checkChildNode(actionAuths2, tree);
937
- };
1122
+ } */
938
1123
  RelationAuth.prototype.checkOperation = function (entity, operation, context) {
939
1124
  var action = operation.action, filter = operation.filter, data = operation.data;
940
1125
  if (action === 'create' && this.createFreeEntities.includes(entity)) {
@@ -954,7 +1139,7 @@ var RelationAuth = /** @class */ (function () {
954
1139
  return false;
955
1140
  }
956
1141
  var updateTree = this.destructOperation(entity, operation, userId);
957
- return this.checkOperationTree(updateTree, context);
1142
+ return this.checkOperationTree2(updateTree, context);
958
1143
  };
959
1144
  /**
960
1145
  * 检查一个operation是否能被通过权限测试
@@ -111,7 +111,7 @@ function addFilterSegment(entity, schema) {
111
111
  addSingleAttr(attr, combined);
112
112
  }
113
113
  var _loop_1 = function (attr) {
114
- var _a;
114
+ var _a, _b;
115
115
  var filters2 = oneToManyFilters[attr].map(function (ele) { return ele[1]; });
116
116
  var sqpOps = filters2.map(function (ele) { return ele['#sqp'] || 'in'; });
117
117
  // 只有全部是同一个子查询算子才能实施合并
@@ -124,10 +124,21 @@ function addFilterSegment(entity, schema) {
124
124
  });
125
125
  }
126
126
  else {
127
- var unioned = unionFilterSegment.apply(void 0, tslib_1.__spreadArray([oneToManyFilters[attr][0][0], schema], tslib_1.__read(filters2), false));
128
- addSingleAttr(attr, Object.assign(unioned, (_a = {},
129
- _a['#sqp'] = sqpOps[0],
130
- _a)));
127
+ var sqpOp = sqpOps[0];
128
+ if (sqpOp === 'not in') {
129
+ // not in 在此变成or查询
130
+ var unioned = unionFilterSegment.apply(void 0, tslib_1.__spreadArray([oneToManyFilters[attr][0][0], schema], tslib_1.__read(filters2), false));
131
+ addSingleAttr(attr, Object.assign(unioned, (_a = {},
132
+ _a['#sqp'] = sqpOp,
133
+ _a)));
134
+ }
135
+ else {
136
+ (0, assert_1.default)(sqpOp === 'in'); // all 和 not all暂时不会出现
137
+ var combined = addFilterSegment.apply(void 0, tslib_1.__spreadArray([oneToManyFilters[attr][0][0], schema], tslib_1.__read(filters2), false));
138
+ addSingleAttr(attr, Object.assign(combined, (_b = {},
139
+ _b['#sqp'] = sqpOp,
140
+ _b)));
141
+ }
131
142
  }
132
143
  };
133
144
  for (var attr in oneToManyFilters) {
@@ -268,12 +279,12 @@ function unionFilterSegment(entity, schema) {
268
279
  * @returns
269
280
  */
270
281
  var tryMergeFilters = function (f1, f2, justTry) {
271
- var e_3, _a, e_4, _b, e_5, _c, e_6, _d, e_7, _e, e_8, _f, e_9, _g, _h, _j, _k, _l, _m;
282
+ var e_3, _a, e_4, _b, e_5, _c, e_6, _d, e_7, _e, e_8, _f, e_9, _g, _h, _j, _k, _l, _m, _o, _p;
272
283
  var pcaResult = possibleCombiningAttrs(f1, f2);
273
284
  if (!pcaResult) {
274
285
  return false;
275
286
  }
276
- var _o = tslib_1.__read(pcaResult, 2), pca1 = _o[0], pca2 = _o[1];
287
+ var _q = tslib_1.__read(pcaResult, 2), pca1 = _q[0], pca2 = _q[1];
277
288
  if (pca1 === '$or' && pca2 === '$or') {
278
289
  try {
279
290
  // 如果双方都是or,有可能可以交叉合并,如:
@@ -303,12 +314,12 @@ function unionFilterSegment(entity, schema) {
303
314
  ]
304
315
  }
305
316
  */
306
- for (var _p = tslib_1.__values(f2[pca2]), _q = _p.next(); !_q.done; _q = _p.next()) {
307
- var f21 = _q.value;
317
+ for (var _r = tslib_1.__values(f2[pca2]), _s = _r.next(); !_s.done; _s = _r.next()) {
318
+ var f21 = _s.value;
308
319
  var success = false;
309
320
  try {
310
- for (var _r = (e_4 = void 0, tslib_1.__values(f1[pca2])), _s = _r.next(); !_s.done; _s = _r.next()) {
311
- var f11 = _s.value;
321
+ for (var _t = (e_4 = void 0, tslib_1.__values(f1[pca2])), _u = _t.next(); !_u.done; _u = _t.next()) {
322
+ var f11 = _u.value;
312
323
  if (tryMergeFilters(f11, f21, true)) {
313
324
  success = true;
314
325
  break;
@@ -318,7 +329,7 @@ function unionFilterSegment(entity, schema) {
318
329
  catch (e_4_1) { e_4 = { error: e_4_1 }; }
319
330
  finally {
320
331
  try {
321
- if (_s && !_s.done && (_b = _r.return)) _b.call(_r);
332
+ if (_u && !_u.done && (_b = _t.return)) _b.call(_t);
322
333
  }
323
334
  finally { if (e_4) throw e_4.error; }
324
335
  }
@@ -330,7 +341,7 @@ function unionFilterSegment(entity, schema) {
330
341
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
331
342
  finally {
332
343
  try {
333
- if (_q && !_q.done && (_a = _p.return)) _a.call(_p);
344
+ if (_s && !_s.done && (_a = _r.return)) _a.call(_r);
334
345
  }
335
346
  finally { if (e_3) throw e_3.error; }
336
347
  }
@@ -338,11 +349,11 @@ function unionFilterSegment(entity, schema) {
338
349
  return true;
339
350
  }
340
351
  try {
341
- for (var _t = tslib_1.__values(f2[pca2]), _u = _t.next(); !_u.done; _u = _t.next()) {
342
- var f21 = _u.value;
352
+ for (var _v = tslib_1.__values(f2[pca2]), _w = _v.next(); !_w.done; _w = _v.next()) {
353
+ var f21 = _w.value;
343
354
  try {
344
- for (var _v = (e_6 = void 0, tslib_1.__values(f1[pca2])), _w = _v.next(); !_w.done; _w = _v.next()) {
345
- var f11 = _w.value;
355
+ for (var _x = (e_6 = void 0, tslib_1.__values(f1[pca2])), _y = _x.next(); !_y.done; _y = _x.next()) {
356
+ var f11 = _y.value;
346
357
  if (tryMergeFilters(f11, f21)) {
347
358
  break;
348
359
  }
@@ -351,7 +362,7 @@ function unionFilterSegment(entity, schema) {
351
362
  catch (e_6_1) { e_6 = { error: e_6_1 }; }
352
363
  finally {
353
364
  try {
354
- if (_w && !_w.done && (_d = _v.return)) _d.call(_v);
365
+ if (_y && !_y.done && (_d = _x.return)) _d.call(_x);
355
366
  }
356
367
  finally { if (e_6) throw e_6.error; }
357
368
  }
@@ -360,7 +371,7 @@ function unionFilterSegment(entity, schema) {
360
371
  catch (e_5_1) { e_5 = { error: e_5_1 }; }
361
372
  finally {
362
373
  try {
363
- if (_u && !_u.done && (_c = _t.return)) _c.call(_t);
374
+ if (_w && !_w.done && (_c = _v.return)) _c.call(_v);
364
375
  }
365
376
  finally { if (e_5) throw e_5.error; }
366
377
  }
@@ -368,8 +379,8 @@ function unionFilterSegment(entity, schema) {
368
379
  }
369
380
  else if (pca1 === '$or') {
370
381
  try {
371
- for (var _x = tslib_1.__values(f1[pca1]), _y = _x.next(); !_y.done; _y = _x.next()) {
372
- var f11 = _y.value;
382
+ for (var _z = tslib_1.__values(f1[pca1]), _0 = _z.next(); !_0.done; _0 = _z.next()) {
383
+ var f11 = _0.value;
373
384
  if (tryMergeFilters(f11, f2, justTry)) {
374
385
  return true;
375
386
  }
@@ -378,7 +389,7 @@ function unionFilterSegment(entity, schema) {
378
389
  catch (e_7_1) { e_7 = { error: e_7_1 }; }
379
390
  finally {
380
391
  try {
381
- if (_y && !_y.done && (_e = _x.return)) _e.call(_x);
392
+ if (_0 && !_0.done && (_e = _z.return)) _e.call(_z);
382
393
  }
383
394
  finally { if (e_7) throw e_7.error; }
384
395
  }
@@ -386,8 +397,8 @@ function unionFilterSegment(entity, schema) {
386
397
  }
387
398
  else if (pca2 === '$or') {
388
399
  try {
389
- for (var _z = tslib_1.__values(f2[pca2]), _0 = _z.next(); !_0.done; _0 = _z.next()) {
390
- var f21 = _0.value;
400
+ for (var _1 = tslib_1.__values(f2[pca2]), _2 = _1.next(); !_2.done; _2 = _1.next()) {
401
+ var f21 = _2.value;
391
402
  if (!tryMergeFilters(f1, f21, true)) {
392
403
  return false;
393
404
  }
@@ -396,7 +407,7 @@ function unionFilterSegment(entity, schema) {
396
407
  catch (e_8_1) { e_8 = { error: e_8_1 }; }
397
408
  finally {
398
409
  try {
399
- if (_0 && !_0.done && (_f = _z.return)) _f.call(_z);
410
+ if (_2 && !_2.done && (_f = _1.return)) _f.call(_1);
400
411
  }
401
412
  finally { if (e_8) throw e_8.error; }
402
413
  }
@@ -404,15 +415,15 @@ function unionFilterSegment(entity, schema) {
404
415
  return true;
405
416
  }
406
417
  try {
407
- for (var _1 = tslib_1.__values(f2[pca2]), _2 = _1.next(); !_2.done; _2 = _1.next()) {
408
- var f12 = _2.value;
418
+ for (var _3 = tslib_1.__values(f2[pca2]), _4 = _3.next(); !_4.done; _4 = _3.next()) {
419
+ var f12 = _4.value;
409
420
  tryMergeFilters(f1, f12);
410
421
  }
411
422
  }
412
423
  catch (e_9_1) { e_9 = { error: e_9_1 }; }
413
424
  finally {
414
425
  try {
415
- if (_2 && !_2.done && (_g = _1.return)) _g.call(_1);
426
+ if (_4 && !_4.done && (_g = _3.return)) _g.call(_3);
416
427
  }
417
428
  finally { if (e_9) throw e_9.error; }
418
429
  }
@@ -470,11 +481,22 @@ function unionFilterSegment(entity, schema) {
470
481
  if (justTry) {
471
482
  return true;
472
483
  }
473
- Object.assign(f1, (_l = {},
474
- _l[pca1] = Object.assign(addFilterSegment(rel[0], schema, f1[pca1], f2[pca2]), (_m = {},
475
- _m['#sqp'] = sqpOp1,
476
- _m)),
477
- _l));
484
+ if (sqpOp1 === 'in') {
485
+ Object.assign(f1, (_l = {},
486
+ _l[pca1] = Object.assign(unionFilterSegment(rel[0], schema, f1[pca1], f2[pca2]), (_m = {},
487
+ _m['#sqp'] = sqpOp1,
488
+ _m)),
489
+ _l));
490
+ }
491
+ else {
492
+ // not in情况子查询变成and
493
+ (0, assert_1.default)(sqpOp1 === 'not in'); // all和not all暂时不支持
494
+ Object.assign(f1, (_o = {},
495
+ _o[pca1] = Object.assign(addFilterSegment(rel[0], schema, f1[pca1], f2[pca2]), (_p = {},
496
+ _p['#sqp'] = sqpOp1,
497
+ _p)),
498
+ _o));
499
+ }
478
500
  }
479
501
  }
480
502
  }
@@ -27,6 +27,7 @@ export declare type SelectOption = {
27
27
  obscure?: boolean;
28
28
  forUpdate?: true;
29
29
  includedDeleted?: true;
30
+ ignoreForeignKeyMiss?: true;
30
31
  dummy?: 1;
31
32
  };
32
33
  export declare type OperateOption = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-domain",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "author": {
5
5
  "name": "XuChang"
6
6
  },