diff --git a/package-lock.json b/package-lock.json index b4dcc2498..6c5ff28e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", "@material-ui/pickers": "^3.3.10", + "@pega/auth": "^0.1.2", "@pega/constellationjs": "SDK-8.23.0", "@pega/cosmos-react-core": "^4.0.1", "@pega/cosmos-react-work": "^4.0.1", @@ -5599,6 +5600,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@pega/auth": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@pega/auth/-/auth-0.1.2.tgz", + "integrity": "sha512-ZpNk4H76zK56AZaLIi/P7IsIHuqRjvy+B7kpS84QsrWRsNovbitiNHrLspDcsD/2rSKxt1V32AUH+YMFTtWo6w==", + "dependencies": { + "node-fetch": "^3.2.10", + "open": "^8.4.2" + } + }, "node_modules/@pega/commitlint-config": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@pega/commitlint-config/-/commitlint-config-0.4.0.tgz", @@ -15129,9 +15139,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "17.0.70", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.70.tgz", - "integrity": "sha512-yqYMK49/cnqw+T8R9/C+RNjRddYmPDGI5lKHi3bOYceQCBAh8X2ngSbZP0gnVeyvHr0T7wEgIIGKT1usNol08w==", + "version": "16.14.52", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.52.tgz", + "integrity": "sha512-4+ZN73hgRW3Gang3QMqWjrqPPkf+lWZYiyG4uXtUbpd+7eiBDw6Gemila6rXDd8DorADupTiIERL6Mb5BQTF2w==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -15146,6 +15156,21 @@ "@types/react": "^17" } }, + "node_modules/@types/react-dom/node_modules/@types/react": { + "version": "17.0.71", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.71.tgz", + "integrity": "sha512-lfqOu9mp16nmaGRrS8deS2Taqhd5Ih0o92Te5Ws6I1py4ytHBcXLqh0YIqVsViqwVI5f+haiFM6hju814BzcmA==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom/node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "node_modules/@types/react-redux": { "version": "7.1.23", "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.23.tgz", @@ -22627,7 +22652,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, "engines": { "node": ">= 12" } @@ -22969,7 +22993,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, "engines": { "node": ">=8" } @@ -25123,7 +25146,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, "funding": [ { "type": "github", @@ -25643,7 +25665,6 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, "dependencies": { "fetch-blob": "^3.1.2" }, @@ -27952,7 +27973,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -28465,7 +28485,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -32761,7 +32780,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true, "funding": [ { "type": "github", @@ -32780,7 +32798,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -34777,10 +34794,9 @@ } }, "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -44903,7 +44919,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true, "engines": { "node": ">= 8" } @@ -49869,6 +49884,15 @@ } } }, + "@pega/auth": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@pega/auth/-/auth-0.1.2.tgz", + "integrity": "sha512-ZpNk4H76zK56AZaLIi/P7IsIHuqRjvy+B7kpS84QsrWRsNovbitiNHrLspDcsD/2rSKxt1V32AUH+YMFTtWo6w==", + "requires": { + "node-fetch": "^3.2.10", + "open": "^8.4.2" + } + }, "@pega/commitlint-config": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@pega/commitlint-config/-/commitlint-config-0.4.0.tgz", @@ -57021,9 +57045,9 @@ "dev": true }, "@types/react": { - "version": "17.0.70", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.70.tgz", - "integrity": "sha512-yqYMK49/cnqw+T8R9/C+RNjRddYmPDGI5lKHi3bOYceQCBAh8X2ngSbZP0gnVeyvHr0T7wEgIIGKT1usNol08w==", + "version": "16.14.52", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.52.tgz", + "integrity": "sha512-4+ZN73hgRW3Gang3QMqWjrqPPkf+lWZYiyG4uXtUbpd+7eiBDw6Gemila6rXDd8DorADupTiIERL6Mb5BQTF2w==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -57043,6 +57067,23 @@ "integrity": "sha512-lnJAZfMEDxfvELeeT24w4rnUYwpzUzQAOTfJQbWYnLcx8AEfz+fXJDCbowIBqNK/Bi4D6j8ovT8Qsda2OtDApA==", "requires": { "@types/react": "^17" + }, + "dependencies": { + "@types/react": { + "version": "17.0.71", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.71.tgz", + "integrity": "sha512-lfqOu9mp16nmaGRrS8deS2Taqhd5Ih0o92Te5Ws6I1py4ytHBcXLqh0YIqVsViqwVI5f+haiFM6hju814BzcmA==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + } } }, "@types/react-redux": { @@ -62718,8 +62759,7 @@ "data-uri-to-buffer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" }, "data-urls": { "version": "3.0.2", @@ -62953,8 +62993,7 @@ "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" }, "define-properties": { "version": "1.1.3", @@ -64643,7 +64682,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, "requires": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -65015,7 +65053,6 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, "requires": { "fetch-blob": "^3.1.2" } @@ -66770,8 +66807,7 @@ "is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" }, "is-dom": { "version": "1.1.0", @@ -67115,7 +67151,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "requires": { "is-docker": "^2.0.0" } @@ -70426,14 +70461,12 @@ "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" }, "node-fetch": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, "requires": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -71969,10 +72002,9 @@ } }, "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "requires": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -79305,8 +79337,7 @@ "web-streams-polyfill": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" }, "webidl-conversions": { "version": "7.0.0", diff --git a/package.json b/package.json index 072253f9e..3db1e4a14 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", "@material-ui/pickers": "^3.3.10", + "@pega/auth": "^0.1.2", "@pega/constellationjs": "SDK-8.23.0", "@pega/cosmos-react-core": "^4.0.1", "@pega/cosmos-react-work": "^4.0.1", diff --git a/src/auth.html b/src/auth.html deleted file mode 100644 index 4c5d22cd6..000000000 --- a/src/auth.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - diff --git a/src/samples/AuthPage/index.jsx b/src/samples/AuthPage/index.jsx index 88dfc396a..56fc129ad 100644 --- a/src/samples/AuthPage/index.jsx +++ b/src/samples/AuthPage/index.jsx @@ -1,22 +1,7 @@ import React from 'react'; -import { getHomeUrl, authIsMainRedirect, authRedirectCallback } from "../../helpers/authManager"; +import { getHomeUrl, authIsMainRedirect, authRedirectCallback } from '@pega/auth/lib/sdk-auth-manager'; +import { authDone } from '@pega/auth/lib/auth-code-redirect'; -function getEmbedOriginFromState(state) { - let embedOrigin = null; - try { - // Expect state to contain the embedding page's origin - if( state ) { - embedOrigin = window.atob(state); - } - // eslint-disable-next-line no-empty - } catch(e) { - } - if( !embedOrigin ) { - // eslint-disable-next-line no-restricted-globals - embedOrigin = location.origin; - } - return embedOrigin; -} export default function AuthPage() { @@ -27,45 +12,7 @@ export default function AuthPage() { location.href = `${getHomeUrl()}portal`; }); } else { - const queryString = window.location.search; - const urlParams = new URLSearchParams(queryString); - const code = urlParams.get("code"); - const state = urlParams.get("state"); - const bTryOpenerLogging = false; - // eslint-disable-next-line no-console - const fnLog = bTryOpenerLogging ? window.opener.console.log : console.log; - let bSuccess = false; - - if (code) { - fnLog("Testing"); - try { - window.opener.authCodeCallback(code); - bSuccess = true; - } catch(e) { - fnLog("auth.html: Failed to directly access authCodeCallback.") - } - - // Post messages require a targetDomain...trying to pass this via state - const embedOrigin = getEmbedOriginFromState(state); - if( !bSuccess ) { - try { - window.opener.postMessage({type:"PegaAuth", code}, embedOrigin); - bSuccess = true; - } catch(e) { - fnLog("auth.html: Failed to directly post message to opener"); - } - } - - if( !bSuccess ) { - window.addEventListener("message", (event) => { - if( event.data && event.data.type && event.data.type==="PegaAuth" ) { - event.source.postMessage({type:"PegaAuth", code}, embedOrigin); - } - }); - } - - } - + authDone(); } return ( diff --git a/src/samples/Embedded/EmbeddedTopLevel/index.tsx b/src/samples/Embedded/EmbeddedTopLevel/index.tsx index 8bafbd23f..19686a96e 100644 --- a/src/samples/Embedded/EmbeddedTopLevel/index.tsx +++ b/src/samples/Embedded/EmbeddedTopLevel/index.tsx @@ -1,26 +1,23 @@ /* eslint-disable react/button-has-type */ // @ts-nocheck - TypeScript type checking to be added soon -import React,{ useState, useEffect } from 'react'; +import React, { useState, useEffect } from 'react'; import { render } from "react-dom"; import Typography from '@material-ui/core/Typography'; import CssBaseline from '@material-ui/core/CssBaseline'; import { createTheme, makeStyles, ThemeProvider } from '@material-ui/core/styles'; +import { sdkIsLoggedIn, loginIfNecessary, sdkSetAuthHeader, sdkSetCustomTokenParamsCB, getSdkConfig } from '@pega/auth/lib/sdk-auth-manager'; import StoreContext from "@pega/react-sdk-components/lib/bridge/Context/StoreContext"; import createPConnectComponent from "@pega/react-sdk-components/lib/bridge/react_pconnect"; -import { sdkIsLoggedIn, loginIfNecessary, sdkSetAuthHeader } from '@pega/react-sdk-components/lib/components/helpers/authManager'; - import EmbeddedSwatch from '../EmbeddedSwatch'; import { compareSdkPCoreVersions } from '@pega/react-sdk-components/lib/components/helpers/versionHelpers'; -import { getSdkConfig } from '@pega/react-sdk-components/lib/components/helpers/config_access'; import { getSdkComponentMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map'; import localSdkComponentMap from '../../../../sdk-local-component-map'; declare const myLoadMashup: any; - const useStyles = makeStyles((theme) => ({ embedTopRibbon: { display: 'none', @@ -281,8 +278,8 @@ export default function EmbeddedTopLevel() { // const thePConnObj =
the RootComponent
; const thePConnObj = ; - // NOTE: For Embedded mode, we add in displayOnlyFA and isMashup to our React context - // so the values are available to any component that may need it. + // NOTE: For Embedded mode, we add in displayOnlyFA to our React context + // so it is available to any component that may need it. // VRS: Attempted to remove displayOnlyFA but it presently handles various components which // SDK does not yet support, so all those need to be fixed up before it can be removed. To // be done in a future sprint. @@ -304,7 +301,7 @@ export default function EmbeddedTopLevel() { * is ready to be rendered * @param inRenderObj the initial, top-level PConnect object to render */ - function initialRender(inRenderObj) { + function initialRender(inRenderObj) { // loadMashup does its own thing so we don't need to do much/anything here @@ -365,7 +362,7 @@ export default function EmbeddedTopLevel() { /** * kick off the application's portal that we're trying to serve up */ - function startMashup() { + function startMashup() { // NOTE: When loadMashup is complete, this will be called. PCore.onPCoreReady(renderObj => { @@ -399,7 +396,7 @@ export default function EmbeddedTopLevel() { // One time (initialization) subscriptions and related unsubscribe useEffect(() => { - getSdkConfig().then( sdkConfig => { + getSdkConfig().then( (sdkConfig:any) => { const sdkConfigAuth = sdkConfig.authConfig; if( !sdkConfigAuth.mashupClientId && sdkConfigAuth.customAuthType === "Basic" ) { @@ -419,6 +416,14 @@ export default function EmbeddedTopLevel() { sdkSetAuthHeader( `Basic ${sB64}`); } + if( sdkConfigAuth.customAuthType === "CustomIdentifier" ) { + // Use custom bearer with specific custom parameter to set the desired operator via + // a userIdentifier property. (Caution: highly insecure...being used for simple demonstration) + sdkSetCustomTokenParamsCB(() => { + return {"userIdentifier": sdkConfigAuth.mashupUserIdentifier }; + }); + } + document.addEventListener("SdkConstellationReady", () => { // start the portal startMashup(); @@ -466,11 +471,11 @@ export default function EmbeddedTopLevel() { const options = { pageName: 'pyEmbedAssignment', - startingFields: { - Package: sLevel - } + startingFields: mashupCaseType === "DIXL-MediaCo-Work-NewService" ? + { + Package: sLevel + } : {} }; - // @ts-ignore PCore.getMashupApi().createCase(mashupCaseType, PCore.getConstants().APP.APP, options).then(() => { // eslint-disable-next-line no-console console.log('createCase rendering is complete'); diff --git a/src/samples/FullPortal/InvalidPortal.tsx b/src/samples/FullPortal/InvalidPortal.tsx new file mode 100644 index 000000000..1492e16d3 --- /dev/null +++ b/src/samples/FullPortal/InvalidPortal.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { logout } from '@pega/auth/lib/sdk-auth-manager'; + +export default function InvalidPortal({ defaultPortal, portals, onSelect }) { + const logOff = () => { + logout().then(() => { + // Reload the page to kick off the login + window.location.reload(); + }); + }; + + return ( +
+
+ Default portal ( {defaultPortal} ) for current operator + is not compatible with SDK.
+
+ Please select one of the portals available to the operator's access group: +
+
+ {portals.map(portal => ( +
onSelect(portal)}> + {portal} +
+ ))} +
+ +
+ ); +} diff --git a/src/samples/FullPortal/index.tsx b/src/samples/FullPortal/index.tsx index 93d7dfab5..dd30aa396 100644 --- a/src/samples/FullPortal/index.tsx +++ b/src/samples/FullPortal/index.tsx @@ -1,18 +1,17 @@ -import React, { useEffect, useMemo } from 'react'; -import ReactDOM from "react-dom"; +import React, { useEffect, useMemo, useState } from 'react'; +import ReactDOM from 'react-dom'; import CssBaseline from '@material-ui/core/CssBaseline'; import { createTheme, ThemeProvider } from '@material-ui/core/styles'; import { useLocation, useHistory } from 'react-router-dom'; import StoreContext from "@pega/react-sdk-components/lib/bridge/Context/StoreContext"; import createPConnectComponent from "@pega/react-sdk-components/lib/bridge/react_pconnect"; -import { SdkConfigAccess } from '@pega/react-sdk-components/lib/components/helpers/config_access'; +import { SdkConfigAccess, loginIfNecessary, getAvailablePortals } from '@pega/auth/lib/sdk-auth-manager'; import { compareSdkPCoreVersions } from '@pega/react-sdk-components/lib/components/helpers/versionHelpers'; -import { loginIfNecessary } from '@pega/react-sdk-components/lib/components/helpers/authManager'; +import InvalidPortal from './InvalidPortal'; import { getSdkComponentMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map'; import localSdkComponentMap from '../../../sdk-local-component-map'; - declare const myLoadPortal: any; declare const myLoadDefaultPortal: any; @@ -23,11 +22,15 @@ function useQuery() { } export default function FullPortal() { + const [portalSelectionScreen, setPortalSelectionScreen] = useState(false); + const [defaultPortalName, setDefaultPortalName] = useState(''); + const [availablePortals, setAvailablePortals] = useState>([]); + const history = useHistory(); const query = useQuery(); if (query.get('portal')) { const portalValue: any = query.get('portal'); - sessionStorage.setItem("rsdk_portalName", portalValue); + sessionStorage.setItem('rsdk_portalName', portalValue); } const theme = createTheme({ @@ -58,16 +61,16 @@ export default function FullPortal() { // const thePConnObj =
the RootComponent
; const thePConnObj = ; - const theComp = - + const theComp = ( + {thePConnObj} - - ; + + + ); return theComp; - } /** @@ -75,8 +78,7 @@ export default function FullPortal() { * is ready to be rendered * @param inRenderObj the initial, top-level PConnect object to render */ - function initialRender(inRenderObj) { - + function initialRender(inRenderObj) { // modified from react_root.js render const { props, @@ -85,7 +87,7 @@ export default function FullPortal() { portalTarget, styleSheetTarget } = inRenderObj; - let target:any = null; + let target: any = null; if (domContainerID !== null) { target = document.getElementById(domContainerID); } else if (portalTarget !== null) { @@ -105,31 +107,25 @@ export default function FullPortal() { // var theComponent =
the Component
; const theComponent = ( - - - ; - - ); + + + ; + + ); - ReactDOM.render( // was { // Check that we're seeing the PCore version we expect @@ -137,47 +133,51 @@ export default function FullPortal() { // Initialize the SdkComponentMap (local and pega-provided) // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars - getSdkComponentMap(localSdkComponentMap).then( (theComponentMap: any) => { + getSdkComponentMap(localSdkComponentMap).then((theComponentMap: any) => { // eslint-disable-next-line no-console console.log(`SdkComponentMap initialized`); // Don't call initialRender until SdkComponentMap is fully initialized initialRender(renderObj); - - }) + }); }); // load the Portal and handle the onPCoreEntry response that establishes the // top level Pega root element (likely a RootContainer) - const thePortal = SdkConfigAccess.getSdkConfigServer().appPortal; + const { appPortal: thePortal, excludePortals } = SdkConfigAccess.getSdkConfigServer(); const defaultPortal = PCore?.getEnvironmentInfo?.().getDefaultPortal?.(); - const queryPortal = sessionStorage.getItem("rsdk_portalName"); + const queryPortal = sessionStorage.getItem('rsdk_portalName'); + // Note: myLoadPortal and myLoadDefaultPortal are set when bootstrapWithAuthHeader is invoked - if ( queryPortal ) { - myLoadPortal("pega-root", queryPortal, []); - } else if( thePortal ) { + if (queryPortal) { + myLoadPortal('pega-root', queryPortal, []); + } else if (thePortal) { // eslint-disable-next-line no-console console.log(`Loading specified appPortal: ${thePortal}`); - myLoadPortal("pega-root", thePortal, []); - } - else if( myLoadDefaultPortal && defaultPortal ) { + myLoadPortal('pega-root', thePortal, []); + } else if (myLoadDefaultPortal && defaultPortal && !excludePortals.includes(defaultPortal)) { // eslint-disable-next-line no-console console.log(`Loading default portal`); - myLoadDefaultPortal("pega-root", []); - } - else { - // This path of selecting a portal by enumerating entries within current user's access group's portals list - // relies on Traditional DX APIs and should be avoided when the Constellation bootstrap supports - // the loadDefaultPortal API - SdkConfigAccess.selectPortal() - .then( () => { - const selPortal = SdkConfigAccess.getSdkConfigServer().appPortal; - myLoadPortal("pega-root", selPortal, []); // this is defined in bootstrap shell that's been loaded already + myLoadDefaultPortal('pega-root', []); + } else { + // eslint-disable-next-line no-console + console.log('Loading portal selection screen'); + setPortalSelectionScreen(true); + setDefaultPortalName(defaultPortal); + // Getting current user's access group's available portals list other than excluded portals (relies on Traditional DX APIs) + getAvailablePortals().then((portals) => { + setAvailablePortals(portals as Array); }); } } + function loadSelectedPortal(portal) { + setPortalSelectionScreen(false); + myLoadPortal('app-root', portal, []); // this is defined in bootstrap shell that's been loaded already + } + + function doRedirectDone() { history.push(window.location.pathname); // appName and mainRedirect params have to be same as earlier invocation @@ -186,20 +186,23 @@ export default function FullPortal() { // One time (initialization) useEffect(() => { - - document.addEventListener("SdkConstellationReady", () => { + document.addEventListener('SdkConstellationReady', () => { // start the portal startPortal(); }); - - // Login if needed, without doing an initial main window redirect + // Login if needed, doing an initial main window redirect loginIfNecessary({appName:'portal', mainRedirect:true, redirectDoneCB:doRedirectDone}); }, []); - return ( + return portalSelectionScreen ? ( + + ) : (
- {/*

React SDK: /portal

*/} -
-
) - +
+ + ); } diff --git a/webpack.config.js b/webpack.config.js index f2856f02e..f37e857e6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -10,13 +10,6 @@ module.exports = (env, argv) => { const pluginsToAdd = []; const webpackMode = argv.mode; - pluginsToAdd.push(new CleanWebpackPlugin()); - pluginsToAdd.push( - new HtmlWebpackPlugin({ - template: './src/auth.html', - filename: 'auth.html' - }) - ); pluginsToAdd.push( new HtmlWebpackPlugin({ template: './src/index.html', @@ -35,7 +28,11 @@ module.exports = (env, argv) => { to: './' }, { - from: './node_modules/@pega/react-sdk-components/lib/components/helpers/auth.js', /* New SDK packaging has moved auth.js into node_modules */ + from: './node_modules/@pega/auth/lib/oauth-client/authDone.html', + to: './auth.html' + }, + { + from: './node_modules/@pega/auth/lib/oauth-client/authDone.js', to: './' }, {