Parse to Heroku migration: Parse-server cloud code doesn't work - ios

I succeeded to migrate my app from Parse to Heroku, now my AppDelegate use this code:
[Parse initializeWithConfiguration:[ParseClientConfiguration configurationWithBlock:^(id<ParseMutableClientConfiguration> configuration) {
configuration.applicationId = #"xxxxxxxx";
configuration.clientKey = #"xxxxxxxx";
configuration.server = #"http://xxxxxxxx.herokuapp.com/parse";
}]];
and not
// [Parse setApplicationId:#"xxxxxxxx"
// clientKey:#"xxxxxxxx"];
// [PFUser enableRevocableSessionInBackground];
Everything works except the cloud code, when I run a cloud code, this is the error from Simulator: [Error]: Invalid function. (Code: 141, Version: 1.12.0)
Here is my cloud file path: /Users/Viny/heroku/parse-server-example/cloud/main.js
I updated and push it with the same main.js from Parse.
Here is my index.js:
// Example express application adding the parse-server module to expose Parse
// compatible API routes.
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var databaseUri = process.env.DATABASE_URI || process.env.MONGOLAB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: process.env.DATABASE_URI || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: 'xxxxxxx',
masterKey: 'xxxxxxx',
fileKey: 'xxxxxxx',
clientKey: 'xxxxxxx',
serverURL: 'http://localhost:1337/parse'
});
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
// If you wish you require them, you can set them as options in the initialization above:
// javascriptKey, restAPIKey, dotNetKey, clientKey
var app = express();
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('I dream of being a web site.');
});
var port = process.env.PORT || 1337;
app.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
Cloud code works as expected with Parse, but doesn't work with Heroku...

Instead of this
configuration.server = #"http://xxxxxxxx.herokuapp.com/parse";
Do this
configuration.server = #"http://xxxxxxxx.herokuapp.com/parse/";

Well, I think I've found the problem, I've two "personal apps" on Heroku for my iOS app: "chilln" (my iOS app name) and "rocky-reef-28464" (automatically created by following this tuto: https://learnappmaking.com/how-to-migrate-parse-app-parse-server-heroku-mongolab/)
I changed my configuration.server to : http://rocky-reef-28464.herokuapp.com/parse/
and now it seems to recognize the cloud code, just this error on simulator: [Error]: <null> (Code: 141, Version: 1.12.0)
Here is a screen of my personal apps on Heroku:
Should I have only one personal apps ?
chilln has the add-ons MongoLab and cfg var: "app_id", "master_key", "mongolab_url", "parse_mount". rocky-reef-28464 hasn't add-ons MongoLab but has only one cfg var: "DATABASE_URI", and has the git heroku repo (I think)
What I've to do ? Merge the two app to one ?

Related

504 timeout when querying Firebase Realtime Database in Next JS / Vercel

I'm facing a 504 error (timeout) when making a request to a Firebase Realtime database
import admin from "firebase-admin";
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert({
project_id: process.env.FIREBASE_PROJECT_ID,
private_key: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
client_email: process.env.FIREBASE_CLIENT_EMAIL,
}),
databaseURL: process.env.FIREBASE_DATABASE,
});
}
const db = admin.database();
export default async (req, res) => {
if (req.method === "GET") {
try {
const snapshot = await db
.ref("properties")
.child(req.query.slug)
.once("value");
const properties = snapshot.val();
return res.status(200).json({ total: properties });
} catch(e) {
console.error(e);
}
}
};
The issue happens here
const snapshot = await db
.ref("properties")
.child(req.query.slug)
.once("value");
I think the vercel app domain (i.e. the staging domain) needs to be added in GCP as an autorised domain, but I can't seem to find out where.
The request works locally (on localhost:3000) so I assume localhost is allowed in GCP.
Any ideas on how to let a Next JS app on Vercel talk to a Firebase Realtime database without a 504 timeout?
Ended up using the Firebase REST api to query firebase realtime database

Error when setting up password reset with Parse Server

I am using Parse Server hosted on Heroku with mongoDB. I am struggling to get the password reset function working. I have followed the instructions and added the below code to index.js. Once this code is added, when the app launches or I try to send an email I get this error: JSON text did not start with array or object and option to allow fragments not set.
I know that this means the server cannot parse the data back but I'm totally unsure how to fix this. Any help is much appreciated!
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
var databaseUri = process.env.DATABASE_URI || process.env.MONGODB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: databaseUri || 'MY_DATABASE_URI',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'MY_APP_ID',
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret!
serverURL: process.env.SERVER_URL || 'MY_SERVER_URL', // Don't forget to change to https if needed
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query subscriptions
}
verifyUserEmails: true,
//The public URL of your app.
//This will appear in the link that is used to verify email addresses and reset passwords.
//Set the mount path as it is in serverURL
publicServerURL: 'MY_SERVER_URL_FROM_HEROKU',
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'MY_APP_NAME',
// The email adapter
emailAdapter: {
module: 'parse-server-simple-mailgun-adapter',
options: {
// The address that your emails come from
fromAddress: 'MY_MAILGUN_DOMAIN',
// Your domain from mailgun.com
domain: 'MY_MAILGUN_DOMAIN',
// Your API key from mailgun.com
apiKey: 'MY_API_KEY_FROM_MAILGUN',
}
}
});
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
// If you wish you require them, you can set them as options in the initialization above:
// javascriptKey, restAPIKey, dotNetKey, clientKey
var app = express();
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('I dream of being a website. Please star the parse-server repo on GitHub!');
});
// There will be a test page available on the /test path of your server url
// Remove this before launching your app
app.get('/test', function(req, res) {
res.sendFile(path.join(__dirname, '/public/test.html'));
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
You're missing a comma after livequery:{...}, before setting verifyUserEmails. Little harder to tell since the block you added for e-mails isn't properly indented.

Parse-Server LiveQuery not sending events

I am trying to get live queries working with iOS and Parse-Server. The following is my setup for my Parse-Server:
...
let api = new ParseServer({
databaseURI: databaseUri || constants.DATABASE_URI,
cloud: process.env.CLOUD_CODE_MAIN || constants.CLOUD_CODE_MAIN,
appId: process.env.APP_ID || constants.APP_ID,
masterKey: process.env.MASTER_KEY || constants.MASTER_KEY,
serverURL: process.env.SERVER_URL || constants.LOCAL_SERVER_URL,
fileKey: process.env.FILE_KEY || constants.FILE_KEY,
appName: process.env.APP_NAME || constants.APP_NAME,
publicServerURL: process.env.SERVER_URL || constants.LOCAL_SERVER_URL,
liveQuery: {
classNames: [Parse.User]
}
});
...
let port = process.env.PORT || 1337;
let httpServer = require('http').createServer(app);
httpServer.listen(port, function () {
console.log('parse_server running on port ' + port + '.');
});
ParseServer.createLiveQueryServer(httpServer, {logLevel: 'VERBOSE'});
...
And this is my code in the iOS app:
let liveQueryClient = ParseLiveQuery.Client(server: "ws://serverurl/", applicationId: "appID", clientKey: "clientKey")
let query = PFUser.query()?.whereKey("objectId", equalTo: "ABC123") as! PFQuery<PFUser>
let subscription = self.liveQueryClient.subscribe(query).handle(Event.updated) { _, user in
debugprint("\(user)")
}
Debugging on local, I can see the user is connecting using the socket because the server logs:
info: Create new client: 0
and when I disconnect, the server logs:
info: Client disconnect: 0
My problem is that whenever I modify the User object in Parse Dashboard, nothings logs on the server side, and the client doesn't receive any events.
Is there another way to set this up?
Can the User class not be used in live queries?
I am not sure about IOS code however this part e.g:
liveQuery: {
classNames: ["YourColumnNameInDatabase","AnotherColumnName"]
}
Make sure to check that you are subscribing to the correct ClassName(ColumnName in Db)
Hope this helps a little...

Can the environmental keys that Parse Server is Using be verified inside the client app?

I was wondering if/how can the Parse-Server environmental variables be verified inside a client IOS App.
For those of us that are yet uncomfortable with backend systems, it would be useful to be able to validate via the client side during testing that the backend Parse-Server is actually using the correct Environmental Keys.
If you are testing the keys to setup parse-server such as appId, clientKey, masterKey, you can implement a verify cloud code.
Once you use appId (or you have set clientKey), you can call this function. Otherwise, you will get errors. You cannot use MasterKey in client-sdk. If you still want to test it, you can implement a rest api with masterKey on your client. But masterKey should not appear in client side, you should avoid user trigger this, or someone may get your masterKey.
Parse.Cloud.define("verify", function(request, response) {
if(request.master==true){
response.success(true);
}else{
response.error(new Error('MasterKey not matched'));
}
});
Edited
By implement a globalConfig obj, verify it as you wish.
Here is a sample.
globalConfig.js
var globalConfig = {};
globalConfig.verify = function(key) {
return globalConfig.keys.testKey==key;
}
module.exports = globalConfig;
index.js (partial)
var globalConfig = require('./globalConfig.js');
var initObj = {
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'myAppId',
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret!
serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse', // Don't forget to change to https if needed
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query subscriptions
},
testKey: "this is test"
}
var api = new ParseServer(initObj);
globalConfig.keys = initObj;
and then you can use globalConfig.verify() to check your keys
a cloud code example
var globalConfig = require('../globalConfig.js');
Parse.Cloud.define('verify', function(req, res) {
res.success(globalConfig.verify(req.params.testKey));
});
or you can use express post
app.post('/test', function(req, res) {
//verify and response
})

Parse.Cloud.afterSave for sending push notifications not working from Heroku server

I did the migration, from Parse to Heroku and everything went smooth. At this point I didn't have any cloud code or push notifications set up on Parse. When I was done with the migration I begin to implement cloud code to handle push notification every time I save a new text message, but the Parse.Cloud.afterSave method is not running. I know main.js is working because if I implement
Parse.Cloud.define('hello', function(req, res) {
res.success('Hi');
});
I get "Hi" return to my console in Xcode, but for some reason Parse.Cloud.afterSave does nothing. I also know my Parse.Cloud.afterSave code is correct because it's that same code I use on another app through parse though. What am I missing?
Here in my index.js file
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
var databaseUri = process.env.DATABASE_URI || process.env.MONGOLAB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: databaseUri || '',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || '',
masterKey: process.env.MASTER_KEY || '',
fileKey: 'XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', // file key from parse
serverURL: process.env.SERVER_URL || '',
push: {
ios: {
pfx: '/Users/alexcruz/Desktop/Certificates.p12', // The filename of private key and certificate in PFX or PKCS12 format from disk
bundleId: 'com.daps.DapsPush', // The bundle identifier associate with your app
production: false // Specifies which environment to connect to: Production (if true) or Sandbox
}
}
});
var app = express();
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('Make sure to star the parse-server repo on GitHub!');
});
// There will be a test page available on the /test path of your server url
// Remove this before launching your app
app.get('/test', function(req, res) {
res.sendFile(path.join(__dirname, '/public/test.html'));
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
Here is my main.js file
//Push Notification for messages that are received
Parse.Cloud.afterSave("MXTMessage", function(request) {
var messageText = request.object.get('message');
var usersReceived = request.object.get('receiver');
var currentUser = Parse.User.current();
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo('user', usersReceived);
pushQuery.notEqualTo('user', currentUser);
Parse.Push.send({
where: pushQuery, // Set our Installation query
data: {
alert: "New message: " + messageText
}
}, {
success: function() {
// Push was successful
},
error: function(error) {
throw "Got an error " + error.code + " : " + error.message;
}
});
});
Thank you
As I am not allowed to comment, I'm going to have to put this in an answer, but just treat it as a comment:
Did you verify the function itself is actually never being called e.g. by adding a console.log at the beginning of the function, or could it be that push itself is not working (you can check that by sending pushes via REST API Calls)? For example, push seems to be broken in parse-server 2.2.0, I had to downgrade to 1.6.0 to get it working.
Workaround could be to create a cloud code function for sending the push and have this function explicitly called by the clients after the message has been saved on the server.
Also you should check this: https://github.com/ParsePlatform/parse-server/issues/301 as you are using Parse.User.current() in your code.
Also, I get the impression that parse-server is not really stable at this time. I experience many bugs using parse-server and Heroku that the app running on parse.com does not have.

Resources