Technical Articles
Create CDC Extension in Node.JS
Here we get into the details of creating an extension endpoint in CDC (a.k.a Gigya) and its deployment in cloud foundry.
The challenge faced by CDC developer is to understand the behavior of CDC extension that is hosted elsewhere, the blog is an attempt to explain the intricacies of creating such an extension using Node.js , this will help in testing an extension events.
Review a step-by-step guide below to create extension using Node.js and test this using postman followed by steps to deploy this on a cloud foundry.
- Getting the right plugins:
VS Code - Create a project: From your visual studio editor, choose Terminal->New Terminal
and create folder ‘Register’(parent folder) and ‘myapp’ (subfolder).
$ mkdir register
$ cd register
$ mkdir myapp
$ cd myapp - Initialize the App: Navigate to the subfolder myapp
$ npm init
Press enter for every question that is being asked in your CLI, this will create a package.json file - Install downloads a package and it’s dependencies.
$ npm install express –save
$ npm install memory-cache –save
$ npm install jws
$ npm install jws-jwk
$ npm install gigya - Create server.js and app.js in sub folder (myapp)
server.js : Define the file to call, when running npm start and to start the server at a given port.// require http modules first const http = require('http'); //import app.js file const app = require('./app'); app.get('/', (req, res, next) => { res.status(200).send('You have called the root directory'); }); //define port to be used const port = process.env.PORT || 3100; const server = http.createServer(app); server.listen(port, () => { // let's print a message when the server run successfully console.log("Server restarted successfully") });
app.js : Define the routes which should handle request( GET, POST)
Initialize code below with your API Key, data center, user key and Secret key
// ********************** // AUXILIAR FUNCTIONS // ********************** const express = require('express'); const cache = require('memory-cache'); const jws = require('jws'); const jws_jwk = require('jws-jwk'); const Gigya = require('gigya').Gigya // Initialize SDK with your API Key , data center, user key and Secret. const gigya = new Gigya('<API_Key>', '<data_center>', '<user_key>' , '<Secret_key>'); const app = express(); const router = express.Router(); // import body-parser app.use(express.json()); // to support JSON-encoded bodies app.use(express.urlencoded({ // to support URL-encoded bodies extended: true })); // Routes which should handle request app.get('/register', (req, res, next) => { res.json(["Array1","Array2","Array3"]); }); app.post('/register', async (req, res) => { var token = req.body.jws; var decoded = jws.decode(token); var jwk = cache.get('jwk'); //verify token var body = JSON.parse(decoded.payload); var ret = { status: 'OK' }; if (body.extensionPoint === 'OnBeforeAccountsRegister' && !body.data.params.email.endsWith('@xyz.com')) { ret.status = 'FAIL'; var customMessage = 'Email should belong to domain "xyz.com" '; ret.data = { validationErrors: [ { fieldName: 'profile.email', message: customMessage }, ] } } res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify(ret)); }); // Global error handler - route handlers/middlewares which throw end up here app.use((err, req, res, next) => { res.status(err.status || 500); res.end(); }); //export app module.exports = app;
- Start the Server: within myapp folder
- Convert to JWS format
the payload include the email id: test1@abc.com which doesn’t end with “xyz” and the extension event is OnBeforeAccountsRegister, the expectation here is status ‘FAIL’ with validation error ‘
Email should belong to domain \”xyz.com\” ‘
"apiKey": "3_ve...tyu",
"callID": "809.....169f",
"extensionPoint": "OnBeforeAccountsRegister",
"data": {
"params": {
"email": "test1@abc.com",
"password": "what ever password the user entered",
"profile": {
"firstName": "test"
},
"data": {
"terms": true
}
},
"context": {
"clientIP": "1.0.0.0"
}
}
}
{
"jws": "eyJhbGciOiJIUzI1NiIsImtpZCI6IlJEQXpSRVl5TmpCRk5USTVSak5ETURrd1JEUkJNMEZDUkRRM1FqQkNSRUpDUmpZNE9ESkZRUSJ9.eyJhcGlLZXkiOiIzX3ZlLi4udHl1IiwiY2FsbElEIjoiODA5Li4uLi4xNjlmIiwiZXh0ZW5zaW9uUG9pbnQiOiJPbkJlZm9yZUFjY291bnRzUmVnaXN0ZXIiLCJkYXRhIjp7InBhcmFtcyI6eyJlbWFpbCI6InRlc3QxQGFiYy5jb20iLCJwYXNzd29yZCI6IndoYXQgZXZlciBwYXNzd29yZCB0aGUgdXNlciBlbnRlcmVkIiwicHJvZmlsZSI6eyJmaXJzdE5hbWUiOiJ0ZXN0In0sImRhdGEiOnsidGVybXMiOnRydWV9fSwiY29udGV4dCI6eyJjbGllbnRJUCI6IjEuMC4wLjAifX19.3tzVu5n3NvXPDIDQaVpJ5UYEA8zs8KpsxAnacovkMac"
}
- Test Using Postman( try the desktop agent, not on the browser)
URL: http://localhost:3100/register
Body: the JWS format encoded in step above
Type: JSON
Response
- Deploy in cloud foundry.1. As a next step we will deploy Node.js App to SCP Cloud Foundry for this we need to create yml in the folder register.
Manifest Folder
Manifest.yml
2. Upload the Manifest file in cloud foundry.
Run the Powershell/msdos in administrator mode and navigate to folder that contain manifest.yml file
cf api api-end-point( example https://api.cf.eu10.hana.ondemand.com )
A. cf api https://api.cf.us10.hana.ondemand.com/ for example
C. cf push
D . Make Note of the URL as this will be used in extension in CDC. You can find this URL within the service that is created in cloud foundry.
- Configure CDC extension with new endpoint and activate it.
Mention the folder name at the end of the Cloud foundry endpoint URL ,here in this example its register.https://myapp-unexpected-camel-ze.cfapps.us10.hana.ondemand.com/register ( you can also test the URL in postman)Its is better to Increase the default timeout to 6000ms as it may take some time to receive response from the Server.
-
With the response received from the server, fail the registration and registration response returned to the client.