I have an array property called courses on my User table in Parse. Any idea why I might getting Cannot modify user XTC9aiDZlL. code=206, message=Cannot modify user XTC9aiDZlL. when I do the following:
user.remove('courses', deletedCourse);
user.save()
where deleteCourse is the course PFObject to delete
Are you signed in as the user you're trying to modify? That can cause problems like this, as Parse usually just lets a user modify themself & the objects they've created.
If you're signed in as the same user you're trying to edit that's another story. This is a glitch that seems to be popping up in the Parse server recently. It's not the best solution but for now you'll need to modify the ACL when you create the user, like this:
let user = PFUser()
let acl = PFACL()
acl.getPublicWriteAccess = true
acl.getPublicReadAccess = true
user.acl = acl
Related
I am doing a query onto a class where I have a pointer to a User.
I do query.include('byUser') and when I log out the query result it's shown but when I try to get a specific attribute like email. It doesnt exist.
I also first thought it was odd that I have to get the User details by doing:
const userDetails = query.get("byUser").attributes;
Do I have to do .attributes? And also why isn't the email showing up. Everything else seems to show up in the attributes section.
Thanks
Please note that in parse, you can not query the email field of other users. you can see the email field only if you are the signed in user. This is a security mechanism.
A. If you want to get the email field for a user object, you can do two things:
Pass the user session token to the query.
new Parse.Query(Parse.User).get(<userId>,{sessionToken:<userSessionToken>});
Use master key. (Note: You have to set the master key before.)
new Parse.Query(Parse.User).find({useMasterKey:true});
B. Your include method is correct and it it will fetch the byUser object. You do not need to use .attributes.
UPDATE:
You can also set a publicEmail field in your User class which will not be filtered out by parse-server. to automate this, you can write a cloud code.
Cloud Code Example (on parse-server V 3.0.0 and above):
PLEASE NOTE THAT YOU CAN NOT USE ASYNC FUNCTIONS FOR PARSE-SERVER < V 3.0.0
Parse.Cloud.beforeSave(Parse.User, async req=>{
if (!req.original && !req.master && req.object.get('email')){
req.object.set('publicEmail',req.object.get('email'));
}
})
Now, if new user sign up, this cloud code will automatically adds a new field to the user object publicEmail which is not filtered by parse-server.
I'm not able to use the node server debugger so I'm posting here to see if I can get a nudge in the right direction.
I am trying to allow multiple users to edit documents created by any of the users within their specific company. My code is below. Any help would be appreciated.
(Server)
ComponentsCollection.allow({
// Passing in the user object (has profile object {company: "1234"}
// Passing in document (has companyId field that is equal to "1234"
update: function(userObject, components) {
return ownsDocument(userObject, components);
}
});
(Server)
// check to ensure user editing document created/owned by the company
ownsDocument = function(userObject, doc) {
return userObject.profile.company === doc.companyId;
}
The error I'm getting is: Exception while invoking method '/components/update' TypeError: Cannot read property 'company' of undefined
I'm trying to be as secure as possible, though am doing some checks before presenting any data to the user, so I'm not sure if this additional check is necessary. Any advice on security for allowing multiple users to edit documents created by the company would be awesome. Thanks in advance. -Chris
Update (solution):
// check that the userId specified owns the documents
ownsDocument = function(userId, doc) {
// Gets the user form the userId being passed in
var userObject = Meteor.users.findOne(userId);
// Checking if the user is associated with the company that created the document being modified
// Returns true/false respectively
return doc.companyId === userObject.profile.companyId;
}
Looking at the docs, it looks like the first argument to the allow/deny functions is a user ID, not a user document. So you'll have to do Meteor.users.findOne(userId) to get to the document first.
Do keep in mind that users can write to their own profile subdocument, so if you don't disable that, users will be able to change their own company, allowing them to edit any post. You should move company outside of profile.
(If you can't use a proper debugger, old-fashioned console.log still works. Adding console.log(userObject) to ownsDocument probably would have revealed the solution.)
Im using parse with JS and i'm trying to do a reverse relationship...
I have the follow tables..
User
Offers
And the User table has a relationship column to relate a user to an offer and I have two types of relationships used_offers and saved_offers both of which tie the user to a offer.
I decided to put the relationship on the User table instead of the Offers table so that the ACL permission mean that only that user can read the relationship rather than anyone being able to read the relationship on a specific offer.
So... my question is... I am trying to list all the offers but I also want to join (if it exists) a relationship, ie so I know the in data returned it the offer is saved or used.
My current code looks like this...
//Get offer object and create query
var Offer = Parse.Object.extend("Offer");
var offerQuery = new Parse.Query(Offer);
var user = Parse.User.current(); //Get user object//Get user object
console.log(user); //Check user object exists (ie logged in)
offerQuery.whereEqualTo("saved_offers", user); //Get user object//Show relationships
offerQuery.include(["user"]); //Get user object//Return the user data also
offerQuery.find({
success: function(object) {
console.log(object);
},
error: function(error) {
console.log(error);
}
});
I get an error of... uncaught TypeError: undefined is not a function
Which im sure is related to the line...
offerQuery.whereEqualTo("saved_offers", user);
Super appreciate any help here, Parse is great but i cannot find specific documenation to use whereEqualTo (if this is the write command to call) in JS.
Many thanks!
It should be equalTo instead of whereEqualTo.
I have a _User class on parse for my application and i want to make it so that its ACL restricts writing from everywhere expect cloud code (W/ master key). The user has a "Verified" boolean column acknowledging weather they are a verified user or not. I do not want them to be able to log in, mess with the javascript, and write themselves in as "verified". I wrote this code but it wont work. Any suggestions?
Parse.Cloud.afterSave("_User", function(request, response) {
request.object.set("verifiedCritic",false);
var publicReadACL = new Parse.ACL();
publicReadACL.setPublicWriteAccess(false);
publicReadACL.setWriteAccess(request.object.id,false);
request.object.setACL(publicReadACL);
request.object.save();
response.success();
});
http://parse.com/docs/js/symbols/Parse.ACL.html#setReadAccess
check "setPublicREAD|WRITEAccess()" and use that in addition to the method you have for an individual user.ID.
When first created or when updated, IMO you want :
PubREAD TRUE
PubWrite FALSE
AND
Write ( thatUsserID, TRUE )
Then with the above and no other additional accretive assess in the array for the ACL , you should get the result that u want in cloud code after issuing "use_master_key" ...
After you create a user, can u use the databrowser to copy/paste the ACL column so that you can verify you have the correct collection of permissions? Then do your updating and the Cloudcode stuff.
Using parse.com and the JavaScipt SDK.
I've got a variable (friendName) that stores a _User record in it.
I know want to save this user back into parse under a new class and into a "pointer" column type. This is so the name can then be associated back to the _User class.
When I try and save the user using
requestFriend.set("username", friendName);
I get the following error in Chrome dev tools.
{"code":111,"error":"invalidtypeforkeyusername,expected*_User,butgotstring"}
To me this indicates that "friendName" is not in the correct format to save back to parse.
But have do I convert it into a _User object to that it can save successfully?
I can post up all code if it helps, but I thought I'd try and keep the post shorter to start with.
Screen shots attached.
Sounds like your schema is expecting it to be a User object. If friendName has the objectId of the user, you can create the object and the SDK will convert it to a pointer
new Parse.User({objectId: friendName});
If friendName is the username, you'd have to first query for the User and then set it. Something like this:
new Parse.Query("_User").equalTo("username", friendName).first().then(function(user) {
requestFriend.set("username", user);
return requestFriend.save();
});