diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index f37cf1ca..2778be21 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -996,4 +996,130 @@ describe('schemas', () => { }) }); + it('should throw with invalid userId (>10 chars)', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/AClass', + headers: masterKeyHeaders, + json: true, + body: { + classLevelPermissions: { + find: { + '1234567890A': true + }, + } + } + }, (error, response, body) => { + expect(body.error).toEqual("'1234567890A' is not a valid key for class level permissions"); + done(); + }) + }); + + it('should throw with invalid userId (<10 chars)', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/AClass', + headers: masterKeyHeaders, + json: true, + body: { + classLevelPermissions: { + find: { + 'a12345678': true + }, + } + } + }, (error, response, body) => { + expect(body.error).toEqual("'a12345678' is not a valid key for class level permissions"); + done(); + }) + }); + + it('should throw with invalid userId (invalid char)', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/AClass', + headers: masterKeyHeaders, + json: true, + body: { + classLevelPermissions: { + find: { + '12345_6789': true + }, + } + } + }, (error, response, body) => { + expect(body.error).toEqual("'12345_6789' is not a valid key for class level permissions"); + done(); + }) + }); + + it('should throw with invalid * (spaces)', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/AClass', + headers: masterKeyHeaders, + json: true, + body: { + classLevelPermissions: { + find: { + ' *': true + }, + } + } + }, (error, response, body) => { + expect(body.error).toEqual("' *' is not a valid key for class level permissions"); + done(); + }) + }); + + it('should throw with invalid * (spaces)', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/AClass', + headers: masterKeyHeaders, + json: true, + body: { + classLevelPermissions: { + find: { + '* ': true + }, + } + } + }, (error, response, body) => { + expect(body.error).toEqual("'* ' is not a valid key for class level permissions"); + done(); + }) + }); + + it('should throw with invalid value', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/AClass', + headers: masterKeyHeaders, + json: true, + body: { + classLevelPermissions: { + find: { + '*': 1 + }, + } + } + }, (error, response, body) => { + expect(body.error).toEqual("'1' is not a valid value for class level permissions find:*:1"); + done(); + }) + }); + + it('should throw with invalid value', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/AClass', + headers: masterKeyHeaders, + json: true, + body: { + classLevelPermissions: { + find: { + '*': "" + }, + } + } + }, (error, response, body) => { + expect(body.error).toEqual("'' is not a valid value for class level permissions find:*:"); + done(); + }) + }); + }); diff --git a/src/Schema.js b/src/Schema.js index c54b9008..846a7490 100644 --- a/src/Schema.js +++ b/src/Schema.js @@ -76,15 +76,41 @@ var requiredColumns = { _Role: ["name", "ACL"] } +// 10 alpha numberic chars + uppercase +const userIdRegex = /^[a-zA-Z0-9]{10}$/; +// Anything that start with role +const roleRegex = /^role:.*/; +// * permission +const publicRegex = /^\*$/ + +const permissionKeyRegex = [userIdRegex, roleRegex, publicRegex]; + +function verifyPermissionKey(key) { + let result = permissionKeyRegex.reduce((isGood, regEx) => { + isGood = isGood || key.match(regEx) != null; + return isGood; + }, false); + if (!result) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid key for class level permissions`); + } +} + let CLPValidKeys = ['find', 'get', 'create', 'update', 'delete', 'addField']; function validateCLP(perms) { if (!perms) { return; } - Object.keys(perms).forEach((key) => { - if (CLPValidKeys.indexOf(key) == -1) { - throw new Parse.Error(Parse.Error.INVALID_JSON, `${key} is not a valid operation for class level permissions`); + Object.keys(perms).forEach((operation) => { + if (CLPValidKeys.indexOf(operation) == -1) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `${operation} is not a valid operation for class level permissions`); } + Object.keys(perms[operation]).forEach((key) => { + verifyPermissionKey(key); + let perm = perms[operation][key]; + if (perm !== true && perm !== false) { + throw new Parse.Error(Parse.Error.INVALID_JSON, `'${perm}' is not a valid value for class level permissions ${operation}:${key}:${perm}`); + } + }); }); } // Valid classes must: