在计算excludePath时逻辑错误
This commit is contained in:
parent
8575186962
commit
409c93a181
|
|
@ -35,22 +35,25 @@ var RelationAuth = /** @class */ (function () {
|
|||
var _a;
|
||||
var anchors = [];
|
||||
var anchorsOnMe = [];
|
||||
for (var attr in filter) {
|
||||
var _loop_1 = function (attr) {
|
||||
// todo $or会发生什么?by Xc
|
||||
if (attr === '$and') {
|
||||
filter[attr].forEach(function (ele) { return anchors.push.apply(anchors, tslib_1.__spreadArray([], tslib_1.__read(findHighestAnchors(entity, ele, path, excludePaths)), false)); });
|
||||
continue;
|
||||
return "continue";
|
||||
}
|
||||
var rel = (0, relation_1.judgeRelation)(_this.schema, entity, attr);
|
||||
if (rel === 2) {
|
||||
var path2 = path ? "".concat(path, ".").concat(attr) : attr;
|
||||
anchors.push.apply(anchors, tslib_1.__spreadArray([], tslib_1.__read(findHighestAnchors(attr, filter[attr], path2, excludePaths)), false));
|
||||
if (!excludePaths[path]) {
|
||||
excludePaths[path] = [path2];
|
||||
}
|
||||
else if (!excludePaths[path].includes(path2)) {
|
||||
excludePaths[path].push(path2);
|
||||
}
|
||||
var attributes = _this.schema[entity].attributes;
|
||||
var ref = attributes.entity.ref;
|
||||
(0, assert_1.default)(ref instanceof Array);
|
||||
ref.forEach(function (refEntity) {
|
||||
if (refEntity !== attr) {
|
||||
var refEntityPath = path ? "".concat(path, ".").concat(refEntity) : refEntity;
|
||||
excludePaths.push(refEntityPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (typeof rel === 'string') {
|
||||
var path2 = path ? "".concat(path, ".").concat(attr) : attr;
|
||||
|
|
@ -69,12 +72,15 @@ var RelationAuth = /** @class */ (function () {
|
|||
relativePath: nextPath,
|
||||
});
|
||||
}
|
||||
if (!excludePaths[path]) {
|
||||
excludePaths[path] = [nextPath];
|
||||
}
|
||||
else if (!excludePaths[path].includes(nextPath)) {
|
||||
excludePaths[path].push(nextPath);
|
||||
}
|
||||
var attributes = _this.schema[entity].attributes;
|
||||
var ref = attributes.entity.ref;
|
||||
(0, assert_1.default)(ref instanceof Array);
|
||||
ref.forEach(function (refEntity) {
|
||||
if (refEntity !== filter.entity) {
|
||||
var refEntityPath = path ? "".concat(path, ".").concat(refEntity) : refEntity;
|
||||
excludePaths.push(refEntityPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (((_a = _this.schema[entity].attributes[attr]) === null || _a === void 0 ? void 0 : _a.type) === 'ref') {
|
||||
var ref = _this.schema[entity].attributes[attr].ref;
|
||||
|
|
@ -90,6 +96,9 @@ var RelationAuth = /** @class */ (function () {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
for (var attr in filter) {
|
||||
_loop_1(attr);
|
||||
}
|
||||
if (anchors.length > 0) {
|
||||
return anchors;
|
||||
|
|
@ -114,7 +123,7 @@ var RelationAuth = /** @class */ (function () {
|
|||
_this.relationalChecker[entity] = function (userId, actions, data, filter, userRelations) {
|
||||
var filter2 = filter || data;
|
||||
(0, assert_1.default)(filter2);
|
||||
var excludePaths = {};
|
||||
var excludePaths = [];
|
||||
var anchors = findHighestAnchors(entity, filter2, '', excludePaths);
|
||||
if (anchors.length === 0) {
|
||||
throw new types_1.OakException('本次查询找不到锚定权限的入口,请确认查询条件合法');
|
||||
|
|
@ -122,12 +131,23 @@ var RelationAuth = /** @class */ (function () {
|
|||
anchors.sort(function (a1, a2) { return a2.relativePath.length - a1.relativePath.length; });
|
||||
// 将这些找到的锚点和authCascadePaths进行锚定,确认userRelation的搜索范围
|
||||
var filters = authCascadePaths.filter(function (path) {
|
||||
// 被entity的外键连接所排队的路径,这个非常重要,否则像extraFile这样的对象会有过多的查询路径
|
||||
for (var k in excludePaths) {
|
||||
if (path[1].startsWith(k) && !excludePaths[k].find(function (ele) { return path[1].startsWith("".concat(ele, ".")) || path[1] === ele; })) {
|
||||
return false;
|
||||
var e_1, _a;
|
||||
try {
|
||||
// 被entity的外键连接所排队的路径,这个非常重要,否则像extraFile这样的对象会有过多的查询路径
|
||||
for (var excludePaths_1 = tslib_1.__values(excludePaths), excludePaths_1_1 = excludePaths_1.next(); !excludePaths_1_1.done; excludePaths_1_1 = excludePaths_1.next()) {
|
||||
var excludePath = excludePaths_1_1.value;
|
||||
if (path[1].startsWith(excludePath)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (excludePaths_1_1 && !excludePaths_1_1.done && (_a = excludePaths_1.return)) _a.call(excludePaths_1);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
return true;
|
||||
}).map(function (path) {
|
||||
// 这里anchor的relativePath按长度倒排,所以找到的第一个匹配关系应该就是最准确的
|
||||
|
|
@ -436,7 +456,7 @@ var RelationAuth = /** @class */ (function () {
|
|||
};
|
||||
(0, assert_1.default)(!(data instanceof Array)); // createMulti这种情况实际中不会出现
|
||||
var changeRoot = false;
|
||||
var _loop_1 = function (attr) {
|
||||
var _loop_2 = function (attr) {
|
||||
var _a;
|
||||
var rel = (0, relation_1.judgeRelation)(_this.schema, entity, attr);
|
||||
if (rel === 2) {
|
||||
|
|
@ -618,7 +638,7 @@ var RelationAuth = /** @class */ (function () {
|
|||
}
|
||||
};
|
||||
for (var attr in data) {
|
||||
_loop_1(attr);
|
||||
_loop_2(attr);
|
||||
}
|
||||
return root;
|
||||
};
|
||||
|
|
@ -641,7 +661,7 @@ var RelationAuth = /** @class */ (function () {
|
|||
this.checkActions(entity, operation, context);
|
||||
};
|
||||
RelationAuth.prototype.getDeducedCheckOperation = function (entity, operation) {
|
||||
var e_1, _a;
|
||||
var e_2, _a;
|
||||
// 如果是deduce的对象,将之转化为所deduce的对象上的权限检查
|
||||
var deduceAttr = this.authDeduceRelationMap[entity];
|
||||
(0, assert_1.default)(deduceAttr === 'entity', "\u5F53\u524D\u53EA\u652F\u6301entity\u4F5C\u4E3Adeduce\u5916\u952E\uFF0Centity\u662F\u300C".concat(entity, "\u300D"));
|
||||
|
|
@ -673,12 +693,12 @@ var RelationAuth = /** @class */ (function () {
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (data_1_1 && !data_1_1.done && (_a = data_1.return)) _a.call(data_1);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
finally { if (e_2) throw e_2.error; }
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -941,9 +961,9 @@ var RelationAuth = /** @class */ (function () {
|
|||
// 算法是先将整个update的根结点对象找到,并找到为其赋权的relation,再用此relation去查找所有子对象上的actionAuth
|
||||
var result = [];
|
||||
var _b = this.destructCascadeOperation(entity, operation), root = _b.root, children_1 = _b.children, userRelations = _b.userRelations;
|
||||
var e_2 = root.entity, d = root.data, f = root.filter, a = root.action;
|
||||
var e_3 = root.entity, d = root.data, f = root.filter, a = root.action;
|
||||
if (userRelations.length > 0) {
|
||||
(0, assert_1.default)(e_2 !== 'user');
|
||||
(0, assert_1.default)(e_3 !== 'user');
|
||||
(0, assert_1.default)(a === 'create' && !(d instanceof Array));
|
||||
var createIds_1 = userRelations.map(function (ele) { return ele.relationId; });
|
||||
// 这里处理的是创建对象时顺带创建相关权限,要检查该权限是不是有create动作授权
|
||||
|
|
@ -953,7 +973,7 @@ var RelationAuth = /** @class */ (function () {
|
|||
relationId: 1,
|
||||
},
|
||||
filter: {
|
||||
destEntity: e_2,
|
||||
destEntity: e_3,
|
||||
deActions: {
|
||||
$contains: 'create',
|
||||
},
|
||||
|
|
@ -965,7 +985,7 @@ var RelationAuth = /** @class */ (function () {
|
|||
var relationIds = aas2.map(function (ele) { return ele.relationId; });
|
||||
var diff = (0, lodash_1.difference)(createIds_1, relationIds);
|
||||
if (diff.length > 0) {
|
||||
throw new types_1.OakUserUnpermittedException("\u60A8\u65E0\u6743\u521B\u5EFA\u300C".concat(e_2, "\u300D\u5BF9\u8C61\u4E0Aid\u4E3A\u300C").concat(diff.join(','), "\u300D\u7684\u7528\u6237\u6743\u9650"));
|
||||
throw new types_1.OakUserUnpermittedException("\u60A8\u65E0\u6743\u521B\u5EFA\u300C".concat(e_3, "\u300D\u5BF9\u8C61\u4E0Aid\u4E3A\u300C").concat(diff.join(','), "\u300D\u7684\u7528\u6237\u6743\u9650"));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
@ -973,14 +993,14 @@ var RelationAuth = /** @class */ (function () {
|
|||
var relationIds = aas.map(function (ele) { return ele.relationId; });
|
||||
var diff = (0, lodash_1.difference)(createIds_1, relationIds);
|
||||
if (diff.length > 0) {
|
||||
throw new types_1.OakUserUnpermittedException("\u60A8\u65E0\u6743\u521B\u5EFA\u300C".concat(e_2, "\u300D\u5BF9\u8C61\u4E0Aid\u4E3A\u300C").concat(diff.join(','), "\u300D\u7684\u7528\u6237\u6743\u9650"));
|
||||
throw new types_1.OakUserUnpermittedException("\u60A8\u65E0\u6743\u521B\u5EFA\u300C".concat(e_3, "\u300D\u5BF9\u8C61\u4E0Aid\u4E3A\u300C").concat(diff.join(','), "\u300D\u7684\u7528\u6237\u6743\u9650"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (['user', 'relation', 'oper', 'operEntity', 'modi', 'modiEntity', 'userRelation', 'actionAuth',
|
||||
'freeActionAuth', 'relationAuth', 'userEntityGrant', 'relation'].includes(e_2)) {
|
||||
'freeActionAuth', 'relationAuth', 'userEntityGrant', 'relation'].includes(e_3)) {
|
||||
// 只要根对象能检查通过就算通过(暂定这个策略)
|
||||
var r = this.checkSpecialEntity(e_2, {
|
||||
var r = this.checkSpecialEntity(e_3, {
|
||||
action: a,
|
||||
data: d,
|
||||
filter: f,
|
||||
|
|
@ -990,7 +1010,7 @@ var RelationAuth = /** @class */ (function () {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!this.relationalChecker[e_2]) {
|
||||
if (!this.relationalChecker[e_3]) {
|
||||
throw new types_1.OakUserUnpermittedException("".concat(root.entity, "\u4E0A\u4E0D\u5B58\u5728\u6709\u6548\u7684actionPath"));
|
||||
}
|
||||
var checker = this.relationalChecker[root.entity](userId, actions || [root.action], root.data, root.filter, userRelations);
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
relativePath: string;
|
||||
};
|
||||
|
||||
const findHighestAnchors = (entity: keyof ED, filter: NonNullable<ED[keyof ED]['Selection']['filter']>, path: string, excludePaths: Record<string, string[]>): Anchor[] => {
|
||||
const findHighestAnchors = (entity: keyof ED, filter: NonNullable<ED[keyof ED]['Selection']['filter']>, path: string, excludePaths: string[]): Anchor[] => {
|
||||
const anchors = [] as Anchor[];
|
||||
const anchorsOnMe = [] as Anchor[];
|
||||
for (const attr in filter) {
|
||||
|
|
@ -85,12 +85,18 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
if (rel === 2) {
|
||||
const path2 = path ? `${path}.${attr}` : attr;
|
||||
anchors.push(...findHighestAnchors(attr, filter[attr], path2, excludePaths));
|
||||
if (!excludePaths[path]) {
|
||||
excludePaths[path] = [path2];
|
||||
}
|
||||
else if (!excludePaths[path].includes(path2)) {
|
||||
excludePaths[path].push(path2);
|
||||
}
|
||||
|
||||
const { attributes } = this.schema[entity];
|
||||
const { ref } = attributes.entity;
|
||||
assert(ref instanceof Array);
|
||||
ref.forEach(
|
||||
(refEntity) => {
|
||||
if (refEntity !== attr) {
|
||||
const refEntityPath = path ? `${path}.${refEntity}` : refEntity;
|
||||
excludePaths.push(refEntityPath);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else if (typeof rel === 'string') {
|
||||
const path2 = path ? `${path}.${attr}` : attr;
|
||||
|
|
@ -109,12 +115,17 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
relativePath: nextPath,
|
||||
});
|
||||
}
|
||||
if (!excludePaths[path]) {
|
||||
excludePaths[path] = [nextPath];
|
||||
}
|
||||
else if (!excludePaths[path].includes(nextPath)) {
|
||||
excludePaths[path].push(nextPath);
|
||||
}
|
||||
const { attributes } = this.schema[entity];
|
||||
const { ref } = attributes.entity;
|
||||
assert(ref instanceof Array);
|
||||
ref.forEach(
|
||||
(refEntity) => {
|
||||
if (refEntity !== filter.entity) {
|
||||
const refEntityPath = path ? `${path}.${refEntity}` : refEntity;
|
||||
excludePaths.push(refEntityPath);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else if (this.schema[entity].attributes[attr as any]?.type === 'ref') {
|
||||
const { ref } = this.schema[entity].attributes[attr as any];
|
||||
|
|
@ -162,7 +173,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
) => {
|
||||
const filter2 = filter || data as ED[keyof ED]['Selection']['filter'];
|
||||
assert(filter2);
|
||||
const excludePaths: Record<string, string[]> = {};
|
||||
const excludePaths: string[] = [];
|
||||
const anchors = findHighestAnchors(entity, filter2 as NonNullable<ED[keyof ED]['Selection']['filter']>, '', excludePaths);
|
||||
if (anchors.length === 0) {
|
||||
throw new OakException('本次查询找不到锚定权限的入口,请确认查询条件合法');
|
||||
|
|
@ -175,8 +186,8 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
const filters = authCascadePaths.filter(
|
||||
(path) => {
|
||||
// 被entity的外键连接所排队的路径,这个非常重要,否则像extraFile这样的对象会有过多的查询路径
|
||||
for (const k in excludePaths) {
|
||||
if (path[1].startsWith(k) && !excludePaths[k].find(ele => path[1].startsWith(`${ele}.`) || path[1] === ele)) {
|
||||
for (const excludePath of excludePaths) {
|
||||
if (path[1].startsWith(excludePath)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -186,7 +197,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
(path) => {
|
||||
// 这里anchor的relativePath按长度倒排,所以找到的第一个匹配关系应该就是最准确的
|
||||
const relatedAnchor = anchors.find(
|
||||
(anchor) => path[1].startsWith(`${anchor.relativePath}.`)
|
||||
(anchor) => path[1].startsWith(`${anchor.relativePath}.`)
|
||||
|| path[1] === anchor.relativePath
|
||||
|| !anchor.relativePath // relativePath如果是'', 所有的路径都成立
|
||||
);
|
||||
|
|
@ -725,7 +736,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
});
|
||||
root = destructFn(rel, operationMto, '', parentFilter2);
|
||||
}
|
||||
else if (rel instanceof Array) {
|
||||
else if (rel instanceof Array) {
|
||||
const [entityOtm, foreignKey] = rel;
|
||||
// 如果是一对多的deduceRelation,可以忽略,其父对象能过就行
|
||||
if (!this.authDeduceRelationMap[entityOtm]) {
|
||||
|
|
@ -1070,7 +1081,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
const { data } = operation as ED['user']['Update'];
|
||||
if (data.hasOwnProperty('userRelation$user')) {
|
||||
const { userRelation$user } = data;
|
||||
const checkUrOperation = ( urOperation: ED['userRelation']['Operation']) => this.checkSpecialEntity('userRelation', urOperation, context);
|
||||
const checkUrOperation = (urOperation: ED['userRelation']['Operation']) => this.checkSpecialEntity('userRelation', urOperation, context);
|
||||
if (userRelation$user instanceof Array) {
|
||||
const result = userRelation$user.map(ur => checkUrOperation(ur));
|
||||
if (result[0] instanceof Promise) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue