From 33e3d256e4fb085b37cf79fe952fc04e882ec79e Mon Sep 17 00:00:00 2001 From: drobnikj Date: Mon, 26 Sep 2022 18:52:52 +0800 Subject: [PATCH 1/3] feat(input_schema): add support for secure input values by adding isSecret flag into sting property --- packages/input_schema/src/schema.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/input_schema/src/schema.json b/packages/input_schema/src/schema.json index b9f978bc1..033041680 100644 --- a/packages/input_schema/src/schema.json +++ b/packages/input_schema/src/schema.json @@ -92,6 +92,7 @@ "minLength": { "type": "integer" }, "maxLength": { "type": "integer" }, "editor": { "enum": ["javascript", "python", "textfield", "textarea", "hidden"] }, + "isSecret": { "type": "boolean" }, "sectionCaption": { "type": "string" }, "sectionDescription": { "type": "string" } }, From 26dc1dcdec490b2cd7735dbfe0eadfe655795921 Mon Sep 17 00:00:00 2001 From: drobnikj Date: Tue, 4 Oct 2022 21:28:13 +0800 Subject: [PATCH 2/3] feat(input_schema): improve isSecret string validation --- packages/input_schema/src/schema.json | 51 +++++++++++++++--- test/input_schema_definition.test.ts | 78 +++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 7 deletions(-) diff --git a/packages/input_schema/src/schema.json b/packages/input_schema/src/schema.json index 033041680..475fc149e 100644 --- a/packages/input_schema/src/schema.json +++ b/packages/input_schema/src/schema.json @@ -79,24 +79,61 @@ "stringProperty": { "title": "String property", "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "type": { "enum": ["string"] }, "title": { "type": "string" }, "description": { "type": "string" }, - "default": { "type": "string" }, - "prefill": { "type": "string" }, "example": { "type": "string" }, - "pattern": { "type": "string" }, "nullable": { "type": "boolean" }, - "minLength": { "type": "integer" }, - "maxLength": { "type": "integer" }, "editor": { "enum": ["javascript", "python", "textfield", "textarea", "hidden"] }, "isSecret": { "type": "boolean" }, "sectionCaption": { "type": "string" }, "sectionDescription": { "type": "string" } }, - "required": ["type", "title", "description", "editor"] + "required": ["type", "title", "description", "editor"], + "if": { + "properties": { + "isSecret": { + "not": { + "const": true + } + } + } + }, + "then": { + "additionalProperties": false, + "properties": { + "type": { "enum": ["string"] }, + "title": { "type": "string" }, + "description": { "type": "string" }, + "default": { "type": "string" }, + "prefill": { "type": "string" }, + "example": { "type": "string" }, + "pattern": { "type": "string" }, + "nullable": { "type": "boolean" }, + "minLength": { "type": "integer" }, + "maxLength": { "type": "integer" }, + "editor": { "enum": ["javascript", "python", "textfield", "textarea", "hidden"] }, + "isSecret": { "type": "boolean" }, + "sectionCaption": { "type": "string" }, + "sectionDescription": { "type": "string" } + } + }, + "else": { + "additionalProperties": false, + "properties": { + "type": { "enum": ["string"] }, + "title": { "type": "string" }, + "description": { "type": "string" }, + "example": { "type": "string" }, + "nullable": { "type": "boolean" }, + "editor": { "enum": ["textfield", "textarea", "hidden"] }, + "isSecret": { "type": "boolean" }, + "sectionCaption": { "type": "string" }, + "sectionDescription": { "type": "string" } + } + } }, "arrayProperty": { "title": "Array property", diff --git a/test/input_schema_definition.test.ts b/test/input_schema_definition.test.ts index e31d8867e..22a77a83a 100644 --- a/test/input_schema_definition.test.ts +++ b/test/input_schema_definition.test.ts @@ -207,5 +207,83 @@ describe('input_schema.json', () => { turnOffConsoleWarnErrors(); }); + + describe('special cases for isSecret string type', () => { + const isSchemaValid = (fields: object, isSecret?: boolean) => { + return ajv.validate(inputSchema, { + title: 'Test input schema', + type: 'object', + schemaVersion: 1, + properties: { + myField: { + title: 'Field title', + description: 'My test field', + type: 'string', + isSecret, + ...fields, + }, + }, + }); + }; + + it('should not allow all editors', () => { + ['textfield', 'textarea', 'hidden'].forEach((editor) => { + expect(isSchemaValid({ editor }, true)).toBe(true); + }); + ['javascript', 'python'].forEach((editor) => { + expect(isSchemaValid({ editor }, true)).toBe(false); + }); + }); + + it('should not allow some fields', () => { + ['minLength', 'maxLength'].forEach((intField) => { + expect(isSchemaValid({ [intField]: 10 }, true)).toBe(false); + }); + ['default', 'prefill', 'pattern'].forEach((stringField) => { + expect(isSchemaValid({ [stringField]: 'bla' }, true)).toBe(false); + }); + }); + + it('should work without isSecret with all editors and properties', () => { + expect(ajv.validate(inputSchema, { + title: 'Test input schema', + type: 'object', + schemaVersion: 1, + properties: { + myField: { + title: 'Field title', + description: 'My test field', + type: 'string', + editor: 'textarea', + isSecret: false, + minLength: 2, + maxLength: 100, + default: 'blablablablabla', + prefill: 'blablablablablablablablablablabla', + }, + }, + })).toBe(true); + + expect(ajv.validate(inputSchema, { + title: 'Test input schema', + type: 'object', + schemaVersion: 1, + properties: { + myField: { + title: 'Field title', + description: 'My test field', + type: 'string', + editor: 'textarea', + isSecret: false, + minLength: 2, + maxLength: 100, + default: 'blablablablabla', + prefill: 'blablablablablablablablablablabla', + bla: 'bla', // Validation failed because additional property + }, + }, + })).toBe(false); + }); + }); }); }); From ab595b965222e55b1493a306452d39c3ae792ce4 Mon Sep 17 00:00:00 2001 From: drobnikj Date: Thu, 6 Oct 2022 19:48:04 +0800 Subject: [PATCH 3/3] chore(input_secrets): fix schema.json def --- packages/input_schema/src/schema.json | 5 +--- test/input_schema.test.ts | 43 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/packages/input_schema/src/schema.json b/packages/input_schema/src/schema.json index 475fc149e..c806d9070 100644 --- a/packages/input_schema/src/schema.json +++ b/packages/input_schema/src/schema.json @@ -84,12 +84,9 @@ "type": { "enum": ["string"] }, "title": { "type": "string" }, "description": { "type": "string" }, - "example": { "type": "string" }, "nullable": { "type": "boolean" }, "editor": { "enum": ["javascript", "python", "textfield", "textarea", "hidden"] }, - "isSecret": { "type": "boolean" }, - "sectionCaption": { "type": "string" }, - "sectionDescription": { "type": "string" } + "isSecret": { "type": "boolean" } }, "required": ["type", "title", "description", "editor"], "if": { diff --git a/test/input_schema.test.ts b/test/input_schema.test.ts index 18b885e77..cdc61fd52 100644 --- a/test/input_schema.test.ts +++ b/test/input_schema.test.ts @@ -145,6 +145,49 @@ describe('input_schema.json', () => { ); }); + it('should throw correct error on field in if/else definition', () => { + const schema = { + title: 'Test input schema', + type: 'object', + schemaVersion: 1, + properties: { + myField: { + title: 'Field title', + type: 'string', + description: 'Some description ...', + editor: 'textfield', + maxLength: true, + }, + }, + }; + + expect(() => validateInputSchema(validator, schema)).toThrow( + 'Input schema is not valid (Field schema.properties.myField.maxLength must be integer)', + ); + }); + + it('should throw correct error in string type else definition', () => { + const schema = { + title: 'Test input schema', + type: 'object', + schemaVersion: 1, + properties: { + myField: { + title: 'Field title', + type: 'string', + isSecret: true, + description: 'Some description ...', + editor: 'textfield', + maxLength: true, + }, + }, + }; + + expect(() => validateInputSchema(validator, schema)).toThrow( + 'Input schema is not valid (Property schema.properties.myField.maxLength is not allowed.)', + ); + }); + it('should throw error on field structure level for a type ENUM STRING', () => { const schema = { title: 'Test input schema',