diff --git a/demo/blocks/Quote.js b/demo/blocks/Quote.js index 9d4d095a91..0b1386a8f4 100644 --- a/demo/blocks/Quote.js +++ b/demo/blocks/Quote.js @@ -9,8 +9,8 @@ module.exports = { { name: 'author', label: 'Author', - type: 'text', - maxLength: 100, + type: 'relationship', + relationTo: 'public-users', required: true, }, { diff --git a/demo/globals/GlobalWithStrictAccess.js b/demo/globals/GlobalWithStrictAccess.js index 77d193d4b0..ab15f5aa7b 100644 --- a/demo/globals/GlobalWithStrictAccess.js +++ b/demo/globals/GlobalWithStrictAccess.js @@ -15,5 +15,20 @@ module.exports = { maxLength: 100, required: true, }, + { + name: 'relationship', + label: 'Test Relationship', + type: 'relationship', + relationTo: 'localized-posts', + hasMany: true, + required: true, + }, + { + name: 'singleRelationship', + label: 'Test Single Relationship', + type: 'relationship', + relationTo: 'localized-posts', + required: true, + }, ], }; diff --git a/demo/payload.config.js b/demo/payload.config.js index fecb7cc73d..b96a2bc801 100644 --- a/demo/payload.config.js +++ b/demo/payload.config.js @@ -70,6 +70,7 @@ module.exports = { graphQL: '/graphql', graphQLPlayground: '/graphql-playground', }, + defaultDepth: 2, compression: {}, paths: { scss: path.resolve(__dirname, 'client/scss/overrides.scss'), diff --git a/src/auth/operations/register.js b/src/auth/operations/register.js index 7588c624d5..10efd5f61e 100644 --- a/src/auth/operations/register.js +++ b/src/auth/operations/register.js @@ -4,6 +4,7 @@ const performFieldOperations = require('../../fields/performFieldOperations'); const register = async (args) => { const { + depth, overrideAccess, config, collection: { @@ -81,6 +82,7 @@ const register = async (args) => { hook: 'afterRead', operationName: 'read', req, + depth, }); // ///////////////////////////////////// diff --git a/src/auth/operations/update.js b/src/auth/operations/update.js index a834514308..8ea33fe02c 100644 --- a/src/auth/operations/update.js +++ b/src/auth/operations/update.js @@ -6,6 +6,7 @@ const performFieldOperations = require('../../fields/performFieldOperations'); const update = async (args) => { const { + depth, config, collection: { Model, @@ -115,6 +116,7 @@ const update = async (args) => { hook: 'afterRead', operationName: 'read', req, + depth, }); // ///////////////////////////////////// diff --git a/src/collections/buildSchema.js b/src/collections/buildSchema.js index 39f196a9c4..6a09f62cf6 100644 --- a/src/collections/buildSchema.js +++ b/src/collections/buildSchema.js @@ -1,5 +1,4 @@ const paginate = require('mongoose-paginate-v2'); -const autopopulate = require('mongoose-autopopulate'); const buildQueryPlugin = require('../mongoose/buildQuery'); const localizationPlugin = require('../localization/plugin'); const buildSchema = require('../mongoose/buildSchema'); @@ -8,8 +7,7 @@ const buildCollectionSchema = (collection, config, schemaOptions = {}) => { const schema = buildSchema(collection.fields, { timestamps: collection.timestamps, ...schemaOptions }); schema.plugin(paginate) - .plugin(buildQueryPlugin) - .plugin(autopopulate); + .plugin(buildQueryPlugin); if (config.localization) { schema.plugin(localizationPlugin, config.localization); diff --git a/src/collections/operations/delete.js b/src/collections/operations/delete.js index 386f0692a0..83ca1db052 100644 --- a/src/collections/operations/delete.js +++ b/src/collections/operations/delete.js @@ -2,8 +2,11 @@ const fs = require('fs'); const { NotFound, Forbidden, ErrorDeletingFile } = require('../../errors'); const executeAccess = require('../../auth/executeAccess'); +const performFieldOperations = require('../../fields/performFieldOperations'); + const deleteQuery = async (args) => { const { + depth, collection: { Model, config: collectionConfig, @@ -14,6 +17,7 @@ const deleteQuery = async (args) => { locale, fallbackLocale, }, + config, } = args; // ///////////////////////////////////// @@ -90,7 +94,19 @@ const deleteQuery = async (args) => { } // ///////////////////////////////////// - // 4. Execute after collection hook + // 6. Execute field-level hooks and access + // ///////////////////////////////////// + + result = await performFieldOperations(config, collectionConfig, { + data: result, + hook: 'afterRead', + operationName: 'read', + req, + depth, + }); + + // ///////////////////////////////////// + // 7. Execute after collection hook // ///////////////////////////////////// await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => { @@ -100,7 +116,7 @@ const deleteQuery = async (args) => { }, Promise.resolve()); // ///////////////////////////////////// - // 5. Return results + // 8. Return results // ///////////////////////////////////// return result; diff --git a/src/collections/operations/find.js b/src/collections/operations/find.js index f6c17a4b0c..519fcfcc0d 100644 --- a/src/collections/operations/find.js +++ b/src/collections/operations/find.js @@ -6,8 +6,8 @@ const find = async (args) => { where, page, limit, - depth, config, + depth, collection: { Model, config: collectionConfig, @@ -16,7 +16,6 @@ const find = async (args) => { req: { locale, fallbackLocale, - payloadAPI, }, } = args; @@ -74,26 +73,8 @@ const find = async (args) => { limit: limit || 10, sort, collation: sort ? { locale: 'en' } : {}, // case-insensitive sort in MongoDB - options: { - autopopulate: false, - }, }; - // Only allow depth override within REST. - // If allowed in GraphQL, it would break resolvers - // as a full object will be returned instead of an ID string - if (payloadAPI === 'REST') { - if (depth && depth !== '0') { - optionsToExecute.options.autopopulate = { - maxDepth: parseInt(depth, 10), - }; - } else { - optionsToExecute.options.autopopulate = { - maxDepth: 2, - }; - } - } - let result = await Model.paginate(query, optionsToExecute); // ///////////////////////////////////// @@ -110,6 +91,7 @@ const find = async (args) => { const data = doc.toJSON({ virtuals: true }); return performFieldOperations(config, collectionConfig, { + depth, data, req, hook: 'afterRead', diff --git a/src/collections/operations/findByID.js b/src/collections/operations/findByID.js index beca715f04..d8e5aa70e0 100644 --- a/src/collections/operations/findByID.js +++ b/src/collections/operations/findByID.js @@ -15,7 +15,6 @@ const findByID = async (args) => { req: { locale, fallbackLocale, - payloadAPI, }, } = args; @@ -54,26 +53,7 @@ const findByID = async (args) => { // 3. Perform database operation // ///////////////////////////////////// - const queryOptionsToExecute = { - autopopulate: false, - }; - - // Only allow depth override within REST. - // If allowed in GraphQL, it would break resolvers - // as a full object will be returned instead of an ID string - if (payloadAPI === 'REST') { - if (depth && depth !== '0') { - queryOptionsToExecute.autopopulate = { - maxDepth: parseInt(depth, 10), - }; - } else { - queryOptionsToExecute.autopopulate = { - maxDepth: 2, - }; - } - } - - let result = await Model.findOne(query, {}, queryOptionsToExecute); + let result = await Model.findOne(query, {}); if (!result && !hasWhereAccess) throw new NotFound(); if (!result && hasWhereAccess) throw new Forbidden(); @@ -89,6 +69,7 @@ const findByID = async (args) => { // ///////////////////////////////////// result = await performFieldOperations(config, collectionConfig, { + depth, req, data: result, hook: 'afterRead', diff --git a/src/collections/operations/update.js b/src/collections/operations/update.js index 9723e472e8..aeab18284f 100644 --- a/src/collections/operations/update.js +++ b/src/collections/operations/update.js @@ -12,6 +12,7 @@ const resizeAndSave = require('../../uploads/imageResizer'); const update = async (args) => { const { config, + depth, collection: { Model, config: collectionConfig, @@ -158,6 +159,7 @@ const update = async (args) => { hook: 'afterRead', operationName: 'read', req, + depth, }); // ///////////////////////////////////// diff --git a/src/collections/requestHandlers/create.js b/src/collections/requestHandlers/create.js index 7b967beec3..06b2ce4493 100644 --- a/src/collections/requestHandlers/create.js +++ b/src/collections/requestHandlers/create.js @@ -9,6 +9,7 @@ const createHandler = (config) => async (req, res, next) => { collection: req.collection, config, data: req.body, + depth: req.query.depth, }); return res.status(httpStatus.CREATED).json({ diff --git a/src/collections/requestHandlers/delete.js b/src/collections/requestHandlers/delete.js index 9a0dd2f285..30a7230ded 100644 --- a/src/collections/requestHandlers/delete.js +++ b/src/collections/requestHandlers/delete.js @@ -9,6 +9,7 @@ const deleteHandler = (config) => async (req, res, next) => { collection: req.collection, config, id: req.params.id, + depth: req.query.depth, }); if (!doc) { diff --git a/src/collections/requestHandlers/update.js b/src/collections/requestHandlers/update.js index 903c7c9ffe..bf81a199ea 100644 --- a/src/collections/requestHandlers/update.js +++ b/src/collections/requestHandlers/update.js @@ -10,6 +10,7 @@ const updateHandler = (config) => async (req, res, next) => { config, id: req.params.id, data: req.body, + depth: req.query.depth, }); return res.status(httpStatus.OK).json({ diff --git a/src/globals/buildModel.js b/src/globals/buildModel.js index d69b6f96e5..af2f714b35 100644 --- a/src/globals/buildModel.js +++ b/src/globals/buildModel.js @@ -1,5 +1,4 @@ const mongoose = require('mongoose'); -const autopopulate = require('mongoose-autopopulate'); const mongooseHidden = require('mongoose-hidden')(); const buildSchema = require('../mongoose/buildSchema'); const localizationPlugin = require('../localization/plugin'); @@ -12,7 +11,6 @@ const buildModel = (config) => { globalsSchema.plugin(localizationPlugin, config.localization); } - globalsSchema.plugin(autopopulate); globalsSchema.plugin(mongooseHidden); const Globals = mongoose.model('globals', globalsSchema); @@ -24,7 +22,6 @@ const buildModel = (config) => { globalSchema.plugin(localizationPlugin, config.localization); } - globalSchema.plugin(autopopulate); globalSchema.plugin(mongooseHidden); Globals.discriminator(globalConfig.slug, globalSchema); diff --git a/src/globals/operations/findOne.js b/src/globals/operations/findOne.js index aa7ede5897..9c0272714b 100644 --- a/src/globals/operations/findOne.js +++ b/src/globals/operations/findOne.js @@ -8,7 +8,6 @@ const findOne = async (args) => { Model, req, req: { - payloadAPI, locale, fallbackLocale, }, @@ -32,23 +31,6 @@ const findOne = async (args) => { // 3. Perform database operation // ///////////////////////////////////// - const queryOptionsToExecute = { - options: {}, - }; - - // Only allow depth override within REST. - // If allowed in GraphQL, it would break resolvers - // as a full object will be returned instead of an ID string - if (payloadAPI === 'REST') { - if (depth && depth !== '0') { - queryOptionsToExecute.options.autopopulate = { - maxDepth: parseInt(depth, 10), - }; - } else { - queryOptionsToExecute.options.autopopulate = false; - } - } - let doc = await Model.findOne({ globalType: slug }); if (!doc) { @@ -71,6 +53,7 @@ const findOne = async (args) => { hook: 'afterRead', operationName: 'read', req, + depth, }); // ///////////////////////////////////// diff --git a/src/globals/operations/update.js b/src/globals/operations/update.js index e8ecfc86cb..1c2e2486cc 100644 --- a/src/globals/operations/update.js +++ b/src/globals/operations/update.js @@ -14,6 +14,7 @@ const update = async (args) => { locale, fallbackLocale, }, + depth, } = args; // ///////////////////////////////////// @@ -91,6 +92,7 @@ const update = async (args) => { hook: 'afterRead', operationName: 'read', req, + depth, }); // ///////////////////////////////////// diff --git a/src/utilities/sanitizeConfig.js b/src/utilities/sanitizeConfig.js index daf1680939..77e22cae56 100644 --- a/src/utilities/sanitizeConfig.js +++ b/src/utilities/sanitizeConfig.js @@ -5,6 +5,8 @@ const sanitizeGlobals = require('../globals/sanitize'); const sanitizeConfig = (config) => { const sanitizedConfig = { ...config }; + if (sanitizedConfig.defaultDepth === undefined) sanitizedConfig.defaultDepth = 2; + sanitizedConfig.collections = sanitizedConfig.collections.map((collection) => sanitizeCollection(sanitizedConfig.collections, collection)); if (sanitizedConfig.globals) {