UNPKG

@iexec/iexec-oracle-factory-wrapper

Version:
242 lines 9.77 kB
import { ethers } from 'ethers'; import jp from 'jsonpath'; import { string, number, object, array } from 'yup'; import { API_KEY_PLACEHOLDER, SUPPORTED_TARGET_BLOCKCHAINS, } from '../config/config.js'; const countSubstrAllowOverlap = (str, substr) => { if (substr.length <= 0) return str.length + 1; let count = 0; let startIndex = 0; while (startIndex > -1) { startIndex = str.indexOf(substr, startIndex); if (startIndex >= 0) { count += 1; startIndex += 1; } } return count; }; const httpsUrlSchema = () => string() .test('is-url-allow-placeholder', '${path} must be a valid url', async (value) => { try { const originalUrl = value || ''; await string() .url() .validate(originalUrl.replace(API_KEY_PLACEHOLDER, 'API_KEY_PLACEHOLDER')); return true; } catch (e) { return false; } }) .test('is-https', '${path} is not https', (value) => !value || value.indexOf('https://') === 0); const httpMethodSchema = () => string().oneOf(['GET', 'POST', 'PUT', 'DELETE']); const bodySchema = () => string().default(''); const headerValueSchema = () => string().required(); const headersMapSchema = () => object() .default({}) .test('values-are-strings', '${path} is not a valid header list', async (value) => { try { await array() .transform((_, orig) => Object.values(orig)) .of(headerValueSchema()) .validate(value); return true; } catch (e) { return false; } }); const apiKeySchema = () => string(); const datasetAddressSchema = () => string() .default('0x0000000000000000000000000000000000000000') .test('is-address', '${path} is not a valid ethereum address', (value) => { try { if (value) { ethers.getAddress(value); } return true; } catch (e) { return false; } }); const jsonPathSchema = () => string().test('is-jsonpath', '${originalValue} is not a valid JSONPath', (str) => { if (str) { try { jp.parse(str); } catch (e) { return false; } } return true; }); const dataTypeSchema = () => string().oneOf(['boolean', 'number', 'string']); const callParamsSchema = () => object({ url: httpsUrlSchema().required(), method: httpMethodSchema().required(), headers: headersMapSchema(), body: bodySchema(), }).noUnknown(true); const strictCallParamsSchema = () => object().test('is-call-params', '${originalValue} is not a valid callParams', async (obj, context) => { try { if (obj && obj.body === '') { await object({ url: httpsUrlSchema().required(), method: httpMethodSchema().required(), headers: headersMapSchema().required(), body: bodySchema(), }) .required() .strict() .noUnknown(true) .validate(obj); } else { await object({ url: httpsUrlSchema().required(), method: httpMethodSchema().required(), headers: headersMapSchema().required(), body: bodySchema().required(), }) .required() .strict() .noUnknown(true) .validate(obj); } return true; } catch (e) { return context.createError({ message: e.message }); } }); const rawParamsSchema = () => callParamsSchema() .shape({ JSONPath: jsonPathSchema().required(), dataType: dataTypeSchema().required(), apiKey: apiKeySchema(), }) .test( // eslint-disable-next-line sonarjs/no-duplicate-string 'no-multiple-apikey', `Found multiple ${API_KEY_PLACEHOLDER} occurrences in API call parameters, it must have at most one occurrence`, (obj, context) => { const { url, headers } = context.originalValue; return (countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) <= 1); }) .test('apikey-provided-when-needed', `Using ${API_KEY_PLACEHOLDER} placeholder but no apiKey provided`, (obj, context) => { const { url, headers, apiKey } = context.originalValue; return !(countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) >= 1 && !apiKey); }) .test('no-unused-apikey', `Provided apiKey but no ${API_KEY_PLACEHOLDER} placeholder found in url or headers`, (obj, context) => { const { url, headers, apiKey } = context.originalValue; return !(apiKey && countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) === 0); }) .noUnknown(true); const paramSetSchema = () => callParamsSchema() .shape({ JSONPath: jsonPathSchema().required(), dataType: dataTypeSchema().required(), dataset: datasetAddressSchema(), }) .test('no-multiple-apikey', `Found multiple ${API_KEY_PLACEHOLDER} occurrences in API call parameters, it must have at most one occurrence`, (obj, context) => { const { url, headers } = context.originalValue; return (countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) <= 1); }) .test('dataset-provided-when-needed', `Using ${API_KEY_PLACEHOLDER} placeholder but no dataset provided`, (obj, context) => { const { url, headers, dataset } = context.originalValue; return !(countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) >= 1 && (!dataset || dataset === '0x0000000000000000000000000000000000000000')); }) .test('no-unused-dataset', `Provided dataset but no ${API_KEY_PLACEHOLDER} placeholder found in url or headers`, (obj, context) => { const { url, headers, dataset } = context.originalValue; return !(dataset && dataset !== '0x0000000000000000000000000000000000000000' && countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) === 0); }) .noUnknown(true); // eslint-disable-next-line @typescript-eslint/no-explicit-any const strictParamSetSchema = () => object() .test('is-params-set', '${originalValue} is not a valid paramSet', async (obj, context) => { try { if (obj && obj.body === '') { await object({ url: httpsUrlSchema().required(), method: httpMethodSchema().required(), headers: headersMapSchema().required(), body: bodySchema(), JSONPath: jsonPathSchema().required(), dataType: dataTypeSchema().required(), dataset: datasetAddressSchema().required(), }) .required() .strict() .noUnknown(true) .validate(obj); } else { await object({ url: httpsUrlSchema().required(), method: httpMethodSchema().required(), headers: headersMapSchema().required(), body: bodySchema().required(), JSONPath: jsonPathSchema().required(), dataType: dataTypeSchema().required(), dataset: datasetAddressSchema().required(), }) .required() .strict() .noUnknown(true) .validate(obj); } return true; } catch (e) { return context.createError({ message: e.message }); } }) .test('no-multiple-apikey', `Found multiple ${API_KEY_PLACEHOLDER} occurrences in API call parameters, it must have at most one occurrence`, (obj, context) => { const { url, headers } = context.originalValue; return (countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) <= 1); }) .test('dataset-provided-when-needed', `Using ${API_KEY_PLACEHOLDER} placeholder but no dataset provided`, (obj, context) => { const { url, headers, dataset } = context.originalValue; return !(countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) >= 1 && (!dataset || dataset === '0x0000000000000000000000000000000000000000')); }) .test('no-unused-dataset', `Provided dataset but no ${API_KEY_PLACEHOLDER} placeholder found in url or headers`, (obj, context) => { const { url, headers, dataset } = context.originalValue; return !(dataset && dataset !== '0x0000000000000000000000000000000000000000' && countSubstrAllowOverlap(JSON.stringify({ url, headers }), API_KEY_PLACEHOLDER) === 0); }); const jsonParamSetSchema = () => string() .strict() .required() .test('is-json', '${originalValue} is not a valid JSON', (value) => { try { JSON.parse(value); return true; } catch (e) { return false; } }) .test('is-params-set', '${originalValue} is not a valid paramSet', async (value, context) => { try { const obj = JSON.parse(value); await strictParamSetSchema().validate(obj); return true; } catch (e) { return context.createError({ message: `${context.originalValue} is not a valid paramSet (${e.message})`, }); } }); const readDataTypeSchema = () => string() .oneOf(['boolean', 'number', 'string', 'raw'], 'dataType read option must be one of the following values: ${values}') .required(); const updateTargetBlockchainsSchema = () => array().of(number().oneOf(SUPPORTED_TARGET_BLOCKCHAINS)).default([]); export { callParamsSchema, rawParamsSchema, paramSetSchema, strictCallParamsSchema, strictParamSetSchema, jsonParamSetSchema, readDataTypeSchema, updateTargetBlockchainsSchema, }; //# sourceMappingURL=validators.js.map