I am facing an issue in parse cloud code. The following is updating score and change date in my gamescore table. But it is not working. while I am doing same in my web code and it is working fine. Am I doing anything wrong here ?
'use strict';
var GameScore = Parse.Object.extend('GameScore');
Parse.Cloud.define('editScore', function(req, res) {
var query = new Parse.Query(GameScore);
query.get(req.params.objectId, {
success: function(gameScore) {
gameScore.set('score', req.params.score);
gameScore.set('date', req.params.date);
gameScore.save(null);
gameScore.fetch(myCallback);
},
error: function(err) {
return res.error(err);
}
});
});
If so then please help me so that I can make it working.
Try adding Parse.Cloud.useMasterKey(); inside the function to bypass any ACL restrictions that could be causing an issue. Example:
var GameScore = Parse.Object.extend('GameScore');
Parse.Cloud.define('editScore', function(req, res) {
// use Master Key to bypass ACL
Parse.Cloud.useMasterKey();
var query = new Parse.Query(GameScore);
query.get(req.params.objectId, {
success: function(gameScore) {
gameScore.set('score', req.params.score);
gameScore.set('date', req.params.date);
gameScore.save(null);
gameScore.fetch(myCallback);
},
error: function(err) {
return res.error(err);
}
});
});
You have 3 issues:
you're not waiting for the save to finish
you're not calling res.success()
you're referencing myCallback which from what you've shown us isn't defined
Simple solution is to replace this line:
gameScore.save(null);
With this code:
gameScore.save().then(function () {
res.success();
});
If you really do need that fetch call you would chain that in:
gameScore.save().then(function () {
return gameScore.fetch(myCallback);
}).then(function () {
res.success();
});
var GameScore = Parse.Object.extend('GameScore');
Parse.Cloud.define('editScore', function(req, res) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query(GameScore);
query.get(req.params.objectId, {
success: function(gameScore) {
gameScore.set('score', req.params.score);
gameScore.set('date', req.params.date);
gameScore.save().then(function() {
gameScore.fetch(callback);
});
},
error: function(err) {
return res.error(err);
}
});
});
using master key we are overriding acl. using then promise method we are calling callback functions after otherwise there is a possibility to get the old data.
Related
I am calling 2 API request 1 after another so I decided to use the waterfall model but I am facing the issue in it
I have tried so much but not able to solve the issue.
Below is my code:
var unirest = require("unirest");
var async = require("async")
exports.user = (req, res, next) => {
const qry = req.params.id
async.waterfall([
(nextCall) => {
var req = unirest("GET", API_URL1);
req.query({
// some query
});
req.headers({
// some headers
});
req.end(function(subCount) {
// if (resp.error) throw new Error(resp.error);
var channelSubCount = subCount.body
nextCall(null, data)
});
},
(data, nextCall => {
console.log(channelSubCount, 'data')
var reqs = unirest("GET", API_URL2);
reqs.query({
// some query
});
reqs.headers({
// some headers
});
reqs.end(function(res) {
// if (res.error) throw new Error(res.error);
console.log(res.body);
return nextCall(null, {
name: 'abc',
photo: 'src',
count: data
})
});
})
], function(finalData) {
// if (error) { alert('Something is wrong!'); }
console.log('final')
res.status(200).json(
finalData
);
});
};
ERROR:
Reference Error: data is not defined
I don't understand why this is happening.
Also some please show me the right way to implement the above things with optimizations.
Any help appreciated...
Looks like you forgot to close parentheses here in your second arrow function definition:
(data, nextCall => {
It's still a valid JavaScript, but the interpreter now treats data not as a function incoming parameter (as you need), but as a variable. But it's not defined anywhere, therefore you have that error.
Make it like this and it will work:
(data, nextCall) => {
I've set up a node.js server-app that I want to do some parse.com requests.
I basically want it to return the parse-object JSON-representation.
My route:
var blog = require('./models/model');
app.get('/api/article/:permalink', function(req, res) {
res.json(blog.getArticle(req.params.permalink));
});
And my model:
var Parse = require('parse/node').Parse, // load the parse for node package
keys = require('../../config/keys'); // keys config-file for hosted services
Parse.initialize(keys.app, keys.js);
module.exports = {
getArticle: function(permalink) {
"use strict";
var Article = Parse.Object.extend('Article');
var query = new Parse.Query(Article);
query.include('category');
query.include('profile');
query.equalTo('permalink', permalink);
query.find().then(function(results) {
return results;
}, function(error) {
return error;
});
}
};
The thing is, this returns nothing when I call an article with a permalink that I know to exist (example: http://localhost/api/article/testFoo). I don't get any errors either.
My browser console flashes a message for a split second that reads:
Resource interpreted as Document but transferred with MIME type application/json: "http://localhost/api/article/testFoo"
Any suggestions to what I am doing wrong?
You are trying to use the return value of an async function. This can't work, you need to pass a callback (or the res object) to your getArticle function, which will then use it to send the data back.
With a callback:
app.get('/api/article/:permalink', function(req, res) {
blog.getArticle(req.params.permalink, function(data) {res.json(data)});
});
...
getArticle: function(permalink,callback) {
...
query.find().then(function(results) {
callback(results);
}, function(error) {
callback({error: error});
});
Any ideas why this isn't working? It comes back with the success message but doesn't actually update anything.
I'm adding an FB user using Parse but since it doesn't have a func to add the username and email trying to do it this way. Any help much appreciated.
JS
Parse.Cloud.run("test", { objectId: "Q8XRUcL22N", name: "Rich", email: "rich#gmail.com"}, {
success: function(results) {
console.log(results);
},
error: function(error) {
console.log(error);
}
});
CLOUD CODE:
Parse.Cloud.define("test", function (request, response) {
Parse.Cloud.useMasterKey();
var uid;
var query = new Parse.Query("_User");
query.count({
success: function (results) {
uid = parseInt(results);
},
error: function () {
response.error("UID lookup failed");
}
});
var query = new Parse.Query(Parse.User);
query.equalTo("objectId", request.params.objectId);
query.first({
success: function (object) {
object.set("username", request.params.name);
object.set("email", request.params.email);
object.set("uid", uid);
var acl = new Parse.ACL();
acl.setPublicWriteAccess(false);
acl.setPublicReadAccess(false);
object.setACL(acl);
object.save();
response.success("Success Message");
},
error: function (error) {
response.error("Error Message");
}
});
});
Thanks
Calling success() or error() on the response halts whatever is underway at the time, including the save() on the user.
Also, it looks like you want to record in the user a count of users at the time the ACL is set. Getting the count must also be serialized with the other operations. (Also, please note that count is only good as an id "uid" to the extent the user count never goes down. What's wrong with the parse objects's id as an id?).
Most of the parse functions return promises, and using them is the only way to not go nuts trying to nest callbacks. So...
Parse.Cloud.define("test", function(request, response) {
Parse.Cloud.useMasterKey();
var uid;
var query = new Parse.Query(Parse.User);
query.count().then(function(count) {
uid = count;
return query.get(request.params.objectId);
}).then(function(object) {
object.set("username", request.params.name);
object.set("email", request.params.email);
object.set("uid", uid);
var acl = new Parse.ACL();
acl.setPublicWriteAccess(false);
acl.setPublicReadAccess(false);
object.setACL(acl);
return object.save();
}).then(function (object) {
response.success(object);
},function(error) {
response.error("Error Message");
});
});
I've configured a FB graph call that would retrieve data from the API, however I'm having trouble inserting it into MongoDb. Right now if I run Photos.find().count(); in the browser it shows that there are photos, however if I run db.Photos.find().count(); in MongoDb it shows nothing. Also, if I run db.users.find(); in MongoDb it returns results from the FB user account, so MongoDb is talking to the API to some extent.
Any thoughts on what might be causing the issue?
Here is my code:
Client:
Template.test.events({
'click #btn-user-data': function(e) {
Meteor.call('getUserData', function(err, data) {
if(err) console.error(err);
});
}
});
Template.facebookphoto.helpers({
pictures: function () {
return Photos.find();
}
});
Server:
function Facebook(accessToken) {
this.fb = Meteor.require('fbgraph');
this.accessToken = accessToken;
this.fb.setAccessToken(this.accessToken);
this.options = {
timeout: 3000,
pool: {maxSockets: Infinity},
headers: {connection: "keep-alive"}
}
this.fb.setOptions(this.options);
}
Facebook.prototype.query = function(query, method) {
var self = this;
var method = (typeof method === 'undefined') ? 'get' : method;
var data = Meteor.sync(function(done) {
self.fb[method](query, function(err, res) {
done(null, res);
});
});
return data.result;
}
Facebook.prototype.getUserData = function() {
return this.query('me/photos');
}
Meteor.methods({
getUserData: function() {
var fb = new Facebook(Meteor.user().services.facebook.accessToken);
var data = fb.getUserData();
_.forEach(data.data, function(photo) {
if(Photos.findOne({id: photo.id})) return;
Photos.insert(photo, function(err) {
if(err) console.error(err);
});
});
}
});
Collection:
Photos = new Meteor.Collection('picture');
Thanks in advance!
Instead of db.Photos.find().count();, try db.picture.find().count();
Photos is just the name you gave to the JavaScript variable. The actual name of the collection in MongoDB is whatever you use when you initialized the Collection - in this case, picture.
I have an Angular service that takes in a roleId and userId and assigns the user to that role and make a pointer in User to that role.
app.service('CRUD', function () {
this.addUserToRole = function (roleId, userId) {
// first we have to find the role we're adding to
var query = new Parse.Query(Parse.Role);
return query.get(roleId, {
success: function (role) {
// then add the user to it
var Database = Parse.Object.extend("User");
var query = new Parse.Query(Database);
console.log(role);
return query.get(userId, {
success: function (user) {
console.log(user);
role.getUsers().add(user);
role.save();
// now we need to tell the user that he has this role
console.log(user);
user.attributes.role.add(role);
user.save();
return user;
},
error: function (err) {
return err;
}
});
},
error: function (err) {
console.log(err);
}
});
}
});
I'm getting {"code":206,"error":"Parse::UserCannotBeAlteredWithoutSessionError"} on user.save();
After some research, I arrived at this website. He uses this code snippet as a JS SDK example:
Parse.Cloud.run('modifyUser', { username: 'userA' }, {
success: function(status) {
// the user was updated successfully
},
error: function(error) {
// error
}
});
and mentions something about a useMasterKey() function.
I'm still unsure how to fix this error.
Add
Parse.Cloud.useMasterKey();
at the beginning of your function.
Set it up as a background job. That is the code snip you found I think and a simpler far more secure means of fondling users and roles
https://parse.com/docs/cloud_code_guide#jobs