10

I've followed every step of this walkthrough, but when I try to create a new row, I get a 403:

code: 119

message: "This user is not allowed to perform the create operation on Messages. You can change this setting in the Data Browser."

My code:

Messages = Parse.Object.extend("Messages")
var message = new Messages();
message.set("sender", Parse.User.current());
message.set("receiver", *anotherUser*);
message.set("subject", "foo")
message.set("body", "bar")
message.save()
.then(
  function(message){
    console.log("success!")
  },function(error){
    console.log("error: ", error);
});

My CLPs are set as follows: enter image description here enter image description here

It looks like someone else posted the same issue in a google group. What are we missing?

5
  • Have you checked to see if the what the value is of Parse.User.current()? My guess is that it's returning a nil user. Also, I've always used PFUser.currentUser(), so maybe give that a go too Commented Oct 23, 2015 at 18:45
  • Just double-checked–I console.log it out just before I save it, and it is a valid user object with an id. Commented Oct 23, 2015 at 20:12
  • Is it different from request.user? Try logging that too to see if they are different Commented Oct 23, 2015 at 21:08
  • They're the same. Just modified my cloudcode as requested and see in my logs, before_save triggered for Messages for user xxxx, where xxxx is the same as the sender field. Commented Oct 23, 2015 at 21:36
  • @Russell have you ever used pointer permissions and had create work as expected? Commented Oct 24, 2015 at 21:37

3 Answers 3

17

I've submitted this as a bug to Parse (Facebook), and they replied:

We have managed to reproduce this issue and it appears to be a valid bug. We are assigning this to the appropriate team.

I will update this answer once the issue has been resolved. If this issue is impacting you, please subscribe to the bug, as this will help prioritize the fix.

UPDATE

Facebook replied:

Turns out that this is actually by design. To create an object, the class should have public create permissions on it

Unfortunately, with this solution, I can create a message "from" any other user (another user set as the sender). This is unacceptable and unusable IMHO.

Sign up to request clarification or add additional context in comments.

Comments

6

That has been a bug since the launch of Pointer Permissions, which effectively makes them useless. My impression is they built this with the idea of letting developers secure existing schemas in one go, but of course you need it to work for future creation.

One workaround would involve combining the older Class Level Permissions and per-row ACL's while being careful to not disable your Data Browser. Let's assume you have classes "Puppy" and "Cat" and both have a field called "owner".

  1. In your Data Browser, for each class where it makes sense to have an owner field, you set its Class Level Permissions for Puppy and Cat each to:

Public - Read: Yes or No, depends on your use case, Write: Yes

Add a Pointer Permission for "owner" - Read: Yes, Write: Yes (can skip this for now, see below)

  1. Then in your cloud/main.js, you can use the following as a starting point (which I often call "types" below, sorry).

  2. When Parse fixes the creation issue, you remove the Public Write Class Level permission (above), leave the Pointer Permission one, and get rid of the workaround code below.

--

var validateAndUpdateOwnerWritePerms = function(request){
    var object = request.object;
    var error = null;
    var owner = object.get('owner');

    if (!Parse.User.current()) {
        error = 'User session required to create or modify object.';
    } else if (!owner) {
        error = 'Owner expected, but not found.';
    } else if (owner && owner.id != Parse.User.current().id && !object.existed()) {
        error = 'User session must match the owner field in the new object.';
    }

    if (request.master) {
        error = null;
    }

    if (error) {
        return error;
    }

    if (object.existed()) {
        return null;
    }

    var acl = new Parse.ACL();
    acl.setReadAccess(owner, true);
    acl.setWriteAccess(owner, true);

    object.setACL(acl);

    return null;
}

// Wrapper that makes beforeSave, beforeDelete, etc. respect master-key calls.
// If you use one of those hooks directly, your tests or admin
// console may not work.
var adminWriteHook = function(cloudHook, dataType, callback) {
    cloudHook(dataType, function(request, response) {
        if (request.master) {
            Parse.Cloud.useMasterKey();
        } else {
            var noUserAllowed = false;
            if (cloudHook == Parse.Cloud.beforeSave &&
                (dataType == Parse.Installation || dataType == Parse.User)) {
                    noUserAllowed = true;
            }
            if (!noUserAllowed && !Parse.User.current()) {
                response.error('Neither user session, nor master key was found.');
                return null;
            }
        }

        return callback(request, response);
    });
};

// Set hooks for permission checks to run on delete and save.
var beforeOwnedTypeWriteHook = function(type) {
    var callback = function (request, response) {
        var error = validateAndUpdateOwnerWritePerms(request);
        if (error) {
            response.error(error);
            return;
        }
        response.success();
    };
    return adminWriteHook(Parse.Cloud.beforeSave, type, callback);
    return adminWriteHook(Parse.Cloud.beforeDelete, type, callback);
};

beforeOwnedTypeWriteHook('Puppy');
beforeOwnedTypeWriteHook('Cat');

Comments

2

Unfortunately it seems that Parse Pointer Permissions do not work as you expect it on Create. The quick fix would be to allow Create permission to Public. Then to ensure that the user who is creating a record is the same as the sender. So you need to perform a manual check in the beforeSave trigger for Messages class in cloud code and if that check fails, reject the record being created.

6 Comments

Good idea about utilizing cloud code but it's always best to use CLPs and ACLs where possible. Since the current user of the app is creating the message object, there shouldn't be any issues. My guess is that there is an error with Parse.User.current() returning nil
What does granting create permission do then?
@Russell As I said pointer permissions unfortunately somehow do not work when sender is creating a record. You need to grant create permissions without them @@adamdport By granting Create permission you let anyone create a record in that class. Add the simple cloud code logic and now only the Sender will be able to create a record. Problem solved as you get the expected behaviour
@MoNazemi I meant what does create do as a pointer CLP, not public. I have no doubts that I could manage these permissions manually through Cloud Code, but I'd like to leverage Parse's OTC solutions whenever possible.
Sadly it does nothing !! Create does not seems to work at all. The workaround given is the only way around it as far as I know. This to me should be reported as a bug to Parse.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.