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