Using Parse User's Master Key to save relations not working - javascript

I am attempting to link a School class with a list of users (a School can have many Users, and a User belongs to a School). Per several suggestions, I am using Parse's Cloud Code and Master key to accomplish this.
My issue is that, instead of passing a string parameter or another User, I am linking a School object to the user.
Here is my Cloud Code, which is causing an error when ran and no changes made to Parse's backend:
Parse.Cloud.define('addNewSchoolRelation', function(request, response) {
var userId = request.params.userId,
associatedSchoolObject = request.params.associatedSchoolObject;
var User = Parse.Object.extend('_User'),
user = new User({ objectId: userId });
var relation = user.relation("schoolRelation");
relation.set(associatedSchoolObject);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
And inside my app, this is how I call it:
PFQuery *schoolQuery = [PFQuery queryWithClassName:#"School"];
[schoolQuery whereKey:#"objectId" equalTo:#"FgpHfOGIdC"]; //this is the test one
[schoolQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error %#", error);
} else {
PFObject *school = [objects firstObject];
[PFCloud callFunctionInBackground:#"addNewSchoolRelation" withParameters:
#{#"userId": #"BHqvZ6PrLl", //testing for now
#"associatedSchoolObject": school,
} //sets that user's newChats
block:^(id object, NSError *error) {
if (error){
NSLog(#"Error %#", error);
} else {
NSLog(#"Saved on remote user");
}
}];
}
}];
I'm pretty sure culprit is in my Javascript code - am I passing the parameter incorrectly? I'm not sure what I'm doing incorrectly and any help is much appreciated, thanks!

Related

Parse Server Push Notification to Specific user issue

I need to send a Push notification after a class is updated by the user, the push notification is working from the Dashboard.
I added this code to my Cloud Code, i can see the logs with the success message, but the notification is not being sent to the user, on the past notification, it shows that was sent, but the audience is Everyone, but pushs sent is 0, this is my Cloud Code
Parse.Cloud.afterSave("Class", function(request, response) {
var inObject = request.object;
if (inObject.get("isLost")){
console.log("inObject is lost");
var targetUser = new Parse.User();
targetUser.id = inObject.get("UserID");
var query = new Parse.Query(Parse.Installation);
query.equalTo("user", targetUser);
Parse.Push.send({
where: query,
data: {
alert: "InObject",
badge: "Increment",
message: "Testando"
}
}, {
success: function() {
// Push was successful
console.log("success");
},
error: function(error) {
// Handle error
console.log("error: "+error.code+" message "+error.message);
throw "Got an error " + error.code + " : " + error.message;
},
useMasterKey: true
});
}
});
I tried to do the double query as the post link, but no success, i loged the user ID and is the same as show on my Installation in the Dashboard.
If i click the Push notification for more details this is the Target that it shows:
Target details from push
Edit
Save code for that class(it's in java):
ParseObject object = new ParseObject(Class.class.getSimpleName());
object.put(NAME, getName());
object.put(UUID, getUUID());
object.put(ICON_ID, getIconID());
object.put(ADDRESS, getAddress());
object.put(ID1, iD1.toString());
object.put(ID2, iD2.toString());
object.put(ID3, iD3.toString());
object.put(IS_LOST, getIsLost());
object.put(USER, parseUserID);
object.put(DISTANCE, getDistance());
object.put(LATITUDE, getLatitude());
object.put(LONGITUDE, getLongitude());
object.saveEventually();
The parseID is being generated by the ParseUser.getCurrentUser().getObjectID();
So, after trying this in a lot of ways, i ended up creating a relation between my object and the ParseUser object, this solved the issue, still i don't know why can't i just save the UserID, but my problem is solved now.

Routing to a specific user profile using iron router (METEOR)

As the question says, I need to create a specific route for every user that I have. In my case employers. Now all the examples on the web are connected with the USERS collection.
In my case I want to route to: "/employer/:_id" but I have the Employer ID in the Collection Employers. So basically I have to get the Employer ID via the key from User ID
Im kinda stuck on returning the Employer ID value to the route...
METHODS.js
getEmployerId: function(currentuser){
employerId = Employer.find({"user":currentuser}).fetch();
return employerId;
}
ROUTER.js
Router.route("/employer/:_id", {
name:"employer",
template:"employer",
layoutTemplate:'employerLayout',
data: function(){
var currentuser = Meteor.userId();
Meteor.call("getEmployerId", currentuser, function(error, result){
if(error){
console.log("error", error);
}
if(result){
return true; // I belive here is where I have to pass it up to the ROUTE
}
});
},
onBeforeAction:function(){
var user = Meteor.userId();
if(!user || !Roles.userIsInRole(user, ['employer'])) {
Router.go("verification");
}else {
this.next();
}
return true;
},
});
And this is how my Employer collection looks like:
meteor:PRIMARY> db.employer.find().pretty()
{
"_id" : "qCFGZa4ogc5LR56PL", // I need this for the route
"createdAt" : ISODate("2015-07-18T13:19:16.098Z"),
"user" : "owfJ4ozrfsp26o8G4" // the key through which i can return the ID, got it from the user session?
}
Anyone has a suggestion how to do this? And is this a good approach for each user(employer) profile? Any tutorial, example or anything that describes an application with user profiles would be much appriciated!
Ok, looks like you're nearly there.
I don't think you want the ::id parameter. You send the user to simply /employer, where he does the sign in, so you have his user id.
Then change getEmployerId to getEmployer: in other words, get the whole of the employer record.
getEmployer: function(currentuser){
return Employer.find({"user":currentuser}).fetch();
}
Then in your data: function of the router instead of returning true you return the record you find. In this way the record is available for your template (that's what the data function is for)
data: function(){
var currentuser = Meteor.userId();
Meteor.call("getEmployer", currentuser, function(error, result){
if(error){
console.log("error", error);
}
if(result){
return result;
}
});
},

angular push adds operator that that results in MongoError

I am implementing the tutorial on the mean stack https://www.youtube.com/watch?v=AEE7DY2AYvI
I am adding a delete feature to remove items from the database on a button click
My client side controller has the following 2 functions to add to db and remove
$scope.createMeetup = function() {
var meetup = new Meetup();
meetup.name = $scope.meetupName;
meetup.$save(function (result) {
$scope.meetups.push(result);
$scope.meetupName = '';
});
}
$scope.deleteMeetup = function() {
item = $scope.meetups[0];
console.log("deleting meetup: " + item["name"]);
Meetup.delete(item);
scope.meetups.shift();
}
My server side has the following code
module.exports.create = function (req, res) {
var meetup = new Meetup(req.body);
meetup.save(function (err, result) {
res.json(result);
});
}
module.exports.remove = function(req, res) {
console.log("GOING TO REMOVE!!!");
console.log(req.query);
item = req.query;
Meetup.remove(item, function (err, results) {
console.log("done");
console.log(err);
console.log(results);
});
}
When I run my code and if I delete an already loaded item in the list, it is removed from Mongodb just fine. But if I add an item to the list and I do not refresh the page, it results in an error at my server that appears as
GOING TO REMOVE!!!
{ '$resolved': 'true',
__v: '0',
_id: '54ec04e70398fab504085178',
name: 'j' }
done
{ [MongoError: unknown top level operator: $resolved]
name: 'MongoError',
code: 2,
err: 'unknown top level operator: $resolved' }
null
I if I refresh the page, the it gets deleted fine. But if I added the entry, angular seems to be adding a new variable $resolved. Why is that happening?
Also another question, What is the proper way to call delete? I call it now but I am not able to put a callback. I want a callback which returns and then I shift the list of items. I tried adding a callback but the code never reaches it.
ie I tried the following
/*
Meetup.delete(item, function () {
console.log("In callback!!");
console.log(returnValue);
console.log(responseHeaders);
$scope.meetups.splice(item);
});
*/
/*Meetup.delete(item,
function (returnValue, responseHeaders) {
console.log("In callback!!");
console.log(returnValue);
console.log(responseHeaders);
$scope.meetups.splice(item);
},
function (httpResponse){
// error handling here
console.log("Need to handle errors");
});
*/
I am very new to node and am confused. Any help is very, very appreciated
Looks like it possible to call item.delete instead of Meetup.delete(item). You can call same methods on model instance. It prevent sending angular properties to server.
But better to make a rest API with delete method
DELETE /meetups/:id
and send just a _id
Meetup.remove({id: item._id});

Adding data to Users and then saving them using Parse Cloud Code

I'm trying to make a cloud function which saves the sender's objectId and username as an array, inside the array "request", for the target and have the target's objectId and username saved as an array, in the array "pending" for the sender.
Parse.Cloud.define("newGameRequest", function(request, response) {//A
// Get the user who called the function
var user = request.user;
var target;
var query = new Parse.Query(Parse.User);
query.get(request.params.friendId, {
success: function(object) {
var target = object;
var friendInfo = [target.objectId, target.username];
var userInfo = [user.objectId, user.username];
user.add("pending",friendInfo);
target.add("request",userInfo);
Parse.Object.saveAll([user, target], { useMasterKey: true });
response.success("Success");
},
error: function(object, error) {
response.error(error);
}
});
});
Looking in the data browser shows that the arrays for each respective user were saved, but saved with null values only ([[null,null]] for both).
The call is from an iOS device and is the following:
[PFCloud callFunctionInBackground:#"newGameRequest"
withParameters:#{#"friendId": self.friend.objectId}
block:^(NSString *result, NSError *error) {
if (!error) {
}
else {
NSLog(#"%#",result);
}
}];
self.friend.objectId has been tested and is the right result.
What is the issue with my cloud code?
I'm an idiot.
getting the object Id of user is the like the following:
user.id
and getting the username is done like this:
user.getUsername()

Parse iOS SDK: Calling Cloud Functions From Xcode

Scenario
I have these two Cloud Functions that I want to use in my application. They check for the online status of the user and I want to set a boolean key "isOnline" for each user to YES if the user is online and to NO if they are not.
var moment = require("moment");
Parse.Cloud.define("registerActivity", function(request, response) {
var user = request.user;
user.set("lastActive", new Date());
user.save().then(function (user) {
response.success();
}, function (error) {
console.log(error);
response.error(error);
});
});
Parse.Cloud.define("getOnlineUsers", function(request, response) {
var userQuery = new Parse.Query(Parse.User);
var activeSince = moment().subtract("minutes", 2).toDate();
userQuery.greaterThan("lastActive", activeSince);
userQuery.find().then(function (users) {
response.success(users);
}, function (error) {
response.error(error);
});
});
Problem
I am not the best with Javascript, and because of that I need some help getting my head around what is happening/what I'm supposed to do.
Questions
1) When do I call "registerActivity" and "getOnlineUsers" inside my Xcode project?
2) Is "response.success(users)" just an array of PFUser Objects?
3) If "2)" is true, then how do I set the bool key "isOnline" for all of the users in the "response.success(users)" to YES if they are in the array?
You would call these functions when you want to get the online users. The code for calling these would be:
[PFCloud callFunctionInBackground:#"registerActivity" withParameters:#{#"user": Put objectId for user here}
block:^(NSString *response, NSError *error) {
if (!error) {
}
}];
[PFCloud callFunctionInBackground:#"getOnlineUsers" withParameters:#{}
block:^(NSArray *users, NSError *error) {
if (!error)
{
} }];
Yes, I believe it would just be an array of PFUser objects, I would run this just to make sure, though.
Once you get the response from "getOnlineUsers" you should probably send it back up to another cloud code function that uses the master key (Parse.Cloud.useMasterKey();) to access/change user objects, and change the "isOnline" field to YES.

Categories