fix(custom-request): parsed not working when the value of the variable is of type o2m. (#2926)

* fix: parse o2m variables doesn\'t work

* fix: currentRecord.id doesn't work

* fix: x-button missing border-bottom

* fix: currentUser with association

* fix: filter underfined

* fix: cannot get the value by variables
This commit is contained in:
Dunqing 2023-11-02 10:26:56 +08:00 committed by GitHub
parent 4bb6ed4813
commit 7bbd7e6f2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 166 additions and 14 deletions

View File

@ -64,7 +64,6 @@ export function RawTextArea(props): JSX.Element {
&:not(:hover) {
border-right-color: transparent;
border-top-color: transparent;
border-bottom-color: transparent;
}
background-color: transparent;
`

View File

@ -7,3 +7,23 @@ exports[`actions send currentRecord.data 1`] = `
"username": "testname",
}
`;
exports[`actions send currentUser with association data 1`] = `
{
"a": [
"member",
"root",
"admin",
],
"b": [
"{{t("Member")}}",
"{{t("Root")}}",
"{{t("Admin")}}",
],
"c": [
1,
1,
1,
],
}
`;

View File

@ -12,7 +12,7 @@ describe('actions', () => {
beforeAll(async () => {
app = mockServer({
registerActions: true,
acl: false,
acl: true,
plugins: ['users', 'auth', 'acl', 'custom-request'],
});
@ -20,7 +20,8 @@ describe('actions', () => {
db = app.db;
repo = db.getRepository('customRequests');
agent = app.agent();
resource = agent.resource('customRequests');
resource = (agent.set('X-Role', 'admin') as any).resource('customRequests');
await agent.login(1);
});
describe('send', () => {
@ -66,5 +67,94 @@ describe('actions', () => {
expect(res.status).toBe(200);
expect(params).toMatchSnapshot();
});
test('parse o2m variables correctly', async () => {
await repo.create({
values: {
key: 'o2m',
options: {
url: '/customRequests:test',
method: 'GET',
data: {
o2m: '{{ currentRecord.o2m.id }}',
},
},
},
});
const res = await resource.send({
filterByTk: 'o2m',
values: {
currentRecord: {
data: {
o2m: [
{
id: 1,
},
{
id: 2,
},
],
},
},
},
});
expect(res.status).toBe(200);
expect(params).toMatchObject({
o2m: [1, 2],
});
});
test('currentRecord.id with collectionName works fine', async () => {
await repo.create({
values: {
key: 'test2',
options: {
method: 'GET',
headers: [],
params: [{ name: 'userId', value: '{{currentRecord.id}}' }],
url: '/users:get',
collectionName: 'users',
data: null,
},
},
});
const userId = 1;
const res = await resource.send({
filterByTk: 'test2',
values: {
currentRecord: {
id: userId,
},
},
});
expect(res.status).toBe(200);
expect(res.body.data.id).toBe(userId);
});
test('currentUser with association data', async () => {
await repo.create({
values: {
key: 'currentUser-with-association-data',
options: {
method: 'POST',
headers: [],
data: {
a: '{{currentUser.roles.name}}',
b: '{{currentUser.roles.title}}',
c: '{{currentUser.roles.rolesUsers.userId}}',
},
url: '/customRequests:test',
},
},
});
const res = await resource.send({
filterByTk: 'currentUser-with-association-data',
});
expect(res.status).toBe(200);
expect(params).toMatchSnapshot();
});
});
});

View File

@ -3,6 +3,7 @@ import { parse } from '@nocobase/utils';
import axios from 'axios';
import CustomRequestPlugin from '../plugin';
import { appendArrayColumn } from '@nocobase/evaluators';
const getHeaders = (headers: Record<string, any>) => {
return Object.keys(headers).reduce((hds, key) => {
@ -29,6 +30,21 @@ const omitNullAndUndefined = (obj: any) => {
}, {});
};
const CurrentUserVariableRegExp = /{{\s*(currentUser[^}]+)\s*}}/g;
const getCurrentUserAppends = (str: string, user) => {
const matched = str.matchAll(CurrentUserVariableRegExp);
return Array.from(matched)
.map((item) => {
const keys = item?.[1].split('.') || [];
const appendKey = keys[1];
if (keys.length > 2 && !Reflect.has(user || {}, appendKey)) {
return appendKey;
}
})
.filter(Boolean);
};
export async function send(this: CustomRequestPlugin, ctx: Context, next: Next) {
const { filterByTk, resourceName, values = {} } = ctx.action.params;
const {
@ -69,35 +85,62 @@ export async function send(this: CustomRequestPlugin, ctx: Context, next: Next)
ctx.withoutDataWrapping = true;
const { collectionName, url, headers = [], params = [], data = {}, ...options } = requestConfig.options;
let currentRecordVariables = {};
let currentRecordValues = {};
if (collectionName && typeof currentRecord.id !== 'undefined') {
const recordRepo = ctx.db.getRepository(collectionName);
currentRecordVariables = await recordRepo.findOne({
currentRecordValues =
(
await recordRepo.findOne({
filterByTk: currentRecord.id,
appends: currentRecord.appends,
});
})
)?.toJSON() || {};
}
let currentUser = ctx.auth.user;
const userAppends = getCurrentUserAppends(
JSON.stringify(url) + JSON.stringify(headers) + JSON.stringify(params) + JSON.stringify(data),
ctx.auth.user,
);
if (userAppends.length) {
currentUser =
(
await ctx.db.getRepository('users').findOne({
filterByTk: ctx.auth.user.id,
appends: userAppends,
})
)?.toJSON() || {};
}
const variables = {
currentRecord: {
...currentRecordVariables,
...currentRecordValues,
...currentRecord.data,
},
currentUser: ctx.auth.user,
currentUser,
currentTime: new Date().toISOString(),
};
const getParsedValue = (value) => {
const template = parse(value);
template.parameters.forEach(({ key }) => {
appendArrayColumn(variables, key);
});
return template(variables);
};
const axiosRequestConfig = {
baseURL: ctx.origin,
...options,
url: parse(url)(variables),
url: getParsedValue(url),
headers: {
Authorization: 'Bearer ' + ctx.getBearerToken(),
...getHeaders(ctx.headers),
...omitNullAndUndefined(parse(arrayToObject(headers))(variables)),
...omitNullAndUndefined(getParsedValue(arrayToObject(headers))),
},
params: parse(arrayToObject(params))(variables),
data: parse(data)(variables),
params: getParsedValue(arrayToObject(params)),
data: getParsedValue(data),
};
const requestUrl = axios.getUri(axiosRequestConfig);