对新的auth设计的大量适配

This commit is contained in:
Xu Chang 2023-04-28 20:02:29 +08:00
parent fc0a391638
commit 6f41bc2b30
6 changed files with 137 additions and 13 deletions

View File

@ -52,9 +52,10 @@ class AppLoader extends types_1.AppLoader {
constructor(path, contextBuilder, dbConfig) {
super(path);
const { storageSchema } = require(`${path}/lib/oak-app-domain/Storage`);
const { ActionCascadePathGraph, RelationCascadePathGraph } = require(`${path}/lib/oak-app-domain/Relation`);
this.externalDependencies = require(`${path}/lib/config/externalDependencies`).default;
this.aspectDict = Object.assign({}, index_1.default, this.requireSth('lib/aspects/index'));
this.dbStore = new DbStore_1.DbStore(storageSchema, contextBuilder, dbConfig);
this.dbStore = new DbStore_1.DbStore(storageSchema, contextBuilder, dbConfig, ActionCascadePathGraph, RelationCascadePathGraph);
this.contextBuilder = contextBuilder;
}
initTriggers() {
@ -67,7 +68,8 @@ class AppLoader extends types_1.AppLoader {
adTriggers.forEach((trigger) => this.dbStore.registerTrigger(trigger));
checkers.forEach((checker) => this.dbStore.registerChecker(checker));
adCheckers.forEach((checker) => this.dbStore.registerChecker(checker));
const dynamicCheckers = (0, checkers_1.createDynamicCheckers)(this.dbStore.getSchema(), authDict);
// todo cascadeRemoveTrigger要挪到Schema定义里
const dynamicCheckers = (0, checkers_1.createDynamicCheckers)(this.dbStore.getSchema(), {});
dynamicCheckers.forEach((checker) => this.dbStore.registerChecker(checker));
const dynamicTriggers = (0, triggers_1.createDynamicTriggers)(this.dbStore.getSchema());
dynamicTriggers.forEach((trigger) => this.dbStore.registerTrigger(trigger));

9
lib/DbStore.d.ts vendored
View File

@ -1,11 +1,16 @@
import { MysqlStore, MySqlSelectOption, MysqlOperateOption } from 'oak-db';
import { EntityDict, StorageSchema, Trigger, Checker, SelectOption } from 'oak-domain/lib/types';
import { EntityDict, StorageSchema, Trigger, Checker, SelectOption, AuthCascadePath } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { MySQLConfiguration } from 'oak-db/lib/MySQL/types/Configuration';
import { AsyncContext, AsyncRowStore } from 'oak-domain/lib/store/AsyncRowStore';
export declare class DbStore<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends MysqlStore<ED, Cxt> implements AsyncRowStore<ED, Cxt> {
private executor;
constructor(storageSchema: StorageSchema<ED>, contextBuilder: (scene?: string) => (store: DbStore<ED, Cxt>) => Promise<AsyncContext<ED>>, mysqlConfiguration: MySQLConfiguration);
private relationAuth;
constructor(storageSchema: StorageSchema<ED>, contextBuilder: (scene?: string) => (store: DbStore<ED, Cxt>) => Promise<Cxt>, mysqlConfiguration: MySQLConfiguration, actionCascadeGraph: AuthCascadePath<ED>[], relationCascadeGraph: AuthCascadePath<ED>[]);
/**
* relationAuth中需要缓存一些维表的数据
*/
private initRelationAuthTriggers;
protected cascadeUpdateAsync<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: AsyncContext<ED>, option: MysqlOperateOption): Promise<import("oak-domain/lib/types").OperationResult<ED>>;
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: MysqlOperateOption): Promise<import("oak-domain/lib/types").OperationResult<ED>>;
select<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: MySqlSelectOption): Promise<Partial<ED[T]["Schema"]>[]>;

View File

@ -3,16 +3,52 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.DbStore = void 0;
const oak_db_1 = require("oak-db");
const TriggerExecutor_1 = require("oak-domain/lib/store/TriggerExecutor");
const RelationAuth_1 = require("oak-domain/lib/store/RelationAuth");
class DbStore extends oak_db_1.MysqlStore {
executor;
constructor(storageSchema, contextBuilder, mysqlConfiguration) {
relationAuth;
constructor(storageSchema, contextBuilder, mysqlConfiguration, actionCascadeGraph, relationCascadeGraph) {
super(storageSchema, mysqlConfiguration);
this.executor = new TriggerExecutor_1.TriggerExecutor((scene) => contextBuilder(scene)(this));
this.relationAuth = new RelationAuth_1.RelationAuth(actionCascadeGraph, relationCascadeGraph, storageSchema);
this.initRelationAuthTriggers(contextBuilder);
}
/**
* relationAuth中需要缓存一些维表的数据
*/
async initRelationAuthTriggers(contextBuilder) {
const context = await contextBuilder()(this);
const freeActionAuths = await this.select('freeActionAuth', {
data: {
id: 1,
deActions: 1,
destEntity: 1,
},
}, context, {
dontCollect: true,
});
this.relationAuth.setFreeActionAuths(freeActionAuths);
const directActionAuths = await this.select('directActionAuth', {
data: {
id: 1,
rootEntity: 1,
path: 1,
deActions: 1,
destEntity: 1,
},
}, context, {
dontCollect: true,
});
this.relationAuth.setDirectionActionAuths(directActionAuths);
await context.commit();
const triggers = this.relationAuth.getAuthDataTriggers();
triggers.forEach((trigger) => this.registerTrigger(trigger));
}
async cascadeUpdateAsync(entity, operation, context, option) {
if (!option.blockTrigger) {
await this.executor.preOperation(entity, operation, context, option);
}
await this.relationAuth.checkRelationAsync(entity, operation, context);
const result = await super.cascadeUpdateAsync(entity, operation, context, option);
if (!option.blockTrigger) {
await this.executor.postOperation(entity, operation, context, option);
@ -47,6 +83,7 @@ class DbStore extends oak_db_1.MysqlStore {
Object.assign(selection, {
action: 'select',
});
await this.relationAuth.checkRelationAsync(entity, selection, context);
if (!option.blockTrigger) {
await this.executor.preOperation(entity, selection, context, option);
}
@ -75,6 +112,7 @@ class DbStore extends oak_db_1.MysqlStore {
const selection2 = Object.assign({
action: 'select',
}, selection);
await this.relationAuth.checkRelationAsync(entity, selection2, context);
if (!option.blockTrigger) {
await this.executor.preOperation(entity, selection2, context, option);
}

View File

@ -32,6 +32,6 @@
"copyfiles": "^2.4.1",
"ts-node": "~10.9.1",
"tslib": "^2.4.0",
"typescript": "~4.7.4"
"typescript": "^4.7.4"
}
}

View File

@ -45,19 +45,47 @@ export class AppLoader<ED extends EntityDict & BaseEntityDict, Cxt extends Async
}
assert(typeof sth === 'object');
const sthOut = {};
const sthOut: Record<string, any> = {};
sthExternal.forEach(
(sth2, idx) => {
assert(typeof sth2 === 'object' && !(sth2 instanceof Array), `${join(this.path, 'node_modules', this.externalDependencies[idx], filePath)}中的default输出对象不是非数组对象与项目对应路径的输出不一致`);
const inter = intersection(Object.keys(sthOut), Object.keys(sth2));
if (inter.length > 0) {
console.warn(`${join(this.path, 'node_modules', this.externalDependencies[idx], filePath)}中的default输出对象中的key值【${inter.join(',')}】与其它对应路径输出的key值有冲突请仔细检查避免错误`);
inter.forEach(
(ele) => {
if (sth2[ele] instanceof Array && sthOut[ele]) {
assert(sthOut[ele] instanceof Array, `${join(this.path, 'node_modules', this.externalDependencies[idx], filePath)}中的default输出对象的${ele}键值是数组,但之前的相应对象的${ele}却不是,请仔细检查以避免错误`);
console.warn(`${join(this.path, 'node_modules', this.externalDependencies[idx], filePath)}中的default输出对象中的key值【${ele}】与其它对应路径输出的key值【${ele}】将以数组格式进行合并,请仔细检查避免错误`);
sth2[ele].push(...sthOut[ele]);
}
else if (!(sth2[ele] instanceof Array) && sthOut[ele]) {
assert(!(sthOut[ele] instanceof Array), `${join(this.path, 'node_modules', this.externalDependencies[idx], filePath)}中的default输出对象的${ele}键值不是数组,但之前的相应对象的${ele}却是,请仔细检查以避免错误`);
console.warn(`${join(this.path, 'node_modules', this.externalDependencies[idx], filePath)}中的default输出对象中的key值【${ele}】将对与其它对应路径输出的key值【${ele}】进行覆盖,请仔细检查避免错误`);
}
}
)
}
Object.assign(sthOut, sth2);
}
);
const inter = intersection(Object.keys(sthOut), Object.keys(sth));
assert(inter.length === 0, `项目${filePath}中的default输出与第三方库中的输出在键值${inter.join(',')}上冲突,请处理`);
if (inter.length > 0) {
inter.forEach(
(ele) => {
if (sth[ele] instanceof Array && sthOut[ele]) {
assert(sthOut[ele] instanceof Array, `项目${filePath}中的default输出对象的${ele}键值是数组,但之前的相应对象的${ele}却不是,请仔细检查以避免错误`);
console.warn(`项目${filePath}中的default输出对象中的key值【${ele}】与其它引用包该路径输出的key值【${ele}】将以数组格式进行合并,请仔细检查避免错误`);
sth[ele].push(...sthOut[ele]);
}
else if (!(sth[ele] instanceof Array) && sthOut[ele]) {
assert(!(sthOut[ele] instanceof Array), `项目${filePath}中的default输出对象的${ele}键值不是数组,但之前的相应对象的${ele}却是,请仔细检查以避免错误`);
console.warn(`项目${filePath}中的default输出对象中的key值【${ele}】将对其它引用包该路径输出的key值【${ele}】进行覆盖,请仔细检查避免错误`);
}
}
)
}
Object.assign(sthOut, sth);
return sthOut;
}
@ -65,9 +93,10 @@ export class AppLoader<ED extends EntityDict & BaseEntityDict, Cxt extends Async
constructor(path: string, contextBuilder: (scene?: string) => (store: DbStore<ED, Cxt>) => Promise<Cxt>, dbConfig: MySQLConfiguration) {
super(path);
const { storageSchema } = require(`${path}/lib/oak-app-domain/Storage`);
const { ActionCascadePathGraph, RelationCascadePathGraph } = require(`${path}/lib/oak-app-domain/Relation`);
this.externalDependencies = require(`${path}/lib/config/externalDependencies`).default;
this.aspectDict = Object.assign({}, generalAspectDict, this.requireSth('lib/aspects/index'));
this.dbStore = new DbStore<ED, Cxt>(storageSchema, contextBuilder, dbConfig);
this.dbStore = new DbStore<ED, Cxt>(storageSchema, contextBuilder, dbConfig, ActionCascadePathGraph, RelationCascadePathGraph);
this.contextBuilder = contextBuilder;
}
@ -91,7 +120,8 @@ export class AppLoader<ED extends EntityDict & BaseEntityDict, Cxt extends Async
(checker) => this.dbStore.registerChecker(checker)
);
const dynamicCheckers = createDynamicCheckers(this.dbStore.getSchema(), authDict);
// todo cascadeRemoveTrigger要挪到Schema定义里
const dynamicCheckers = createDynamicCheckers(this.dbStore.getSchema(), {});
dynamicCheckers.forEach(
(checker) => this.dbStore.registerChecker(checker)
);

View File

@ -1,24 +1,72 @@
import { MysqlStore, MySqlSelectOption, MysqlOperateOption } from 'oak-db';
import { EntityDict, Context, StorageSchema, Trigger, Checker, RowStore, SelectOption } from 'oak-domain/lib/types';
import { EntityDict, Context, StorageSchema, Trigger, Checker, RowStore, SelectOption, AuthCascadePath } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { TriggerExecutor } from 'oak-domain/lib/store/TriggerExecutor';
import { MySQLConfiguration, } from 'oak-db/lib/MySQL/types/Configuration';
import { AsyncContext, AsyncRowStore } from 'oak-domain/lib/store/AsyncRowStore';
import { RelationAuth } from 'oak-domain/lib/store/RelationAuth';
export class DbStore<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends MysqlStore<ED, Cxt> implements AsyncRowStore<ED, Cxt> {
private executor: TriggerExecutor<ED>;
private relationAuth: RelationAuth<ED>;
constructor(storageSchema: StorageSchema<ED>, contextBuilder: (scene?: string) => (store: DbStore<ED, Cxt>) => Promise<AsyncContext<ED>>, mysqlConfiguration: MySQLConfiguration) {
constructor(
storageSchema: StorageSchema<ED>,
contextBuilder: (scene?: string) => (store: DbStore<ED, Cxt>) => Promise<Cxt>,
mysqlConfiguration: MySQLConfiguration,
actionCascadeGraph: AuthCascadePath<ED>[],
relationCascadeGraph: AuthCascadePath<ED>[]) {
super(storageSchema, mysqlConfiguration);
this.executor = new TriggerExecutor((scene) => contextBuilder(scene)(this));
this.relationAuth = new RelationAuth(actionCascadeGraph, relationCascadeGraph, storageSchema);
this.initRelationAuthTriggers(contextBuilder);
}
/**
* relationAuth中需要缓存一些维表的数据
*/
private async initRelationAuthTriggers(contextBuilder: (scene?: string) => (store: DbStore<ED, Cxt>) => Promise<Cxt>) {
const context = await contextBuilder()(this);
await context.begin();
// 先direct后free因为RelationAuth中会根据free判断是否完成
const directActionAuths = await this.select('directActionAuth', {
data: {
id: 1,
rootEntity: 1,
path: 1,
deActions: 1,
destEntity: 1,
},
}, context, {
dontCollect: true,
});
this.relationAuth.setDirectionActionAuths(directActionAuths as ED['directActionAuth']['OpSchema'][]);
const freeActionAuths = await this.select('freeActionAuth', {
data: {
id: 1,
deActions: 1,
destEntity: 1,
},
}, context, {
dontCollect: true,
});
this.relationAuth.setFreeActionAuths(freeActionAuths as ED['freeActionAuth']['OpSchema'][]);
await context.commit();
const triggers = this.relationAuth.getAuthDataTriggers<Cxt>();
triggers.forEach(
(trigger) => this.registerTrigger(trigger)
);
}
protected async cascadeUpdateAsync<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: AsyncContext<ED>, option: MysqlOperateOption) {
if (!option.blockTrigger) {
await this.executor.preOperation(entity, operation, context, option);
}
await this.relationAuth.checkRelationAsync(entity, operation, context);
const result = await super.cascadeUpdateAsync(entity, operation, context, option);
if (!option.blockTrigger) {
await this.executor.postOperation(entity, operation, context, option);
@ -66,7 +114,7 @@ export class DbStore<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncCo
Object.assign(selection, {
action: 'select',
});
await this.relationAuth.checkRelationAsync(entity, selection, context);
if (!option.blockTrigger) {
await this.executor.preOperation(entity, selection as ED[T]['Operation'], context, option);
}
@ -99,6 +147,7 @@ export class DbStore<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncCo
action: 'select',
}, selection) as ED[T]['Operation'];
await this.relationAuth.checkRelationAsync(entity, selection2, context);
if (!option.blockTrigger) {
await this.executor.preOperation(entity, selection2, context, option);
}