简化了checker定义
This commit is contained in:
parent
c1eae2142f
commit
a49e37a5fe
|
|
@ -3155,13 +3155,21 @@ function outputStorage(outputDir, printer) {
|
|||
} */
|
||||
if (hasRelationDef) {
|
||||
var type = hasRelationDef.type;
|
||||
(0, assert_1.default)(ts.isUnionTypeNode(type));
|
||||
var types = type.types;
|
||||
var relationTexts = types.map(function (ele) {
|
||||
(0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
|
||||
return ele.literal.text;
|
||||
});
|
||||
propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("relation"), factory.createArrayLiteralExpression(relationTexts.map(function (ele) { return factory.createStringLiteral(ele); }))));
|
||||
if (ts.isUnionTypeNode(type)) {
|
||||
var types = type.types;
|
||||
var relationTexts = types.map(function (ele) {
|
||||
(0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
|
||||
return ele.literal.text;
|
||||
});
|
||||
propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("relation"), factory.createArrayLiteralExpression(relationTexts.map(function (ele) { return factory.createStringLiteral(ele); }))));
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(ts.isLiteralTypeNode(type));
|
||||
(0, assert_1.default)(ts.isStringLiteral(type.literal));
|
||||
propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("relation"), factory.createArrayLiteralExpression([
|
||||
type.literal
|
||||
])));
|
||||
}
|
||||
}
|
||||
var sdTypeArguments = [
|
||||
factory.createTypeReferenceNode(factory.createIdentifier("OpSchema"), undefined)
|
||||
|
|
|
|||
|
|
@ -138,49 +138,22 @@ function translateCheckerInAsyncContext(checker) {
|
|||
});
|
||||
});
|
||||
}
|
||||
case 'expression':
|
||||
case 'expressionRelation': {
|
||||
var expression_1 = checker.expression, errMsg_2 = checker.errMsg;
|
||||
case 'logical':
|
||||
case 'logicalRelation': {
|
||||
var checkerFn_2 = checker.checker;
|
||||
return (function (_a, context, option) {
|
||||
var operation = _a.operation;
|
||||
return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||
var exprResult, expressionEntity, expr, expressionFilter, _b, result, isLegal;
|
||||
return tslib_1.__generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
return tslib_1.__generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
case 0:
|
||||
if (context.isRoot() && type === 'expressionRelation') {
|
||||
if (context.isRoot() && type === 'logicalRelation') {
|
||||
return [2 /*return*/, 0];
|
||||
}
|
||||
return [4 /*yield*/, expression_1(operation, context, option)];
|
||||
return [4 /*yield*/, checkerFn_2(operation, context, option)];
|
||||
case 1:
|
||||
exprResult = _c.sent();
|
||||
if (!(typeof exprResult === 'string')) return [3 /*break*/, 2];
|
||||
throw new Exception_1.OakUserUnpermittedException(exprResult || errMsg_2);
|
||||
case 2:
|
||||
if (!(exprResult === undefined)) return [3 /*break*/, 3];
|
||||
_b.sent();
|
||||
return [2 /*return*/, 0];
|
||||
case 3:
|
||||
expressionEntity = exprResult.entity, expr = exprResult.expr, expressionFilter = exprResult.filter;
|
||||
return [4 /*yield*/, context.select(expressionEntity, {
|
||||
data: {
|
||||
$expr: expr,
|
||||
},
|
||||
filter: expressionFilter,
|
||||
}, Object.assign({}, option, { dontCollect: true }))];
|
||||
case 4:
|
||||
_b = tslib_1.__read.apply(void 0, [_c.sent(), 1]), result = _b[0];
|
||||
isLegal = result ? result.$expr : false;
|
||||
if (!isLegal) {
|
||||
// 条件判定为假,抛异常
|
||||
if (type === 'expression') {
|
||||
throw new Exception_1.OakRowInconsistencyException(undefined, errMsg_2);
|
||||
}
|
||||
else {
|
||||
throw new Exception_1.OakUserUnpermittedException(errMsg_2);
|
||||
}
|
||||
}
|
||||
_c.label = 5;
|
||||
case 5: return [2 /*return*/, 0];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -196,11 +169,11 @@ function translateCheckerInSyncContext(checker) {
|
|||
var entity = checker.entity, type = checker.type;
|
||||
switch (type) {
|
||||
case 'data': {
|
||||
var checkerFn_2 = checker.checker;
|
||||
return function (operation, context) { return checkerFn_2(operation.data, context); };
|
||||
var checkerFn_3 = checker.checker;
|
||||
return function (operation, context) { return checkerFn_3(operation.data, context); };
|
||||
}
|
||||
case 'row': {
|
||||
var filter_3 = checker.filter, errMsg_3 = checker.errMsg;
|
||||
var filter_3 = checker.filter, errMsg_2 = checker.errMsg;
|
||||
return function (operation, context, option) {
|
||||
var operationFilter = operation.filter, action = operation.action;
|
||||
var filter2 = typeof filter_3 === 'function' ? filter_3(operation, context, option) : filter_3;
|
||||
|
|
@ -214,12 +187,12 @@ function translateCheckerInSyncContext(checker) {
|
|||
if ((0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter, true)) {
|
||||
return;
|
||||
}
|
||||
throw new Exception_1.OakRowInconsistencyException(undefined, errMsg_3);
|
||||
throw new Exception_1.OakRowInconsistencyException(undefined, errMsg_2);
|
||||
}
|
||||
};
|
||||
}
|
||||
case 'relation': {
|
||||
var filter_4 = checker.relationFilter, errMsg_4 = checker.errMsg;
|
||||
var filter_4 = checker.relationFilter, errMsg_3 = checker.errMsg;
|
||||
return function (operation, context, option) {
|
||||
if (context.isRoot()) {
|
||||
return;
|
||||
|
|
@ -231,43 +204,17 @@ function translateCheckerInSyncContext(checker) {
|
|||
if ((0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter, true)) {
|
||||
return;
|
||||
}
|
||||
throw new Exception_1.OakUserUnpermittedException(errMsg_4);
|
||||
throw new Exception_1.OakUserUnpermittedException(errMsg_3);
|
||||
};
|
||||
}
|
||||
case 'expression':
|
||||
case 'expressionRelation': {
|
||||
var expression_2 = checker.expression, errMsg_5 = checker.errMsg;
|
||||
case 'logical':
|
||||
case 'logicalRelation': {
|
||||
var checkerFn_4 = checker.checker;
|
||||
return function (operation, context, option) {
|
||||
if (context.isRoot() && type === 'expressionRelation') {
|
||||
if (context.isRoot() && type === 'logicalRelation') {
|
||||
return;
|
||||
}
|
||||
var exprResult = expression_2(operation, context, option);
|
||||
if (typeof exprResult === 'string') {
|
||||
throw new Exception_1.OakUserUnpermittedException(exprResult || errMsg_5);
|
||||
}
|
||||
else if (exprResult === undefined) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(!(exprResult instanceof Promise));
|
||||
var expressionEntity = exprResult.entity, expr = exprResult.expr, expressionFilter = exprResult.filter;
|
||||
var _a = tslib_1.__read(context.select(expressionEntity, {
|
||||
data: {
|
||||
$expr: expr,
|
||||
},
|
||||
filter: expressionFilter,
|
||||
}, Object.assign({}, option, { dontCollect: true })), 1), result = _a[0];
|
||||
var isLegal = result ? result.$expr : false;
|
||||
if (!isLegal) {
|
||||
// 条件判定为假,抛异常
|
||||
if (type === 'expression') {
|
||||
throw new Exception_1.OakRowInconsistencyException(undefined, errMsg_5);
|
||||
}
|
||||
else {
|
||||
throw new Exception_1.OakUserUnpermittedException(errMsg_5);
|
||||
}
|
||||
}
|
||||
}
|
||||
checkerFn_4(operation, context, option);
|
||||
};
|
||||
}
|
||||
default: {
|
||||
|
|
@ -428,8 +375,8 @@ function createAuthCheckers(schema, authDict) {
|
|||
checkers.push({
|
||||
entity: userEntityName_1,
|
||||
action: 'create',
|
||||
type: 'expressionRelation',
|
||||
expression: function (operation, context) {
|
||||
type: 'relation',
|
||||
relationFilter: function (operation, context) {
|
||||
var data = operation.data;
|
||||
(0, assert_1.default)(!(data instanceof Array));
|
||||
var _a = data, relation = _a.relation, _b = entityIdAttr_1, entityId = _a[_b];
|
||||
|
|
@ -438,15 +385,7 @@ function createAuthCheckers(schema, authDict) {
|
|||
return;
|
||||
}
|
||||
var filter = raFilterMakerDict_1[relation](userId);
|
||||
return {
|
||||
entity: entity,
|
||||
filter: (0, filter_1.combineFilters)([filter, { id: entityId }]),
|
||||
expr: {
|
||||
$gt: [{
|
||||
'#attr': '$$createAt$$',
|
||||
}, 0]
|
||||
},
|
||||
};
|
||||
return filter;
|
||||
},
|
||||
errMsg: '越权操作',
|
||||
});
|
||||
|
|
@ -500,34 +439,34 @@ function createAuthCheckers(schema, authDict) {
|
|||
* create动作所增加的auth约束只可能在外键的对象上,但因为还有级联和触发器,不太容易在创建前检查,先放在创建后
|
||||
*/
|
||||
var _c = actionAuth[a];
|
||||
checkers.push({
|
||||
entity: entity,
|
||||
/* checkers.push({
|
||||
entity,
|
||||
action: a,
|
||||
type: 'expressionRelation',
|
||||
when: 'after',
|
||||
expression: function (operation, context) {
|
||||
expression: (operation, context) => {
|
||||
// 在插入后检查
|
||||
var makeExprInner = function (data) {
|
||||
var id = data.id;
|
||||
const makeExprInner = (data: ED[keyof ED]['CreateSingle']['data']) => {
|
||||
const { id } = data;
|
||||
return {
|
||||
entity: entity,
|
||||
filter: (0, filter_1.combineFilters)([filter, { id: id }]),
|
||||
entity,
|
||||
filter: combineFilters([filter, { id }]),
|
||||
expr: {
|
||||
$gt: [{
|
||||
'#attr': '$$createAt$$',
|
||||
}, 0]
|
||||
'#attr': '$$createAt$$',
|
||||
}, 0] as any
|
||||
},
|
||||
};
|
||||
};
|
||||
var filter = filterMaker(context.getCurrentUserId());
|
||||
var data = operation.data;
|
||||
const filter = filterMaker(context.getCurrentUserId()!);
|
||||
const { data } = operation as ED[keyof ED]['Create'];
|
||||
if (data instanceof Array) {
|
||||
throw new Error('需要expr支持count');
|
||||
}
|
||||
return makeExprInner(data);
|
||||
},
|
||||
errMsg: '定义的actionAuth中检查出来越权操作',
|
||||
});
|
||||
}); */
|
||||
}
|
||||
else {
|
||||
checkers.push({
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ export declare type RelationChecker<ED extends EntityDict, T extends keyof ED, C
|
|||
priority?: number;
|
||||
type: 'relation';
|
||||
entity: T;
|
||||
action: Omit<ED[T]['Action'], 'create'> | Array<Omit<ED[T]['Action'], 'create'>>;
|
||||
when?: 'after';
|
||||
action: ED[T]['Action'] | Array<ED[T]['Action']>;
|
||||
relationFilter: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => ED[T]['Selection']['filter'] | Promise<ED[T]['Selection']['filter']>;
|
||||
errMsg: string;
|
||||
conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter'] | Promise<ED[T]['Selection']['filter']>);
|
||||
|
|
@ -44,27 +45,25 @@ export declare type ExpressionTask<ED extends EntityDict, T extends keyof ED> =
|
|||
filter: ED[T]['Selection']['filter'];
|
||||
};
|
||||
export declare type ExpressionTaskCombination<ED extends EntityDict> = ExpressionTask<ED, keyof ED>;
|
||||
export declare type ExpressionChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
export declare type LogicalChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
priority?: number;
|
||||
type: 'expression';
|
||||
type: 'logical';
|
||||
when?: 'after';
|
||||
entity: T;
|
||||
action: ED[T]['Action'] | Array<ED[T]['Action']>;
|
||||
expression: <T2 extends keyof ED>(operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => ExpressionTaskCombination<ED> | undefined | string | Promise<ExpressionTaskCombination<ED> | string | undefined>;
|
||||
errMsg: string;
|
||||
checker: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => void | Promise<void>;
|
||||
conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
|
||||
};
|
||||
export declare type ExpressionRelationChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
export declare type LogicalRelationChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
priority?: number;
|
||||
type: 'expressionRelation';
|
||||
type: 'logicalRelation';
|
||||
when?: 'after';
|
||||
entity: T;
|
||||
action: ED[T]['Action'] | Array<ED[T]['Action']>;
|
||||
expression: <T2 extends keyof ED>(operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => ExpressionTaskCombination<ED> | undefined | string | Promise<ExpressionTaskCombination<ED> | string | undefined>;
|
||||
errMsg: string;
|
||||
checker: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => void | Promise<void>;
|
||||
conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
|
||||
};
|
||||
export declare type Checker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = DataChecker<ED, T, Cxt> | RowChecker<ED, T, Cxt> | RelationChecker<ED, T, Cxt> | ExpressionChecker<ED, T, Cxt> | ExpressionRelationChecker<ED, T, Cxt>;
|
||||
export declare type Checker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = DataChecker<ED, T, Cxt> | RowChecker<ED, T, Cxt> | RelationChecker<ED, T, Cxt> | LogicalChecker<ED, T, Cxt> | LogicalRelationChecker<ED, T, Cxt>;
|
||||
export declare type AuthDef<ED extends EntityDict, T extends keyof ED> = {
|
||||
relationAuth?: CascadeRelationAuth<NonNullable<ED[T]['Relation']>>;
|
||||
actionAuth?: CascadeActionAuth<ED[T]['Action']>;
|
||||
|
|
|
|||
|
|
@ -5899,23 +5899,39 @@ function outputStorage(outputDir: string, printer: ts.Printer) {
|
|||
} */
|
||||
if (hasRelationDef) {
|
||||
const { type } = hasRelationDef;
|
||||
assert(ts.isUnionTypeNode(type));
|
||||
const { types } = type;
|
||||
const relationTexts = types.map(
|
||||
ele => {
|
||||
assert(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
|
||||
return ele.literal.text;
|
||||
}
|
||||
)
|
||||
propertyAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("relation"),
|
||||
factory.createArrayLiteralExpression(relationTexts.map(
|
||||
ele => factory.createStringLiteral(ele)
|
||||
)),
|
||||
if (ts.isUnionTypeNode(type)) {
|
||||
const { types } = type;
|
||||
const relationTexts = types.map(
|
||||
ele => {
|
||||
assert(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
|
||||
return ele.literal.text;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
propertyAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("relation"),
|
||||
factory.createArrayLiteralExpression(relationTexts.map(
|
||||
ele => factory.createStringLiteral(ele)
|
||||
)),
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
assert(ts.isLiteralTypeNode(type));
|
||||
assert(ts.isStringLiteral(type.literal));
|
||||
|
||||
propertyAssignments.push(
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("relation"),
|
||||
factory.createArrayLiteralExpression(
|
||||
[
|
||||
type.literal
|
||||
]
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
const sdTypeArguments = [
|
||||
factory.createTypeReferenceNode(
|
||||
factory.createIdentifier("OpSchema"),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { addFilterSegment, checkFilterRepel } from "../store/filter";
|
|||
import { DeduceCreateOperation, EntityDict, OperateOption, SelectOption, TriggerDataAttribute, TriggerTimestampAttribute } from "../types/Entity";
|
||||
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||
import { Logger } from "../types/Logger";
|
||||
import { Checker, CheckerType, ExpressionChecker, RelationChecker } from '../types/Auth';
|
||||
import { Checker, CheckerType, LogicalChecker, RelationChecker } from '../types/Auth';
|
||||
import { Trigger, CreateTriggerCrossTxn, CreateTrigger, CreateTriggerInTxn, SelectTriggerAfter, UpdateTrigger } from "../types/Trigger";
|
||||
import { AsyncContext } from './AsyncRowStore';
|
||||
import { SyncContext } from './SyncRowStore';
|
||||
|
|
@ -57,7 +57,7 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict> {
|
|||
entity,
|
||||
action: action as 'update',
|
||||
fn,
|
||||
when: (checker as ExpressionChecker<ED, T, Cxt>).when || 'before',
|
||||
when: (checker as LogicalChecker<ED, T, Cxt>).when || 'before',
|
||||
filter: conditionalFilter,
|
||||
} as UpdateTrigger<ED, T, Cxt>;
|
||||
this.registerTrigger(trigger);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import assert from 'assert';
|
||||
import { addFilterSegment, checkFilterContains, combineFilters } from "../store/filter";
|
||||
import { OakDataException, OakRowInconsistencyException, OakUserUnpermittedException } from '../types/Exception';
|
||||
import { AuthDef, AuthDefDict, CascadeRelationItem, Checker, CreateTriggerInTxn, EntityDict, ExpressionRelationChecker, ExpressionTask, ExpressionTaskCombination, OperateOption, RefOrExpression, RelationHierarchy, CascadeRelationAuth, SelectOption, StorageSchema, Trigger, UpdateTriggerInTxn } from "../types";
|
||||
import { AuthDef, AuthDefDict, CascadeRelationItem, Checker, CreateTriggerInTxn, EntityDict, LogicalRelationChecker, ExpressionTask, ExpressionTaskCombination, OperateOption, RefOrExpression, RelationHierarchy, CascadeRelationAuth, SelectOption, StorageSchema, Trigger, UpdateTriggerInTxn } from "../types";
|
||||
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||
import { AsyncContext } from "./AsyncRowStore";
|
||||
import { getFullProjection } from './actionDef';
|
||||
|
|
@ -96,39 +96,14 @@ export function translateCheckerInAsyncContext<
|
|||
return 0;
|
||||
}) as UpdateTriggerInTxn<ED, keyof ED, Cxt>['fn'];
|
||||
}
|
||||
case 'expression':
|
||||
case 'expressionRelation': {
|
||||
const { expression, errMsg } = checker;
|
||||
case 'logical':
|
||||
case 'logicalRelation': {
|
||||
const { checker: checkerFn } = checker;
|
||||
return (async ({ operation }, context, option) => {
|
||||
if (context.isRoot() && type === 'expressionRelation') {
|
||||
if (context.isRoot() && type === 'logicalRelation') {
|
||||
return 0;
|
||||
}
|
||||
const exprResult = await expression(operation, context, option);
|
||||
if (typeof exprResult === 'string') {
|
||||
throw new OakUserUnpermittedException(exprResult || errMsg);
|
||||
}
|
||||
else if (exprResult === undefined) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const { entity: expressionEntity, expr, filter: expressionFilter } = exprResult;
|
||||
const [result] = await context.select(expressionEntity, {
|
||||
data: {
|
||||
$expr: expr,
|
||||
},
|
||||
filter: expressionFilter,
|
||||
}, Object.assign({}, option, { dontCollect: true }));
|
||||
const isLegal = result ? result.$expr as boolean : false;
|
||||
if (!isLegal) {
|
||||
// 条件判定为假,抛异常
|
||||
if (type === 'expression') {
|
||||
throw new OakRowInconsistencyException(undefined, errMsg);
|
||||
}
|
||||
else {
|
||||
throw new OakUserUnpermittedException(errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
await checkerFn(operation, context, option);
|
||||
return 0;
|
||||
}) as UpdateTriggerInTxn<ED, keyof ED, Cxt>['fn'];
|
||||
}
|
||||
|
|
@ -184,40 +159,14 @@ export function translateCheckerInSyncContext<
|
|||
throw new OakUserUnpermittedException(errMsg);
|
||||
};
|
||||
}
|
||||
case 'expression':
|
||||
case 'expressionRelation': {
|
||||
const { expression, errMsg } = checker;
|
||||
case 'logical':
|
||||
case 'logicalRelation': {
|
||||
const { checker: checkerFn } = checker;
|
||||
return (operation, context, option) => {
|
||||
if (context.isRoot() && type === 'expressionRelation') {
|
||||
if (context.isRoot() && type === 'logicalRelation') {
|
||||
return;
|
||||
}
|
||||
const exprResult = expression(operation, context, option);
|
||||
if (typeof exprResult === 'string') {
|
||||
throw new OakUserUnpermittedException(exprResult || errMsg);
|
||||
}
|
||||
else if (exprResult === undefined) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
assert(!(exprResult instanceof Promise));
|
||||
const { entity: expressionEntity, expr, filter: expressionFilter } = exprResult;
|
||||
const [result] = context.select(expressionEntity, {
|
||||
data: {
|
||||
$expr: expr,
|
||||
},
|
||||
filter: expressionFilter,
|
||||
}, Object.assign({}, option, { dontCollect: true }));
|
||||
const isLegal = result ? result.$expr as boolean : false;
|
||||
if (!isLegal) {
|
||||
// 条件判定为假,抛异常
|
||||
if (type === 'expression') {
|
||||
throw new OakRowInconsistencyException(undefined, errMsg);
|
||||
}
|
||||
else {
|
||||
throw new OakUserUnpermittedException(errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
checkerFn(operation, context, option);
|
||||
};
|
||||
}
|
||||
default: {
|
||||
|
|
@ -386,8 +335,8 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
|||
checkers.push({
|
||||
entity: userEntityName as keyof ED,
|
||||
action: 'create',
|
||||
type: 'expressionRelation',
|
||||
expression: (operation, context) => {
|
||||
type: 'relation',
|
||||
relationFilter: (operation, context) => {
|
||||
const { data } = operation as ED[keyof ED]['Create'];
|
||||
assert(!(data instanceof Array));
|
||||
const { relation, [entityIdAttr]: entityId } = data;
|
||||
|
|
@ -396,15 +345,7 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
|||
return;
|
||||
}
|
||||
const filter = raFilterMakerDict[relation]!(userId!);
|
||||
return {
|
||||
entity,
|
||||
filter: combineFilters([filter, { id: entityId }]),
|
||||
expr: {
|
||||
$gt: [{
|
||||
'#attr': '$$createAt$$',
|
||||
}, 0]
|
||||
},
|
||||
}
|
||||
return filter;
|
||||
},
|
||||
errMsg: '越权操作',
|
||||
});
|
||||
|
|
@ -465,7 +406,7 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
|||
* create动作所增加的auth约束只可能在外键的对象上,但因为还有级联和触发器,不太容易在创建前检查,先放在创建后
|
||||
*/
|
||||
const { } = actionAuth[a as ED[keyof ED]['Action']]!;
|
||||
checkers.push({
|
||||
/* checkers.push({
|
||||
entity,
|
||||
action: a,
|
||||
type: 'expressionRelation',
|
||||
|
|
@ -492,7 +433,7 @@ export function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt e
|
|||
return makeExprInner(data);
|
||||
},
|
||||
errMsg: '定义的actionAuth中检查出来越权操作',
|
||||
});
|
||||
}); */
|
||||
}
|
||||
else {
|
||||
checkers.push({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||
import { OpSchema as Modi, Filter } from '../base-app-domain/Modi/Schema';
|
||||
import { Checker, Operation, StorageSchema, RowChecker, EntityDict, OakRowLockedException, Context, OperateOption, Trigger, RemoveTrigger, RelationChecker, ExpressionChecker, ExpressionRelationChecker, OakUserUnpermittedException } from '../types';
|
||||
import { Checker, Operation, StorageSchema, RowChecker, EntityDict, OakRowLockedException, Context, OperateOption, Trigger, RemoveTrigger, RelationChecker, LogicalChecker, LogicalRelationChecker, OakUserUnpermittedException } from '../types';
|
||||
import { appendOnlyActions } from '../actions/action';
|
||||
import { difference } from '../utils/lodash';
|
||||
import { AsyncContext } from './AsyncRowStore';
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ export type RelationChecker<ED extends EntityDict, T extends keyof ED, Cxt exten
|
|||
priority?: number;
|
||||
type: 'relation';
|
||||
entity: T;
|
||||
action: Omit<ED[T]['Action'], 'create'> | Array<Omit<ED[T]['Action'], 'create'>>;
|
||||
when?: 'after';
|
||||
action: ED[T]['Action'] | Array<ED[T]['Action']>;
|
||||
relationFilter: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => ED[T]['Selection']['filter'] | Promise<ED[T]['Selection']['filter']>; // 生成一个额外的relation相关的filter,加在原先的filter上
|
||||
errMsg: string;
|
||||
conditionalFilter?: ED[T]['Update']['filter'] | (
|
||||
|
|
@ -59,39 +60,37 @@ export type ExpressionTask<ED extends EntityDict, T extends keyof ED> = {
|
|||
|
||||
export type ExpressionTaskCombination<ED extends EntityDict> = ExpressionTask<ED, keyof ED>;
|
||||
|
||||
export type ExpressionChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
export type LogicalChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
priority?: number;
|
||||
type: 'expression';
|
||||
type: 'logical';
|
||||
when?: 'after';
|
||||
entity: T;
|
||||
action: ED[T]['Action'] | Array<ED[T]['Action']>;
|
||||
expression: <T2 extends keyof ED>(
|
||||
checker: (
|
||||
operation: ED[T]['Operation'] | ED[T]['Selection'],
|
||||
context: Cxt,
|
||||
option: OperateOption | SelectOption
|
||||
) => ExpressionTaskCombination<ED> | undefined | string | Promise<ExpressionTaskCombination<ED> | string | undefined> ; // 生成一个带表达式的查询任务数组,表达式结果为true代表可以过(or关系)。如果返回undefined直接过,返回string直接挂
|
||||
errMsg: string;
|
||||
) => void | Promise<void>;
|
||||
conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
|
||||
};
|
||||
|
||||
export type ExpressionRelationChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
export type LogicalRelationChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
|
||||
priority?: number;
|
||||
type: 'expressionRelation';
|
||||
type: 'logicalRelation';
|
||||
when?: 'after';
|
||||
entity: T;
|
||||
action: ED[T]['Action'] | Array<ED[T]['Action']>;
|
||||
expression: <T2 extends keyof ED>(
|
||||
checker: (
|
||||
operation: ED[T]['Operation'] | ED[T]['Selection'],
|
||||
context: Cxt,
|
||||
option: OperateOption | SelectOption
|
||||
) => ExpressionTaskCombination<ED> | undefined | string | Promise<ExpressionTaskCombination<ED> | string | undefined> ; // 生成一个带表达式的查询任务数组,表达式结果为true代表可以过(or关系)。如果返回undefined直接过,返回string直接挂
|
||||
errMsg: string;
|
||||
) => void | Promise<void>;
|
||||
conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
|
||||
};
|
||||
|
||||
|
||||
export type Checker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> =
|
||||
DataChecker<ED, T, Cxt> | RowChecker<ED, T, Cxt> | RelationChecker<ED, T, Cxt> | ExpressionChecker<ED, T, Cxt> | ExpressionRelationChecker<ED, T, Cxt>;
|
||||
DataChecker<ED, T, Cxt> | RowChecker<ED, T, Cxt> | RelationChecker<ED, T, Cxt> | LogicalChecker<ED, T, Cxt> | LogicalRelationChecker<ED, T, Cxt>;
|
||||
|
||||
|
||||
export type AuthDef<ED extends EntityDict, T extends keyof ED> = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue