mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-23 07:38:58 -04:00
Added nested keys check after root keys check for environment editor. (#2685)
Co-authored-by: Opender Singh <opender.singh@konghq.com> Co-authored-by: James Gatz <jamesgatzos@gmail.com> Co-authored-by: Dimitri Mitropoulos <dimitrimitropoulos@gmail.com>
This commit is contained in:
@@ -1,26 +1,149 @@
|
||||
import { NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME } from '../../../../templating';
|
||||
import { ensureKeyIsValid } from '../environment-editor';
|
||||
import { checkNestedKeys, ensureKeyIsValid } from '../environment-editor';
|
||||
|
||||
describe('ensureKeyIsValid', () => {
|
||||
it.each(['$', '$a', '$ab'])('%s should be invalid when as key begins with $', key => {
|
||||
expect(ensureKeyIsValid(key)).toBe(`"${key}" cannot begin with '$' or contain a '.'`);
|
||||
describe('ensureKeyIsValid()', () => {
|
||||
it.each([
|
||||
'$',
|
||||
'$a',
|
||||
'$ab',
|
||||
])('"%s" should be invalid when key begins with $', key => {
|
||||
expect(ensureKeyIsValid(key, false)).toBe(`"${key}" cannot begin with '$' or contain a '.'`);
|
||||
});
|
||||
|
||||
it.each(['.', 'a.', '.a', 'a.b'])('%s should be invalid when key contains .', key => {
|
||||
expect(ensureKeyIsValid(key)).toBe(`"${key}" cannot begin with '$' or contain a '.'`);
|
||||
it.each([
|
||||
'.',
|
||||
'a.',
|
||||
'.a',
|
||||
'a.b',
|
||||
])('"%s" should be invalid when key contains .', key => {
|
||||
expect(ensureKeyIsValid(key, false)).toBe(`"${key}" cannot begin with '$' or contain a '.'`);
|
||||
});
|
||||
|
||||
it.each(['$a.b', '$.'])('%s should be invalid when key starts with $ and contains .', key => {
|
||||
expect(ensureKeyIsValid(key)).toBe(`"${key}" cannot begin with '$' or contain a '.'`);
|
||||
it.each([
|
||||
'$a.b',
|
||||
'$.',
|
||||
])('"%s" should be invalid when key starts with $ and contains .', key => {
|
||||
expect(ensureKeyIsValid(key, false)).toBe(`"${key}" cannot begin with '$' or contain a '.'`);
|
||||
});
|
||||
|
||||
const name = NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME;
|
||||
|
||||
it(`${name} as a key should be invalid`, () => {
|
||||
expect(ensureKeyIsValid(name)).toBe(`"${name}" is a reserved key`);
|
||||
it.each([
|
||||
'_',
|
||||
])('"%s" should be invalid when key is _', key => {
|
||||
expect(ensureKeyIsValid(key, true)).toBe(`"${key}" is a reserved key`);
|
||||
});
|
||||
|
||||
it.each(['a', 'ab', 'a$', 'a$b', 'a-b', `a${name}b`, `${name}ab`])('%s should be valid', key => {
|
||||
expect(ensureKeyIsValid(key)).toBe(null);
|
||||
it.each([
|
||||
'_',
|
||||
'a',
|
||||
'ab',
|
||||
'a$',
|
||||
'a$b',
|
||||
'a-b',
|
||||
`a${NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME}b`,
|
||||
`${NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME}ab`,
|
||||
])('"%s" should be valid as a nested key', key => {
|
||||
expect(ensureKeyIsValid(key, false)).toBe(null);
|
||||
});
|
||||
|
||||
it.each([
|
||||
'a',
|
||||
'ab',
|
||||
'a$',
|
||||
'a$b',
|
||||
'a-b',
|
||||
`a${NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME}b`,
|
||||
`${NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME}ab`,
|
||||
])('"%s" should be valid as a root value', key => {
|
||||
expect(ensureKeyIsValid(key, true)).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkNestedKeys()', () => {
|
||||
it('should check root property and error', () => {
|
||||
const obj = {
|
||||
'base-url': 'https://api.insomnia.rest',
|
||||
'$nes.ted': {
|
||||
'path-with-hyphens': '/path-with-hyphen',
|
||||
},
|
||||
'ar-ray': [
|
||||
'/first',
|
||||
{
|
||||
'second': 'second',
|
||||
},
|
||||
{
|
||||
'third': 'third',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const err = checkNestedKeys(obj);
|
||||
|
||||
expect(err).toBe('"$nes.ted" cannot begin with \'$\' or contain a \'.\'');
|
||||
});
|
||||
|
||||
it('should check nested property and error', () => {
|
||||
const obj = {
|
||||
'base-url': 'https://api.insomnia.rest',
|
||||
'nested': {
|
||||
'$path-wi.th-hyphens': '/path-with-hyphen',
|
||||
},
|
||||
'ar-ray': [
|
||||
'/first',
|
||||
{
|
||||
'second': 'second',
|
||||
},
|
||||
{
|
||||
'third': 'third',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const err = checkNestedKeys(obj);
|
||||
|
||||
expect(err).toBe('"$path-wi.th-hyphens" cannot begin with \'$\' or contain a \'.\'');
|
||||
});
|
||||
|
||||
it('should check for complex objects inside array', () => {
|
||||
const obj = {
|
||||
'base-url': 'https://api.insomnia.rest',
|
||||
'nested': {
|
||||
'path-with-hyphens': '/path-with-hyphen',
|
||||
},
|
||||
'ar-ray': [
|
||||
'/first',
|
||||
{
|
||||
'second': 'second',
|
||||
},
|
||||
{
|
||||
'thi.rd': 'third',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const err = checkNestedKeys(obj);
|
||||
|
||||
expect(err).toBe('"thi.rd" cannot begin with \'$\' or contain a \'.\'');
|
||||
});
|
||||
|
||||
it('should check nested properties and pass', () => {
|
||||
const obj = {
|
||||
'base-url': 'https://api.insomnia.rest',
|
||||
'nested': {
|
||||
'path-with-hyphens': '/path-with-hyphen',
|
||||
},
|
||||
'ar-ray': [
|
||||
'/first',
|
||||
{
|
||||
'second': 'second',
|
||||
},
|
||||
{
|
||||
'third': 'third',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const err = checkNestedKeys(obj);
|
||||
|
||||
expect(err).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,21 +5,52 @@ import React, { PureComponent } from 'react';
|
||||
import { AUTOBIND_CFG, JSON_ORDER_PREFIX, JSON_ORDER_SEPARATOR } from '../../../common/constants';
|
||||
import { NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME } from '../../../templating';
|
||||
import CodeEditor from '../codemirror/code-editor';
|
||||
|
||||
// NeDB field names cannot begin with '$' or contain a period '.'
|
||||
// Docs: https://github.com/DeNA/nedb#inserting-documents
|
||||
const INVALID_NEDB_KEY_REGEX = /^\$|\./;
|
||||
export const ensureKeyIsValid = (key: string): string | null => {
|
||||
|
||||
export const ensureKeyIsValid = (key: string, isRoot: boolean): string | null => {
|
||||
if (key.match(INVALID_NEDB_KEY_REGEX)) {
|
||||
return `"${key}" cannot begin with '$' or contain a '.'`;
|
||||
}
|
||||
|
||||
if (key === NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME) {
|
||||
return `"${NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME}" is a reserved key`; // verbiage WIP
|
||||
if (key === NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME && isRoot) {
|
||||
return `"${NUNJUCKS_TEMPLATE_GLOBAL_PROPERTY_NAME}" is a reserved key`;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively check nested keys in and immediately return when an invalid key found
|
||||
*/
|
||||
export function checkNestedKeys(obj: Record<string, any>, isRoot = true): string | null {
|
||||
for (const key in obj) {
|
||||
let result: string | null = null;
|
||||
|
||||
// Check current key
|
||||
result = ensureKeyIsValid(key, isRoot);
|
||||
|
||||
// Exit if necessary
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check nested keys
|
||||
if (typeof obj[key] === 'object') {
|
||||
result = checkNestedKeys(obj[key], false);
|
||||
}
|
||||
|
||||
// Exit if necessary
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export interface EnvironmentInfo {
|
||||
object: Record<string, any>;
|
||||
propertyOrder: Record<string, any> | null;
|
||||
@@ -64,14 +95,11 @@ class EnvironmentEditor extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
// Check for invalid key names
|
||||
// TODO: these only check root properties, not nested properties
|
||||
if (value && value.object) {
|
||||
for (const key of Object.keys(value.object)) {
|
||||
error = ensureKeyIsValid(key);
|
||||
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
// Check root and nested properties
|
||||
const err = checkNestedKeys(value.object);
|
||||
if (err) {
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user