-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from pegasystems/bugfix/libs
Add support for oauthConnect component
- Loading branch information
Showing
15 changed files
with
438 additions
and
2 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<title>Demo Login</title> | ||
<meta charset="utf-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0, viewport-fit=cover" /> | ||
<style></style> | ||
</head> | ||
<body> | ||
<img width="250" height="100" src="pega-logo.svg" alt="Constellation UI Gallery"> | ||
<p>This popup window simulates an external application login credentials</p> | ||
<button onclick="window.close();">Click to simulate login and close this window</button> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ | |
"pasteable", | ||
"PHARMACODE", | ||
"reactflow", | ||
"SAOAUTH", | ||
"Talia", | ||
"timegrid", | ||
"widthpx" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { Meta, Primary, Controls, Story } from '@storybook/blocks'; | ||
import * as DemoStories from './demo.stories'; | ||
|
||
<Meta of={DemoStories} /> | ||
|
||
# Overview | ||
|
||
The OAuth Connect component facilitates seamless third-party authentication using the OAuth 2.0 authorization code grant flow. | ||
When a user is not yet authenticated, a 'Connect' button will appear in the widget. Clicking this button initiates a popup window, redirecting the user to the external identity provider for authorization. | ||
Upon successful authorization, the widget displays a 'Disconnect' button, allowing users to revoke their access token. | ||
|
||
While the 'Disconnect' button is visible by default, it can be hidden from the user interface if necessary. | ||
|
||
Other limitations: | ||
|
||
- Authentication is handled through external URL and does not support a custom authorization View | ||
- There is no UI into the widget from your 3rd party application. The JWT token will be available to the component and can be used to call other APIs or to load a URL inside an iframe. | ||
|
||
<Primary /> | ||
|
||
## Props | ||
|
||
<Controls /> | ||
|
||
## Example | ||
|
||
Here is how to configure this component in authoring UI: | ||
|
||
![Data Page Configuration](OAuthConnect_Configuration_5.png) | ||
|
||
To use the component, you will need to have the data page D_OAuthConnect available - This DP is provided as part of the Computerland demo application. | ||
|
||
![Data Page Configuration](OAuthConnect_Configuration_1.png) | ||
|
||
![Data Page Configuration](OAuthConnect_Configuration_2.png) | ||
|
||
The DP will react to the following events to the server (AUTHENTICATE, AUTHORIZE, REVOKE). These events will be used to perform the connect / disconnect functionality. | ||
|
||
When create the authentication profile, make sure that the redirect url is point to YOURHOST/prweb/PRRestService/oauth2/v1/redirect so that the redirect endpoint and the activity 'pzGetAccessToken' is called. | ||
|
||
![Data Page Configuration](OAuthConnect_Configuration_3.png) | ||
|
||
In 23.1, this activity does not call the Constellation Messaging server to notify that the widget should refresh. To workaround this issue, the pyCloseWindow has been extended in the Computerland application to call the activity on load of the HTML fragment. | ||
|
||
![Data Page Configuration](OAuthConnect_Configuration_4.png) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{ | ||
"name": "Pega_Extensions_OAuthConnect", | ||
"label": "OAuth Connect", | ||
"description": "Allows to integrate external applications into Constellation UI using OAuth 2.0 authorization code grant flow", | ||
"organization": "Pega", | ||
"version": "1.0.0", | ||
"library": "Extensions", | ||
"allowedApplications": [], | ||
"componentKey": "Pega_Extensions_OAuthConnect", | ||
"type": "Widget", | ||
"subtype": ["PAGE", "CASE"], | ||
"properties": [ | ||
{ | ||
"name": "heading", | ||
"label": "Heading", | ||
"format": "TEXT", | ||
"defaultValue": "Demo Application" | ||
}, | ||
{ | ||
"name": "profileName", | ||
"label": "Authentication profile", | ||
"format": "TEXT", | ||
"required": "true" | ||
}, | ||
{ | ||
"name": "connectLabel", | ||
"label": "Connect button text", | ||
"format": "TEXT", | ||
"defaultValue": "Connect", | ||
"visibility": "(!customAuth = true)" | ||
}, | ||
{ | ||
"name": "showDisconnect", | ||
"label": "Show disconnect", | ||
"format": "BOOLEAN", | ||
"defaultValue": true | ||
}, | ||
{ | ||
"name": "disconnectLabel", | ||
"label": "Disconnect button text", | ||
"format": "TEXT", | ||
"defaultValue": "Disconnect", | ||
"visibility": "showDisconnect = true" | ||
}, | ||
{ | ||
"label": "Conditions", | ||
"format": "GROUP", | ||
"properties": [ | ||
{ | ||
"name": "visibility", | ||
"label": "Visibility", | ||
"format": "VISIBILITY" | ||
} | ||
] | ||
} | ||
] | ||
} |
141 changes: 141 additions & 0 deletions
141
src/components/Pega_Extensions_OAuthConnect/demo.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import type { StoryObj } from '@storybook/react'; | ||
import { PegaExtensionsOAuthConnect, type OAuthConnectProps } from './index'; | ||
|
||
interface OAuthConnectStoryProps extends OAuthConnectProps { | ||
isConnected: boolean; | ||
} | ||
|
||
export default { | ||
title: 'Widgets/OAuth Connect', | ||
argTypes: { | ||
getPConnect: { | ||
table: { | ||
disable: true | ||
} | ||
} | ||
}, | ||
component: PegaExtensionsOAuthConnect | ||
}; | ||
|
||
const setPCore = (args: { isConnected: boolean; profileName: string }) => { | ||
const { isConnected, profileName } = args; | ||
(window as any).PCore = { | ||
getConstants: () => { | ||
return { | ||
CASE_INFO: { | ||
CASE_INFO_ID: 'ID' | ||
} | ||
}; | ||
}, | ||
getMessagingServiceManager: () => { | ||
return { | ||
subscribe: () => { | ||
/* nothing */ | ||
}, | ||
unsubscribe: () => { | ||
/* nothing */ | ||
} | ||
}; | ||
}, | ||
getEnvironmentInfo: () => { | ||
return { | ||
getOperatorIdentifier: () => { | ||
return 'operator'; | ||
} | ||
}; | ||
}, | ||
getSemanticUrlUtils: () => { | ||
return { | ||
getResolvedSemanticURL: () => { | ||
return '/case/case-1'; | ||
}, | ||
getActions: () => { | ||
return { | ||
ACTION_OPENWORKBYHANDLE: 'openWorkByHandle' | ||
}; | ||
} | ||
}; | ||
}, | ||
getDataPageUtils: () => { | ||
return { | ||
getPageDataAsync: ( | ||
data: string, | ||
context: string, | ||
parameters: { Event: string; ProfileName: string; gadgetId: string } | ||
) => { | ||
const { Event, ProfileName, gadgetId } = parameters; | ||
switch (Event) { | ||
case 'AUTHENTICATE': | ||
if (isConnected) { | ||
return Promise.resolve({ | ||
pyServiceType: 'AUTHENTICATE', | ||
pyTaskStatus: true, | ||
pyIsAuthenticated: true, | ||
pyAccessToken: 'xxxx', | ||
pyLabel: profileName, | ||
pyExpiresAt: '20270828T181056.516 GMT' | ||
}); | ||
} else { | ||
return Promise.resolve({ | ||
pyServiceType: 'AUTHENTICATE', | ||
pyTaskStatus: true, | ||
pyIsAuthenticated: false | ||
}); | ||
} | ||
case 'AUTHORIZE': | ||
return Promise.resolve({ | ||
pyServiceType: 'AUTHORIZE', | ||
pyOauthURLRedirect: 'login-demo.html', | ||
pyTaskStatus: true | ||
}); | ||
case 'REVOKE': | ||
return Promise.resolve({ | ||
pyServiceType: 'REVOKE', | ||
pyTaskStatus: true | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
}; | ||
}; | ||
|
||
type Story = StoryObj<OAuthConnectStoryProps>; | ||
export const Default: Story = { | ||
render: (args: any) => { | ||
setPCore(args); | ||
const props = { | ||
...args, | ||
getPConnect: () => { | ||
return { | ||
getCaseInfo: () => { | ||
return { | ||
getKey: () => 'OPGO8L-CARINSUR-WORK A-5' | ||
}; | ||
}, | ||
getActionsApi: () => { | ||
return { | ||
openWorkByHandle: () => { | ||
/* nothing */ | ||
}, | ||
showCasePreview: () => { | ||
/* nothing */ | ||
} | ||
}; | ||
}, | ||
getContextName: () => '', | ||
getValue: () => 'OPGO8L-CARINSUR-WORK A-5' | ||
}; | ||
} | ||
}; | ||
return <PegaExtensionsOAuthConnect {...props} />; | ||
}, | ||
args: { | ||
heading: 'Demo Application', | ||
profileName: 'Demo application', | ||
connectLabel: 'Connect', | ||
showDisconnect: true, | ||
isConnected: false, | ||
disconnectLabel: 'Disconnect' | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { render, screen } from '@testing-library/react'; | ||
import { composeStories } from '@storybook/react'; | ||
import * as DemoStories from './demo.stories'; | ||
|
||
const { Default } = composeStories(DemoStories); | ||
|
||
test('renders OAuth Connect component with default args', async () => { | ||
render(<Default />); | ||
expect(await screen.findByText('Demo Application')).toBeVisible(); | ||
const buttonElement = screen.getByRole('button', { name: 'Connect' }); | ||
expect(buttonElement).not.toBeNull(); | ||
}); |
Oops, something went wrong.