From b2ff2e83c3bacd1ff98ee07cf4155dad0e6e7d0a Mon Sep 17 00:00:00 2001 From: alencarlucas Date: Thu, 15 Aug 2019 15:02:32 -0300 Subject: [PATCH 1/3] feat: Avoid setting a relation as required or with a defaultValue --- spec/schemas.spec.js | 47 +++++++++++++++++++++++++++++ src/Controllers/SchemaController.js | 24 +++++++++++---- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index 0ff8a22e66..6fccc7329e 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -431,6 +431,7 @@ describe('schemas', () => { defaultValue: false, }, defaultZero: { type: 'Number', defaultValue: 0 }, + relation: { type: 'Relation', targetClass: 'SomeClass' } }, }, }).then(async response => { @@ -457,6 +458,7 @@ describe('schemas', () => { defaultValue: false, }, defaultZero: { type: 'Number', defaultValue: 0 }, + relation: { type: 'Relation', targetClass: 'SomeClass' } }, classLevelPermissions: defaultClassLevelPermissions, }); @@ -479,10 +481,55 @@ describe('schemas', () => { expect(obj.get('defaultFalse')).toEqual(false); expect(obj.get('defaultZero')).toEqual(0); expect(obj.get('ptr')).toBeUndefined(); + expect(obj.get('relation')).toBeUndefined(); done(); }); }); + it('try to set a relation field as a required field', async (done) => { + try { + await request({ + url: 'http://localhost:8378/1/schemas', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'NewClassWithRelationRequired', + fields: { + foo: { type: 'String' }, + relation: { type: 'Relation', targetClass: 'SomeClass', required: true } + }, + }, + }); + fail('should fail'); + } catch (e) { + expect(e.data.code).toEqual(111); + } + done(); + }); + + it('try to set a relation field with a default value', async (done) => { + try { + await request({ + url: 'http://localhost:8378/1/schemas', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'NewClassRelationWithOptions', + fields: { + foo: { type: 'String' }, + relation: { type: 'Relation', targetClass: 'SomeClass', defaultValue: { type: 'Relation', targetClass: '_User' } } + }, + }, + }); + fail('should fail'); + } catch (e) { + expect(e.data.code).toEqual(111); + } + done(); + }); + it('validated the data type of default values when creating a new class', async () => { try { await request({ diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index aa68ce7617..785fe8bb0e 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -895,22 +895,34 @@ export default class SchemaController { error: 'field ' + fieldName + ' cannot be added', }; } - const type = fields[fieldName]; - const error = fieldTypeIsInvalid(type); + const fieldType = fields[fieldName]; + const error = fieldTypeIsInvalid(fieldType); if (error) return { code: error.code, error: error.message }; - if (type.defaultValue !== undefined) { - let defaultValueType = getType(type.defaultValue); + if (fieldType.defaultValue !== undefined) { + let defaultValueType = getType(fieldType.defaultValue); if (typeof defaultValueType === 'string') { defaultValueType = { type: defaultValueType }; + } else if (typeof defaultValueType === 'object' && fieldType.type === 'Relation') { + return { + code: Parse.Error.INCORRECT_TYPE, + error: `The 'default value' option is not applicable for ${typeToString(fieldType)}` + }; } - if (!dbTypeMatchesObjectType(type, defaultValueType)) { + if (!dbTypeMatchesObjectType(fieldType, defaultValueType)) { return { code: Parse.Error.INCORRECT_TYPE, error: `schema mismatch for ${className}.${fieldName} default value; expected ${typeToString( - type + fieldType )} but got ${typeToString(defaultValueType)}`, }; } + } else if (fieldType.required) { + if (typeof fieldType === 'object' && fieldType.type === 'Relation') { + return { + code: Parse.Error.INCORRECT_TYPE, + error: `The 'required' option is not applicable for ${typeToString(fieldType)}` + }; + } } } } From d2a29092ddfbfa2d40c232dbda917fad5e5ff005 Mon Sep 17 00:00:00 2001 From: alencarlucas Date: Tue, 20 Aug 2019 15:57:16 -0300 Subject: [PATCH 2/3] chore: Test to update a class with a relation field with options --- spec/schemas.spec.js | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index 6fccc7329e..cf204a6388 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -530,6 +530,59 @@ describe('schemas', () => { done(); }); + it('try to update schemas with a relation field with options', async (done) => { + await request({ + url: 'http://localhost:8378/1/schemas', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'NewClassRelationWithOptions', + fields: { + foo: { type: 'String' } + }, + }, + }); + try { + await request({ + url: 'http://localhost:8378/1/schemas/NewClassRelationWithOptions', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'NewClassRelationWithOptions', + fields: { + relation: { type: 'Relation', targetClass: 'SomeClass', required: true } + }, + _method: "PUT" + } + }); + fail('should fail'); + } catch (e) { + expect(e.data.code).toEqual(111); + } + + try { + await request({ + url: 'http://localhost:8378/1/schemas/NewClassRelationWithOptions', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'NewClassRelationWithOptions', + fields: { + relation: { type: 'Relation', targetClass: 'SomeClass', defaultValue: { type: 'Relation', targetClass: '_User' } } + }, + _method: "PUT" + } + }); + fail('should fail'); + } catch (e) { + expect(e.data.code).toEqual(111); + } + done(); + }); + it('validated the data type of default values when creating a new class', async () => { try { await request({ From e14dcce44c4f16711a45468caa110cf216c16e80 Mon Sep 17 00:00:00 2001 From: alencarlucas Date: Tue, 20 Aug 2019 18:28:40 -0300 Subject: [PATCH 3/3] chore: Improve tests --- spec/schemas.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index cf204a6388..b257c001bf 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -519,7 +519,7 @@ describe('schemas', () => { className: 'NewClassRelationWithOptions', fields: { foo: { type: 'String' }, - relation: { type: 'Relation', targetClass: 'SomeClass', defaultValue: { type: 'Relation', targetClass: '_User' } } + relation: { type: 'Relation', targetClass: 'SomeClass', defaultValue: { __type: 'Relation', className: '_User' } } }, }, }); @@ -571,7 +571,7 @@ describe('schemas', () => { body: { className: 'NewClassRelationWithOptions', fields: { - relation: { type: 'Relation', targetClass: 'SomeClass', defaultValue: { type: 'Relation', targetClass: '_User' } } + relation: { type: 'Relation', targetClass: 'SomeClass', defaultValue: { __type: 'Relation', className: '_User' } } }, _method: "PUT" }