Skip to content

Commit a637a42

Browse files
authored
Merge pull request #888 from wso2/feature-governance
Implement governance and compliance dashboards
2 parents ee7daad + 8570123 commit a637a42

File tree

60 files changed

+9913
-296
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+9913
-296
lines changed

portals/admin/src/main/webapp/WEB-INF/web.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
<servlet-mapping>
120120
<servlet-name>index</servlet-name>
121121
<url-pattern>/tasks/*</url-pattern>
122+
<url-pattern>/governance/*</url-pattern>
122123
<url-pattern>/microgateway/*</url-pattern>
123124
<url-pattern>/settings/*</url-pattern>
124125
<url-pattern>/categories/*</url-pattern>

portals/admin/src/main/webapp/package-lock.json

Lines changed: 352 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portals/admin/src/main/webapp/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"@mui/lab": "^5.0.0-alpha.160",
3838
"@mui/material": "^5.15.4",
3939
"@mui/system": "^5.15.4",
40+
"@mui/x-charts": "^7.24.0",
4041
"@mui/x-date-pickers": "^7.14.0",
4142
"@mui/x-tree-view": "^6.17.0",
4243
"@react-pdf/renderer": "^3.4.4",

portals/admin/src/main/webapp/services/login/login_callback.jsp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@
140140
cookie.setMaxAge((int) expiresIn);
141141
response.addCookie(cookie);
142142
143+
cookie = new Cookie("AM_ADMIN_ACC_TOKEN_DEFAULT_P2", accessTokenPart2);
144+
cookie.setPath(proxyContext != null ? proxyContext + "/api/am/governance/" : "/api/am/governance/");
145+
cookie.setHttpOnly(true);
146+
cookie.setSecure(true);
147+
cookie.setMaxAge((int) expiresIn);
148+
response.addCookie(cookie);
149+
143150
cookie = new Cookie("AM_REF_TOKEN_DEFAULT_P2", refreshTokenPart2);
144151
cookie.setPath(context + "/");
145152
cookie.setHttpOnly(true);

portals/admin/src/main/webapp/services/logout/logout_callback.jsp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@
4141
cookie.setMaxAge(2);
4242
response.addCookie(cookie);
4343
44+
cookie = new Cookie("AM_ADMIN_ACC_TOKEN_DEFAULT_P2", "");
45+
cookie.setPath("/api/am/governance/" + context + "/");
46+
cookie.setHttpOnly(true);
47+
cookie.setSecure(true);
48+
cookie.setMaxAge(2);
49+
response.addCookie(cookie);
50+
4451
cookie = new Cookie("AM_REF_TOKEN_DEFAULT_P2", "");
4552
cookie.setPath(context + "/");
4653
cookie.setHttpOnly(true);

portals/admin/src/main/webapp/services/refresh/refresh.jsp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@
139139
cookie.setMaxAge((int) expiresIn);
140140
response.addCookie(cookie);
141141
142+
cookie = new Cookie("AM_ADMIN_ACC_TOKEN_DEFAULT_P2", accessTokenPart2);
143+
cookie.setPath("/api/am/governance/");
144+
cookie.setHttpOnly(true);
145+
cookie.setSecure(true);
146+
cookie.setMaxAge((int) expiresIn);
147+
response.addCookie(cookie);
148+
142149
cookie = new Cookie("AM_REF_TOKEN_DEFAULT_P2", refreshTokenPart2);
143150
cookie.setPath(context + "/");
144151
cookie.setHttpOnly(true);

portals/admin/src/main/webapp/site/public/locales/en.json

Lines changed: 184 additions & 0 deletions
Large diffs are not rendered by default.

portals/admin/src/main/webapp/site/public/locales/fr.json

Lines changed: 184 additions & 0 deletions
Large diffs are not rendered by default.

portals/admin/src/main/webapp/source/dev/auth_login.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,13 @@ function devServerBefore(app) {
153153
maxAge,
154154
});
155155

156+
res.cookie('AM_ACC_TOKEN_DEFAULT_P2', accessTokenPart2, {
157+
path: '/api/am/governance/',
158+
httpOnly: true,
159+
secure: true,
160+
maxAge,
161+
});
162+
156163
res.cookie('AM_ACC_TOKEN_DEFAULT_P2', accessTokenPart2, {
157164
path: '/api/am/service-catalog/v1/',
158165
httpOnly: true,

portals/admin/src/main/webapp/source/src/app/components/AdminPages/Addons/ListBase.jsx

Lines changed: 115 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ function ListBase(props) {
5656
addedActions,
5757
enableCollapsable,
5858
renderExpandableRow,
59+
useContentBase,
5960
} = props;
6061

6162
const [searchText, setSearchText] = useState('');
@@ -223,6 +224,7 @@ function ListBase(props) {
223224
customToolbar: null,
224225
responsive: 'vertical',
225226
searchText,
227+
rowsPerPageOptions: [5, 10, 25, 50, 100],
226228
onColumnSortChange,
227229
textLabels: {
228230
body: {
@@ -244,137 +246,137 @@ function ListBase(props) {
244246
},
245247
expandableRows: enableCollapsable,
246248
renderExpandableRow,
249+
...props.options,
247250
};
248251

249252
// If no apiCall is provided OR,
250253
// retrieved data is empty, display an information card.
251254
if (!apiCall || (data && data.length === 0)) {
252-
return (
253-
<ContentBase
254-
{...pageProps}
255-
pageStyle='small'
256-
>
257-
<Card>
258-
<CardContent>
259-
{emptyBoxTitle}
260-
{emptyBoxContent}
261-
</CardContent>
262-
<CardActions>
263-
{addButtonOverride || (
264-
EditComponent && (<EditComponent updateList={fetchData} {...addButtonProps} />)
265-
)}
266-
</CardActions>
267-
</Card>
268-
</ContentBase>
255+
const content = (
256+
<Card>
257+
<CardContent>
258+
{emptyBoxTitle}
259+
{emptyBoxContent}
260+
</CardContent>
261+
<CardActions>
262+
{addButtonOverride || (
263+
EditComponent && (<EditComponent updateList={fetchData} {...addButtonProps} />)
264+
)}
265+
</CardActions>
266+
</Card>
269267
);
268+
269+
return useContentBase ? (
270+
<ContentBase {...pageProps} pageStyle='small'>{content}</ContentBase>
271+
) : content;
270272
}
271273

272274
// If apiCall is provided and data is not retrieved yet, display progress component
273275
if (!error && apiCall && !data) {
274-
return (
275-
<ContentBase pageStyle='paperLess'>
276-
<InlineProgress />
277-
</ContentBase>
278-
279-
);
276+
const content = <InlineProgress />;
277+
return useContentBase ? (
278+
<ContentBase pageStyle='paperLess'>{content}</ContentBase>
279+
) : content;
280280
}
281-
if (error) {
282-
return (
283-
<ContentBase {...pageProps}>
284-
<Alert severity='error'>{error}</Alert>
285-
</ContentBase>
286281

287-
);
282+
if (error) {
283+
const content = <Alert severity='error'>{error}</Alert>;
284+
return useContentBase ? (
285+
<ContentBase {...pageProps}>{content}</ContentBase>
286+
) : content;
288287
}
289-
return (
288+
289+
const mainContent = (
290290
<>
291-
<ContentBase {...pageProps}>
292-
{(searchActive || addButtonProps) && (
293-
<AppBar
294-
sx={{ borderBottom: '1px solid rgba(0, 0, 0, 0.12)' }}
295-
position='static'
296-
color='default'
297-
elevation={0}
298-
>
299-
<Toolbar>
300-
<Grid container spacing={2} alignItems='center'>
291+
{(searchActive || addButtonProps) && (
292+
<AppBar
293+
sx={{ borderBottom: '1px solid rgba(0, 0, 0, 0.12)' }}
294+
position='static'
295+
color='default'
296+
elevation={0}
297+
>
298+
<Toolbar>
299+
<Grid container spacing={2} alignItems='center'>
301300

302-
<Grid item>
303-
{searchActive && (<SearchIcon sx={{ display: 'block' }} color='inherit' />)}
304-
</Grid>
305-
<Grid item xs>
306-
{searchActive && (
307-
<TextField
308-
variant='standard'
309-
fullWidth
310-
placeholder={searchPlaceholder}
311-
sx={(theme) => ({
312-
'& .search-input': {
313-
fontSize: theme.typography.fontSize,
314-
},
315-
})}
316-
InputProps={{
317-
disableUnderline: true,
318-
className: 'search-input',
319-
}}
320-
// eslint-disable-next-line react/jsx-no-duplicate-props
321-
inputProps={{
322-
'aria-label': 'search-by-policy',
323-
}}
324-
onChange={filterData}
325-
value={searchText}
301+
<Grid item>
302+
{searchActive && (<SearchIcon sx={{ display: 'block' }} color='inherit' />)}
303+
</Grid>
304+
<Grid item xs>
305+
{searchActive && (
306+
<TextField
307+
variant='standard'
308+
fullWidth
309+
placeholder={searchPlaceholder}
310+
sx={(theme) => ({
311+
'& .search-input': {
312+
fontSize: theme.typography.fontSize,
313+
},
314+
})}
315+
InputProps={{
316+
disableUnderline: true,
317+
className: 'search-input',
318+
}}
319+
// eslint-disable-next-line react/jsx-no-duplicate-props
320+
inputProps={{
321+
'aria-label': 'search-by-policy',
322+
}}
323+
onChange={filterData}
324+
value={searchText}
325+
/>
326+
)}
327+
</Grid>
328+
<Grid item>
329+
{addButtonOverride || (
330+
EditComponent && (
331+
<EditComponent
332+
updateList={fetchData}
333+
{...addButtonProps}
326334
/>
327-
)}
328-
</Grid>
329-
<Grid item>
330-
{addButtonOverride || (
331-
EditComponent && (
332-
<EditComponent
333-
updateList={fetchData}
334-
{...addButtonProps}
335-
/>
336-
)
337-
)}
338-
<Tooltip title={(
339-
<FormattedMessage
340-
id='AdminPages.Addons.ListBase.reload'
341-
defaultMessage='Reload'
335+
)
336+
)}
337+
<Tooltip title={(
338+
<FormattedMessage
339+
id='AdminPages.Addons.ListBase.reload'
340+
defaultMessage='Reload'
341+
/>
342+
)}
343+
>
344+
<IconButton onClick={fetchData} size='large'>
345+
<RefreshIcon
346+
aria-label='refresh-advanced-policies'
347+
sx={{ display: 'block' }}
348+
color='inherit'
342349
/>
343-
)}
344-
>
345-
<IconButton onClick={fetchData} size='large'>
346-
<RefreshIcon
347-
aria-label='refresh-advanced-policies'
348-
sx={{ display: 'block' }}
349-
color='inherit'
350-
/>
351-
</IconButton>
352-
</Tooltip>
353-
</Grid>
350+
</IconButton>
351+
</Tooltip>
354352
</Grid>
355-
</Toolbar>
356-
</AppBar>
353+
</Grid>
354+
</Toolbar>
355+
</AppBar>
356+
)}
357+
<div>
358+
{data && data.length > 0 && (
359+
<MUIDataTable
360+
title={null}
361+
data={data}
362+
columns={columns}
363+
options={options}
364+
/>
357365
)}
366+
</div>
367+
{data && data.length === 0 && (
358368
<div>
359-
{data && data.length > 0 && (
360-
<MUIDataTable
361-
title={null}
362-
data={data}
363-
columns={columns}
364-
options={options}
365-
/>
366-
)}
369+
<Typography color='textSecondary' align='center'>
370+
{noDataMessage}
371+
</Typography>
367372
</div>
368-
{data && data.length === 0 && (
369-
<div>
370-
<Typography color='textSecondary' align='center'>
371-
{noDataMessage}
372-
</Typography>
373-
</div>
374-
)}
375-
</ContentBase>
373+
)}
376374
</>
377375
);
376+
377+
return useContentBase ? (
378+
<ContentBase {...pageProps}>{mainContent}</ContentBase>
379+
) : mainContent;
378380
}
379381

380382
ListBase.defaultProps = {
@@ -404,7 +406,10 @@ ListBase.defaultProps = {
404406
columProps: null,
405407
enableCollapsable: false,
406408
renderExpandableRow: null,
409+
useContentBase: true,
410+
options: {},
407411
};
412+
408413
ListBase.propTypes = {
409414
EditComponent: PropTypes.element,
410415
editComponentProps: PropTypes.shape({}),
@@ -432,5 +437,7 @@ ListBase.propTypes = {
432437
addedActions: PropTypes.shape([]),
433438
enableCollapsable: PropTypes.bool,
434439
renderExpandableRow: PropTypes.func,
440+
useContentBase: PropTypes.bool,
441+
options: PropTypes.shape({}),
435442
};
436443
export default ListBase;

0 commit comments

Comments
 (0)