修改了RelationAuth中updateFree的结构
This commit is contained in:
parent
ccf11e87d5
commit
1595dbb51a
|
|
@ -1,10 +1,2 @@
|
|||
import { AuthCascadePath, AuthDeduceRelationMap } from "../types/Entity";
|
||||
import { EntityDict } from "./EntityDict";
|
||||
import { CreateOperationData as Relation } from "./Relation/Schema";
|
||||
export declare const ActionCascadePathGraph: AuthCascadePath<EntityDict>[];
|
||||
export declare const RelationCascadePathGraph: AuthCascadePath<EntityDict>[];
|
||||
export declare const relations: Relation[];
|
||||
export declare const deducedRelationMap: AuthDeduceRelationMap<EntityDict>;
|
||||
export declare const selectFreeEntities: (keyof EntityDict)[];
|
||||
export declare const updateFreeEntities: (keyof EntityDict)[];
|
||||
export declare const createFreeEntities: (keyof EntityDict)[];
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createFreeEntities = exports.updateFreeEntities = exports.selectFreeEntities = exports.deducedRelationMap = exports.relations = exports.RelationCascadePathGraph = exports.ActionCascadePathGraph = void 0;
|
||||
exports.ActionCascadePathGraph = [];
|
||||
exports.RelationCascadePathGraph = [];
|
||||
exports.relations = void 0;
|
||||
exports.relations = [];
|
||||
exports.deducedRelationMap = {};
|
||||
exports.selectFreeEntities = [];
|
||||
exports.updateFreeEntities = [];
|
||||
exports.createFreeEntities = [];
|
||||
|
|
|
|||
|
|
@ -1,11 +1,27 @@
|
|||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export declare function registerIgnoredForeignKeyMap(map: Record<string, string[]>): void;
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export declare function registerFreeEntities(selectFreeEntities?: string[], createFreeEntities?: string[], updateFreeEntities?: string[]): void;
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export declare function registerIgnoredRelationPathMap(map: Record<string, string[]>): void;
|
||||
/**
|
||||
* 很多路径虽然最后指向同一对象,但不能封掉,封了会导致查询的时候找不到对应的路径path
|
||||
* @param map
|
||||
*/
|
||||
export declare function registerFixedDestinationPathMap(map: Record<string, string[]>): void;
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export declare function registerDeducedRelationMap(map: Record<string, string>): void;
|
||||
export declare function analyzeEntities(inputDir: string, relativePath?: string): void;
|
||||
export declare function buildSchema(outputDir: string): void;
|
||||
|
|
|
|||
|
|
@ -3255,6 +3255,10 @@ function analyzeInModi() {
|
|||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 此部分功能不再使用
|
||||
* @param map
|
||||
*/
|
||||
let IGNORED_FOREIGN_KEY_MAP = {};
|
||||
let IGNORED_RELATION_PATH_MAP = {};
|
||||
let DEDUCED_RELATION_MAP = {};
|
||||
|
|
@ -3263,16 +3267,28 @@ let CREATE_FREE_ENTITIES = [];
|
|||
let UPDATE_FREE_ENTITIES = [];
|
||||
let FIXED_DESTINATION_PATH_MAP = {};
|
||||
let FIXED_FOR_ALL_DESTINATION_PATH_ENTITIES = [];
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
function registerIgnoredForeignKeyMap(map) {
|
||||
IGNORED_FOREIGN_KEY_MAP = map;
|
||||
}
|
||||
exports.registerIgnoredForeignKeyMap = registerIgnoredForeignKeyMap;
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
function registerFreeEntities(selectFreeEntities = [], createFreeEntities = [], updateFreeEntities = []) {
|
||||
SELECT_FREE_ENTITIES = selectFreeEntities;
|
||||
CREATE_FREE_ENTITIES = createFreeEntities;
|
||||
UPDATE_FREE_ENTITIES = updateFreeEntities;
|
||||
}
|
||||
exports.registerFreeEntities = registerFreeEntities;
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
function registerIgnoredRelationPathMap(map) {
|
||||
for (const k in map) {
|
||||
IGNORED_RELATION_PATH_MAP[(0, string_1.firstLetterUpperCase)(k)] = map[k];
|
||||
|
|
@ -3297,6 +3313,10 @@ function registerFixedDestinationPathMap(map) {
|
|||
}
|
||||
}
|
||||
exports.registerFixedDestinationPathMap = registerFixedDestinationPathMap;
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
function registerDeducedRelationMap(map) {
|
||||
for (const k in map) {
|
||||
const entity = (0, string_1.firstLetterUpperCase)(k);
|
||||
|
|
@ -3314,6 +3334,7 @@ function registerDeducedRelationMap(map) {
|
|||
exports.registerDeducedRelationMap = registerDeducedRelationMap;
|
||||
/**
|
||||
* 输出所有和User相关的对象的后继
|
||||
* 此函数不再使用
|
||||
*/
|
||||
function outputRelation(outputDir, printer) {
|
||||
const ExcludedEntities = ['Oper', 'User', 'OperEntity', 'Modi', 'ModiEntity', 'UserRelation', 'Relation', 'RelationAuth', 'ActionAuth'];
|
||||
|
|
@ -3464,6 +3485,47 @@ function outputRelation(outputDir, printer) {
|
|||
const filename = path_1.default.join(outputDir, 'Relation.ts');
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
}
|
||||
/**
|
||||
* 输出oak-app-domain中的Relation.ts文件
|
||||
* 不再输出actionAuthGraph和relationAuthGraph两个复杂的对象
|
||||
* @param outputDir
|
||||
* @param printer
|
||||
*/
|
||||
function outputRelation2(outputDir, printer) {
|
||||
const entityRelations = [];
|
||||
for (const entity in Schema) {
|
||||
const { hasRelationDef } = Schema[entity];
|
||||
if (hasRelationDef) {
|
||||
const { type } = hasRelationDef;
|
||||
if (ts.isUnionTypeNode(type)) {
|
||||
const { types } = type;
|
||||
const relations = types.map(ele => {
|
||||
(0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
|
||||
return ele.literal.text;
|
||||
});
|
||||
entityRelations.push([(0, string_1.firstLetterLowerCase)(entity), relations]);
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isLiteralTypeNode(type));
|
||||
(0, assert_1.default)(ts.isStringLiteral(type.literal));
|
||||
const relations = [type.literal.text];
|
||||
entityRelations.push([(0, string_1.firstLetterLowerCase)(entity), relations]);
|
||||
}
|
||||
}
|
||||
}
|
||||
const stmts = [
|
||||
factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, undefined, factory.createIdentifier("EntityDict"))])), factory.createStringLiteral("./EntityDict"), undefined),
|
||||
factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("CreateOperationData"), factory.createIdentifier("Relation"))])), factory.createStringLiteral("./Relation/Schema"), undefined),
|
||||
factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("relations"), undefined, factory.createArrayTypeNode(factory.createTypeReferenceNode(factory.createIdentifier("Relation"), undefined)), factory.createArrayLiteralExpression((0, lodash_1.flatten)(entityRelations.map(([entity, relations]) => relations.map((relation) => factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment(factory.createIdentifier("id"), factory.createStringLiteral((0, uuid_1.formUuid)(entity, relation))),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("entity"), factory.createStringLiteral(entity)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("name"), factory.createStringLiteral(relation))
|
||||
], true)))), true))], ts.NodeFlags.Const))
|
||||
];
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(stmts), ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, /*setParentNodes*/ false, ts.ScriptKind.TS));
|
||||
const filename = path_1.default.join(outputDir, 'Relation.ts');
|
||||
(0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
|
||||
}
|
||||
function analyzeEntities(inputDir, relativePath) {
|
||||
const files = (0, fs_1.readdirSync)(inputDir);
|
||||
const fullFilenames = files.map(ele => {
|
||||
|
|
@ -3492,7 +3554,7 @@ function buildSchema(outputDir) {
|
|||
outputAction(outputDir, printer);
|
||||
outputEntityDict(outputDir, printer);
|
||||
outputStorage(outputDir, printer);
|
||||
outputRelation(outputDir, printer);
|
||||
outputRelation2(outputDir, printer);
|
||||
outputIndexTs(outputDir);
|
||||
if (!process.env.COMPLING_AS_LIB) {
|
||||
outputPackageJson(outputDir);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export { storageSchema, selectFreeEntities } from './base-app-domain';
|
||||
export { storageSchema } from './base-app-domain';
|
||||
export type { EntityDict as BaseEntityDict } from './base-app-domain';
|
||||
export * from './store/AsyncRowStore';
|
||||
export * from './store/SyncRowStore';
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.expandUuidTo36Bytes = exports.shrinkUuidTo32Bytes = exports.generateNewId = exports.generateNewIdAsync = exports.compareVersion = exports.checkAttributesScope = exports.checkAttributesNotNull = exports.composeUrl = exports.assert = exports.SimpleConnector = exports.selectFreeEntities = exports.storageSchema = void 0;
|
||||
exports.expandUuidTo36Bytes = exports.shrinkUuidTo32Bytes = exports.generateNewId = exports.generateNewIdAsync = exports.compareVersion = exports.checkAttributesScope = exports.checkAttributesNotNull = exports.composeUrl = exports.assert = exports.SimpleConnector = exports.storageSchema = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
var base_app_domain_1 = require("./base-app-domain");
|
||||
Object.defineProperty(exports, "storageSchema", { enumerable: true, get: function () { return base_app_domain_1.storageSchema; } });
|
||||
Object.defineProperty(exports, "selectFreeEntities", { enumerable: true, get: function () { return base_app_domain_1.selectFreeEntities; } });
|
||||
tslib_1.__exportStar(require("./store/AsyncRowStore"), exports);
|
||||
tslib_1.__exportStar(require("./store/SyncRowStore"), exports);
|
||||
tslib_1.__exportStar(require("./store/CascadeStore"), exports);
|
||||
|
|
|
|||
|
|
@ -1,27 +1,18 @@
|
|||
import { EntityDict } from "../base-app-domain";
|
||||
import { StorageSchema } from "../types";
|
||||
import { AuthCascadePath, EntityDict as BaseEntityDict, AuthDeduceRelationMap } from "../types/Entity";
|
||||
import { EntityDict as BaseEntityDict, AuthDeduceRelationMap } from "../types/Entity";
|
||||
import { AsyncContext } from "./AsyncRowStore";
|
||||
import { SyncContext } from "./SyncRowStore";
|
||||
export declare class RelationAuth<ED extends EntityDict & BaseEntityDict> {
|
||||
private actionCascadePathGraph;
|
||||
private relationCascadePathGraph;
|
||||
private authDeduceRelationMap;
|
||||
private schema;
|
||||
static SPECIAL_ENTITIES: string[];
|
||||
private selectFreeEntities;
|
||||
private createFreeEntities;
|
||||
private updateFreeEntities;
|
||||
constructor(schema: StorageSchema<ED>, actionCascadePathGraph: AuthCascadePath<ED>[], relationCascadePathGraph: AuthCascadePath<ED>[], authDeduceRelationMap: AuthDeduceRelationMap<ED>, selectFreeEntities?: (keyof ED)[], createFreeEntities?: (keyof ED)[], updateFreeEntities?: (keyof ED)[]);
|
||||
private updateFreeDict;
|
||||
constructor(schema: StorageSchema<ED>, authDeduceRelationMap: AuthDeduceRelationMap<ED>, selectFreeEntities?: (keyof ED)[], updateFreeDict?: {
|
||||
[A in keyof ED]?: string[];
|
||||
});
|
||||
checkRelationSync<T extends keyof ED, Cxt extends SyncContext<ED>>(entity: T, operation: Omit<ED[T]['Operation'] | ED[T]['Selection'], 'id'>, context: Cxt): void;
|
||||
/**
|
||||
* 查询当前用户在对应entity上可以操作的relationIds
|
||||
* @param entity
|
||||
* @param entityId
|
||||
* @param context
|
||||
* @returns
|
||||
*/
|
||||
private getGrantedRelationIds;
|
||||
checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]['Operation'] | ED[T]['Selection'], 'id'>, context: Cxt): Promise<void>;
|
||||
private checkUserRelation;
|
||||
private checkOperateSpecialEntities2;
|
||||
|
|
|
|||
|
|
@ -11,21 +11,15 @@ const action_1 = require("../actions/action");
|
|||
const lodash_1 = require("../utils/lodash");
|
||||
const env_1 = require("../compiler/env");
|
||||
class RelationAuth {
|
||||
actionCascadePathGraph;
|
||||
relationCascadePathGraph;
|
||||
authDeduceRelationMap;
|
||||
schema;
|
||||
static SPECIAL_ENTITIES = env_1.SYSTEM_RESERVE_ENTITIES;
|
||||
selectFreeEntities;
|
||||
createFreeEntities;
|
||||
updateFreeEntities;
|
||||
constructor(schema, actionCascadePathGraph, relationCascadePathGraph, authDeduceRelationMap, selectFreeEntities, createFreeEntities, updateFreeEntities) {
|
||||
this.actionCascadePathGraph = actionCascadePathGraph;
|
||||
this.relationCascadePathGraph = relationCascadePathGraph;
|
||||
updateFreeDict;
|
||||
constructor(schema, authDeduceRelationMap, selectFreeEntities, updateFreeDict) {
|
||||
this.schema = schema;
|
||||
this.selectFreeEntities = selectFreeEntities || [];
|
||||
this.createFreeEntities = createFreeEntities || [];
|
||||
this.updateFreeEntities = updateFreeEntities || [];
|
||||
this.updateFreeDict = updateFreeDict || {};
|
||||
this.authDeduceRelationMap = Object.assign({}, authDeduceRelationMap, {
|
||||
modi: 'entity',
|
||||
});
|
||||
|
|
@ -37,52 +31,6 @@ class RelationAuth {
|
|||
}
|
||||
this.checkActions2(entity, operation, context);
|
||||
}
|
||||
/**
|
||||
* 查询当前用户在对应entity上可以操作的relationIds
|
||||
* @param entity
|
||||
* @param entityId
|
||||
* @param context
|
||||
* @returns
|
||||
*/
|
||||
getGrantedRelationIds(entity, entityId, context) {
|
||||
const result = context.select('relationAuth', {
|
||||
data: {
|
||||
id: 1,
|
||||
destRelationId: 1,
|
||||
destRelation: {
|
||||
id: 1,
|
||||
name: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
display: 1,
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
sourceRelation: {
|
||||
userRelation$relation: {
|
||||
userId: context.getCurrentUserId(),
|
||||
}
|
||||
},
|
||||
destRelation: {
|
||||
entity: entity,
|
||||
$or: [
|
||||
{
|
||||
entityId,
|
||||
},
|
||||
{
|
||||
entityId: {
|
||||
$exists: false,
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
}, {});
|
||||
if (result instanceof Promise) {
|
||||
return result.then((r2) => r2.map(ele => ele.destRelation));
|
||||
}
|
||||
return result.map(ele => ele.destRelation);
|
||||
}
|
||||
// 后台检查filter是否满足relation约束
|
||||
async checkRelationAsync(entity, operation, context) {
|
||||
if (context.isRoot()) {
|
||||
|
|
@ -141,10 +89,6 @@ class RelationAuth {
|
|||
}, { dontCollect: true });
|
||||
const checkRelationAuth = (relationAuth) => {
|
||||
const { destRelation, sourceRelationId, path } = relationAuth;
|
||||
if (action === 'create' && path === '') {
|
||||
// 自己建立自己,一定可以通过
|
||||
return 1;
|
||||
}
|
||||
const destEntityFilter = {};
|
||||
if (path) {
|
||||
(0, lodash_1.set)(destEntityFilter, path, {
|
||||
|
|
@ -962,204 +906,9 @@ class RelationAuth {
|
|||
};
|
||||
return checkNode(tree);
|
||||
}
|
||||
/* private checkOperationTree<Cxt extends AsyncContext<ED> | SyncContext<ED>>(tree: OperationTree<ED>, context: Cxt) {
|
||||
const actionAuths2 = this.findActionAuthsOnNode(tree, context);
|
||||
|
||||
const checkChildNode = (actionAuths: ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema'][]>, node: OperationTree<ED>): boolean | Promise<boolean> => {
|
||||
const checkChildNodeInner = (legalAuths: ED['actionAuth']['Schema'][]) => {
|
||||
// 因为如果children是数组的话,会把数组中所有的action并起来查询,所以在这里还要再确认一次
|
||||
|
||||
const realLegalPaths = legalAuths.filter(
|
||||
(ele) => {
|
||||
if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
|
||||
return true;
|
||||
}
|
||||
// 有一种例外情况,是在tree的根结点findActionAuthsOnNode时,deduce出了另外一个对象的权限,此时肯定可以通过,但不能再使用这条路径对children进行进一步判断了
|
||||
if (node === tree) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
const checkChildren = () => {
|
||||
const { children } = node;
|
||||
const childPath = Object.keys(children);
|
||||
if (childPath.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const selfLegalPaths = realLegalPaths.filter(
|
||||
(ele) => {
|
||||
if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
// assert(selfLegalPaths.length > 0, `对象${node.entity as string}的权限检查是用deduce的对象通过的,无法再进一步对子对象加以判断`);
|
||||
const childResult = childPath.map(
|
||||
(childPath) => {
|
||||
const child = children[childPath];
|
||||
const childEntity = child instanceof Array ? child[0].entity : child.entity;
|
||||
// 这里如果该子结点能deduce到父,则直接通过
|
||||
if (this.authDeduceRelationMap[childEntity]) {
|
||||
assert(this.authDeduceRelationMap[childEntity] === 'entity');
|
||||
const rel = judgeRelation(this.schema, childEntity, childPath);
|
||||
if (rel === 2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const pathToParent = childPath.endsWith('$entity') ? node.entity as string : childPath.split('$')[1];
|
||||
if (child instanceof Array) {
|
||||
const childActions = child.map(ele => ele.action);
|
||||
const childLegalAuths = selfLegalPaths.map(
|
||||
(ele) => {
|
||||
const { paths, relationId } = ele;
|
||||
const paths2 = paths.map(
|
||||
(path) => path ? `${pathToParent}.${path}` : pathToParent
|
||||
);
|
||||
return context.select('actionAuth', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
paths: {
|
||||
$overlaps: paths2,
|
||||
},
|
||||
destEntity: childEntity as string,
|
||||
deActions: {
|
||||
$overlaps: childActions,
|
||||
},
|
||||
relationId: relationId || {
|
||||
$exists: false,
|
||||
},
|
||||
}
|
||||
}, { dontCollect: true })
|
||||
}
|
||||
).flat() as ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema']>[];
|
||||
if (childLegalAuths[0] instanceof Promise) {
|
||||
return Promise.all(childLegalAuths).then(
|
||||
(clas) => child.map(
|
||||
(c) => checkChildNode(clas, c)
|
||||
)
|
||||
)
|
||||
}
|
||||
return child.map(
|
||||
(c) => checkChildNode(childLegalAuths as ED['actionAuth']['Schema'][], c)
|
||||
);
|
||||
}
|
||||
|
||||
const childLegalAuths = realLegalPaths.map(
|
||||
(ele) => {
|
||||
const { paths, relationId } = ele;
|
||||
const paths2 = paths.map(
|
||||
(path) => path ? `${pathToParent}.${path}` : pathToParent
|
||||
);
|
||||
return context.select('actionAuth', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
paths: {
|
||||
$overlaps: paths2,
|
||||
},
|
||||
destEntity: childEntity as string,
|
||||
deActions: {
|
||||
$overlaps: child.action,
|
||||
},
|
||||
relationId: relationId || {
|
||||
$exists: false,
|
||||
},
|
||||
}
|
||||
}, { dontCollect: true })
|
||||
}
|
||||
).flat() as ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema']>[];
|
||||
|
||||
if (childLegalAuths[0] instanceof Promise) {
|
||||
return Promise.all(childLegalAuths).then(
|
||||
(clas) => checkChildNode(clas.flat(), child)
|
||||
);
|
||||
}
|
||||
return checkChildNode(childLegalAuths as ED['actionAuth']['Schema'][], child);
|
||||
}
|
||||
).flat();
|
||||
|
||||
if (childResult[0] instanceof Promise) {
|
||||
return Promise.all(childResult).then(
|
||||
(r) => !r.includes(false)
|
||||
);
|
||||
}
|
||||
return !childResult.includes(false);
|
||||
};
|
||||
|
||||
if (RelationAuth.SPECIAL_ENTITIES.includes(node.entity as string)) {
|
||||
// 特殊entity走特别的路径判断
|
||||
const result = this.checkOperateSpecialEntities2(node.entity, node.action, node.filter, context);
|
||||
|
||||
if (result instanceof Promise) {
|
||||
return result.then(
|
||||
(r) => {
|
||||
if (r) {
|
||||
return checkChildren();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
if (result) {
|
||||
if (node.entity === 'user') {
|
||||
// 如果当前是对user对象操作,需要加上一个指向它自身的actionAuth,否则剩下的子对象会判定不过
|
||||
// user的操作权限由应用自己决定,如果user的操作最终过不去,这里放过也没关系
|
||||
assert(node === tree && realLegalPaths.length === 0); // user不可能是非根结点
|
||||
realLegalPaths.push({
|
||||
id: 'temp',
|
||||
paths: [''],
|
||||
$$createAt$$: 1,
|
||||
$$updateAt$$: 1,
|
||||
$$seq$$: 'temp',
|
||||
destEntity: 'user',
|
||||
deActions: [node.action],
|
||||
});
|
||||
}
|
||||
return checkChildren();
|
||||
}
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('对象operate权限检查不通过', node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (realLegalPaths.length === 0) {
|
||||
if (node === tree) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('对象operate权限检查不通过', node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// 如果不是tree的根结点,相对路径上的actionAuth找不到,还可以尝试从自身的filter去重试其它路径
|
||||
return this.checkOperationTree(node, context);
|
||||
}
|
||||
|
||||
return checkChildren();
|
||||
};
|
||||
|
||||
if (actionAuths instanceof Promise) {
|
||||
return actionAuths.then(
|
||||
(aars) => checkChildNodeInner(aars)
|
||||
);
|
||||
}
|
||||
return checkChildNodeInner(actionAuths);
|
||||
};
|
||||
|
||||
return checkChildNode(actionAuths2, tree);
|
||||
} */
|
||||
checkOperation(entity, operation, context) {
|
||||
const { action, filter, data } = operation;
|
||||
if (action === 'create' && this.createFreeEntities.includes(entity)) {
|
||||
return true;
|
||||
}
|
||||
else if (action === 'update' && this.updateFreeEntities.includes(entity)) {
|
||||
if (this.updateFreeDict[entity] && this.updateFreeDict[entity].includes(action)) {
|
||||
return true;
|
||||
}
|
||||
const userId = context.getCurrentUserId();
|
||||
|
|
|
|||
|
|
@ -185,11 +185,13 @@ export type Configuration = {
|
|||
actionType?: ActionType;
|
||||
static?: boolean;
|
||||
};
|
||||
export type AuthCascadePath<ED extends EntityDict> = [keyof ED, string, keyof ED, boolean];
|
||||
export type AuthDeduceRelationMap<ED extends EntityDict> = {
|
||||
[T in keyof ED]?: keyof ED[T]['OpSchema'];
|
||||
};
|
||||
export type SelectFreeEntities<ED extends EntityDict> = (keyof ED)[];
|
||||
export type UpdateFreeDict<ED extends EntityDict> = {
|
||||
[A in keyof ED]?: string[];
|
||||
};
|
||||
export type OtmKey<K extends string> = K | `${K}$${number}`;
|
||||
export interface SubDataDef<ED extends EntityDict, T extends keyof ED> {
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { AsyncContext } from '../store/AsyncRowStore';
|
|||
import { createRemoveCheckers, createCreateCheckers } from '../store/checker';
|
||||
import { createModiRelatedCheckers } from '../store/modi';
|
||||
import { SyncContext } from '../store/SyncRowStore';
|
||||
import { StorageSchema, EntityDict as BaseEntityDict, Checker, AuthCascadePath, CascadeRemoveDefDict } from '../types';
|
||||
import { StorageSchema, EntityDict as BaseEntityDict, Checker } from '../types';
|
||||
|
||||
export function createDynamicCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>) {
|
||||
const checkers: Checker<ED, keyof ED, Cxt>[] = [];
|
||||
|
|
|
|||
|
|
@ -6236,6 +6236,10 @@ function analyzeInModi() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 此部分功能不再使用
|
||||
* @param map
|
||||
*/
|
||||
let IGNORED_FOREIGN_KEY_MAP: Record<string, string[]> = {};
|
||||
let IGNORED_RELATION_PATH_MAP: Record<string, string[]> = {};
|
||||
let DEDUCED_RELATION_MAP: Record<string, string> = {};
|
||||
|
|
@ -6245,10 +6249,18 @@ let UPDATE_FREE_ENTITIES: string[] = [];
|
|||
let FIXED_DESTINATION_PATH_MAP: Record<string, string[]> = {};
|
||||
let FIXED_FOR_ALL_DESTINATION_PATH_ENTITIES: string[] = [];
|
||||
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export function registerIgnoredForeignKeyMap(map: Record<string, string[]>) {
|
||||
IGNORED_FOREIGN_KEY_MAP = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export function registerFreeEntities(
|
||||
selectFreeEntities: string[] = [],
|
||||
createFreeEntities: string[] = [],
|
||||
|
|
@ -6258,6 +6270,10 @@ export function registerFreeEntities(
|
|||
UPDATE_FREE_ENTITIES = updateFreeEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export function registerIgnoredRelationPathMap(map: Record<string, string[]>) {
|
||||
for (const k in map) {
|
||||
IGNORED_RELATION_PATH_MAP[firstLetterUpperCase(k)] = map[k];
|
||||
|
|
@ -6282,6 +6298,10 @@ export function registerFixedDestinationPathMap(map: Record<string, string[]>) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 此函数不再使用
|
||||
* @param map
|
||||
*/
|
||||
export function registerDeducedRelationMap(map: Record<string, string>) {
|
||||
for (const k in map) {
|
||||
const entity = firstLetterUpperCase(k);
|
||||
|
|
@ -6303,6 +6323,7 @@ export function registerDeducedRelationMap(map: Record<string, string>) {
|
|||
|
||||
/**
|
||||
* 输出所有和User相关的对象的后继
|
||||
* 此函数不再使用
|
||||
*/
|
||||
function outputRelation(outputDir: string, printer: ts.Printer) {
|
||||
const ExcludedEntities = ['Oper', 'User', 'OperEntity', 'Modi', 'ModiEntity', 'UserRelation', 'Relation', 'RelationAuth', 'ActionAuth'];
|
||||
|
|
@ -6719,6 +6740,114 @@ function outputRelation(outputDir: string, printer: ts.Printer) {
|
|||
writeFileSync(filename, result, { flag: 'w' });
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出oak-app-domain中的Relation.ts文件
|
||||
* 不再输出actionAuthGraph和relationAuthGraph两个复杂的对象
|
||||
* @param outputDir
|
||||
* @param printer
|
||||
*/
|
||||
function outputRelation2(outputDir: string, printer: ts.Printer) {
|
||||
const entityRelations: [string, string[]][] = [];
|
||||
for (const entity in Schema) {
|
||||
const { hasRelationDef } = Schema[entity];
|
||||
if (hasRelationDef) {
|
||||
const { type } = hasRelationDef;
|
||||
if (ts.isUnionTypeNode(type)) {
|
||||
const { types } = type;
|
||||
const relations = types.map(
|
||||
ele => {
|
||||
assert(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
|
||||
return ele.literal.text;
|
||||
}
|
||||
);
|
||||
entityRelations.push([firstLetterLowerCase(entity), relations]);
|
||||
}
|
||||
else {
|
||||
assert(ts.isLiteralTypeNode(type));
|
||||
assert(ts.isStringLiteral(type.literal));
|
||||
const relations = [type.literal.text];
|
||||
entityRelations.push([firstLetterLowerCase(entity), relations]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const stmts: ts.Statement[] = [
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
undefined,
|
||||
factory.createIdentifier("EntityDict")
|
||||
)])
|
||||
),
|
||||
factory.createStringLiteral("./EntityDict"),
|
||||
undefined
|
||||
),
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
undefined,
|
||||
factory.createNamedImports([factory.createImportSpecifier(
|
||||
false,
|
||||
factory.createIdentifier("CreateOperationData"),
|
||||
factory.createIdentifier("Relation")
|
||||
)])
|
||||
),
|
||||
factory.createStringLiteral("./Relation/Schema"),
|
||||
undefined
|
||||
),
|
||||
factory.createVariableStatement(
|
||||
[factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
||||
factory.createVariableDeclarationList(
|
||||
[factory.createVariableDeclaration(
|
||||
factory.createIdentifier("relations"),
|
||||
undefined,
|
||||
factory.createArrayTypeNode(factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("Relation"),
|
||||
undefined
|
||||
)),
|
||||
factory.createArrayLiteralExpression(
|
||||
flatten(entityRelations.map(
|
||||
([entity, relations]) => relations.map(
|
||||
(relation) => factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("id"),
|
||||
factory.createStringLiteral(formUuid(entity, relation))
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("entity"),
|
||||
factory.createStringLiteral(entity)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("name"),
|
||||
factory.createStringLiteral(relation)
|
||||
)
|
||||
],
|
||||
true
|
||||
)
|
||||
)
|
||||
)),
|
||||
true
|
||||
)
|
||||
)],
|
||||
ts.NodeFlags.Const
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
const result = printer.printList(
|
||||
ts.ListFormat.SourceFileStatements,
|
||||
factory.createNodeArray(stmts),
|
||||
ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, /*setParentNodes*/ false, ts.ScriptKind.TS));
|
||||
const filename = PathLib.join(outputDir, 'Relation.ts');
|
||||
writeFileSync(filename, result, { flag: 'w' });
|
||||
}
|
||||
|
||||
export function analyzeEntities(inputDir: string, relativePath?: string) {
|
||||
const files = readdirSync(inputDir);
|
||||
const fullFilenames = files.map(
|
||||
|
|
@ -6755,7 +6884,7 @@ export function buildSchema(outputDir: string): void {
|
|||
outputAction(outputDir, printer);
|
||||
outputEntityDict(outputDir, printer);
|
||||
outputStorage(outputDir, printer);
|
||||
outputRelation(outputDir, printer);
|
||||
outputRelation2(outputDir, printer);
|
||||
outputIndexTs(outputDir);
|
||||
|
||||
if (!process.env.COMPLING_AS_LIB) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
export { storageSchema, selectFreeEntities } from './base-app-domain';
|
||||
export { storageSchema } from './base-app-domain';
|
||||
|
||||
export type { EntityDict as BaseEntityDict } from './base-app-domain';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import assert from "assert";
|
||||
import { EntityDict } from "../base-app-domain";
|
||||
import { OakException, OakUniqueViolationException, OakUnloggedInException, OakUserInvisibleException, OakUserUnpermittedException, StorageSchema } from "../types";
|
||||
import { AuthCascadePath, EntityDict as BaseEntityDict, AuthDeduceRelationMap } from "../types/Entity";
|
||||
import { OakUnloggedInException, OakUserInvisibleException, OakUserUnpermittedException, StorageSchema } from "../types";
|
||||
import { EntityDict as BaseEntityDict, AuthDeduceRelationMap } from "../types/Entity";
|
||||
import { AsyncContext } from "./AsyncRowStore";
|
||||
import { checkFilterContains, combineFilters } from "./filter";
|
||||
import { judgeRelation } from "./relation";
|
||||
|
|
@ -34,30 +34,25 @@ type CheckRelationResult = {
|
|||
};
|
||||
|
||||
export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
||||
private actionCascadePathGraph: AuthCascadePath<ED>[];
|
||||
private relationCascadePathGraph: AuthCascadePath<ED>[];
|
||||
private authDeduceRelationMap: AuthDeduceRelationMap<ED>;
|
||||
private schema: StorageSchema<ED>;
|
||||
static SPECIAL_ENTITIES = SYSTEM_RESERVE_ENTITIES;
|
||||
|
||||
private selectFreeEntities: (keyof ED)[];
|
||||
private createFreeEntities: (keyof ED)[];
|
||||
private updateFreeEntities: (keyof ED)[];
|
||||
private updateFreeDict: {
|
||||
[A in keyof ED]?: string[];
|
||||
};
|
||||
|
||||
|
||||
constructor(schema: StorageSchema<ED>,
|
||||
actionCascadePathGraph: AuthCascadePath<ED>[],
|
||||
relationCascadePathGraph: AuthCascadePath<ED>[],
|
||||
authDeduceRelationMap: AuthDeduceRelationMap<ED>,
|
||||
selectFreeEntities?: (keyof ED)[],
|
||||
createFreeEntities?: (keyof ED)[],
|
||||
updateFreeEntities?: (keyof ED)[]) {
|
||||
this.actionCascadePathGraph = actionCascadePathGraph;
|
||||
this.relationCascadePathGraph = relationCascadePathGraph;
|
||||
updateFreeDict?: {
|
||||
[A in keyof ED]?: string[];
|
||||
}) {
|
||||
this.schema = schema;
|
||||
this.selectFreeEntities = selectFreeEntities || [];
|
||||
this.createFreeEntities = createFreeEntities || [];
|
||||
this.updateFreeEntities = updateFreeEntities || [];
|
||||
this.updateFreeDict = updateFreeDict || {};
|
||||
this.authDeduceRelationMap = Object.assign({}, authDeduceRelationMap, {
|
||||
modi: 'entity',
|
||||
});
|
||||
|
|
@ -77,55 +72,6 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
this.checkActions2(entity, operation, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户在对应entity上可以操作的relationIds
|
||||
* @param entity
|
||||
* @param entityId
|
||||
* @param context
|
||||
* @returns
|
||||
*/
|
||||
private getGrantedRelationIds<Cxt extends AsyncContext<ED> | SyncContext<ED>>(entity: keyof ED, entityId: string, context: Cxt) {
|
||||
const result = context.select('relationAuth', {
|
||||
data: {
|
||||
id: 1,
|
||||
destRelationId: 1,
|
||||
destRelation: {
|
||||
id: 1,
|
||||
name: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
display: 1,
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
sourceRelation: {
|
||||
userRelation$relation: {
|
||||
userId: context.getCurrentUserId(),
|
||||
}
|
||||
},
|
||||
destRelation: {
|
||||
entity: entity as string,
|
||||
$or: [
|
||||
{
|
||||
entityId,
|
||||
},
|
||||
{
|
||||
entityId: {
|
||||
$exists: false,
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
}, {});
|
||||
if (result instanceof Promise) {
|
||||
return result.then(
|
||||
(r2) => r2.map(ele => ele.destRelation!)
|
||||
);
|
||||
}
|
||||
return result.map(ele => ele.destRelation!);
|
||||
}
|
||||
|
||||
|
||||
// 后台检查filter是否满足relation约束
|
||||
async checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]['Operation'] | ED[T]['Selection'], 'id'>, context: Cxt) {
|
||||
|
|
@ -190,11 +136,6 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
|
||||
const checkRelationAuth = (relationAuth: ED['relationAuth']['Schema']) => {
|
||||
const { destRelation, sourceRelationId, path } = relationAuth;
|
||||
if (action === 'create' && path === '') {
|
||||
// 自己建立自己,一定可以通过
|
||||
return 1;
|
||||
}
|
||||
|
||||
const destEntityFilter: ED[keyof ED]['Selection']['filter'] = {};
|
||||
|
||||
if (path) {
|
||||
|
|
@ -1266,198 +1207,6 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
return checkNode(tree);
|
||||
}
|
||||
|
||||
/* private checkOperationTree<Cxt extends AsyncContext<ED> | SyncContext<ED>>(tree: OperationTree<ED>, context: Cxt) {
|
||||
const actionAuths2 = this.findActionAuthsOnNode(tree, context);
|
||||
|
||||
const checkChildNode = (actionAuths: ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema'][]>, node: OperationTree<ED>): boolean | Promise<boolean> => {
|
||||
const checkChildNodeInner = (legalAuths: ED['actionAuth']['Schema'][]) => {
|
||||
// 因为如果children是数组的话,会把数组中所有的action并起来查询,所以在这里还要再确认一次
|
||||
|
||||
const realLegalPaths = legalAuths.filter(
|
||||
(ele) => {
|
||||
if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
|
||||
return true;
|
||||
}
|
||||
// 有一种例外情况,是在tree的根结点findActionAuthsOnNode时,deduce出了另外一个对象的权限,此时肯定可以通过,但不能再使用这条路径对children进行进一步判断了
|
||||
if (node === tree) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
const checkChildren = () => {
|
||||
const { children } = node;
|
||||
const childPath = Object.keys(children);
|
||||
if (childPath.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const selfLegalPaths = realLegalPaths.filter(
|
||||
(ele) => {
|
||||
if (ele.destEntity === node.entity && ele.deActions.includes(node.action)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
// assert(selfLegalPaths.length > 0, `对象${node.entity as string}的权限检查是用deduce的对象通过的,无法再进一步对子对象加以判断`);
|
||||
const childResult = childPath.map(
|
||||
(childPath) => {
|
||||
const child = children[childPath];
|
||||
const childEntity = child instanceof Array ? child[0].entity : child.entity;
|
||||
// 这里如果该子结点能deduce到父,则直接通过
|
||||
if (this.authDeduceRelationMap[childEntity]) {
|
||||
assert(this.authDeduceRelationMap[childEntity] === 'entity');
|
||||
const rel = judgeRelation(this.schema, childEntity, childPath);
|
||||
if (rel === 2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const pathToParent = childPath.endsWith('$entity') ? node.entity as string : childPath.split('$')[1];
|
||||
if (child instanceof Array) {
|
||||
const childActions = child.map(ele => ele.action);
|
||||
const childLegalAuths = selfLegalPaths.map(
|
||||
(ele) => {
|
||||
const { paths, relationId } = ele;
|
||||
const paths2 = paths.map(
|
||||
(path) => path ? `${pathToParent}.${path}` : pathToParent
|
||||
);
|
||||
return context.select('actionAuth', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
paths: {
|
||||
$overlaps: paths2,
|
||||
},
|
||||
destEntity: childEntity as string,
|
||||
deActions: {
|
||||
$overlaps: childActions,
|
||||
},
|
||||
relationId: relationId || {
|
||||
$exists: false,
|
||||
},
|
||||
}
|
||||
}, { dontCollect: true })
|
||||
}
|
||||
).flat() as ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema']>[];
|
||||
if (childLegalAuths[0] instanceof Promise) {
|
||||
return Promise.all(childLegalAuths).then(
|
||||
(clas) => child.map(
|
||||
(c) => checkChildNode(clas, c)
|
||||
)
|
||||
)
|
||||
}
|
||||
return child.map(
|
||||
(c) => checkChildNode(childLegalAuths as ED['actionAuth']['Schema'][], c)
|
||||
);
|
||||
}
|
||||
|
||||
const childLegalAuths = realLegalPaths.map(
|
||||
(ele) => {
|
||||
const { paths, relationId } = ele;
|
||||
const paths2 = paths.map(
|
||||
(path) => path ? `${pathToParent}.${path}` : pathToParent
|
||||
);
|
||||
return context.select('actionAuth', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
paths: {
|
||||
$overlaps: paths2,
|
||||
},
|
||||
destEntity: childEntity as string,
|
||||
deActions: {
|
||||
$overlaps: child.action,
|
||||
},
|
||||
relationId: relationId || {
|
||||
$exists: false,
|
||||
},
|
||||
}
|
||||
}, { dontCollect: true })
|
||||
}
|
||||
).flat() as ED['actionAuth']['Schema'][] | Promise<ED['actionAuth']['Schema']>[];
|
||||
|
||||
if (childLegalAuths[0] instanceof Promise) {
|
||||
return Promise.all(childLegalAuths).then(
|
||||
(clas) => checkChildNode(clas.flat(), child)
|
||||
);
|
||||
}
|
||||
return checkChildNode(childLegalAuths as ED['actionAuth']['Schema'][], child);
|
||||
}
|
||||
).flat();
|
||||
|
||||
if (childResult[0] instanceof Promise) {
|
||||
return Promise.all(childResult).then(
|
||||
(r) => !r.includes(false)
|
||||
);
|
||||
}
|
||||
return !childResult.includes(false);
|
||||
};
|
||||
|
||||
if (RelationAuth.SPECIAL_ENTITIES.includes(node.entity as string)) {
|
||||
// 特殊entity走特别的路径判断
|
||||
const result = this.checkOperateSpecialEntities2(node.entity, node.action, node.filter, context);
|
||||
|
||||
if (result instanceof Promise) {
|
||||
return result.then(
|
||||
(r) => {
|
||||
if (r) {
|
||||
return checkChildren();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
if (result) {
|
||||
if (node.entity === 'user') {
|
||||
// 如果当前是对user对象操作,需要加上一个指向它自身的actionAuth,否则剩下的子对象会判定不过
|
||||
// user的操作权限由应用自己决定,如果user的操作最终过不去,这里放过也没关系
|
||||
assert(node === tree && realLegalPaths.length === 0); // user不可能是非根结点
|
||||
realLegalPaths.push({
|
||||
id: 'temp',
|
||||
paths: [''],
|
||||
$$createAt$$: 1,
|
||||
$$updateAt$$: 1,
|
||||
$$seq$$: 'temp',
|
||||
destEntity: 'user',
|
||||
deActions: [node.action],
|
||||
});
|
||||
}
|
||||
return checkChildren();
|
||||
}
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('对象operate权限检查不通过', node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (realLegalPaths.length === 0) {
|
||||
if (node === tree) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('对象operate权限检查不通过', node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// 如果不是tree的根结点,相对路径上的actionAuth找不到,还可以尝试从自身的filter去重试其它路径
|
||||
return this.checkOperationTree(node, context);
|
||||
}
|
||||
|
||||
return checkChildren();
|
||||
};
|
||||
|
||||
if (actionAuths instanceof Promise) {
|
||||
return actionAuths.then(
|
||||
(aars) => checkChildNodeInner(aars)
|
||||
);
|
||||
}
|
||||
return checkChildNodeInner(actionAuths);
|
||||
};
|
||||
|
||||
return checkChildNode(actionAuths2, tree);
|
||||
} */
|
||||
|
||||
private checkOperation<T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>>(
|
||||
entity: T,
|
||||
|
|
@ -1465,11 +1214,8 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict>{
|
|||
context: Cxt,
|
||||
) {
|
||||
const { action, filter, data } = operation;
|
||||
if (action === 'create' && this.createFreeEntities.includes(entity)) {
|
||||
return true;
|
||||
}
|
||||
else if (action === 'update' && this.updateFreeEntities.includes(entity)) {
|
||||
return true;
|
||||
if (this.updateFreeDict[entity] && this.updateFreeDict[entity]!.includes(action)) {
|
||||
return true;
|
||||
}
|
||||
const userId = context.getCurrentUserId();
|
||||
if (!userId) {
|
||||
|
|
|
|||
|
|
@ -262,11 +262,13 @@ export type Configuration = {
|
|||
static?: boolean; // 标识是维表(变动较小,相对独立)
|
||||
};
|
||||
|
||||
export type AuthCascadePath<ED extends EntityDict> = [keyof ED, string, keyof ED, boolean];
|
||||
export type AuthDeduceRelationMap<ED extends EntityDict> = {
|
||||
[T in keyof ED]?: keyof ED[T]['OpSchema'];
|
||||
};
|
||||
export type SelectFreeEntities<ED extends EntityDict> = (keyof ED)[];
|
||||
export type UpdateFreeDict<ED extends EntityDict> = {
|
||||
[A in keyof ED]?: string[];
|
||||
};
|
||||
// 一对多的键值的扩展
|
||||
export type OtmKey<K extends string> = K | `${K}$${number}`;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue