JKHeadley / rest-hapi

🚀 A RESTful API generator for Node.js

Home Page:https://resthapi.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

getAll request on '_MANY' association

clegirar opened this issue · comments

Describe the bug
I want to get '_MANY' association and rest-hapi return all datas of the model of association

To Reproduce
Steps to reproduce the behavior:

  1. Create '_MANY' association
associations: {
	companies: {
		type: '_MANY',
		alias: 'companies',
		model: 'companies',
	},
},
  1. I am creating companies in the model companies

Capture d’écran 2019-08-22 à 18 07 04

  1. I post an id company in my companies association

Capture d’écran 2019-08-22 à 18 19 53

  1. I get the association companies and response contains all the companies whereas in the companies association i have only one company
{
  "docs": [
    {
      "_id": "5d5cae2e3356752c4f2d4414",
      "subsidiaries": [
        {
          "_id": "5d5cae373356752c4f2d4416",
          "subsidiaries": [],
          "name": "string",
          "naf": "string",
          "siret": "string",
          "createdBy": "5d5c9e1a6b233e246ad4f611",
          "createdAt": "2019-08-21T02:36:39.450Z",
          "institutions": []
        }
      ],
      "name": "string",
      "naf": "string",
      "siret": "string",
      "createdBy": "5d5c9e1a6b233e246ad4f611",
      "createdAt": "2019-08-21T02:36:30.548Z",
      "institutions": []
    },
    {
      "_id": "5d5cae373356752c4f2d4416",
      "subsidiaries": [],
      "name": "string",
      "naf": "string",
      "siret": "string",
      "createdBy": "5d5c9e1a6b233e246ad4f611",
      "createdAt": "2019-08-21T02:36:39.450Z",
      "institutions": []
    },
    {
      "_id": "5d5ebd0207b9b804f763dc2a",
      "subsidiaries": [],
      "name": "Hey",
      "naf": "string",
      "siret": "string",
      "createdBy": "5d5db71b1c99220acc90ae45",
      "createdAt": "2019-08-22T16:04:18.189Z",
      "institutions": []
    }
  ],
  "pages": {
    "current": 1,
    "prev": 0,
    "hasPrev": false,
    "next": 2,
    "hasNext": false,
    "total": null
  },
  "items": {
    "begin": null,
    "end": null,
    "total": 3
  }
}

Expected behavior
getAll request on '_MANY' association should return only the id's of the association and not fulld datas of the corresponding model.

Desktop (please complete the following information):

  • OS: OSX
  • Browser: Chrome
  • Version: 76.0.3809.100

Additional context
Sorry for my deplorable English, i hope its comprehensive ! Thanks for your answer.

Hi @Clemssss, thanks for reaching out.

I believe I understand the issue you describe, though I will need some more information since I am unable to replicate it on my end.

  1. Is this response from a REST endpoint (i.e GET /<your entity>/{ownerId}/companies) or from a wrapper method?

  2. Could you display the JSON for the original parent object containing the _MANY relationship? (i.e. the result of GET /<your entity>/{_id})

Let's start from there and see if we can figure out what's going wrong. Thanks!

Thank @JKHeadley for your speedy response !

  1. Yes is the response from the REST endpoint GET /<your entity>/{ownerId}/companies

  2. This is the response of GET /<your entity>/{_id} (companies is the _MANY relationship and she is embed), in itself this endpoint (GET /<your entity>/{_id}) return the _MANY relationship but if an endpoint is created just for this it would make more sense no ?

{
  "_id": "5d5db71b1c99220acc90ae45",
  "companies": [
    {
      "_id": "5d5cae373356752c4f2d4416",
      "subsidiaries": [],
      "name": "string",
      "naf": "string",
      "siret": "string",
      "createdBy": "5d5c9e1a6b233e246ad4f611",
      "createdAt": "2019-08-21T02:36:39.450Z",
      "institutions": []
    }
  ],
  "email": "test@test.com",
  "password": "$2b$10$N4QlJTSrMfurtS3/U13bi.Dr0e2CxidEufFUrKT.PuEgY/DLFdaWW",
  "firstName": "string",
  "lastName": "string",
  "rights": {
    "user": true,
    "oppusUser": false
  },
  "createdAt": "2019-08-21T21:26:51.661Z"
}

Once again thanks very much for your time and your reply!
(PS: I would like to know what happened about this issue #149 ?)

Hmm, yes GET /<your entity>/{ownerId}/companies should return the same documents as the embedded companies field. I'm not sure why it is not in your case. Would you be able to share some code (mainly model files) that will allow me to replicate the issue?

Sure.
UserSchema ()

const UserSchema = new Schema({
	firstName: { type: String, required: true },
	lastName: { type: String, required: true },
	phone: { type: String },
	email: { type: String, required: true, index: { unique: true } },
	password: { type: String, required: true },
	authyId: { type: String },
	companies: [{ type: Schema.Types.ObjectId, ref: 'company' }],
	rights: { type: Schema.Types.Mixed, default: {} },
	savedData: { type: Schema.Types.Mixed, default: {} },
});

module.exports = () => {
	UserSchema.statics = {
		collectionName: 'user',
		routeOptions: {
			associations: {
				companies: {
					type: '_MANY',
					alias: 'companies',
					model: 'company',
				},
			},
			find: {
				pre: (_id, query, request) => {
					const user = request.auth.credentials;
					if (!_id || user._id !== _id) {
						throw Boom.unauthorized('You are not authorized with this account.');
					}
					return {
						$embed: ['companies'],
					};
				},
			},
			list: {
				pre: (query, request) => {
					const user = request.auth.credentials;
					if (!user.rights.oppusUser) {
						throw Boom.unauthorized('You are not authorized with this account.');
					}
					return {
						$embed: ['companies'],
					};
				},
			},
		},
	};
	return UserSchema;
};

CompanySchema

const CompanySchema = new Schema({
	name: { type: String, required: true },
	naf: { type: String, required: true },
	siret: { type: String, required: true },
	institutions: [{
		name: { type: String },
		address: {
			city: { type: String },
			street: { type: String },
			complementary: { type: String },
			zipCode: { type: String },
		},
		numberOfEmployees: { type: Number },
	}],
	subsidiaries: [{ type: Schema.Types.ObjectId, ref: 'company' }],
});

module.exports = () => {
	CompanySchema.statics = {
		collectionName: 'company',
		routeOptions: {
			associations: {
				subsidiaries: {
					type: '_MANY',
					alias: 'subsidiaries',
					model: 'company',
				},
			},
			find: {
				pre: () => ({
					$embed: ['subsidiaries'],
				}),
			},
			list: {
				pre: () => ({
					$embed: ['subsidiaries'],
				}),
			},
		},
	};
	return CompanySchema;
};

Ohh, i find, its the find and list pre-middlewares in the CompanySchema.
If i delete it, it works, but i don't know why ...?

Hi @Clemssss, it's because you are overriding the query parameter in the middleware function instead of modifying it. getAll internally uses the query parameter to filter the results based on the ownerId. When you override it, you erase the filter and therefore get all of the company documents rather than the docs under the ownerId.

Try changing your middleware to:

	find: {
	  pre: (_id, query, request, Log) => ({
            ...query,
            $embed: ['subsidiaries']
          }),
	},
	list: {
	  pre: (query, request, Log) => ({
            ...query,
            $embed: ['subsidiaries']
          }),
	},

Exactly, im stupid ... Thanks for your response !

Not at all, its easy to miss!