<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>article Qlik Sense Repository API/Engine API(Enigma.js) example with JWT authentication: duplicate/scramble/export in Official Support Articles</title>
    <link>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/ta-p/1717897</link>
    <description>&lt;P&gt;This article is provided as a sample on how to use the Repository API/Engine API (Enigma.js) with JWT authentication.&lt;/P&gt;
&lt;P&gt;Workflow of the sample:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Authenticate with JWT on the first call (Duplicate app) and retrieve session id&lt;/LI&gt;
&lt;LI&gt;Run Engine API call (Loop scramble data for each field in the app)&lt;/LI&gt;
&lt;LI&gt;Reuse the same session in the consequent API calls to scramble and export the app, then write it to disk.&lt;/LI&gt;
&lt;/OL&gt;
&lt;H3&gt;&lt;FONT color="#339966"&gt;&lt;STRONG&gt;Requirements&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/H3&gt;
&lt;OL&gt;
&lt;LI&gt;A virtual proxy using JWT authentication with prefix "jwt" and cookie name "X-Qlik-Session-jwt" must be set up, the JWT token must be generated and placed in the variable jwttoken&lt;/LI&gt;
&lt;LI&gt;Node.js must be installed (This example was built and tested in version&amp;nbsp;v10.16.0, there might be slight differences depending on the version)&lt;/LI&gt;
&lt;/OL&gt;
&lt;BLOCKQUOTE class="quote"&gt;This customization is provided as is. Qlik Support cannot provide continued support of the solution. For assistance, reach out to our &lt;A href="https://community.qlik.com/t5/Official-Support-Articles/How-and-when-to-contact-Qlik-s-Professional-Services-and/ta-p/1714936" target="_blank" rel="noopener"&gt;Professional Services&lt;/A&gt; or engage in our active &lt;A href="https://community.qlik.com/t5/Integration-Extension-APIs/bd-p/qlik-sense-integration-extension-api" target="_blank" rel="noopener"&gt;Integrations forum&lt;/A&gt;.&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;FONT color="#339966"&gt;&lt;STRONG&gt;Usage&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;Copy the following script in a file called "scramble-jwt.js"&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;const WebSocket = require('ws');
const enigma = require('enigma.js');
const schema = require('enigma.js/schemas/12.170.2.json');
const fs = require('fs');
const rp = require('request-promise');

var servername = 'localhost';
var jwttoken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJBZG1pbmlzdHJhdG9yIiwiZG9taWQiOiJET01BSU4iLCJhZG1pbiI6dHJ1ZX0.ruQ6wbgqNsfhtnO-6g7qTxGFiq71XAtHuUZlDoZ9LjAASQUmOMksffMgoMxXxc1irCHTGcfaHYkrdghoy61JznKH31Q5AKuIpKYaD5Z6GeJJMYbw5VZO5rpT-1zznaMBUzWFMTHO7oUU_4fNc9XGxiEn-Y7hwAe2zc3vwEjBxbuY8PMZu71xGel4Vr7jHpFLWQNtJyfHQ';

var options = {
  uri: `https://${servername}/jwt/qrs/App/${process.argv[2]}/copy?xrfkey=1234567891234567`,
  headers: {'content-type': 'application/json','X-Qlik-xrfkey': '1234567891234567','Authorization': `Bearer ${jwttoken}`},
  method: 'POST',
json: true,
  rejectUnauthorized: false,
  resolveWithFullResponse: true
};
 
const qParam = {
  "qInfo": {
    "qId": "",
    "qType": "FieldList"
  },
  "qFieldListDef": {
    "qShowSystem": true,
    "qShowHidden": true,
    "qShowSemantic": true,
    "qShowSrcTables": true
  }
};
 
(async () =&amp;gt; {
  try {

	var AppNewId = await rp(options, function (error, response, body) {
        if(error) 
        {
            console.log('Error: '+error);
        } 
        else 
        {
            return response;
        }
    });
	
	const sessionid = await AppNewId.rawHeaders.toString().split('X-Qlik-Session-jwt=')[1].split(';')[0];
	await console.log(AppNewId.body.id);
	await console.log('session id:'+sessionid);
	
	
	console.log('Connecting to engine.');
    const session = enigma.create({
	schema,
	url: `wss://${servername}/jwt/app/`,
	createSocket: url =&amp;gt; new WebSocket(url, {
	rejectUnauthorized: false,
    headers: {
      'Cookie': `X-Qlik-Session-jwt=${sessionid}`,
		},
		}),
	});

    const qix = await session.open();
    var app = await qix.openDoc(AppNewId.body.id);
    const objsession = await app.createSessionObject(qParam);
             
    const fields = await objsession.getLayout();
    const results = fields.qFieldList.qItems;
 
    for (var p in results) {
        var myfield = JSON.stringify(results[p]['qName']).replace(/"/gi,'');
                            if (myfield.includes("$")==false){
                                          await app.scramble(myfield);
                            }
      }
 
    await app.doSave();
	
	var optionsexport = {
	uri: `https://${servername}/jwt/qrs/App/${AppNewId.body.id}/export/42754ecc-c143-4024-aa99-69d7e45a9025?skipData=false&amp;amp;xrfkey=1234567891234567`,
	headers: {'content-type': 'application/json','X-Qlik-xrfkey': '1234567891234567','Cookie': `X-Qlik-Session-jwt=${sessionid}`},
	method: 'POST',
	json: true,
	rejectUnauthorized: false
	};
	
	//export file
	var url = await rp(optionsexport, function (error, response, body) {
        if(error) 
        {
            console.log('Error: '+error);
        } 
        else 
        {
            return body;
        }
    });
	
	
	//download file
	var newurl = await `https://${servername}/jwt${url.downloadPath}`;
	var dest = await './scrambled_app.qvf';
	
  rp.get({
  url: newurl,
  encoding: null,
  rejectUnauthorized: false,
  headers:{'Cookie': `X-Qlik-Session-jwt=${sessionid}`}
}).then(function (res) {
	console.log(res);
	console.log(newurl);
    const buffer = Buffer.from(res, 'utf8');
	console.log(buffer);
    fs.writeFileSync(dest, buffer);
  });
 
    await session.close();
    console.log('Session closed.');
  } catch (err) {
    console.log('Whoops! An error occurred.', err);
    process.exit(1);
  }
})();&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Copy the file in a folder and type the following commands:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;npm install
node scramble-jwt.js da109a0e-4753-40c9-8c5f-aa8cbbb26e86&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In the above,&amp;nbsp;da109a0e-4753-40c9-8c5f-aa8cbbb26e86 is the guid of the app that you want to scramble.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Wed, 26 Jul 2023 08:06:40 GMT</pubDate>
    <dc:creator>Damien_V</dc:creator>
    <dc:date>2023-07-26T08:06:40Z</dc:date>
    <item>
      <title>Qlik Sense Repository API/Engine API(Enigma.js) example with JWT authentication: duplicate/scramble/export</title>
      <link>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/ta-p/1717897</link>
      <description>&lt;P&gt;This article is provided as a sample on how to use the Repository API/Engine API (Enigma.js) with JWT authentication.&lt;/P&gt;
&lt;P&gt;Workflow of the sample:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Authenticate with JWT on the first call (Duplicate app) and retrieve session id&lt;/LI&gt;
&lt;LI&gt;Run Engine API call (Loop scramble data for each field in the app)&lt;/LI&gt;
&lt;LI&gt;Reuse the same session in the consequent API calls to scramble and export the app, then write it to disk.&lt;/LI&gt;
&lt;/OL&gt;
&lt;H3&gt;&lt;FONT color="#339966"&gt;&lt;STRONG&gt;Requirements&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/H3&gt;
&lt;OL&gt;
&lt;LI&gt;A virtual proxy using JWT authentication with prefix "jwt" and cookie name "X-Qlik-Session-jwt" must be set up, the JWT token must be generated and placed in the variable jwttoken&lt;/LI&gt;
&lt;LI&gt;Node.js must be installed (This example was built and tested in version&amp;nbsp;v10.16.0, there might be slight differences depending on the version)&lt;/LI&gt;
&lt;/OL&gt;
&lt;BLOCKQUOTE class="quote"&gt;This customization is provided as is. Qlik Support cannot provide continued support of the solution. For assistance, reach out to our &lt;A href="https://community.qlik.com/t5/Official-Support-Articles/How-and-when-to-contact-Qlik-s-Professional-Services-and/ta-p/1714936" target="_blank" rel="noopener"&gt;Professional Services&lt;/A&gt; or engage in our active &lt;A href="https://community.qlik.com/t5/Integration-Extension-APIs/bd-p/qlik-sense-integration-extension-api" target="_blank" rel="noopener"&gt;Integrations forum&lt;/A&gt;.&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;FONT color="#339966"&gt;&lt;STRONG&gt;Usage&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;Copy the following script in a file called "scramble-jwt.js"&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;const WebSocket = require('ws');
const enigma = require('enigma.js');
const schema = require('enigma.js/schemas/12.170.2.json');
const fs = require('fs');
const rp = require('request-promise');

var servername = 'localhost';
var jwttoken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJBZG1pbmlzdHJhdG9yIiwiZG9taWQiOiJET01BSU4iLCJhZG1pbiI6dHJ1ZX0.ruQ6wbgqNsfhtnO-6g7qTxGFiq71XAtHuUZlDoZ9LjAASQUmOMksffMgoMxXxc1irCHTGcfaHYkrdghoy61JznKH31Q5AKuIpKYaD5Z6GeJJMYbw5VZO5rpT-1zznaMBUzWFMTHO7oUU_4fNc9XGxiEn-Y7hwAe2zc3vwEjBxbuY8PMZu71xGel4Vr7jHpFLWQNtJyfHQ';

var options = {
  uri: `https://${servername}/jwt/qrs/App/${process.argv[2]}/copy?xrfkey=1234567891234567`,
  headers: {'content-type': 'application/json','X-Qlik-xrfkey': '1234567891234567','Authorization': `Bearer ${jwttoken}`},
  method: 'POST',
json: true,
  rejectUnauthorized: false,
  resolveWithFullResponse: true
};
 
const qParam = {
  "qInfo": {
    "qId": "",
    "qType": "FieldList"
  },
  "qFieldListDef": {
    "qShowSystem": true,
    "qShowHidden": true,
    "qShowSemantic": true,
    "qShowSrcTables": true
  }
};
 
(async () =&amp;gt; {
  try {

	var AppNewId = await rp(options, function (error, response, body) {
        if(error) 
        {
            console.log('Error: '+error);
        } 
        else 
        {
            return response;
        }
    });
	
	const sessionid = await AppNewId.rawHeaders.toString().split('X-Qlik-Session-jwt=')[1].split(';')[0];
	await console.log(AppNewId.body.id);
	await console.log('session id:'+sessionid);
	
	
	console.log('Connecting to engine.');
    const session = enigma.create({
	schema,
	url: `wss://${servername}/jwt/app/`,
	createSocket: url =&amp;gt; new WebSocket(url, {
	rejectUnauthorized: false,
    headers: {
      'Cookie': `X-Qlik-Session-jwt=${sessionid}`,
		},
		}),
	});

    const qix = await session.open();
    var app = await qix.openDoc(AppNewId.body.id);
    const objsession = await app.createSessionObject(qParam);
             
    const fields = await objsession.getLayout();
    const results = fields.qFieldList.qItems;
 
    for (var p in results) {
        var myfield = JSON.stringify(results[p]['qName']).replace(/"/gi,'');
                            if (myfield.includes("$")==false){
                                          await app.scramble(myfield);
                            }
      }
 
    await app.doSave();
	
	var optionsexport = {
	uri: `https://${servername}/jwt/qrs/App/${AppNewId.body.id}/export/42754ecc-c143-4024-aa99-69d7e45a9025?skipData=false&amp;amp;xrfkey=1234567891234567`,
	headers: {'content-type': 'application/json','X-Qlik-xrfkey': '1234567891234567','Cookie': `X-Qlik-Session-jwt=${sessionid}`},
	method: 'POST',
	json: true,
	rejectUnauthorized: false
	};
	
	//export file
	var url = await rp(optionsexport, function (error, response, body) {
        if(error) 
        {
            console.log('Error: '+error);
        } 
        else 
        {
            return body;
        }
    });
	
	
	//download file
	var newurl = await `https://${servername}/jwt${url.downloadPath}`;
	var dest = await './scrambled_app.qvf';
	
  rp.get({
  url: newurl,
  encoding: null,
  rejectUnauthorized: false,
  headers:{'Cookie': `X-Qlik-Session-jwt=${sessionid}`}
}).then(function (res) {
	console.log(res);
	console.log(newurl);
    const buffer = Buffer.from(res, 'utf8');
	console.log(buffer);
    fs.writeFileSync(dest, buffer);
  });
 
    await session.close();
    console.log('Session closed.');
  } catch (err) {
    console.log('Whoops! An error occurred.', err);
    process.exit(1);
  }
})();&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Copy the file in a folder and type the following commands:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;npm install
node scramble-jwt.js da109a0e-4753-40c9-8c5f-aa8cbbb26e86&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In the above,&amp;nbsp;da109a0e-4753-40c9-8c5f-aa8cbbb26e86 is the guid of the app that you want to scramble.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 26 Jul 2023 08:06:40 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/ta-p/1717897</guid>
      <dc:creator>Damien_V</dc:creator>
      <dc:date>2023-07-26T08:06:40Z</dc:date>
    </item>
    <item>
      <title>Re: Qlik Sense Repository API/Engine API(Enigma.js) example with JWT authentication: duplicate/scramble/export</title>
      <link>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/tac-p/2096720#M9745</link>
      <description>&lt;P&gt;Hi! can you share the package.json file? because I'm having problems to install dependecies .&lt;/P&gt;
&lt;P&gt;Regards&lt;/P&gt;</description>
      <pubDate>Mon, 24 Jul 2023 18:16:44 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/tac-p/2096720#M9745</guid>
      <dc:creator>david_hg96</dc:creator>
      <dc:date>2023-07-24T18:16:44Z</dc:date>
    </item>
    <item>
      <title>Re: Qlik Sense Repository API/Engine API(Enigma.js) example with JWT authentication: duplicate/scramble/export</title>
      <link>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/tac-p/2097315#M9760</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.qlik.com/t5/user/viewprofilepage/user-id/69905"&gt;@david_hg96&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I've attached the package.json (thank you, Damien, for the assist!). You may get a warning when using it, but it is still valid.&lt;/P&gt;
&lt;P&gt;All the best,&lt;BR /&gt;Sonja&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 26 Jul 2023 08:09:50 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/tac-p/2097315#M9760</guid>
      <dc:creator>Sonja_Bauernfeind</dc:creator>
      <dc:date>2023-07-26T08:09:50Z</dc:date>
    </item>
    <item>
      <title>Re: Qlik Sense Repository API/Engine API(Enigma.js) example with JWT authentication: duplicate/scramble/export</title>
      <link>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/tac-p/2097537#M9767</link>
      <description>&lt;P&gt;Hello thank you very much. I was able to run the example successfully. Greetings! excellent contribution&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 26 Jul 2023 15:51:07 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Official-Support-Articles/Qlik-Sense-Repository-API-Engine-API-Enigma-js-example-with-JWT/tac-p/2097537#M9767</guid>
      <dc:creator>david_hg96</dc:creator>
      <dc:date>2023-07-26T15:51:07Z</dc:date>
    </item>
  </channel>
</rss>

