directus
77 строк · 2.7 Кб
1import type { ExtensionSandboxRequestedScopes } from '@directus/extensions';
2import encodeUrl from 'encodeurl';
3import globToRegExp from 'glob-to-regexp';
4import type { Reference } from 'isolated-vm';
5import { getAxios } from '../../../../../request/index.js';
6
7export function requestGenerator(requestedScopes: ExtensionSandboxRequestedScopes): (
8url: Reference<string>,
9options: Reference<{
10method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
11body?: Record<string, any> | string;
12headers?: Record<string, string>;
13}>,
14) => Promise<{
15status: number;
16statusText: string;
17headers: Record<string, any>;
18data: string;
19}> {
20return async (url, options) => {
21if (url.typeof !== 'string') throw new TypeError('Request url has to be of type string');
22
23if (options.typeof !== 'undefined' && options.typeof !== 'object') {
24throw new TypeError('Request options has to be of type object');
25}
26
27const urlCopied = await url.copy();
28
29const permissions = requestedScopes.request;
30
31if (permissions === undefined) throw new Error('No permission to access "request"');
32
33const urlAllowed = permissions.urls.some((urlScope) => {
34const regex = globToRegExp(urlScope);
35return regex.test(urlCopied);
36});
37
38if (urlAllowed === false) {
39throw new Error(`No permission to request "${urlCopied}"`);
40}
41
42const method = options.typeof !== 'undefined' ? await options.get('method', { reference: true }) : undefined;
43const body = options.typeof !== 'undefined' ? await options.get('body', { reference: true }) : undefined;
44const headers = options.typeof !== 'undefined' ? await options.get('headers', { reference: true }) : undefined;
45
46if (method !== undefined && method.typeof !== 'undefined' && method.typeof !== 'string') {
47throw new TypeError('Request method has to be of type string');
48}
49
50if (body !== undefined && body.typeof !== 'undefined' && body.typeof !== 'string' && body.typeof !== 'object') {
51throw new TypeError('Request body has to be of type string or object');
52}
53
54if (headers !== undefined && headers.typeof !== 'undefined' && headers.typeof !== 'object') {
55throw new TypeError('Request headers has to be of type object');
56}
57
58const methodCopied = await method?.copy();
59const bodyCopied = await body?.copy();
60const headersCopied = await headers?.copy();
61
62if (!permissions.methods.includes(methodCopied ?? 'GET')) {
63throw new Error(`No permission to use request method "${methodCopied}"`);
64}
65
66const axios = await getAxios();
67
68const result = await axios({
69url: encodeUrl(urlCopied),
70method: methodCopied ?? 'GET',
71data: bodyCopied ?? null,
72headers: headersCopied ?? {},
73});
74
75return { status: result.status, statusText: result.statusText, headers: result.headers, data: result.data };
76};
77}
78