renames policy to access

This commit is contained in:
James
2020-07-08 11:00:50 -04:00
parent 1becc97ea7
commit e818537fe9
48 changed files with 290 additions and 276 deletions

View File

@@ -1,7 +1,7 @@
const roles = require('../policies/roles');
const checkRole = require('../policies/checkRole');
const roles = require('../access/roles');
const checkRole = require('../access/checkRole');
const policy = ({ req: { user } }) => {
const access = ({ req: { user } }) => {
const result = checkRole(['admin'], user);
return result;
};
@@ -13,11 +13,11 @@ module.exports = {
plural: 'Admins',
},
useAsTitle: 'email',
policies: {
create: policy,
read: policy,
update: policy,
delete: policy,
access: {
create: access,
read: access,
update: access,
delete: access,
admin: () => true,
},
auth: {

View File

@@ -1,4 +1,4 @@
const checkRole = require('../policies/checkRole');
const checkRole = require('../access/checkRole');
const Email = require('../content-blocks/Email');
const Quote = require('../content-blocks/Quote');
const NumberBlock = require('../content-blocks/Number');
@@ -18,7 +18,7 @@ const AllFields = {
return null;
},
policies: {
access: {
read: () => true,
},
fields: [
@@ -29,7 +29,7 @@ const AllFields = {
required: true,
defaultValue: 'Default Value',
unique: true,
policies: {
access: {
create: ({ req: { user } }) => checkRole(['admin'], user),
update: ({ req: { user } }) => checkRole(['admin'], user),
read: ({ req: { user } }) => Boolean(user),
@@ -154,7 +154,7 @@ const AllFields = {
label: 'Repeater Text 2',
type: 'text',
required: true,
policies: {
access: {
read: ({ req: { user } }) => Boolean(user),
update: ({ req: { user } }) => {
return checkRole(['admin'], user);

View File

@@ -1,7 +1,7 @@
const path = require('path');
const checkRole = require('../policies/checkRole');
const checkRole = require('../access/checkRole');
const policy = ({ req: { user } }) => {
const access = ({ req: { user } }) => {
const isAdmin = checkRole(['admin'], user);
if (isAdmin) {
@@ -27,11 +27,11 @@ module.exports = {
staticURL: '/files',
staticDir: path.resolve(__dirname, '../files'),
},
policies: {
access: {
create: () => true,
read: policy,
update: policy,
delete: policy,
read: access,
update: access,
delete: access,
},
useAsTitle: 'filename',
fields: [

View File

@@ -9,7 +9,7 @@ module.exports = {
singular: 'Flexible Content',
plural: 'Flexible Content',
},
policies: {
access: {
read: () => true,
},
fields: [

View File

@@ -6,7 +6,7 @@ module.exports = {
plural: 'Hooks',
},
useAsTitle: 'title',
policies: {
access: {
create: () => true,
read: () => true,
update: () => true,

View File

@@ -5,7 +5,7 @@ module.exports = {
plural: 'Localized Posts',
},
useAsTitle: 'title',
policies: {
access: {
read: () => true,
},
preview: (doc, token) => {

View File

@@ -4,7 +4,7 @@ const LocalizedRepeaters = {
singular: 'Localized Repeater',
plural: 'Localized Repeaters',
},
policies: {
access: {
read: () => true,
},
fields: [

View File

@@ -6,7 +6,7 @@ module.exports = {
singular: 'Media',
plural: 'Media',
},
policies: {
access: {
read: () => true,
},
upload: {

View File

@@ -4,7 +4,7 @@ const NestedRepeater = {
singular: 'Nested Repeater',
plural: 'Nested Repeaters',
},
policies: {
access: {
read: () => true,
},
fields: [

View File

@@ -1,6 +1,6 @@
const checkRole = require('../policies/checkRole');
const checkRole = require('../access/checkRole');
const policy = ({ req: { user } }) => checkRole(['admin'], user);
const access = ({ req: { user } }) => checkRole(['admin'], user);
module.exports = {
slug: 'public-users',
@@ -9,7 +9,7 @@ module.exports = {
plural: 'Public Users',
},
useAsTitle: 'email',
policies: {
access: {
admin: () => false,
create: () => true,
read: () => true,
@@ -38,10 +38,10 @@ module.exports = {
label: 'This field should only be readable and editable by Admins with "admin" role',
type: 'text',
defaultValue: 'test',
policies: {
create: policy,
read: policy,
update: policy,
access: {
create: access,
read: access,
update: access,
},
},
],

View File

@@ -1,6 +1,6 @@
module.exports = {
slug: 'relationship-a',
policies: {
access: {
read: () => true,
},
labels: {

View File

@@ -1,6 +1,6 @@
module.exports = {
slug: 'relationship-b',
policies: {
access: {
read: () => true,
},
labels: {

View File

@@ -1,13 +1,13 @@
const checkRole = require('../policies/checkRole');
const checkRole = require('../access/checkRole');
module.exports = {
slug: 'strict-policies',
slug: 'strict-access',
labels: {
singular: 'Strict Policy',
plural: 'Strict Policies',
singular: 'Strict Access',
plural: 'Strict Access',
},
useAsTitle: 'email',
policies: {
access: {
create: () => true,
read: ({ req: { user } }) => {
if (checkRole(['admin'], user)) {

View File

@@ -4,7 +4,7 @@ module.exports = {
singular: 'Validation',
plural: 'Validations',
},
policies: {
access: {
read: () => true,
},
fields: [

View File

@@ -1,11 +1,11 @@
const checkRole = require('../policies/checkRole');
const checkRole = require('../access/checkRole');
const Quote = require('../content-blocks/Quote');
const CallToAction = require('../content-blocks/CallToAction');
module.exports = {
slug: 'flexible-global',
label: 'Flexible Global',
policies: {
access: {
update: ({ req: { user } }) => checkRole(['admin'], user),
read: () => true,
},

View File

@@ -1,9 +1,9 @@
const checkRole = require('../policies/checkRole');
const checkRole = require('../access/checkRole');
module.exports = {
slug: 'global-with-policies',
label: 'Global with Policies',
policies: {
slug: 'global-with-access',
label: 'Global with Strict Access',
access: {
update: ({ req: { user } }) => checkRole(['admin'], user),
read: ({ req: { user } }) => checkRole(['admin'], user),
},

View File

@@ -1,9 +1,9 @@
const checkRole = require('../policies/checkRole');
const checkRole = require('../access/checkRole');
module.exports = {
slug: 'navigation-repeater',
label: 'Navigation Repeater',
policies: {
access: {
update: ({ req: { user } }) => checkRole(['admin', 'user'], user),
read: () => true,
},

View File

@@ -22,7 +22,7 @@ const Validations = require('./collections/Validations');
const FlexibleGlobal = require('./globals/FlexibleGlobal');
const NavigationRepeater = require('./globals/NavigationRepeater');
const GlobalWithPolicies = require('./globals/GlobalWithPolicies');
const GlobalWithStrictAccess = require('./globals/GlobalWithStrictAccess');
module.exports = {
admin: {
@@ -53,7 +53,7 @@ module.exports = {
],
globals: [
NavigationRepeater,
GlobalWithPolicies,
GlobalWithStrictAccess,
FlexibleGlobal,
],
cookiePrefix: 'payload',
@@ -89,11 +89,9 @@ module.exports = {
},
},
hooks: {
afterError: (err, response) => {
afterError: () => {
console.error('global error config handler');
},
},
webpack: (config) => {
return config;
},
webpack: (config) => config,
};

View File

@@ -1,8 +1,8 @@
const { Forbidden } = require('../errors');
const executePolicy = async (operation, policy) => {
if (policy) {
const result = await policy(operation);
const executeAccess = async (operation, access) => {
if (access) {
const result = await access(operation);
if (!result) {
throw new Forbidden();
@@ -18,4 +18,4 @@ const executePolicy = async (operation, policy) => {
throw new Forbidden();
};
module.exports = executePolicy;
module.exports = executeAccess;

View File

@@ -0,0 +1,40 @@
const executeStatic = require('./executeAccess');
const { Forbidden } = require('../errors');
const getExecuteStaticPolicy = ({ config, Model }) => async (req, res, next) => {
try {
if (req.path) {
const policyResult = await executeStatic({ req, isReadingStaticFile: true }, config.access.read);
if (typeof policyResult === 'object') {
const filename = decodeURI(req.path).replace(/^\/|\/$/g, '');
const queryToBuild = {
where: {
and: [
{
filename: {
equals: filename,
},
},
policyResult,
],
},
};
const query = await Model.buildQuery(queryToBuild, req.locale);
const doc = await Model.findOne(query);
if (!doc) {
throw new Forbidden();
}
}
}
return next();
} catch (error) {
return next(error);
}
};
module.exports = getExecuteStaticPolicy;

View File

@@ -1,42 +1,40 @@
const executePolicy = require('./executePolicy');
const executePolicy = require('./executeAccess');
const { Forbidden } = require('../errors');
const getExecuteStaticPolicy = ({ config, Model }) => {
return async (req, res, next) => {
try {
if (req.path) {
const policyResult = await executePolicy({ req, isReadingStaticFile: true }, config.policies.read);
const getExecuteStaticPolicy = ({ config, Model }) => async (req, res, next) => {
try {
if (req.path) {
const policyResult = await executePolicy({ req, isReadingStaticFile: true }, config.policies.read);
if (typeof policyResult === 'object') {
const filename = decodeURI(req.path).replace(/^\/|\/$/g, '');
if (typeof policyResult === 'object') {
const filename = decodeURI(req.path).replace(/^\/|\/$/g, '');
const queryToBuild = {
where: {
and: [
{
filename: {
equals: filename,
},
const queryToBuild = {
where: {
and: [
{
filename: {
equals: filename,
},
policyResult,
],
},
};
},
policyResult,
],
},
};
const query = await Model.buildQuery(queryToBuild, req.locale);
const doc = await Model.findOne(query);
const query = await Model.buildQuery(queryToBuild, req.locale);
const doc = await Model.findOne(query);
if (!doc) {
throw new Forbidden();
}
if (!doc) {
throw new Forbidden();
}
}
return next();
} catch (error) {
return next(error);
}
};
return next();
} catch (error) {
return next(error);
}
};
module.exports = getExecuteStaticPolicy;

View File

@@ -1,4 +1,4 @@
const { policies } = require('../../operations');
const { access } = require('../../operations');
const formatName = require('../../../graphql/utilities/formatName');
const formatConfigNames = (results, configs) => {
@@ -19,7 +19,7 @@ const policyResolver = config => async (_, __, context) => {
req: context,
};
let policyResults = await policies(options);
let policyResults = await access(options);
policyResults = formatConfigNames(policyResults, config.collections);
policyResults = formatConfigNames(policyResults, config.globals);

View File

@@ -6,7 +6,7 @@ const init = require('./init');
const forgotPassword = require('./forgotPassword');
const resetPassword = require('./resetPassword');
const update = require('./update');
const policies = require('./policies');
const access = require('./access');
module.exports = {
login,
@@ -17,5 +17,5 @@ module.exports = {
forgotPassword,
resetPassword,
update,
policies,
access,
};

View File

@@ -1,6 +1,6 @@
const allOperations = ['create', 'read', 'update', 'delete'];
const policies = async (args) => {
const access = async (args) => {
const {
config,
req,
@@ -13,9 +13,9 @@ const policies = async (args) => {
const isLoggedIn = !!(user);
const userCollectionConfig = (user && user.collection) ? config.collections.find((collection) => collection.slug === user.collection) : null;
const createPolicyPromise = async (obj, policy, operation, disableWhere = false) => {
const createPolicyPromise = async (obj, access, operation, disableWhere = false) => {
const updatedObj = obj;
const result = await policy({ req });
const result = await access({ req });
if (typeof result === 'object' && !disableWhere) {
updatedObj[operation] = {
@@ -36,8 +36,8 @@ const policies = async (args) => {
if (field.name) {
if (!updatedObj[field.name]) updatedObj[field.name] = {};
if (field.policies && typeof field.policies[operation] === 'function') {
promises.push(createPolicyPromise(updatedObj[field.name], field.policies[operation], operation, true));
if (field.access && typeof field.access[operation] === 'function') {
promises.push(createPolicyPromise(updatedObj[field.name], field.access[operation], operation, true));
} else {
updatedObj[field.name][operation] = {
permission: isLoggedIn,
@@ -62,8 +62,8 @@ const policies = async (args) => {
operations.forEach((operation) => {
executeFieldPolicies(results[entity.slug].fields, entity.fields, operation);
if (typeof entity.policies[operation] === 'function') {
promises.push(createPolicyPromise(results[entity.slug], entity.policies[operation], operation));
if (typeof entity.access[operation] === 'function') {
promises.push(createPolicyPromise(results[entity.slug], entity.access[operation], operation));
} else {
results[entity.slug][operation] = {
permission: isLoggedIn,
@@ -73,7 +73,7 @@ const policies = async (args) => {
};
if (userCollectionConfig) {
results.canAccessAdmin = userCollectionConfig.policies.admin ? userCollectionConfig.policies.admin(args) : isLoggedIn;
results.canAccessAdmin = userCollectionConfig.access.admin ? userCollectionConfig.access.admin(args) : isLoggedIn;
} else {
results.canAccessAdmin = false;
}
@@ -91,4 +91,4 @@ const policies = async (args) => {
return results;
};
module.exports = policies;
module.exports = access;

View File

@@ -6,7 +6,7 @@ const forgotPassword = require('./forgotPassword');
const resetPassword = require('./resetPassword');
const registerFirstUser = require('./registerFirstUser');
const update = require('./update');
const policies = require('./policies');
const access = require('./access');
const me = require('./me');
module.exports = {
@@ -18,6 +18,6 @@ module.exports = {
update,
resetPassword,
registerFirstUser,
policies,
access,
me,
};

View File

@@ -1,14 +1,14 @@
const passport = require('passport');
const executePolicy = require('../executePolicy');
const executeStatic = require('../executeAccess');
const performFieldOperations = require('../../fields/performFieldOperations');
const register = async (args) => {
// /////////////////////////////////////
// 1. Retrieve and execute policy
// 1. Retrieve and execute access
// /////////////////////////////////////
if (!args.overridePolicy) {
await executePolicy(args, args.collection.config.policies.create);
await executeStatic(args, args.collection.config.access.create);
}
let options = { ...args };
@@ -24,7 +24,7 @@ const register = async (args) => {
}
// /////////////////////////////////////
// 3. Execute field-level hooks, policies, and validation
// 3. Execute field-level hooks, access, and validation
// /////////////////////////////////////
options.data = await performFieldOperations(args.collection.config, { ...options, hook: 'beforeCreate', operationName: 'create' });
@@ -62,7 +62,7 @@ const register = async (args) => {
result = result.toJSON({ virtuals: true });
// /////////////////////////////////////
// 7. Execute field-level hooks and policies
// 7. Execute field-level hooks and access
// /////////////////////////////////////
result = await performFieldOperations(args.collection.config, {

View File

@@ -1,15 +1,15 @@
const deepmerge = require('deepmerge');
const overwriteMerge = require('../../utilities/overwriteMerge');
const { NotFound, Forbidden } = require('../../errors');
const executePolicy = require('../executePolicy');
const executeStatic = require('../executeAccess');
const performFieldOperations = require('../../fields/performFieldOperations');
const update = async (args) => {
// /////////////////////////////////////
// 1. Execute policy
// 1. Execute access
// /////////////////////////////////////
const policyResults = await executePolicy(args, args.config.policies.update);
const policyResults = await executeStatic(args, args.config.access.update);
const hasWherePolicy = typeof policyResults === 'object';
let options = { ...args };
@@ -64,7 +64,7 @@ const update = async (args) => {
options.data = deepmerge(userJSON, options.data, { arrayMerge: overwriteMerge });
// /////////////////////////////////////
// 4. Execute field-level hooks, policies, and validation
// 4. Execute field-level hooks, access, and validation
// /////////////////////////////////////
options.data = await performFieldOperations(args.config, { ...options, hook: 'beforeUpdate', operationName: 'update' });
@@ -92,7 +92,7 @@ const update = async (args) => {
user = user.toJSON({ virtuals: true });
// /////////////////////////////////////
// 7. Execute field-level hooks and policies
// 7. Execute field-level hooks and access
// /////////////////////////////////////
user = performFieldOperations(args.config, {

View File

@@ -1,9 +1,9 @@
const httpStatus = require('http-status');
const { policies } = require('../operations');
const { access } = require('../operations');
const policiesHandler = config => async (req, res, next) => {
try {
const policyResults = await policies({
const policyResults = await access({
req,
config,
});

View File

@@ -7,7 +7,7 @@ const forgotPassword = require('./forgotPassword');
const resetPassword = require('./resetPassword');
const registerFirstUser = require('./registerFirstUser');
const update = require('./update');
const policies = require('./policies');
const access = require('./access');
const logout = require('./logout');
module.exports = {
@@ -21,5 +21,5 @@ module.exports = {
registerFirstUser,
resetPassword,
update,
policies,
access,
};

View File

@@ -86,10 +86,10 @@ const UserProvider = ({ children }) => {
setLastLocationChange(Date.now());
}, [pathname]);
// When user changes, get new policies
// When user changes, get new access
useEffect(() => {
async function getPermissions() {
const request = await requests.get(`${serverURL}${api}/policies`);
const request = await requests.get(`${serverURL}${api}/access`);
if (request.status === 200) {
const json = await request.json();

View File

@@ -1,6 +1,6 @@
const mkdirp = require('mkdirp');
const executePolicy = require('../../auth/executePolicy');
const executeStatic = require('../../auth/executeAccess');
const { MissingFile } = require('../../errors');
const resizeAndSave = require('../../uploads/imageResizer');
@@ -12,10 +12,10 @@ const performFieldOperations = require('../../fields/performFieldOperations');
const create = async (args) => {
// /////////////////////////////////////
// 1. Retrieve and execute policy
// 1. Retrieve and execute access
// /////////////////////////////////////
await executePolicy(args, args.config.policies.create);
await executeStatic(args, args.config.access.create);
let options = { ...args };
@@ -30,7 +30,7 @@ const create = async (args) => {
}
// /////////////////////////////////////
// 3. Execute field-level policies, hooks, and validation
// 3. Execute field-level access, hooks, and validation
// /////////////////////////////////////
options.data = await performFieldOperations(args.config, { ...options, hook: 'beforeCreate', operationName: 'create' });
@@ -99,7 +99,7 @@ const create = async (args) => {
result = result.toJSON({ virtuals: true });
// /////////////////////////////////////
// 6. Execute field-level hooks and policies
// 6. Execute field-level hooks and access
// /////////////////////////////////////
result = await performFieldOperations(args.config, {

View File

@@ -1,13 +1,13 @@
const fs = require('fs');
const { NotFound, Forbidden, ErrorDeletingFile } = require('../../errors');
const executePolicy = require('../../auth/executePolicy');
const executeStatic = require('../../auth/executeAccess');
const deleteQuery = async (args) => {
// /////////////////////////////////////
// 1. Retrieve and execute policy
// 1. Retrieve and execute access
// /////////////////////////////////////
const policyResults = await executePolicy(args, args.config.policies.delete);
const policyResults = await executeStatic(args, args.config.access.delete);
const hasWherePolicy = typeof policyResults === 'object';
let options = {

View File

@@ -1,12 +1,12 @@
const executePolicy = require('../../auth/executePolicy');
const executeStatic = require('../../auth/executeAccess');
const performFieldOperations = require('../../fields/performFieldOperations');
const find = async (args) => {
// /////////////////////////////////////
// 1. Retrieve and execute policy
// 1. Retrieve and execute access
// /////////////////////////////////////
const policyResults = await executePolicy(args, args.config.policies.read);
const policyResults = await executeStatic(args, args.config.access.read);
const hasWherePolicy = typeof policyResults === 'object';
const queryToBuild = {};
@@ -96,7 +96,7 @@ const find = async (args) => {
let result = await Model.paginate(query, optionsToExecute);
// /////////////////////////////////////
// 4. Execute field-level policies
// 4. Execute field-level access
// /////////////////////////////////////
result = {

View File

@@ -1,13 +1,13 @@
const { Forbidden, NotFound } = require('../../errors');
const executePolicy = require('../../auth/executePolicy');
const executeStatic = require('../../auth/executeAccess');
const performFieldOperations = require('../../fields/performFieldOperations');
const findByID = async (args) => {
// /////////////////////////////////////
// 1. Retrieve and execute policy
// 1. Retrieve and execute access
// /////////////////////////////////////
const policyResults = await executePolicy(args, args.config.policies.read);
const policyResults = await executeStatic(args, args.config.access.read);
const hasWherePolicy = typeof policyResults === 'object';
const queryToBuild = {
@@ -85,7 +85,7 @@ const findByID = async (args) => {
result = result.toJSON({ virtuals: true });
// /////////////////////////////////////
// 4. Execute field-level hooks and policies
// 4. Execute field-level hooks and access
// /////////////////////////////////////
result = await performFieldOperations(args.config, {

View File

@@ -1,6 +1,6 @@
const deepmerge = require('deepmerge');
const overwriteMerge = require('../../utilities/overwriteMerge');
const executePolicy = require('../../auth/executePolicy');
const executeStatic = require('../../auth/executeAccess');
const { NotFound, Forbidden } = require('../../errors');
const performFieldOperations = require('../../fields/performFieldOperations');
const imageMIMETypes = require('../../uploads/imageMIMETypes');
@@ -11,10 +11,10 @@ const resizeAndSave = require('../../uploads/imageResizer');
const update = async (args) => {
// /////////////////////////////////////
// 1. Execute policy
// 1. Execute access
// /////////////////////////////////////
const policyResults = await executePolicy(args, args.config.policies.update);
const policyResults = await executeStatic(args, args.config.access.update);
const hasWherePolicy = typeof policyResults === 'object';
let options = { ...args };
@@ -78,7 +78,7 @@ const update = async (args) => {
options.data = deepmerge(options.originalDoc, options.data, { arrayMerge: overwriteMerge });
// /////////////////////////////////////
// 4. Execute field-level hooks, policies, and validation
// 4. Execute field-level hooks, access, and validation
// /////////////////////////////////////
options.data = await performFieldOperations(args.config, { ...options, hook: 'beforeUpdate', operationName: 'update' });
@@ -135,7 +135,7 @@ const update = async (args) => {
doc = doc.toJSON({ virtuals: true });
// /////////////////////////////////////
// 7. Execute field-level hooks and policies
// 7. Execute field-level hooks and access
// /////////////////////////////////////
doc = await performFieldOperations(args.config, {

View File

@@ -28,7 +28,7 @@ const sanitizeCollection = (collections, collection) => {
// /////////////////////////////////
if (!sanitizedCollectionConfig.hooks) sanitizedCollectionConfig.hooks = {};
if (!sanitizedCollectionConfig.policies) sanitizedCollectionConfig.policies = {};
if (!sanitizedCollectionConfig.access) sanitizedCollectionConfig.access = {};
if (sanitizedCollectionConfig.upload) {
if (!sanitizedCollectionConfig.upload.staticDir) sanitizedCollectionConfig.upload.staticDir = sanitizedCollectionConfig.slug;

View File

@@ -1,6 +1,6 @@
const express = require('express');
const passport = require('passport');
const getExecuteStaticPolicy = require('../auth/getExecuteStaticPolicy');
const getExecuteStaticAccess = require('../auth/getExecuteStaticAccess');
const authenticate = require('./middleware/authenticate');
function initStatic() {
@@ -13,7 +13,7 @@ function initStatic() {
router.use(passport.initialize());
router.use(authenticate(this.config));
router.use(getExecuteStaticPolicy(collection));
router.use(getExecuteStaticAccess(collection));
router.use(express.static(config.upload.staticDir));
this.express.use(`${config.upload.staticURL}`, router);

View File

@@ -9,7 +9,7 @@ module.exports = async (config, operation) => {
} = operation;
// Maintain a top-level list of promises
// so that all async field policies / validations / hooks
// so that all async field access / validations / hooks
// can run in parallel
const validationPromises = [];
const policyPromises = [];
@@ -32,8 +32,8 @@ module.exports = async (config, operation) => {
const createPolicyPromise = async (data, originalDoc, field) => {
const resultingData = data;
if (field.policies && field.policies[operationName]) {
const result = await field.policies[operationName](operation);
if (field.access && field.access[operationName]) {
const result = await field.access[operationName](operation);
if (!result && operationName === 'update' && originalDoc[field.name] !== undefined) {
resultingData[field.name] = originalDoc[field.name];

View File

@@ -1,5 +1,5 @@
const { MissingFieldType } = require('../errors');
const validations = require('../fields/validations');
const validations = require('./validations');
const sanitizeFields = (fields) => {
if (!fields) return [];
@@ -16,7 +16,7 @@ const sanitizeFields = (fields) => {
}
if (!field.hooks) field.hooks = {};
if (!field.policies) field.policies = {};
if (!field.access) field.access = {};
if (field.fields) field.fields = sanitizeFields(field.fields);

View File

@@ -1,12 +1,12 @@
const executePolicy = require('../../auth/executePolicy');
const executeStatic = require('../../auth/executeAccess');
const performFieldOperations = require('../../fields/performFieldOperations');
const findOne = async (args) => {
// /////////////////////////////////////
// 1. Retrieve and execute policy
// 1. Retrieve and execute access
// /////////////////////////////////////
await executePolicy(args, args.config.policies.read);
await executeStatic(args, args.config.access.read);
let options = { ...args };
@@ -67,7 +67,7 @@ const findOne = async (args) => {
// /////////////////////////////////////
// 4. Execute field-level hooks and policies
// 4. Execute field-level hooks and access
// /////////////////////////////////////
result = performFieldOperations(args.config, {

View File

@@ -1,14 +1,14 @@
const deepmerge = require('deepmerge');
const overwriteMerge = require('../../utilities/overwriteMerge');
const executePolicy = require('../../auth/executePolicy');
const executeStatic = require('../../auth/executeAccess');
const performFieldOperations = require('../../fields/performFieldOperations');
const update = async (args) => {
// /////////////////////////////////////
// 1. Retrieve and execute policy
// 1. Retrieve and execute access
// /////////////////////////////////////
await executePolicy(args, args.config.policies.update);
await executeStatic(args, args.config.access.update);
let options = { ...args };
@@ -54,7 +54,7 @@ const update = async (args) => {
options.data = deepmerge(globalJSON, options.data, { arrayMerge: overwriteMerge });
// /////////////////////////////////////
// 5. Execute field-level hooks, policies, and validation
// 5. Execute field-level hooks, access, and validation
// /////////////////////////////////////
options.data = await performFieldOperations(args.config, { ...options, hook: 'beforeUpdate', operationName: 'update' });
@@ -70,7 +70,7 @@ const update = async (args) => {
global = global.toJSON({ virtuals: true });
// /////////////////////////////////////
// 7. Execute field-level hooks and policies
// 7. Execute field-level hooks and access
// /////////////////////////////////////
global = await performFieldOperations(args.config, {

View File

@@ -20,7 +20,7 @@ const sanitizeGlobals = (globals) => {
// /////////////////////////////////
if (!sanitizedGlobal.hooks) sanitizedGlobal.hooks = {};
if (!sanitizedGlobal.policies) sanitizedGlobal.policies = {};
if (!sanitizedGlobal.access) sanitizedGlobal.access = {};
// /////////////////////////////////
// Sanitize fields

View File

@@ -11,7 +11,7 @@ const initCollections = require('../collections/graphql/init');
const initGlobals = require('../globals/graphql/init');
const buildWhereInputType = require('./schema/buildWhereInputType');
const errorHandler = require('./errorHandler');
const { policies } = require('../auth/graphql/resolvers');
const { access } = require('../auth/graphql/resolvers');
class GraphQL {
constructor(init) {
@@ -50,9 +50,9 @@ class GraphQL {
this.initCollections();
this.initGlobals();
this.Query.fields.Policies = {
this.Query.fields.Access = {
type: this.buildPoliciesType(),
resolve: policies(this.config),
resolve: access(this.config),
};
this.Query = {

View File

@@ -2,61 +2,59 @@ const { GraphQLJSONObject } = require('graphql-type-json');
const { GraphQLBoolean, GraphQLNonNull, GraphQLObjectType } = require('graphql');
const formatName = require('../utilities/formatName');
const buildFields = (label, fieldsToBuild) => {
return fieldsToBuild.reduce((builtFields, field) => {
if (field.name) {
const fieldName = formatName(field.name);
const buildFields = (label, fieldsToBuild) => fieldsToBuild.reduce((builtFields, field) => {
if (field.name) {
const fieldName = formatName(field.name);
const objectTypeFields = ['create', 'read', 'update', 'delete'].reduce((operations, operation) => {
const capitalizedOperation = operation.charAt(0).toUpperCase() + operation.slice(1);
return {
...operations,
[operation]: {
type: new GraphQLObjectType({
name: `${label}_${fieldName}_${capitalizedOperation}`,
fields: {
permission: {
type: new GraphQLNonNull(GraphQLBoolean),
},
},
}),
},
};
}, {});
if (field.fields) {
objectTypeFields.fields = {
type: new GraphQLObjectType({
name: `${label}_${fieldName}_Fields`,
fields: buildFields(`${label}_${fieldName}`, field.fields),
}),
};
}
const objectTypeFields = ['create', 'read', 'update', 'delete'].reduce((operations, operation) => {
const capitalizedOperation = operation.charAt(0).toUpperCase() + operation.slice(1);
return {
...builtFields,
[field.name]: {
...operations,
[operation]: {
type: new GraphQLObjectType({
name: `${label}_${fieldName}`,
fields: objectTypeFields,
name: `${label}_${fieldName}_${capitalizedOperation}`,
fields: {
permission: {
type: new GraphQLNonNull(GraphQLBoolean),
},
},
}),
},
};
}
}, {});
if (!field.name && field.fields) {
const subFields = buildFields(label, field.fields);
return {
...builtFields,
...subFields,
if (field.fields) {
objectTypeFields.fields = {
type: new GraphQLObjectType({
name: `${label}_${fieldName}_Fields`,
fields: buildFields(`${label}_${fieldName}`, field.fields),
}),
};
}
return builtFields;
}, {});
};
return {
...builtFields,
[field.name]: {
type: new GraphQLObjectType({
name: `${label}_${fieldName}`,
fields: objectTypeFields,
}),
},
};
}
if (!field.name && field.fields) {
const subFields = buildFields(label, field.fields);
return {
...builtFields,
...subFields,
};
}
return builtFields;
}, {});
const buildEntity = (label, entityFields, operations) => {
const formattedLabel = formatName(label);
@@ -75,7 +73,7 @@ const buildEntity = (label, entityFields, operations) => {
fields[operation] = {
type: new GraphQLObjectType({
name: `${formattedLabel}${capitalizedOperation}Policy`,
name: `${formattedLabel}${capitalizedOperation}Access`,
fields: {
permission: { type: new GraphQLNonNull(GraphQLBoolean) },
where: { type: GraphQLJSONObject },
@@ -97,7 +95,7 @@ function buildPoliciesType() {
Object.values(this.config.collections).forEach((collection) => {
fields[formatName(collection.slug)] = {
type: new GraphQLObjectType({
name: formatName(`${collection.labels.singular}Policy`),
name: formatName(`${collection.labels.singular}Access`),
fields: buildEntity(collection.labels.singular, collection.fields, ['create', 'read', 'update', 'delete']),
}),
};
@@ -106,14 +104,14 @@ function buildPoliciesType() {
Object.values(this.config.globals).forEach((global) => {
fields[formatName(global.slug)] = {
type: new GraphQLObjectType({
name: formatName(`${global.label}Policy`),
name: formatName(`${global.label}Access`),
fields: buildEntity(global.label, global.fields, ['read', 'update']),
}),
};
});
return new GraphQLObjectType({
name: 'Policies',
name: 'Access',
fields,
});
}

View File

@@ -17,7 +17,7 @@ const sanitizeConfig = require('./utilities/sanitizeConfig');
const buildEmail = require('./email/build');
const identifyAPI = require('./express/middleware/identifyAPI');
const errorHandler = require('./express/middleware/errorHandler');
const { policies } = require('./auth/requestHandlers');
const { access } = require('./auth/requestHandlers');
class Payload {
constructor(options) {
@@ -53,7 +53,7 @@ class Payload {
this.initGlobals();
this.initAdmin();
this.router.get('/policies', policies(this.config));
this.router.get('/access', access(this.config));
this.router.use(
this.config.routes.graphQL,

View File

@@ -3,7 +3,7 @@ const { Schema } = require('mongoose');
const { MissingSelectOptions } = require('../errors');
const formatBaseSchema = (field) => {
const createPolicy = field.policies && field.policies.create;
const createPolicy = field.access && field.access.create;
return {
hide: field.hidden === 'api' || field.hidden === true,
@@ -49,71 +49,51 @@ const buildSchema = (configFields, options = {}) => {
};
const fieldToSchemaMap = {
number: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: Number },
};
},
text: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
};
},
email: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
};
},
textarea: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
};
},
richText: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: Schema.Types.Mixed },
};
},
code: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
};
},
radio: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
};
},
checkbox: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: Boolean },
};
},
date: (field, fields) => {
return {
...fields,
[field.name]: { ...formatBaseSchema(field), type: Date },
};
},
upload: (field, fields) => {
return {
...fields,
[field.name]: {
...formatBaseSchema(field),
type: Schema.Types.ObjectId,
autopopulate: true,
ref: field.relationTo,
},
};
},
number: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: Number },
}),
text: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
}),
email: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
}),
textarea: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
}),
richText: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: Schema.Types.Mixed },
}),
code: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
}),
radio: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: String },
}),
checkbox: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: Boolean },
}),
date: (field, fields) => ({
...fields,
[field.name]: { ...formatBaseSchema(field), type: Date },
}),
upload: (field, fields) => ({
...fields,
[field.name]: {
...formatBaseSchema(field),
type: Schema.Types.ObjectId,
autopopulate: true,
ref: field.relationTo,
},
}),
relationship: (field, fields) => {
let schema = {};
@@ -178,7 +158,7 @@ const fieldToSchemaMap = {
...fields,
[field.name]: {
...formatBaseSchema(field),
required: field.fields.some(subField => subField.required === true),
required: field.fields.some((subField) => subField.required === true),
type: schema,
},
};