Merge branch 'feat/dataSource-manager' of https://github.com/nocobase/nocobase into feat/dataSource-manager

This commit is contained in:
dream2023 2024-01-31 22:43:33 +08:00
commit 8aca1d0bba
5 changed files with 27 additions and 11 deletions

View File

@ -77,6 +77,7 @@ export abstract class DataSource {
const { resourceName, resourceOf } = ctx.action; const { resourceName, resourceOf } = ctx.action;
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.restApiMiddleware()])(ctx, next);
}; };
} }

View File

@ -269,18 +269,16 @@ export class Resourcer {
if (skipIfDataSourceExists) { if (skipIfDataSourceExists) {
const dataSource = ctx.get('x-data-source'); const dataSource = ctx.get('x-data-source');
if (dataSource) { if (dataSource) {
await next(); return next();
return;
} }
} }
ctx.resourcer = this; ctx.resourcer = this;
const connectionName = ctx.get('x-connection');
let params = parseRequest( let params = parseRequest(
{ {
path: ctx.request.path, path: ctx.request.path,
method: ctx.request.method, method: ctx.request.method,
namespace: connectionName,
}, },
{ {
prefix: this.options.prefix || prefix, prefix: this.options.prefix || prefix,
@ -302,7 +300,6 @@ export class Resourcer {
path: ctx.request.path, path: ctx.request.path,
method: ctx.request.method, method: ctx.request.method,
type: resource.options.type, type: resource.options.type,
namespace: connectionName,
}, },
{ {
prefix: this.options.prefix || prefix, prefix: this.options.prefix || prefix,
@ -318,10 +315,6 @@ export class Resourcer {
// action 需要 clone 之后再赋给 ctx // action 需要 clone 之后再赋给 ctx
ctx.action = this.getAction(getNameByParams(params), params.actionName).clone(); ctx.action = this.getAction(getNameByParams(params), params.actionName).clone();
if (params && params.resourceName && params.resourceName.includes('@')) {
params.resourceName = params.resourceName.replace(`${connectionName}@`, '');
}
ctx.action.setContext(ctx); ctx.action.setContext(ctx);
ctx.action.actionName = params.actionName; ctx.action.actionName = params.actionName;
ctx.action.resourceOf = params.associatedIndex; ctx.action.resourceOf = params.associatedIndex;

View File

@ -9,7 +9,7 @@ import fs from 'fs';
import i18next from 'i18next'; import i18next from 'i18next';
import bodyParser from 'koa-bodyparser'; import bodyParser from 'koa-bodyparser';
import { resolve } from 'path'; import { resolve } from 'path';
import { RecordableHistogram, createHistogram } from 'perf_hooks'; import { createHistogram, RecordableHistogram } from 'perf_hooks';
import Application, { ApplicationOptions } from './application'; import Application, { ApplicationOptions } from './application';
import { parseVariables } from './middlewares'; import { parseVariables } from './middlewares';
import { dateTemplate } from './middlewares/data-template'; import { dateTemplate } from './middlewares/data-template';
@ -98,7 +98,7 @@ export function registerMiddlewares(app: Application, options: ApplicationOption
app.use(db2resource, { tag: 'db2resource', after: 'dataWrapping' }); app.use(db2resource, { tag: 'db2resource', after: 'dataWrapping' });
app.use(app.resourcer.restApiMiddleware({ skipIfDataSourceExists: true }), { tag: 'restApi', after: 'db2resource' }); app.use(app.resourcer.restApiMiddleware({ skipIfDataSourceExists: true }), { tag: 'restApi', after: 'db2resource' });
app.use(app.dataSourceManager.middleware()); app.use(app.dataSourceManager.middleware(), { tag: 'dataSource', after: 'restApi' });
} }
export const createAppProxy = (app: Application) => { export const createAppProxy = (app: Application) => {

View File

@ -94,6 +94,25 @@ describe('data source with acl', () => {
await app.destroy(); await app.destroy();
}); });
it('should call application middleware', async () => {
const middlewareFn = vi.fn();
app.use(async (ctx, next) => {
middlewareFn();
await next();
});
const adminUser = await app.db.getRepository('users').create({
values: {
roles: ['root'],
},
});
const adminAgent: any = app.agent().login(adminUser).set('x-data-source', 'mockInstance1');
const listRes = await adminAgent.resource('api/posts').list();
expect(listRes.status).toBe(200);
expect(middlewareFn).toBeCalledTimes(1);
});
it('should allow root user', async () => { it('should allow root user', async () => {
const adminUser = await app.db.getRepository('users').create({ const adminUser = await app.db.getRepository('users').create({
values: { values: {

View File

@ -79,6 +79,9 @@ export class PluginDataSourceManagerServer extends Plugin {
this.app.use(async (ctx, next) => { this.app.use(async (ctx, next) => {
await next(); await next();
if (!ctx.action) {
return;
}
const { actionName, resourceName, params } = ctx.action; const { actionName, resourceName, params } = ctx.action;