Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

include={field} not working on specific object request #1124

Closed
3 tasks done
nkranes opened this issue Mar 21, 2016 · 8 comments
Closed
3 tasks done

include={field} not working on specific object request #1124

nkranes opened this issue Mar 21, 2016 · 8 comments

Comments

@nkranes
Copy link

nkranes commented Mar 21, 2016

For implementation related questions or technical support, please refer to the Stack Overflow and Server Fault communities.

Make sure these boxes are checked before submitting your issue -- thanks for reporting issues back to Parse Server!

Environment Setup

parse-server running locally

Steps to reproduce

1 - Insert a class
curl -X POST -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" -H "X-Parse-Master-Key: XXXX" -d '{
"platform" : "Android",
"isMerged" : "true"
}' "http://localhost:1337/parse/classes/AppConfig"

ObjectId: uq9RVGSIrv

2 - Insert another class
curl -X POST -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" -H "X-Parse-Master-Key: XXXX" -d '{
"name" : "John Smith",
"streetAddress" : "123 Main St"
}' "http://localhost:1337/parse/classes/Player"

ObjectId: UoBKuO29mp

3 - Insert a few types of relations between the 2 classes, since I'm not sure what the correct syntax is
curl -X PUT -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" -H "X-Parse-Master-Key: XXXX" -d '{"player":{"__op":"AddUnique","objects":[{"__type":"Pointer","className":"Player","objectId":"UoBKuO29mp"}]}}
' "http://localhost:1337/parse/classes/AppConfig/uq9RVGSIrv"

curl -X PUT -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" -H "X-Parse-Master-Key: XXXX" -d '{"player2":{"__op":"AddRelation","objects":[{"__type":"Pointer","className":"Player","objectId":"UoBKuO29mp"}]}}
' "http://localhost:1337/parse/classes/AppConfig/uq9RVGSIrv"

curl -X PUT -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" -d '{"player3":{"__op":"Add","objects":[{"__type":"Pointer","className":"Player","objectId":"UoBKuO29mp"}]}}
' "http://localhost:1337/parse/classes/AppConfig/uq9RVGSIrv"

curl -X POST -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" -d '{"Level" : "TWO", "player4":{"__op":"AddUnique","objects":[{"__type":"Pointer","className":"Player","objectId":"UoBKuO29mp"}]}}
' "http://localhost:1337/parse/classes/AppConfig"

4 - Get the AppConfig object and notice the "include=" does not work
curl -X GET -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" "http://localhost:1337/parse/classes/AppConfig/uq9RVGSIrv?include=player"

Results:

{
  "objectId": "uq9RVGSIrv",
  "platform": "Android",
  "isMerged": "true",
  "updatedAt": "2016-03-21T17:47:11.682Z",
  "createdAt": "2016-03-21T16:56:14.816Z",
  "player": [
    {
      "__type": "Pointer",
      "className": "Player",
      "objectId": "UoBKuO29mp"
    }
  ],
  "player3": [
    {
      "__type": "Pointer",
      "className": "Player",
      "objectId": "UoBKuO29mp"
    }
  ]
}

5 - Get rid of the objectId in the query and it works as expected
curl -X GET -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" "http://localhost:1337/parse/classes/AppConfig?include=player"

{
  "results": [
    {
      "objectId": "uq9RVGSIrv",
      "platform": "Android",
      "isMerged": "true",
      "updatedAt": "2016-03-21T17:47:11.682Z",
      "createdAt": "2016-03-21T16:56:14.816Z",
      "player": [
        {
          "objectId": "UoBKuO29mp",
          "name": "John Smith",
          "streetAddress": "123 Main St",
          "updatedAt": "2016-03-21T16:54:44.271Z",
          "createdAt": "2016-03-21T16:54:44.271Z",
          "__type": "Object",
          "className": "Player"
        }
      ],
      "player3": [
        {
          "__type": "Pointer",
          "className": "Player",
          "objectId": "UoBKuO29mp"
        }
      ]
    },
    {
      "objectId": "UvBVu5EKB3",
      "Level": "TWO",
      "player4": [
        {
          "__type": "Pointer",
          "className": "Player",
          "objectId": "UoBKuO29mp"
        }
      ],
      "updatedAt": "2016-03-21T17:49:20.945Z",
      "createdAt": "2016-03-21T17:49:20.945Z"
    }
  ]
}

OR

curl -X GET -H "X-Parse-Application-Id: XXXX" -H "Content-Type: application/json" "http://localhost:1337/parse/classes/AppConfig?include=player&include=player4&include=player3"

{
  "results": [
    {
      "objectId": "uq9RVGSIrv",
      "platform": "Android",
      "isMerged": "true",
      "updatedAt": "2016-03-21T17:47:11.682Z",
      "createdAt": "2016-03-21T16:56:14.816Z",
      "player": [
        {
          "objectId": "UoBKuO29mp",
          "name": "John Smith",
          "streetAddress": "123 Main St",
          "updatedAt": "2016-03-21T16:54:44.271Z",
          "createdAt": "2016-03-21T16:54:44.271Z",
          "__type": "Object",
          "className": "Player"
        }
      ],
      "player3": [
        {
          "objectId": "UoBKuO29mp",
          "name": "John Smith",
          "streetAddress": "123 Main St",
          "updatedAt": "2016-03-21T16:54:44.271Z",
          "createdAt": "2016-03-21T16:54:44.271Z",
          "__type": "Object",
          "className": "Player"
        }
      ]
    },
    {
      "objectId": "UvBVu5EKB3",
      "Level": "TWO",
      "player4": [
        {
          "objectId": "UoBKuO29mp",
          "name": "John Smith",
          "streetAddress": "123 Main St",
          "updatedAt": "2016-03-21T16:54:44.271Z",
          "createdAt": "2016-03-21T16:54:44.271Z",
          "__type": "Object",
          "className": "Player"
        }
      ],
      "updatedAt": "2016-03-21T17:49:20.945Z",
      "createdAt": "2016-03-21T17:49:20.945Z"
    }
  ]
}

I think this is not the expected behavior.

Thanks!

Logs/Trace

@oleksiy-nesterov
Copy link

confirm

@dtsymbal
Copy link

2.2.1 - bug exists

@jeremyjackson89
Copy link
Contributor

This is an issue for me as well -- 2.2.0

Edit: Confirming for 2.2.2

@andrew-makarenko
Copy link

confirm

1 similar comment
@kos984
Copy link

kos984 commented Mar 30, 2016

confirm

@jeremyjackson89
Copy link
Contributor

Temp Fix

This is working for me at the moment, at least until the parse team provides an update. Hopefully this helps some of you as well.

EDIT (2016-03-30 1:42PM EST): Fixed handleGet() to allow the keys query to return specific object keys.

EDIT (2016-04-01 12:08 EST): Submitted a pull request that should fix this.

If you go into the code and look inside of parse-server/lib/Routers/ClassesRouter.js there's an array with objects that have key value pairs for functions. On 2.2.2 on line 137 there's this bit of code:

key: 'handleGet',
value: function handleGet(req) {
    return _rest2.default.find(req.config, req.auth, req.params.className, { objectId: req.params.objectId }).then(function(response) {
        if (!response.results || response.results.length == 0) {
            throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
        }

        if (req.params.className === "_User") {

            delete response.results[0].sessionToken;

            var user = response.results[0];

            if (req.auth.user && user.objectId == req.auth.user.id) {
                // Force the session token
                response.results[0].sessionToken = req.info.sessionToken;
            }
        }
        return {
            response: response.results[0]
        };
    });
}

If you look at the method above it on line 42 (handleFind), you can see where they're parsing through the query parameters. So I took some of that and added it to handleGet():

key: 'handleGet',
value: function handleGet(req) {
  var body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query));
  var options = {};
  var allowConstraints = ['include', 'keys'];

  var _iteratorNormalCompletion = true;
  var _didIteratorError = false;
  var _iteratorError = undefined;

  try {
    for (var _iterator = Object.keys(body)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
      var key = _step.value;

      if (allowConstraints.indexOf(key) === -1) {
        throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Improper encode of parameter');
      }
    }
  } catch (err) {
    _didIteratorError = true;
    _iteratorError = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion && _iterator.return) {
        _iterator.return();
      }
    } finally {
      if (_didIteratorError) {
        throw _iteratorError;
      }
    }
  }

  if (body.include) {
    options.include = String(body.include);
  }
  if (typeof body.keys == 'string') {
    options.keys = body.keys;
  }
  return _rest2.default.find(req.config, req.auth, req.params.className, { objectId: req.params.objectId }, options).then(function (response) {
    if (!response.results || response.results.length == 0) {
      throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
    }

    if (req.params.className === "_User") {

      delete response.results[0].sessionToken;

      var user = response.results[0];

      if (req.auth.user && user.objectId == req.auth.user.id) {
        // Force the session token
        response.results[0].sessionToken = req.info.sessionToken;
      }
    }
    return { response: response.results[0] };
  });
}

@hramos
Copy link
Contributor

hramos commented Apr 2, 2016

No need to wait for the Parse team, you can open a pull request :) Make sure to also include tests in your PR.

@flovilmart
Copy link
Contributor

I believe this has been merged with #1280.

Please reopen if it wasn't

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants