Parse-server: Parse-server returning empty results unless using master key when ACL set.

Created on 18 Mar 2016  路  12Comments  路  Source: parse-community/parse-server

For implementation related questions or technical support, please refer to the stackoverflow community.

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

Environment Setup

parse-server 2.1.6 running locally and on Heroku
Database migrated to mLab

Steps to reproduce

  1. Migrated database on mLab (note, migration complete so both parse.com and parse-server using the new database)
  2. Existing (or new) user which has ACL set to a role with itself as the only member
  3. Run a test query via the API console on local parse server (or heroku) and parse.com, using the object ID of the user. parse-server returns empty array, parse.com returns the correct array

    Issue

Using the dashboard (running locally) as well as using Cloud Code and parse JS functions, queries are reporting empty unless using the master key is used in the copied database. These queries return as expected via the Parse.com API. Both are using the mLabs hosted database as migration is complete so it does not appear to be related to the database structure. All data appears correct within the database, and when using the master key to view records or the dashboard browser the ACL appears correct. It does not work when the ACL is set to a role nor when it is set to an individual user.

Screenshot attached running side by side off the same parse-dashboard. Window on the left = database hosted on mLab and server on heroku, window on right = parse.com.

parse acl issue

Most helpful comment

I found what I was doing wrong in #1090.

This is expected. In Node, there is no concept of a current user. You need to be explicit about each call.

So, I needed to:

request.user.save("field", "value", { sessionToken: request.user.getSessionToken() })
    .then(function(user) {
      console.log("User was updated");
    }, function(error) {
      console.error(error);
    });

All 12 comments

cc @drew-gross

This seems like an ACL or CLP issue in the server. @oli107 can you provide the CLPs for your _User collection (found in the _SCHEMA collection), as well as the contents of the database for the f0E... user?

_SCHEMA for _User:
"_metadata": {
"class_permissions": {
"get": {
"_": true
},
"find": {
"_": true
},
"update": {
"_": true
},
"create": {
"_": true
},
"delete": {
"_": true
},
"addField": {
"_": true
},
"readUserFields": [],
"writeUserFields": []
},
"auth_options": {
"twitter": {
"enabled": true
},
"anonymous": {
"enabled": false
},
"_enable_by_default": true,
"username": {
"enabled": true
},
"facebook": {
"enabled": true
}
}
},

Database content for user (note role contains mildly sensitive data, so replaced role name as role_admin. Is usually [name]_admin):
{
"_id": "f0EAbbFSUH",
"_acl": {
"f0EAbbFSUH": {
"r": true,
"w": true
}
},
"_created_at": {
"$date": "2014-02-03T00:37:38.674Z"
},
"_email_verify_token": "RLYAeM4nBQ9i6h588knTAIAE3",
"_hashed_password": "xx",
"_p_Clinic": "OtherClass$BxRIe4QjSJ",
"_perishable_token": "vl88cecoqln2hh9lk0f0vt8r3",
"_rperm": [
"f0EAbbFSUH",
"role:role_admin"
],
"_session_token": "kxi4mpv3g7ar8arzvc1wo7p77",
"_updated_at": {
"$date": "2016-03-17T22:59:55.658Z"
},
"_wperm": [
"f0EAbbFSUH",
"role:role_admin"
],
"email": "xx",
"emailVerified": false,
"role": "admin",
"username": "xx",
"verificationCode": "013DRbdv",
"verified": true
}

I believe I have found the issue although I may be way out of my depth.
In SessionsRouter.js, handleMe (line 76), the default master key is passed to the rest adapter:

key: 'handleMe',
    value: function handleMe(req) {
      // TODO: Verify correct behavior
      if (!req.info || !req.info.sessionToken) {
        throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token required.');
      }
      return _rest2.default.find(req.config, _Auth2.default.master(req.config), '_Session', { _session_token: req.info.sessionToken }).then(function (response) {
        if (!response.results || response.results.length == 0) {
          throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token not found.');
        }
        return {
          response: response.results[0]
        };
      });
    }

As such, in the RestQuery.js line 41 onwards is never called because it is never the case that both the class name is _Session, and the masterkey is false. This means the "restwhere" adding the user object id is never included.

if (!this.auth.isMaster) {
        this.findOptions.acl = this.auth.user ? [this.auth.user.id] : null;
        if (this.className == '_Session') {
            if (!this.findOptions.acl) {
                throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'This session token is invalid.');
            }
            this.restWhere = {
                '$and': [this.restWhere, {
                    'user': {
                        __type: 'Pointer',
                        className: '_User',
                        objectId: this.auth.user.id
                    }
                }]
            };
        }
    }

Not sure wether this is related but querying for Parse.Roles also always returns an empty array:
One of my Roles:

{
  "_id": "caNa9YcIWP",
  "_rperm": [
    "role:admin"
  ],
  "_wperm": [
    "role:admin"
  ],
  "name": "customer",
  "_updated_at": new Date(1458995061018),
  "_created_at": new Date(1458922826602)
}

My Query (role of user = admin)

let query = new Parse.Query(Parse.Role);
query.find().then(roles => {
  this.roles = roles;
  console.log(this.roles);
}, error => {
  console.log('Error: ' + error.code + ' ' + error.message);
});

Result is empty array (Parse-Server version 2.2.2)

EDIT:
My problem was caused by another issue. So my query is working.

@oli107 is it only occurring for _User or other classes too?

It seems like if the "Public" ACL is not set to true then it will never return anything unless you set the MasterKey.

For me this happening on other classes too. I'm using Parse Server 2.2.6. My class Client has full read/write/find/etc CLP permissions.

The ACL on the record I'm expect is:

image

I then query using the new Parse Dashboard and set run as to be the objectId of the User "Dd0TeojH82" and I don't get back the records. No query parameters set.

If I add "Public Read" permissions then I see it in the response

This was occurring on all classes but I think this may be an issue with the parse-dashboard not setting the user on the request correctly as opposed to an issue with Parse Server. Like others, I was lost for a bit of time on the fact that any requests using parse-server need to pass either a session token or a masterkey boolean in the options. Documentation on that was quite sparse, I think it is improved now?
Once I corrected this, all my cloud code runs, but the dashboard is still not functioning as it should, I presume for the same reason. I stopped using it for now, but when I last checked I think the Session Keys were not being passed or generated correctly for user queries. Probably best for this to be opened in the dashboard repo.

I should've added that it also fails in my app when I send the sessionKey too for that specific user.

I take that back - it looks like for some reason when i was testing I'd got logged out from Parse so the session key I was trying was invalid - as @oli107 says perhaps this should be closed and re-opened under the parse-dashboard.

This is happening to me in curl as well. Self write permissions are set for users but I get 206 error when I try to do so without the master key.

curl -X GET -H "X-Parse-Application-Id: <id>" \
-H "X-Parse-Revocable-Session: 1" \
-G --data-urlencode 'username=luissuarez' --data-urlencode 'password=luisito'\
http://localhost:1337/parse/login

{
"ACL":{"g8gph8CCH1":{"read":true,"write":true},"*":{"read":true}},
  .
  .
  .
"sessionToken":"r:32ff1612ec2989b404ae856926d95f93"
}

Then I call a post that saves something and then triggers some after save code where I try to update the request.user:

curl -X POST -H "X-Parse-Application-Id: passport-server" \
-H "X-Parse-Session-Token: r:32ff1612ec2989b404ae856926d95f93" \
-H "Content-Type: application/json" \
-d  '<json data>' http://localhost:1337/parse/classes/Something

In the afterSave I try to save the request.user but I get 206 error:

request.user.save("field", "value")
    .then(function(user) {
      console.log("User was updated");
    }, function(error) {
      console.error(error);
    });

If I add useMasterKey option to that save call it works correctly.

I am using Parse Server v2.2.6.

I found what I was doing wrong in #1090.

This is expected. In Node, there is no concept of a current user. You need to be explicit about each call.

So, I needed to:

request.user.save("field", "value", { sessionToken: request.user.getSessionToken() })
    .then(function(user) {
      console.log("User was updated");
    }, function(error) {
      console.error(error);
    });
Was this page helpful?
0 / 5 - 0 ratings

Related issues

sanergulec picture sanergulec  路  4Comments

carjo422 picture carjo422  路  3Comments

kilabyte picture kilabyte  路  4Comments

dpaid picture dpaid  路  3Comments

shardul08 picture shardul08  路  3Comments