introduces field-level policies on find operations
This commit is contained in:
41
src/auth/executeFieldPolicies.js
Normal file
41
src/auth/executeFieldPolicies.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const createPolicyPromise = async (args, data, field, operation) => {
|
||||
const resultingData = data;
|
||||
const result = await field.policies[operation](args);
|
||||
|
||||
if (!result) {
|
||||
delete resultingData[field.name];
|
||||
}
|
||||
};
|
||||
|
||||
const iterateFields = async (args, data, fields, operation, promises) => {
|
||||
fields.forEach((field) => {
|
||||
const dataToValidate = data || {};
|
||||
|
||||
if (data[field.name] || field.name === undefined) {
|
||||
if (field.policies[operation]) {
|
||||
promises.push(createPolicyPromise(args, data, field, operation));
|
||||
} else if (field.fields) {
|
||||
if (field.name === undefined) {
|
||||
iterateFields(args, dataToValidate, field.fields, operation, promises);
|
||||
} else if (field.type === 'repeater' || field.type === 'flexible') {
|
||||
dataToValidate[field.name].forEach((rowData) => {
|
||||
iterateFields(args, rowData, field.fields, operation, promises);
|
||||
});
|
||||
} else {
|
||||
iterateFields(args, dataToValidate[field.name], field.fields, operation, promises);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = async (args, data, fields, operation) => {
|
||||
try {
|
||||
const promises = [];
|
||||
iterateFields(args, data, fields, operation, promises);
|
||||
await Promise.all(promises);
|
||||
return data;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -16,19 +16,25 @@ const register = async (args) => {
|
||||
let options = { ...args };
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 2. Validate incoming data
|
||||
// 2. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Validate incoming data
|
||||
// /////////////////////////////////////
|
||||
|
||||
await validateCreate(args.data, args.collection.config.fields);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Execute before register field-level hooks
|
||||
// 4. Execute before register field-level hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
options.data = await executeFieldHooks(options, args.collection.config.fields, args.data, 'beforeCreate');
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute before register hook
|
||||
// 5. Execute before register hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { beforeRegister } = args.collection.config.hooks;
|
||||
@@ -38,7 +44,7 @@ const register = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Perform register
|
||||
// 6. Perform register
|
||||
// /////////////////////////////////////
|
||||
|
||||
const {
|
||||
@@ -68,7 +74,7 @@ const register = async (args) => {
|
||||
await passport.authenticate('local');
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 6. Execute after register hook
|
||||
// 7. Execute after register hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const afterRegister = args.collection.config.hooks;
|
||||
@@ -78,7 +84,7 @@ const register = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 7. Return user
|
||||
// 8. Return user
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result.toJSON({ virtuals: true });
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
const { NotFound } = require('../../errors');
|
||||
const executePolicy = require('../executePolicy');
|
||||
const validate = require('../../validation/validateUpdate');
|
||||
|
||||
const update = async (args) => {
|
||||
try {
|
||||
@@ -10,12 +11,23 @@ const update = async (args) => {
|
||||
|
||||
await executePolicy(args, args.config.policies.update);
|
||||
|
||||
// Await validation here
|
||||
|
||||
let options = { ...args };
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 1. Execute before update hook
|
||||
// 2. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Validate incoming data
|
||||
// /////////////////////////////////////
|
||||
|
||||
await validate(args.data, args.config.fields);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute before update hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { beforeUpdate } = args.config.hooks;
|
||||
@@ -25,7 +37,7 @@ const update = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 2. Perform update
|
||||
// 5. Perform update
|
||||
// /////////////////////////////////////
|
||||
|
||||
const {
|
||||
@@ -61,7 +73,7 @@ const update = async (args) => {
|
||||
user = user.toJSON({ virtuals: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Execute after update hook
|
||||
// 6. Execute after update hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const afterUpdateHook = args.config.hooks && args.config.hooks.afterUpdate;
|
||||
@@ -71,7 +83,7 @@ const update = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Return user
|
||||
// 7. Return user
|
||||
// /////////////////////////////////////
|
||||
|
||||
return user;
|
||||
|
||||
@@ -19,20 +19,26 @@ const create = async (args) => {
|
||||
let options = { ...args };
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 2. Validate incoming data
|
||||
// 2. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Validate incoming data
|
||||
// /////////////////////////////////////
|
||||
|
||||
await validateCreate(args.data, args.config.fields);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Execute before create field-level hooks
|
||||
// 4. Execute before create field-level hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
options.data = await executeFieldHooks(options, args.config.fields, args.data, 'beforeCreate', args.data);
|
||||
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Upload and resize any files that may be present
|
||||
// 5. Upload and resize any files that may be present
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (args.config.upload) {
|
||||
@@ -65,7 +71,7 @@ const create = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Execute before collection hook
|
||||
// 6. Execute before collection hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { beforeCreate } = args.config.hooks;
|
||||
@@ -75,7 +81,7 @@ const create = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 6. Perform database operation
|
||||
// 7. Perform database operation
|
||||
// /////////////////////////////////////
|
||||
|
||||
const {
|
||||
@@ -99,7 +105,7 @@ const create = async (args) => {
|
||||
result = result.toJSON({ virtuals: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 7. Execute after collection hook
|
||||
// 8. Execute after collection hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { afterCreate } = args.config.hooks;
|
||||
@@ -109,7 +115,7 @@ const create = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 8. Return results
|
||||
// 9. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const merge = require('lodash.merge');
|
||||
const executePolicy = require('../../auth/executePolicy');
|
||||
const executeFieldPolicies = require('../../auth/executeFieldPolicies');
|
||||
const executeFieldHooks = require('../../fields/executeHooks');
|
||||
|
||||
const find = async (args) => {
|
||||
@@ -75,7 +76,7 @@ const find = async (args) => {
|
||||
let result = await Model.paginate(query, optionsToExecute);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute field-level afterRead hooks
|
||||
// 4. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = {
|
||||
@@ -84,12 +85,25 @@ const find = async (args) => {
|
||||
if (locale && doc.setLocale) {
|
||||
doc.setLocale(locale, fallbackLocale);
|
||||
}
|
||||
|
||||
const json = doc.toJSON({ virtuals: true });
|
||||
return executeFieldPolicies(args, json, args.config.fields, 'read');
|
||||
})),
|
||||
};
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Execute field-level afterRead hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = {
|
||||
...result,
|
||||
docs: await Promise.all(result.docs.map(async (doc) => {
|
||||
return executeFieldHooks(options, args.config.fields, doc, 'afterRead', doc);
|
||||
})),
|
||||
};
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Execute afterRead collection hook
|
||||
// 6. Execute afterRead collection hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { afterRead } = args.config.hooks;
|
||||
@@ -99,24 +113,19 @@ const find = async (args) => {
|
||||
afterReadResult = {
|
||||
...result,
|
||||
docs: await Promise.all(result.docs.map(async (doc) => {
|
||||
const json = doc.toJSON({ virtuals: true });
|
||||
return afterRead({
|
||||
options,
|
||||
doc,
|
||||
json,
|
||||
}) || json;
|
||||
}) || doc;
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 6. Return results
|
||||
// 7. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return afterReadResult || {
|
||||
...result,
|
||||
docs: result.docs.map(doc => doc.toJSON({ virtuals: true })),
|
||||
};
|
||||
return afterReadResult || result;
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,13 @@ const findByID = async (args) => {
|
||||
result = await executeFieldHooks(options, options.config.fields, result, 'afterRead', result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Execute after collection hook
|
||||
// 5. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 6. Execute after collection hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { afterRead } = args.config.hooks;
|
||||
@@ -96,12 +102,12 @@ const findByID = async (args) => {
|
||||
json = await afterRead({
|
||||
...options,
|
||||
result,
|
||||
json,
|
||||
doc: json,
|
||||
}) || json;
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 6. Return results
|
||||
// 7. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return json;
|
||||
|
||||
@@ -17,19 +17,25 @@ const update = async (args) => {
|
||||
let options = { ...args };
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 2. Validate incoming data
|
||||
// 2. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Validate incoming data
|
||||
// /////////////////////////////////////
|
||||
|
||||
await validate(args.data, args.config.fields);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Execute before update field-level hooks
|
||||
// 4. Execute before update field-level hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
options.data = await executeFieldHooks(options, args.config.fields, args.data, 'beforeUpdate', args.data);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute before collection hook
|
||||
// 5. Execute before collection hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { beforeUpdate } = args.config.hooks;
|
||||
@@ -39,7 +45,7 @@ const update = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Perform database operation
|
||||
// 6. Perform database operation
|
||||
// /////////////////////////////////////
|
||||
|
||||
let {
|
||||
@@ -74,7 +80,7 @@ const update = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 6. Upload and resize any files that may be present
|
||||
// 7. Upload and resize any files that may be present
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (args.config.upload) {
|
||||
@@ -105,7 +111,7 @@ const update = async (args) => {
|
||||
result = result.toJSON({ virtuals: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 7. Execute after collection hook
|
||||
// 8. Execute after collection hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { afterUpdate } = args.config.hooks;
|
||||
@@ -115,7 +121,7 @@ const update = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 8. Return results
|
||||
// 9. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
|
||||
@@ -25,6 +25,7 @@ function initAdmin() {
|
||||
|
||||
this.express.use(this.config.routes.admin, router);
|
||||
} else {
|
||||
this.express.use(this.config.routes.admin, history());
|
||||
this.express.use(this.initWebpack());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ const sanitizeFields = (fields) => {
|
||||
}
|
||||
|
||||
if (!field.hooks) field.hooks = {};
|
||||
if (!field.policies) field.policies = {};
|
||||
|
||||
if (field.fields) field.fields = sanitizeFields(field.fields);
|
||||
|
||||
|
||||
@@ -64,14 +64,21 @@ const findOne = async (args) => {
|
||||
|
||||
let json = result.toJSON({ virtuals: true });
|
||||
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute after collection field-level hooks
|
||||
// 4. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Execute after collection field-level hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await executeFieldHooks(options, args.config.fields, result, 'afterRead', result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Execute after collection hook
|
||||
// 6. Execute after collection hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { afterRead } = args.config.hooks;
|
||||
@@ -81,7 +88,7 @@ const findOne = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 6. Return results
|
||||
// 7. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return json;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const executePolicy = require('../../auth/executePolicy');
|
||||
const executeFieldHooks = require('../../fields/executeHooks');
|
||||
const validate = require('../../validation/validateUpdate');
|
||||
|
||||
const update = async (args) => {
|
||||
try {
|
||||
@@ -11,16 +12,26 @@ const update = async (args) => {
|
||||
|
||||
let options = { ...args };
|
||||
|
||||
// Await validation here
|
||||
// /////////////////////////////////////
|
||||
// 2. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 2. Execute before update field-level hooks
|
||||
// 3. Validate incoming data
|
||||
// /////////////////////////////////////
|
||||
|
||||
await validate(args.data, args.config.fields);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute before update field-level hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
options.data = await executeFieldHooks(options, args.config.fields, args.data, 'beforeUpdate', args.data);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 2. Execute before global hook
|
||||
// 5. Execute before global hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { beforeUpdate } = args.config.hooks;
|
||||
@@ -30,7 +41,7 @@ const update = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Perform database operation
|
||||
// 6. Perform database operation
|
||||
// /////////////////////////////////////
|
||||
|
||||
const {
|
||||
@@ -61,7 +72,7 @@ const update = async (args) => {
|
||||
result = result.toJSON({ virtuals: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute after global hook
|
||||
// 7. Execute after global hook
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { afterUpdate } = args.config.hooks;
|
||||
@@ -71,7 +82,7 @@ const update = async (args) => {
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Return results
|
||||
// 8. Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user