Skip to content

Commit 72e367d

Browse files
author
mehara-rothila
committed
Move consumer secret input to dialog on Try Out page
When multiple client secrets are enabled, the consumer secret field was displayed inline on the DevPortal Try Out page. This moves the field into a popup dialog that opens when clicking GET TEST KEY, keeping the page clean and consistent with existing dialog patterns. Resolves #4809
1 parent 283dec1 commit 72e367d

File tree

1 file changed

+89
-55
lines changed

1 file changed

+89
-55
lines changed

portals/devportal/src/main/webapp/source/src/app/components/Shared/ApiTryOut/TryOutController.jsx

Lines changed: 89 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import PropTypes from 'prop-types';
2727
import TextField from '@mui/material/TextField';
2828
import {
2929
Radio, RadioGroup, FormControlLabel, FormControl, CircularProgress, Tooltip,
30+
Dialog, DialogTitle, DialogContent, DialogActions,
3031
} from '@mui/material';
3132
import HelpOutline from '@mui/icons-material/HelpOutline';
3233
import IconButton from '@mui/material/IconButton';
@@ -189,6 +190,7 @@ function TryOutController(props) {
189190
const [tokenValue, setTokenValue] = useState('');
190191
const [consumerSecret, setConsumerSecret] = useState('');
191192
const [showSecret, setShowSecret] = useState(false);
193+
const [secretDialogOpen, setSecretDialogOpen] = useState(false);
192194
const apiID = api.id;
193195
const restApi = new Api();
194196
const user = AuthManager.getUser();
@@ -351,7 +353,8 @@ function TryOutController(props) {
351353
/**
352354
* Generate access token
353355
* */
354-
function generateAccessToken() {
356+
function generateAccessToken(secretOverride) {
357+
const secret = (typeof secretOverride === 'string') ? secretOverride : consumerSecret;
355358
if (api.lifeCycleStatus) {
356359
setIsUpdating(true);
357360
const applicationPromise = Application.get(selectedApplication);
@@ -363,7 +366,7 @@ function TryOutController(props) {
363366
scopes,
364367
undefined,
365368
undefined,
366-
consumerSecret
369+
secret
367370
))
368371
.then((response) => {
369372
console.log('token generated successfully ' + response);
@@ -611,12 +614,8 @@ function TryOutController(props) {
611614
const isConsumerSecretRequired = isMultipleClientSecretsAllowed && securitySchemeType === 'OAUTH' &&
612615
selectedKMObject && !selectedKMObject.enableTokenHashing;
613616

614-
// When multiple client secrets are allowed, for OAuth security scheme, the consumer secret should
615-
// be available for the Get Test Key button to be enabled.
616-
let enableGetTestKeyButton = true; // default
617-
if (securitySchemeType === 'OAUTH' && isMultipleClientSecretsAllowed) {
618-
enableGetTestKeyButton = isConsumerSecretRequired ? !!consumerSecret?.trim() : true; // must provide consumer secret
619-
}
617+
// Consumer secret is now collected via dialog, so GET TEST KEY is always enabled.
618+
const enableGetTestKeyButton = true;
620619

621620
useEffect(() => {
622621
if (securitySchemeType === 'API-KEY') {
@@ -796,52 +795,86 @@ function TryOutController(props) {
796795
</Grid>
797796
)
798797
)}
799-
{/* New Consumer Secret Field - Only shows for OAUTH */}
800-
<Box display='block' justifyContent='center'>
801-
<Grid x={8} md={6} className={classes.tokenType} item>
802-
{isConsumerSecretRequired && (
803-
<TextField
804-
fullWidth
805-
margin='normal'
806-
variant='outlined'
807-
label={(
808-
<FormattedMessage
809-
id='Apis.Details.ApiConsole.consumer.secret.text.field'
810-
defaultMessage='Consumer Secret'
811-
/>
812-
)}
813-
name='consumerSecret'
814-
onChange={handleChanges}
815-
type={showSecret ? 'text' : 'password'}
816-
value={consumerSecret || ''}
817-
id='consumerSecretInput'
818-
helperText={
819-
!consumerSecret?.trim()
820-
? <FormattedMessage
798+
{/* Consumer Secret Dialog - Opens when GET TEST KEY is clicked (multiple secrets mode) */}
799+
{isConsumerSecretRequired && (
800+
<Dialog
801+
open={secretDialogOpen}
802+
onClose={() => setSecretDialogOpen(false)}
803+
fullWidth
804+
maxWidth='sm'
805+
>
806+
<DialogTitle>
807+
<FormattedMessage
808+
id='Apis.Details.ApiConsole.generate.test.key.dialog.title'
809+
defaultMessage='Generate Test Key'
810+
/>
811+
</DialogTitle>
812+
<DialogContent>
813+
<TextField
814+
fullWidth
815+
margin='normal'
816+
variant='outlined'
817+
label={(
818+
<FormattedMessage
819+
id='Apis.Details.ApiConsole.consumer.secret.text.field'
820+
defaultMessage='Consumer Secret'
821+
/>
822+
)}
823+
name='consumerSecret'
824+
onChange={handleChanges}
825+
type={showSecret ? 'text' : 'password'}
826+
value={consumerSecret || ''}
827+
id='consumerSecretInput'
828+
helperText={(
829+
<FormattedMessage
821830
id='Apis.Details.TryOutConsole.consumerSecret.required.helper'
822-
defaultMessage='Consumer Secret is required to generate a new Test Key.'
831+
defaultMessage='Enter the Consumer Secret for the selected application to generate a test key.'
823832
/>
824-
: null
825-
}
826-
InputProps={{
827-
autoComplete: 'new-password',
828-
endAdornment: (
829-
<InputAdornment position='end'>
830-
<IconButton
831-
edge='end'
832-
aria-label='toggle consumer secret visibility'
833-
onClick={() => setShowSecret(!showSecret)}
834-
size='large'
835-
>
836-
{showSecret ? <VisibilityOff /> : <Visibility />}
837-
</IconButton>
838-
</InputAdornment>
839-
),
833+
)}
834+
InputProps={{
835+
autoComplete: 'new-password',
836+
endAdornment: (
837+
<InputAdornment position='end'>
838+
<IconButton
839+
edge='end'
840+
aria-label='toggle consumer secret visibility'
841+
onClick={() => setShowSecret(!showSecret)}
842+
size='large'
843+
>
844+
{showSecret ? <VisibilityOff /> : <Visibility />}
845+
</IconButton>
846+
</InputAdornment>
847+
),
848+
}}
849+
/>
850+
</DialogContent>
851+
<DialogActions>
852+
<Button onClick={() => {
853+
setSecretDialogOpen(false);
854+
setConsumerSecret('');
840855
}}
841-
/>
842-
)}
843-
</Grid>
844-
</Box>
856+
>
857+
<FormattedMessage
858+
id='Apis.Details.ApiConsole.generate.test.key.dialog.cancel'
859+
defaultMessage='Cancel'
860+
/>
861+
</Button>
862+
<Button
863+
variant='contained'
864+
onClick={() => {
865+
setSecretDialogOpen(false);
866+
generateAccessToken(consumerSecret);
867+
}}
868+
disabled={!consumerSecret?.trim()}
869+
>
870+
<FormattedMessage
871+
id='Apis.Details.ApiConsole.generate.test.key.dialog.generate'
872+
defaultMessage='Generate'
873+
/>
874+
</Button>
875+
</DialogActions>
876+
</Dialog>
877+
)}
845878
{((!api.advertiseInfo || !api.advertiseInfo.advertised)
846879
&& (api.gatewayVendor === 'wso2' || !api.gatewayVendor)) ? (
847880
<Box display='block' justifyContent='center'>
@@ -954,7 +987,8 @@ function TryOutController(props) {
954987
<>
955988
<Button
956989
onClick={securitySchemeType === 'API-KEY' ? generateApiKey
957-
: generateAccessToken}
990+
: (isConsumerSecretRequired
991+
? () => setSecretDialogOpen(true) : generateAccessToken)}
958992
variant='contained'
959993
color='grey'
960994
className={classes.genKeyButton}
@@ -981,11 +1015,11 @@ function TryOutController(props) {
9811015
id='Apis.Details.TryOutConsole.access.token.tooltip'
9821016
defaultMessage='You can use your existing Access Token or generate a new Test Key.'
9831017
/>
984-
{!enableGetTestKeyButton && securitySchemeType === 'OAUTH' && isMultipleClientSecretsAllowed && (
1018+
{isConsumerSecretRequired && (
9851019
<div style={{ marginTop: 4, fontWeight: 500 }}>
9861020
<FormattedMessage
987-
id='Apis.Details.TryOutConsole.consumer.secret.required'
988-
defaultMessage='Consumer Secret is required to generate a new Test Key.'
1021+
id='Apis.Details.TryOutConsole.consumer.secret.dialog.hint'
1022+
defaultMessage='You will be prompted for the Consumer Secret.'
9891023
/>
9901024
</div>
9911025
)}

0 commit comments

Comments
 (0)