mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-01 18:52:20 +08:00
chore: main datasource api (#3880)
* chore: main datasource api * chore: test * chore: console.log * chore: middleware order * chore: test * chore: middleware order * chore: test * chore: middleware options
This commit is contained in:
parent
a93d2ddab2
commit
79f14d9024
@ -335,7 +335,7 @@ export class ACL extends EventEmitter {
|
||||
can: ctx.can({ resource: resourceName, action: actionName }),
|
||||
};
|
||||
|
||||
return compose(acl.middlewares.nodes)(ctx, next);
|
||||
return await compose(acl.middlewares.nodes)(ctx, next);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,17 +24,16 @@ export class DataSourceManager {
|
||||
|
||||
middleware() {
|
||||
return async (ctx, next) => {
|
||||
const name = ctx.get('x-data-source');
|
||||
if (name) {
|
||||
if (this.dataSources.has(name)) {
|
||||
const ds = this.dataSources.get(name);
|
||||
ctx.dataSource = ds;
|
||||
return ds.middleware(this.middlewares)(ctx, next);
|
||||
} else {
|
||||
ctx.throw(`data source ${name} does not exist`);
|
||||
}
|
||||
const name = ctx.get('x-data-source') || 'main';
|
||||
|
||||
if (!this.dataSources.has(name)) {
|
||||
ctx.throw(`data source ${name} does not exist`);
|
||||
}
|
||||
await next();
|
||||
|
||||
const ds = this.dataSources.get(name);
|
||||
ctx.dataSource = ds;
|
||||
|
||||
return ds.middleware(this.middlewares)(ctx, next);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -62,13 +62,19 @@ export abstract class DataSource extends EventEmitter {
|
||||
if (this.resourceManager.isDefined(resourceName)) {
|
||||
return next();
|
||||
}
|
||||
// 如果经过加载后是已经定义的表
|
||||
if (!this.collectionManager.hasCollection(resourceName)) {
|
||||
|
||||
const splitResult = resourceName.split('.');
|
||||
|
||||
const collectionName = splitResult[0];
|
||||
|
||||
if (!this.collectionManager.hasCollection(collectionName)) {
|
||||
return next();
|
||||
}
|
||||
|
||||
this.resourceManager.define({
|
||||
name: resourceName,
|
||||
});
|
||||
|
||||
return next();
|
||||
};
|
||||
}
|
||||
@ -86,7 +92,7 @@ export abstract class DataSource extends EventEmitter {
|
||||
return this.collectionManager.getRepository(resourceName, resourceOf);
|
||||
};
|
||||
|
||||
return compose([this.collectionToResourceMiddleware(), this.resourceManager.restApiMiddleware()])(ctx, next);
|
||||
return compose([this.collectionToResourceMiddleware(), this.resourceManager.middleware()])(ctx, next);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1073,13 +1073,6 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
|
||||
this._dataSourceManager.use(this._authManager.middleware(), { tag: 'auth' });
|
||||
this._dataSourceManager.use(validateFilterParams, { tag: 'validate-filter-params', before: ['auth'] });
|
||||
|
||||
this.resourcer.use(this._authManager.middleware(), { tag: 'auth' });
|
||||
this.resourcer.use(validateFilterParams, { tag: 'validate-filter-params', before: ['auth'] });
|
||||
|
||||
if (this.options.acl !== false) {
|
||||
this.resourcer.use(this.acl.middleware(), { tag: 'acl', after: ['auth'] });
|
||||
}
|
||||
|
||||
this._locales = new Locale(createAppProxy(this));
|
||||
|
||||
if (options.perfHooks) {
|
||||
@ -1103,10 +1096,12 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
|
||||
database: this.createDatabase(options),
|
||||
acl: createACL(),
|
||||
resourceManager: createResourcer(options),
|
||||
useACL: options.acl,
|
||||
});
|
||||
|
||||
this._dataSourceManager = new DataSourceManager();
|
||||
|
||||
// can not use await here
|
||||
this.dataSourceManager.dataSources.set('main', mainDataSourceInstance);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ export default (app: Application) => {
|
||||
.option('--quickstart')
|
||||
.action(async (...cliArgs) => {
|
||||
const [options] = cliArgs;
|
||||
console.log('start options', options);
|
||||
if (options.quickstart) {
|
||||
if (await app.isInstalled()) {
|
||||
await app.upgrade();
|
||||
|
@ -81,16 +81,7 @@ export function registerMiddlewares(app: Application, options: ApplicationOption
|
||||
app.use(dataWrapping(), { tag: 'dataWrapping', after: 'i18n' });
|
||||
}
|
||||
|
||||
app.resourcer.use(parseVariables, {
|
||||
tag: 'parseVariables',
|
||||
after: 'acl',
|
||||
});
|
||||
|
||||
app.resourcer.use(dateTemplate, { tag: 'dateTemplate', after: 'acl' });
|
||||
|
||||
app.use(db2resource, { tag: 'db2resource', after: 'dataWrapping' });
|
||||
app.use(app.resourcer.restApiMiddleware({ skipIfDataSourceExists: true }), { tag: 'restApi', after: 'db2resource' });
|
||||
app.use(app.dataSourceManager.middleware(), { tag: 'dataSource', after: 'restApi' });
|
||||
app.use(app.dataSourceManager.middleware(), { tag: 'dataSource', after: 'dataWrapping' });
|
||||
}
|
||||
|
||||
export const createAppProxy = (app: Application) => {
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { DataSourceOptions, SequelizeDataSource } from '@nocobase/data-source-manager';
|
||||
import { db2resource, parseVariables } from './middlewares';
|
||||
import { dateTemplate } from './middlewares/data-template';
|
||||
|
||||
export class MainDataSource extends SequelizeDataSource {
|
||||
init(options: DataSourceOptions = {}) {
|
||||
@ -15,5 +17,16 @@ export class MainDataSource extends SequelizeDataSource {
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (options.useACL !== false) {
|
||||
this.resourceManager.use(this.acl.middleware(), { group: 'acl', after: 'auth' });
|
||||
}
|
||||
|
||||
this.resourceManager.use(parseVariables, {
|
||||
group: 'parseVariables',
|
||||
after: 'acl',
|
||||
});
|
||||
|
||||
this.resourceManager.use(dateTemplate, { group: 'dateTemplate', after: 'acl' });
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,6 @@ export function dataWrapping() {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!ctx?.action?.params) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (ctx.body instanceof stream.Readable) {
|
||||
return;
|
||||
}
|
||||
@ -59,6 +55,8 @@ export function dataWrapping() {
|
||||
if (ctx.body && ctx.state.messages?.length) {
|
||||
ctx.body.messages = ctx.state.messages;
|
||||
}
|
||||
|
||||
ctx.dataWrapped = true;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,6 @@ import Database from '@nocobase/database';
|
||||
import { getNameByParams, parseRequest, ResourcerContext, ResourceType } from '@nocobase/resourcer';
|
||||
|
||||
export async function db2resource(ctx: ResourcerContext & { db: Database }, next: () => Promise<any>) {
|
||||
const dataSource = ctx.get('x-data-source');
|
||||
if (dataSource) {
|
||||
return next();
|
||||
}
|
||||
const resourcer = ctx.resourcer;
|
||||
const database = ctx.db;
|
||||
|
||||
@ -33,13 +29,9 @@ export async function db2resource(ctx: ResourcerContext & { db: Database }, next
|
||||
|
||||
const splitResult = resourceName.split('.');
|
||||
|
||||
let collectionName = splitResult[0];
|
||||
const collectionName = splitResult[0];
|
||||
const fieldName = splitResult[1];
|
||||
|
||||
if (collectionName.includes('@')) {
|
||||
collectionName = collectionName.split('@')[1];
|
||||
}
|
||||
|
||||
// 如果经过加载后是已经定义的表
|
||||
if (!database.hasCollection(collectionName)) {
|
||||
return next();
|
||||
|
@ -188,6 +188,7 @@ describe('destroy action with acl', () => {
|
||||
},
|
||||
{
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
|
||||
@ -224,6 +225,7 @@ describe('destroy action with acl', () => {
|
||||
},
|
||||
{
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
|
||||
@ -282,6 +284,7 @@ describe('destroy action with acl', () => {
|
||||
},
|
||||
{
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -88,6 +88,7 @@ describe('list action with acl', () => {
|
||||
},
|
||||
{
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
|
||||
@ -132,6 +133,7 @@ describe('list action with acl', () => {
|
||||
},
|
||||
{
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
|
||||
@ -172,6 +174,7 @@ describe('list action with acl', () => {
|
||||
},
|
||||
{
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
|
||||
@ -214,6 +217,7 @@ describe('list action with acl', () => {
|
||||
},
|
||||
{
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -692,7 +692,7 @@ export class PluginACL extends Plugin {
|
||||
ctx.logger.error(error);
|
||||
}
|
||||
},
|
||||
{ after: 'restApi', group: 'after' },
|
||||
{ after: 'dataSource', group: 'with-acl-meta' },
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -21,17 +21,24 @@ export class PluginAPIKeysServer extends Plugin {
|
||||
}
|
||||
|
||||
async load() {
|
||||
this.app.resourcer.use(async (ctx, next) => {
|
||||
const { resourceName, actionName } = ctx.action;
|
||||
if (resourceName === this.resourceName && ['list', 'destroy'].includes(actionName)) {
|
||||
ctx.action.mergeParams({
|
||||
filter: {
|
||||
createdById: ctx.auth.user.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
await next();
|
||||
});
|
||||
this.app.resourcer.use(
|
||||
async (ctx, next) => {
|
||||
const { resourceName, actionName } = ctx.action;
|
||||
if (resourceName === this.resourceName && ['list', 'destroy'].includes(actionName)) {
|
||||
ctx.action.mergeParams({
|
||||
filter: {
|
||||
createdById: ctx.auth.user.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
await next();
|
||||
},
|
||||
{
|
||||
group: 'apiKeys',
|
||||
before: 'acl',
|
||||
after: 'auth',
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user