Skip to content

Commit

Permalink
BED-4541: Add server version to profile page (#696)
Browse files Browse the repository at this point in the history
* add version to profile page

* included in error-state

* add optional chaining to display

* WIP

* updated version content

* remove y padding on page

* Add test mock for api version
  • Loading branch information
StephenHinck committed Jul 17, 2024
1 parent 09e66d6 commit 68ac15e
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 81 deletions.
42 changes: 42 additions & 0 deletions packages/javascript/bh-shared-ui/src/components/ApiVersion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2024 Specter Ops, Inc.
//
// Licensed under the Apache License, Version 2.0
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

import { Box, Skeleton, Typography } from '@mui/material';
import { apiClient } from '../utils';
import React from 'react';
import { useQuery } from 'react-query';

const ApiVersion: React.FC = () => {
const getVersionQuery = useQuery(['Version'], ({ signal }) =>
apiClient.version({ signal }).then((res) => res.data.data)
);

const version = getVersionQuery;

if (getVersionQuery.isLoading)
return (
<Box paddingX={2}>
<Skeleton variant='text' />
</Box>
);

if (getVersionQuery.isError)
return <Typography variant='body2'>API Version: Unknown, please refresh the page or report a bug.</Typography>;

return <Typography variant='body2'>API Version: {version.data.server_version}</Typography>;
};

export default ApiVersion;
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type PageWithTitleProps = ContainerProps<
const PageWithTitle: React.FC<PageWithTitleProps> = ({ title, pageDescription, children, ...rest }) => {
return (
<Container maxWidth='xl' {...rest}>
<Box component={'header'} my={2}>
<Box component={'header'} >
{title && <Typography variant='h1'>{title}</Typography>}
{pageDescription}
</Box>
Expand Down
2 changes: 2 additions & 0 deletions packages/javascript/bh-shared-ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,5 @@ export { default as WebGLDisabledAlert } from './WebGLDisabledAlert';

export * from './DocumentationLinks';
export { default as DocumentationLinks } from './DocumentationLinks';

export { default as ApiVersion } from './ApiVersion';
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ import { setupServer } from 'msw/node';
const server = setupServer(
rest.get(`/api/v2/self`, (req, res) => {
return res();
}),
rest.get(`/api/version`, (req, res, ctx) => {
return res(
ctx.json({
data: {
API: {
current_version: 'v2',
deprecated_version: 'v1',
},
server_version: 'v999.999.999',
},
})
);
})
);

Expand Down
177 changes: 97 additions & 80 deletions packages/javascript/bh-shared-ui/src/views/UserProfile/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { PutUserAuthSecretRequest } from 'js-client-library';
import { useNotifications } from '../../providers';
import { apiClient, getUsername } from '../../utils';
import {
ApiVersion,
Disable2FADialog,
Enable2FADialog,
PageWithTitle,
Expand Down Expand Up @@ -104,6 +105,9 @@ const UserProfile = () => {
<br />
Please try refreshing the page or logging in again.
</Alert>
<Box sx={{ flexGrow: 1, alignContent: 'flex-end' }}>
<ApiVersion></ApiVersion>
</Box>
</PageWithTitle>
);
}
Expand All @@ -120,61 +124,49 @@ const UserProfile = () => {
Review and manage your user account.
</Typography>
}>
<Typography variant='h2'>User Information</Typography>

<Grid container spacing={2} alignItems='center'>
<Grid item xs={3}>
<Typography variant='body1'>Email</Typography>
</Grid>
<Grid item xs={9}>
<Typography variant='body1'>{user?.email_address}</Typography>
</Grid>

<Grid item xs={3}>
<Typography variant='body1'>Name</Typography>
</Grid>
<Grid item xs={9}>
<Typography variant='body1'>
<TextWithFallback text={getUsername(user)} fallback='Unknown' />
</Typography>
</Grid>
<Box
display={'flex'}
flexDirection={'column'}
justifyContent={'space-between'}
height={'80vh'}
margin={'0'}
padding={'0'}>
<Typography variant='h2'>User Information</Typography>
<Box>
<Grid container spacing={2} alignItems='center'>
<Grid item xs={3}>
<Typography variant='body1'>Email</Typography>
</Grid>
<Grid item xs={9}>
<Typography variant='body1'>{user?.email_address}</Typography>
</Grid>

<Grid item xs={3}>
<Typography variant='body1'>Role</Typography>
</Grid>
<Grid item xs={9}>
<Typography variant='body1'>
<TextWithFallback text={user?.roles?.[0]?.name} fallback='Unknown' />
</Typography>
</Grid>
</Grid>
<Grid item xs={3}>
<Typography variant='body1'>Name</Typography>
</Grid>
<Grid item xs={9}>
<Typography variant='body1'>
<TextWithFallback text={getUsername(user)} fallback='Unknown' />
</Typography>
</Grid>

<Box mt={2}>
<Typography variant='h2'>Authentication</Typography>
</Box>
<Grid container spacing={2} alignItems='center'>
<Grid container item>
<Grid item xs={3}>
<Typography variant='body1'>API Key Management</Typography>
</Grid>
<Grid item xs={2}>
<Button
variant='contained'
color='primary'
size='small'
disableElevation
fullWidth
onClick={() => setUserTokenManagementDialogOpen(true)}
data-testid='my-profile_button-api-key-management'>
API Key Management
</Button>
<Grid item xs={3}>
<Typography variant='body1'>Role</Typography>
</Grid>
<Grid item xs={9}>
<Typography variant='body1'>
<TextWithFallback text={user?.roles?.[0]?.name} fallback='Unknown' />
</Typography>
</Grid>
</Grid>
</Grid>
{user.saml_provider_id === null && (
<>

<Box mt={2}>
<Typography variant='h2'>Authentication</Typography>
</Box>
<Grid container spacing={2} alignItems='center'>
<Grid container item>
<Grid item xs={3}>
<Typography variant='body1'>Password</Typography>
<Typography variant='body1'>API Key Management</Typography>
</Grid>
<Grid item xs={2}>
<Button
Expand All @@ -183,40 +175,65 @@ const UserProfile = () => {
size='small'
disableElevation
fullWidth
onClick={() => setChangePasswordDialogOpen(true)}
data-testid='my-profile_button-reset-password'>
Reset Password
onClick={() => setUserTokenManagementDialogOpen(true)}
data-testid='my-profile_button-api-key-management'>
API Key Management
</Button>
</Grid>
</Grid>
{user.saml_provider_id === null && (
<>
<Grid container item>
<Grid item xs={3}>
<Typography variant='body1'>Password</Typography>
</Grid>
<Grid item xs={2}>
<Button
variant='contained'
color='primary'
size='small'
disableElevation
fullWidth
onClick={() => setChangePasswordDialogOpen(true)}
data-testid='my-profile_button-reset-password'>
Reset Password
</Button>
</Grid>
</Grid>

<Grid container item>
<Grid item xs={3}>
<Typography variant='body1'>Multi-Factor Authentication</Typography>
</Grid>
<Grid item xs={9}>
<Box display='flex' alignItems='center'>
<Switch
inputProps={{
'aria-label': 'Multi-Factor Authentication Enabled',
}}
checked={user.AuthSecret?.totp_activated}
onChange={() => {
if (!user.AuthSecret?.totp_activated) setEnable2FADialogOpen(true);
else setDisable2FADialogOpen(true);
}}
color='primary'
data-testid='my-profile_switch-multi-factor-authentication'
/>
{user.AuthSecret?.totp_activated && (
<Typography variant='body1'>Enabled</Typography>
)}
</Box>
</Grid>
</Grid>
</>
)}
</Grid>
<Grid container item>
<Grid item xs={3}>
<Typography variant='body1'>Multi-Factor Authentication</Typography>
</Grid>
<Grid item xs={9}>
<Box display='flex' alignItems='center'>
<Switch
inputProps={{
'aria-label': 'Multi-Factor Authentication Enabled',
}}
checked={user.AuthSecret?.totp_activated}
onChange={() => {
if (!user.AuthSecret?.totp_activated)
setEnable2FADialogOpen(true);
else setDisable2FADialogOpen(true);
}}
color='primary'
data-testid='my-profile_switch-multi-factor-authentication'
/>
{user.AuthSecret?.totp_activated && (
<Typography variant='body1'>Enabled</Typography>
)}
</Box>
</Grid>
</Grid>
</>
)}
</Grid>
</Box>
<Box sx={{ flexGrow: 1, alignContent: 'flex-end' }}>
<ApiVersion></ApiVersion>
</Box>
</Box>
</PageWithTitle>

<PasswordDialog
Expand Down

0 comments on commit 68ac15e

Please sign in to comment.