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 validation here is for the event OnBeforeAccountsRegister when email id ends with domain other than ‘xyz.com’, it throws an error ‘Email should belong to domain “xyz.com’

      Sample payload for OnBeforeAccountsRegister is available at the link below

      https://help.sap.com/viewer/8b8d6fffe113457094a17701f63e3d6a/GIGYA/en-US/4153ec2f70b21014bbc5a10ce40…
      This is in “json” format which needs to be converted into “jws” format, online tool like jwt.io can help with conversion( here you can edit the decoded information one at a time as per our requirement and this in turn encoded the format in jws ), finally we need this( jws) to test in postman.

      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)

 

The final step is to test using postman and check for the response in case the email ends with             domain other than xyz.com.

 

          URL: http://localhost:3100/register
          Body: the JWS format encoded in step above
          Type:  JSON

 

 

Response

 

{
    “status”: “FAIL”,
    “data”: {
        “validationErrors”: [
            {
                “fieldName”: “profile.email”,
                “message”: “Email should belong to domain “xyz.com” “
            }
        ]
    }
}

 

    • 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

 

 

B. cf login and if you have multiple org, choose the org where you shall upload this.

 

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.

    • Test the extension by registering an account with email ending with domain other than ‘xyz.com’ .

      With the response received from the server, fail the registration and registration response returned to the client.

 

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x