parse-community / parse-server

Parse Server for Node.js / Express
https://parseplatform.org
Apache License 2.0
20.8k stars 4.77k forks source link

Can't save a default value for new users. #3373

Closed QB3L closed 7 years ago

QB3L commented 7 years ago

After the changes to have to use master key by passing it on methods, I've encountered a problem. I've seen some similar questions but nothing with a solution for setting a value on the user class on a beforeSave scenario as I don't have a way to force the use of a masterkey on beforeSave. What options do I have?

`Parse.Cloud.beforeSave(Parse.User, function(request, response) {

var user = request.object;
if (user.isNew) {
    user.set("premium", false); //Default new user to non-premium upon creation
} 
response.success();

});`

flovilmart commented 7 years ago

isNew is a function https://parseplatform.github.io/Parse-SDK-JS/api/classes/Parse.Object.html#methods_isNew

But that should work as is.

QB3L commented 7 years ago

It only works if I change permissions and allow changes on User. Right now I just get an error "Permission denied for action addField on class _User"

natanrolnik commented 7 years ago

@QB3L check how you are setting up the permissions on the _User class; I'm specifically referring to allowing or disabling adding new fields to a class. Go over the security section in the docs. One suggestion I would make is: launch the dashboard, and try to add the "premium" property via dashboard, and run again your code. That should work.

natanrolnik commented 7 years ago

Also, what are your CLPs defined for the _User class?

QB3L commented 7 years ago

My CLPs do not permit addField and I think that is the root problem (only have Read/Find enabled). But I wanted only the parse server via the masterkey to perform any changes on the User class to keep it extra secure. I am worried of just enabling Public addFields as that may permit users to perhaps send a Sign Up request with a new field I may not want. I may be overreacting security wise as I am not permitting _User creation but wanted to be as secure as possible. I just wanted to know if there was a way of letting the code know on beforeSave to use masterkey and perform any changes necessary to the class.

Does the parse server (beforeSave) run with a different role so that I may add a new role on CLP perhaps and permit addField only for that role?

flovilmart commented 7 years ago

If the field exist, addField should let it pass through, as well the field exists in the Schéma.

Do you have some logs of the failure?

QB3L commented 7 years ago

I changed the permissions (thinking this would fix it). I think something else might be going on as now I have a different error.

"Permission denied for action create on class _User"

I updated parse recently not sure what changed. Any ideas? I will check logs

flovilmart commented 7 years ago

If you're preventing _User class creation from CLP, that's what'a expected...

QB3L commented 7 years ago

hmmm this is interesting. I don't remember making any changes to the permissions in a long time and only now this is giving me problems. I was able to create a user via Sign Up without permitting Public Create on _User. Before the upgrade, I was able to do Parse.Cloud.UseMasterKey() (part of the reason I updated the code)...did that have a global effect perhaps and was letting me create users before?

What options do I have to create users now? Do I need to write my own cloud function to create users?

flovilmart commented 7 years ago

Can you provide:

QB3L commented 7 years ago

This is the CLP as it is right now (to make it work)

user-clp

Code that create users:

    var username = req.body.username;
    var password = req.body.password;
    if (username !== undefined && password !== undefined) {
        var user = new Parse.User();
        user.set("username", username);
        user.set("password", password);
        user.set("email", username);
        user.signUp(null, {
            success: function(user) {
                // Hooray! Make them login now
                res.send(jsonOk({redirect:"/signin"}));
            },
            error: function(user, error) {
                // Some error on signup
                res.status(200).send(jsonError(error.message));
            }
        });
    } else {
        res.status(400).send("Missing Parameters");
    }

beforeSave Code never had Parse.Cloud.useMasterKey() inside. What I had said is that useMasterKey() was called on other cloud functions. Hence my question that maybe it worked because it was global and I had called a cloud function before and from then on it used the master key.

flovilmart commented 7 years ago

Yes, useMasterKey() 'leaked' before, we should have taken steps earlier to prevent that.

However, you should not need the addFields CLP on, if the column exist on the _User table.

QB3L commented 7 years ago

Cool, i'll try that out. Thanks for the help.

Is there any other straightforward way to achieve what I want without permitting Public write?

Only option I see is to create my own signup and put useMasterKey parameter on save operation.