Allow protectedFields for Authenticated users and Public. Fix userField with keys/excludedKeys (#6415)

* fix error message and test it

* protected fields fixes

* clean

* remove duplicate test, add some comments

* no need for 'requiresAuthentication'
This commit is contained in:
Old Grandpa
2020-02-19 12:34:08 +03:00
committed by GitHub
parent ca1ae336c9
commit 292bdb713a
9 changed files with 1390 additions and 45 deletions

View File

@@ -175,32 +175,62 @@ const volatileClasses = Object.freeze([
// Anything that start with role
const roleRegex = /^role:.*/;
// Anything that starts with userField
const pointerPermissionRegex = /^userField:.*/;
// Anything that starts with userField (allowed for protected fields only)
const protectedFieldsPointerRegex = /^userField:.*/;
// * permission
const publicRegex = /^\*$/;
const requireAuthenticationRegex = /^requiresAuthentication$/;
const authenticatedRegex = /^authenticated$/;
const pointerFieldsRegex = /^pointerFields$/;
const requiresAuthenticationRegex = /^requiresAuthentication$/;
const permissionKeyRegex = Object.freeze([
roleRegex,
pointerPermissionRegex,
const clpPointerRegex = /^pointerFields$/;
// regex for validating entities in protectedFields object
const protectedFieldsRegex = Object.freeze([
protectedFieldsPointerRegex,
publicRegex,
requireAuthenticationRegex,
pointerFieldsRegex,
authenticatedRegex,
roleRegex,
]);
// clp regex
const clpFieldsRegex = Object.freeze([
clpPointerRegex,
publicRegex,
requiresAuthenticationRegex,
roleRegex,
]);
function validatePermissionKey(key, userIdRegExp) {
let matchesSome = false;
for (const regEx of permissionKeyRegex) {
for (const regEx of clpFieldsRegex) {
if (key.match(regEx) !== null) {
matchesSome = true;
break;
}
}
// userId depends on startup options so it's dynamic
const valid = matchesSome || key.match(userIdRegExp) !== null;
if (!valid) {
throw new Parse.Error(
Parse.Error.INVALID_JSON,
`'${key}' is not a valid key for class level permissions`
);
}
}
function validateProtectedFieldsKey(key, userIdRegExp) {
let matchesSome = false;
for (const regEx of protectedFieldsRegex) {
if (key.match(regEx) !== null) {
matchesSome = true;
break;
}
}
// userId regex depends on launch options so it's dynamic
const valid = matchesSome || key.match(userIdRegExp) !== null;
if (!valid) {
throw new Parse.Error(
@@ -264,7 +294,7 @@ function validateCLP(
if (operationKey === 'protectedFields') {
for (const entity in operation) {
// throws on unexpected key
validatePermissionKey(entity, userIdRegExp);
validateProtectedFieldsKey(entity, userIdRegExp);
const protectedFields = operation[entity];
@@ -301,6 +331,8 @@ function validateCLP(
// throws on unexpected key
validatePermissionKey(entity, userIdRegExp);
// entity can be either:
// "pointerFields": string[]
if (entity === 'pointerFields') {
const pointerFields = operation[entity];
@@ -311,13 +343,14 @@ function validateCLP(
} else {
throw new Parse.Error(
Parse.Error.INVALID_JSON,
`'${pointerFields}' is not a valid value for protectedFields[${entity}] - expected an array.`
`'${pointerFields}' is not a valid value for ${operationKey}[${entity}] - expected an array.`
);
}
// proceed with next entity key
continue;
}
// or [entity]: boolean
const permit = operation[entity];
if (permit !== true) {