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:
parent
4bb6ed4813
commit
7bbd7e6f2b
@ -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;
|
||||
`
|
||||
|
@ -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,
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user