diff --git a/packages/strapi-generate-api/templates/mongoose/service.template b/packages/strapi-generate-api/templates/mongoose/service.template index 3219190e32..d76d1ffcae 100755 --- a/packages/strapi-generate-api/templates/mongoose/service.template +++ b/packages/strapi-generate-api/templates/mongoose/service.template @@ -18,15 +18,21 @@ module.exports = { */ fetchAll: (params) => { - const convertedParams = strapi.utils.models.convertParams('<%= globalID.toLowerCase() %>', params); + // Convert `params` object to filters compatible with Mongo. + const filters = strapi.utils.models.convertParams('<%= globalID.toLowerCase() %>', params); + // Select field to populate. + const populate = <%= globalID %>.associations + .filter(ast => ast.autoPopulate !== false) + .map(ast => ast.alias) + .join(' '); return <%= globalID %> .find() - .where(convertedParams.where) - .sort(convertedParams.sort) - .skip(convertedParams.start) - .limit(convertedParams.limit) - .populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' ')); + .where(filters.where) + .sort(filters.sort) + .skip(filters.start) + .limit(filters.limit) + .populate(populate); }, /** @@ -36,9 +42,15 @@ module.exports = { */ fetch: (params) => { + // Select field to populate. + const populate = <%= globalID %>.associations + .filter(ast => ast.autoPopulate !== false) + .map(ast => ast.alias) + .join(' '); + return <%= globalID %> .findOne(_.pick(params, _.keys(<%= globalID %>.schema.paths))) - .populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' ')); + .populate(populate); }, /** @@ -48,12 +60,15 @@ module.exports = { */ add: async (values) => { - const query = await <%= globalID %>.create(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias')))); - const data = query.toJSON ? query.toJSON() : query; + // Extract values related to relational data. + const relations = _.pick(values, <%= globalID %>.associations.map(ast => ast.alias)); + const data = _.omit(values, <%= globalID %>.associations.map(ast => ast.alias)); - await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(data, { values })); + // Create entry with no-relational data. + const entry = await <%= globalID %>.create(data); - return query; + // Create relational data and return the entry. + return <%= globalID %>.updateRelations({ id: entry.id, values: relations }); }, /** @@ -63,11 +78,15 @@ module.exports = { */ edit: async (params, values) => { - // Note: The current method will return the full response of Mongo. - // To get the updated object, you have to execute the `findOne()` method - // or use the `findOneOrUpdate()` method with `{ new:true }` option. - await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(_.clone(params), { values })); - return <%= globalID %>.update(params, values, { multi: true }); + // Extract values related to relational data. + const relations = _.pick(values, <%= globalID %>.associations.map(a => a.alias)); + const data = _.omit(values, <%= globalID %>.associations.map(a => a.alias)); + + // Update entry with no-relational data. + const entry = await <%= globalID %>.update(params, data, { multi: true }); + + // Update relational data and return the entry. + return <%= globalID %>.updateRelations(Object.assign(params, { values: relations })); }, /** @@ -77,20 +96,31 @@ module.exports = { */ remove: async params => { + // Select field to populate. + const populate = <%= globalID %>.associations + .filter(ast => ast.autoPopulate !== false) + .map(ast => ast.alias) + .join(' '); + // Note: To get the full response of Mongo, use the `remove()` method // or add spent the parameter `{ passRawResult: true }` as second argument. - const data = await <%= globalID %>.findOneAndRemove(params, {}) - .populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' ')); + const data = await <%= globalID %> + .findOneAndRemove(params, {}) + .populate(populate); - _.forEach(<%= globalID %>.associations, async association => { - const search = (_.endsWith(association.nature, 'One')) ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } }; - const update = (_.endsWith(association.nature, 'One')) ? { [association.via]: null } : { $pull: { [association.via]: data._id } }; + await Promise.all( + <%= globalID %>.associations.map(async association => { + const search = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } }; + const update = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: null } : { $pull: { [association.via]: data._id } }; - await strapi.models[association.model || association.collection].update( - search, - update, - { multi: true }); - }); + // Retrieve model. + const model = association.plugin ? + strapi.plugins[association.plugin].models[association.model || association.collection] : + strapi.models[association.model || association.collection]; + + return model.update(search, update, { multi: true }); + }) + ); return data; } diff --git a/packages/strapi-mongoose/lib/relations.js b/packages/strapi-mongoose/lib/relations.js index 065ebf8eda..4b07ae1600 100644 --- a/packages/strapi-mongoose/lib/relations.js +++ b/packages/strapi-mongoose/lib/relations.js @@ -8,7 +8,7 @@ const _ = require('lodash'); module.exports = { - getModel: async function (model, plugin) { + getModel: function (model, plugin) { return _.get(strapi.plugins, [plugin, 'models', model]) || get(strapi, ['models', model]) || undefined; }, @@ -125,6 +125,8 @@ module.exports = { // Push the work into the flow process. toAdd.forEach(value => { + value = _.isString(value) ? { [this.primaryKey]: value } : value; + if (association.nature === 'manyToMany' && !_.isArray(params.values[this.primaryKey] || params[this.primaryKey])) { value[details.via] = (value[details.via] || []) .concat([(params.values[this.primaryKey] || params[this.primaryKey])]) @@ -136,7 +138,7 @@ module.exports = { } virtualFields.push( - module.exports.addRelation(model, { + module.exports.addRelation.call(model, { id: value[this.primaryKey] || value.id || value._id, values: _.pick(value, [this.primaryKey, details.via]), foreignKey: current @@ -145,6 +147,8 @@ module.exports = { }); toRemove.forEach(value => { + value = _.isString(value) ? { [this.primaryKey]: value } : value; + if (association.nature === 'manyToMany' && !_.isArray(params.values[this.primaryKey])) { value[details.via] = value[details.via].filter(x => x.toString() !== params.values[this.primaryKey].toString()); } else { @@ -152,7 +156,7 @@ module.exports = { } virtualFields.push( - module.export.removeRelation(model, { + module.exports.removeRelation.call(model, { id: value[this.primaryKey] || value.id || value._id, values: _.pick(value, [this.primaryKey, details.via]), foreignKey: current @@ -213,7 +217,7 @@ module.exports = { // Remove relations in the other side. toAdd.forEach(id => { virtualFields.push( - module.exports.addRelationMorph(model, { + module.exports.addRelationMorph.call(model, { id, alias: association.via, ref: this.globalId, @@ -226,7 +230,7 @@ module.exports = { // Remove relations in the other side. toRemove.forEach(id => { virtualFields.push( - module.exports.removeRelationMorph(model, { + module.exports.removeRelationMorph.call(model, { id, alias: association.via, ref: this.globalId, @@ -262,7 +266,7 @@ module.exports = { .findOne({ [this.primaryKey]: params[this.primaryKey] || params.id }) - .populate(model.associations.map(x => x.alias).join(' ')); + .populate(this.associations.map(x => x.alias).join(' ')); }, addRelation: async function (params) { diff --git a/packages/strapi-plugin-users-permissions/models/User.settings.json b/packages/strapi-plugin-users-permissions/models/User.settings.json index 99479b1cba..40d08f202d 100644 --- a/packages/strapi-plugin-users-permissions/models/User.settings.json +++ b/packages/strapi-plugin-users-permissions/models/User.settings.json @@ -38,6 +38,10 @@ "via": "users", "plugin": "users-permissions", "configurable": false + }, + "article": { + "model": "article", + "via": "authors" } } -} +} \ No newline at end of file diff --git a/packages/strapi/lib/middlewares/boom/index.js b/packages/strapi/lib/middlewares/boom/index.js index dd023d3fcd..ad2940835a 100644 --- a/packages/strapi/lib/middlewares/boom/index.js +++ b/packages/strapi/lib/middlewares/boom/index.js @@ -25,7 +25,7 @@ module.exports = strapi => { await next(); } catch (error) { // Log error. - strapi.log.error(error); + console.error(error); // Wrap error into a Boom's response. ctx.status = error.status || 500;