diff --git a/README.md b/README.md index 3ee8aba..1a4c9e0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This project was created using NodeJS 14.16. This application aims to demonstrat ## Dashboard view - ![Dashboard view](https://github.com/boldbi/react-with-nodejs-sample/assets/129486688/9608f9e1-99f8-4375-9724-d15820cb690f) + ![Dashboard view](/images/dashboard.png) ## Prerequisites @@ -15,32 +15,28 @@ The samples require the following to run. > **NOTE:** Node.js v14.16 to v18.18 are supported. -### Help link - -* - #### Supported browsers -* Google Chrome, Microsoft Edge, Mozilla Firefox, and Safari. +* Google Chrome, Microsoft Edge, and Mozilla Firefox. ## Configuration * Please ensure that you have enabled embed authentication on the `embed settings` page. If it is not currently enabled, please refer to the following image or detailed [instructions](https://help.boldbi.com/site-administration/embed-settings/#get-embed-secret-code?utm_source=github&utm_medium=backlinks) to enable it. - ![Embed Settings](https://github.com/boldbi/aspnet-core-sample/assets/91586758/b3a81978-9eb4-42b2-92bb-d1e2735ab007) + ![Embed Settings](/images/enable-embedsecretkey.png) * To download the `embedConfig.json` file, please follow this [link](https://help.boldbi.com/site-administration/embed-settings/#get-embed-configuration-file?utm_source=github&utm_medium=backlinks) for reference. Additionally, you can refer to the following image for visual guidance. - ![Embed Settings Download](https://github.com/boldbi/aspnet-core-sample/assets/91586758/d27d4cfc-6a3e-4c34-975e-f5f22dea6172) - ![EmbedConfig Properties](https://github.com/boldbi/aspnet-core-sample/assets/91586758/d6ce925a-0d4c-45d2-817e-24d6d59e0d63) + ![Embed Settings Download](/images/download-embedsecretkey.png) + ![EmbedConfig Properties](/images/embedconfig-file.png) * Copy the downloaded `embedConfig.json` file and paste it into the designated [location](https://github.com/boldbi/react-with-nodejs-sample/tree/master) within the application. Please ensure that you have placed it in the application as shown in the following image. - ![EmbedConfig image](https://github.com/boldbi/react-with-nodejs-sample/assets/129486688/6dc248bc-306c-497f-9aed-421abb2ca710) + ![EmbedConfig image](/images/embedconfig-location.png) ## Developer IDE -* Visual studio code() +* [Visual Studio Code]() ### Run a Sample Using Visual Studio Code @@ -60,7 +56,7 @@ The samples require the following to run. * After executing the command, the application will automatically launch in the default browser. You can access it at the specified port number (e.g., ). - ![Dashboard view](https://github.com/boldbi/react-with-nodejs-sample/assets/129486688/9608f9e1-99f8-4375-9724-d15820cb690f) + ![dashboard view](/images/dashboard.png) > **NOTE:** If the API host is already in use, modify the port number per your preference in embed.js and update that Dashboard.js file. diff --git a/client/src/Dashboard/Dashboard.js b/client/src/Dashboard/Dashboard.js index 2a06ad5..c3142b8 100644 --- a/client/src/Dashboard/Dashboard.js +++ b/client/src/Dashboard/Dashboard.js @@ -2,12 +2,11 @@ import React from 'react'; import '../index'; import {BoldBI} from '@boldbi/boldbi-embedded-sdk'; - //NodeJs application will run on http://localhost:8080, which needs to be set as apiHost. const apiHost="http://localhost:8080"; -//Url of the authorizationserver action in the ValuesController of the NodeJs application. -const authorizationUrl="/authorizationserver/get"; +//Url of the TokenGeneration action in embed.js +const tokenGenerationUrl = "/tokengeneration"; class Dashboard extends React.Component { constructor(props) { @@ -20,24 +19,34 @@ class Dashboard extends React.Component { this.BoldBiObj = new BoldBI(); }; - renderDashboard(data) { - this.dashboard= BoldBI.create({ - serverUrl: data.ServerUrl+"/" + data.SiteIdentifier, - dashboardId: data.DashboardId, - embedContainerId: "dashboard", - embedType: data.EmbedType, - environment: data.Environment, - mode:BoldBI.Mode.View, - width:"100%", - height: window.innerHeight + 'px', - expirationTime:100000, - authorizationServer: { - url: apiHost + authorizationUrl - } - }); + getEmbedToken() { + return fetch(apiHost + tokenGenerationUrl, { // Backend application URL + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({}) + }) + .then(response => { + if (!response.ok) throw new Error("Token fetch failed"); + return response.text(); + }); + } + + renderDashboard(data) { + this.getEmbedToken() + .then(accessToken => { + const dashboard = BoldBI.create({ + serverUrl: data.ServerUrl + "/" + data.SiteIdentifier, + dashboardId: data.DashboardId, + embedContainerId: "dashboard", + embedToken: accessToken + }); - this.dashboard.loadDashboard(); - } + dashboard.loadDashboard(); + }) + .catch(err => { + console.error("Error rendering dashboard:", err); + }); + }; render() { return ( diff --git a/client/src/index.js b/client/src/index.js index 85850fd..37c113a 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,6 +1,4 @@ -import React from 'react'; import {createRoot } from 'react-dom/client'; import App from './App'; -createRoot(document.getElementById('root')).render(); - +createRoot(document.getElementById('root')).render(); \ No newline at end of file diff --git a/embed.js b/embed.js index d90328e..b58dbff 100644 --- a/embed.js +++ b/embed.js @@ -1,11 +1,9 @@ var fs = require("fs"); var http = require("http"); var https = require("https"); -var url = require("url"); var express = require('express'); var cors = require('cors'); var app = express(); -var crypto = require('crypto'); const path = require('path'); app.use(cors()); //Parse JSON bodies (as sent by API clients). @@ -15,54 +13,77 @@ app.use(express.json()); const port = 8080; let appconfig; +const configPath = path.join(__dirname, 'embedConfig.json'); +let rawConfig; try { - appconfig = JSON.parse(fs.readFileSync('embedConfig.json')); -} catch (error) { - console.error('Error: embedConfig.json file not found.'); - process.exit(1); //Exit the program with a non-zero exit code to indicate an error. + rawConfig = fs.readFileSync(configPath, 'utf8'); +} catch (err) { + console.error(`Error: cannot read embedConfig.json at ${configPath}:`, err.message); + process.exit(1); +} +try { + if (rawConfig && rawConfig.charCodeAt(0) === 0xFEFF) { + rawConfig = rawConfig.slice(1); + } + rawConfig = rawConfig.trim(); + appconfig = JSON.parse(rawConfig); +} catch (err) { + console.error(`Error: invalid JSON in embedConfig.json at ${configPath}:`, err.message); + process.exit(1); } -var embedSecret = appconfig.EmbedSecret; +app.post('/TokenGeneration', function (req, response) { + const embedDetails = { + email: appconfig.UserEmail, + serverurl: appconfig.ServerUrl, + siteidentifier: appconfig.SiteIdentifier, + embedsecret: appconfig.EmbedSecret, + dashboard: { // Dashboard ID property is mandatory only when using BoldBI version 14.1.11. + id: appconfig.DashboardId + } + } -var userEmail = appconfig.UserEmail; + const parsedUrl = new URL(embedDetails.serverurl); + const postData = JSON.stringify(embedDetails); + const client = parsedUrl.protocol === 'https:' ? https : http; + const options = { + hostname: parsedUrl.hostname, + port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80), + path: `${parsedUrl.pathname}/api/${embedDetails.siteidentifier}/embed/authorize`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(postData) + } + }; -app.post('/authorizationserver/get', async function (req, response){ - var embedQuerString = req.body.embedQuerString; - var dashboardServerApiUrl = req.body.dashboardServerApiUrl; - - embedQuerString += "&embed_user_email=" + userEmail; - embedQuerString += "&embed_server_timestamp=" + Math.round((new Date()).getTime() / 1000); - var embedSignature = "&embed_signature=" + GetSignatureUrl(embedQuerString); - var embedDetailsUrl = "/embed/authorize?" + embedQuerString+embedSignature; - - var serverProtocol = url.parse(dashboardServerApiUrl).protocol == 'https:' ? https : http; - serverProtocol.get(dashboardServerApiUrl+embedDetailsUrl, function(res){ - var str = ''; - res.on('data', function (chunk) { - str += chunk; - }); - res.on('end', function () { - response.send(str); - }); + const requ = client.request(options, res => { + let result = ''; + res.setEncoding('utf8'); + res.on('data', chunk => result += chunk); + res.on('end', () => { + const resultparse = JSON.parse(result); // Parse the response + response.send(resultparse?.Data?.access_token); }); -}) + }); -function GetSignatureUrl(queryString) -{ - var keyBytes = Buffer.from(embedSecret); - var hmac = crypto.createHmac('sha256', keyBytes); - data = hmac.update(queryString); - gen_hmac= data.digest().toString('base64'); + requ.on('error', (e) => { + console.error("Error fetching embed token:", e.message); + }); + + requ.write(postData); + requ.end(); +}) -return gen_hmac; -} app.get('/GetData', (req, res) => { - const serverEmbedConfigData = path.join(__dirname, 'embedConfig.json'); - const jsonData = fs.readFileSync(serverEmbedConfigData, 'utf8'); - const parsedData = JSON.parse(jsonData); + const parsedData = appconfig; const clientEmbedConfigData = { - DashboardId: parsedData.DashboardId, ServerUrl: parsedData.ServerUrl, SiteIdentifier: parsedData.SiteIdentifier, EmbedType: parsedData.EmbedType, Environment: parsedData.Environment + DashboardId: parsedData.DashboardId, + ServerUrl: parsedData.ServerUrl, + SiteIdentifier: parsedData.SiteIdentifier, + EmbedType: parsedData.EmbedType, + Environment: parsedData.Environment }; res.send(clientEmbedConfigData); diff --git a/images/dashboard.png b/images/dashboard.png new file mode 100644 index 0000000..cea010f Binary files /dev/null and b/images/dashboard.png differ diff --git a/images/download-embedsecretkey.png b/images/download-embedsecretkey.png new file mode 100644 index 0000000..abe0c1b Binary files /dev/null and b/images/download-embedsecretkey.png differ diff --git a/images/embedconfig-file.png b/images/embedconfig-file.png new file mode 100644 index 0000000..4ba11a5 Binary files /dev/null and b/images/embedconfig-file.png differ diff --git a/images/embedconfig-location.png b/images/embedconfig-location.png new file mode 100644 index 0000000..32171dd Binary files /dev/null and b/images/embedconfig-location.png differ diff --git a/images/enable-embedsecretkey.png b/images/enable-embedsecretkey.png new file mode 100644 index 0000000..cbd4a7c Binary files /dev/null and b/images/enable-embedsecretkey.png differ diff --git a/package.json b/package.json index 0fc6e82..f176313 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "main": "embed.js", "dependencies": { - "@boldbi/boldbi-embedded-sdk": "^6.18.11", + "@boldbi/boldbi-embedded-sdk": "^15.1.65", "cors": "^2.8.5", "express": "^4.18.2" },