├── .gitignore ├── LICENSE ├── README.md ├── package.json └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | private-key.pem 3 | certificate.pem 4 | webhook.key 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Parse, LLC. All rights reserved. 2 | 3 | You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | copy, modify, and distribute this software in source code or binary form for use 5 | in connection with the web services and APIs provided by Parse. 6 | 7 | As with any software that integrates with the Parse platform, your use of 8 | this software is subject to the Parse Terms of Service 9 | [https://www.parse.com/about/terms]. This copyright notice shall be 10 | included in all copies or substantial portions of the software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CloudCodeWebhooks-Express 2 | 3 | An ExpressJS based Parse Cloud Code Webhooks server. 4 | 5 | For deployment on Heroku, switch to the Heroku branch. 6 | 7 | ### Getting Started 8 | 9 | Using npm, install the required modules: 10 | 11 | ``` 12 | npm install 13 | ``` 14 | 15 | Cloud Code Webhooks requires an HTTPS connection, and so a valid SSL certificate is required. Self-signed certificates are not accepted. 16 | 17 | Update the locations at the top of `server.js` to point to your certificate and private key files, or place the files in this folder named `private-key.pem` and `certificate.pem`. These files will be ignored by git. 18 | 19 | Create a file named `webhook.key` and in it place the secret key from the Parse.com settings for your app. 20 | 21 | ``` 22 | echo "YourWebhookKeyHere" >> webhook.key 23 | ``` 24 | 25 | Create routes in `server.js` for your different cloud code triggers and cloud functions. Examples are provided. 26 | 27 | Start the server to listen for connections: 28 | 29 | ``` 30 | node server.js 31 | ``` 32 | 33 | It's common to use a daemon like [forever](https://github.com/foreverjs/forever) to keep your script running in the background and for it to restart if it happens to crash. You can install forever and start the daemon like so: 34 | 35 | ``` 36 | npm install forever -g 37 | forever start server.js 38 | ``` 39 | 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Parse-Open-Cloud-Code-Example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node server.js" 7 | }, 8 | "dependencies": { 9 | "body-parser": "^1.12.2", 10 | "express": "^4.12.3", 11 | "parse": "~1.3.5" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | // Parse Cloud Code Webhooks example for Express JS 2 | 3 | // Require Node Modules 4 | var https = require('https'), 5 | fs = require('fs'), 6 | express = require('express'), 7 | bodyParser = require('body-parser'), 8 | Parse = require('parse').Parse; 9 | 10 | // Load SSL Certificate details, and the apps Webhook key 11 | var privateKey = fs.readFileSync('private-key.pem'), 12 | certificate = fs.readFileSync('certificate.pem'), 13 | webhookKey = fs.readFileSync('webhook.key').toString().trim(); 14 | 15 | var serverOptions = { 16 | key: privateKey, 17 | cert: certificate 18 | }; 19 | 20 | // Express middleware to enforce security using the Webhook Key 21 | function validateWebhookRequest(req, res, next) { 22 | if (req.get('X-Parse-Webhook-Key') !== webhookKey) return errorResponse(res, 'Unauthorized Request.'); 23 | next(); 24 | } 25 | 26 | // Parse middleware to inflate a beforeSave object to a Parse.Object 27 | function inflateParseObject(req, res, next) { 28 | var object = req.body.object; 29 | var className = object.className; 30 | var parseObject = new Parse.Object(className); 31 | parseObject._finishFetch(object); 32 | req.body.object = parseObject; 33 | next(); 34 | } 35 | 36 | function successResponse(res, data) { 37 | data = data || true; 38 | res.status(200).send({ "success" : data }); 39 | } 40 | 41 | function errorResponse(res, message) { 42 | message = message || true; 43 | res.status(500).send({ "error" : message }); 44 | } 45 | 46 | var app = express(); 47 | var jsonParser = bodyParser.json(); 48 | 49 | app.use(validateWebhookRequest); 50 | app.use(jsonParser); 51 | 52 | /* 53 | * Define routes here 54 | */ 55 | 56 | app.post('/success', inflateParseObject, function(req, res) { 57 | var requestData = req.body; 58 | requestData.object.set('extra', 'fizzbuzz'); 59 | successResponse(res, requestData.object); 60 | }); 61 | 62 | app.post('/error', function(req, res) { 63 | errorResponse(res, "No thanks."); 64 | }); 65 | 66 | app.post('/hello', function(req, res) { 67 | successResponse(res, "Hello!"); 68 | }); 69 | 70 | app.post('/addNumbers', function(req, res) { 71 | var params = req.body.params; 72 | successResponse(res, params.a + params.b); 73 | }); 74 | 75 | app.use(function(err, req, res, next) { 76 | res.status(err.status || 500); 77 | res.end('{"error":"Request Failed."}'); 78 | }); 79 | 80 | /* 81 | * Launch the HTTPS server 82 | */ 83 | 84 | var server = https.createServer(serverOptions, app); 85 | server.listen(443, function() { 86 | console.log('Cloud Code Webhooks server running on port 443.'); 87 | }); 88 | 89 | --------------------------------------------------------------------------------