Skip to content

Commit

Permalink
yarn format:apply
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Sep 27, 2022
1 parent 94c3a69 commit ad1e169
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 64 deletions.
17 changes: 12 additions & 5 deletions src/app/AppLayout/AuthModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const AuthModal: React.FunctionComponent<AuthModalProps> = (props) => {
first(),
filter((target) => target !== NO_TARGET),
map((target) => target.connectUrl),
mergeMap(connectUrl => context.jmxCredentials.setCredential(connectUrl, username, password))
mergeMap((connectUrl) => context.jmxCredentials.setCredential(connectUrl, username, password))
)
.subscribe((result) => {
if (result) {
Expand All @@ -89,10 +89,17 @@ export const AuthModal: React.FunctionComponent<AuthModalProps> = (props) => {
title="Authentication Required"
description={
<Text>
This target JVM requires authentication. The credentials you provide here will be passed from Cryostat to the target when establishing JMX connections.
Enter credentials specific to this target, or go to <Link onClick={props.onDismiss} to="/security">Security</Link> to add a credential matching multiple targets.
Visit <Link onClick={props.onDismiss} to="/settings">Settings</Link> to confirm and configure whether these credentials will be held only for this browser session
or stored encrypted in the Cryostat backend.
This target JVM requires authentication. The credentials you provide here will be passed from Cryostat to the
target when establishing JMX connections. Enter credentials specific to this target, or go to{' '}
<Link onClick={props.onDismiss} to="/security">
Security
</Link>{' '}
to add a credential matching multiple targets. Visit{' '}
<Link onClick={props.onDismiss} to="/settings">
Settings
</Link>{' '}
to confirm and configure whether these credentials will be held only for this browser session or stored
encrypted in the Cryostat backend.
</Text>
}
>
Expand Down
3 changes: 2 additions & 1 deletion src/app/Settings/AutoRefresh.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const Component = () => {

export const AutoRefresh: UserSetting = {
title: 'Auto-Refresh',
description: 'Set the refresh period for content views. Views normally update dynamically via WebSocket notifications, so this should not be needed unless WebSockets are not working.',
description:
'Set the refresh period for content views. Views normally update dynamically via WebSocket notifications, so this should not be needed unless WebSockets are not working.',
content: Component,
};
81 changes: 41 additions & 40 deletions src/app/Settings/CredentialsStorage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { Link } from 'react-router-dom';
import { Select, SelectOption, SelectVariant, Text } from '@patternfly/react-core';

import { UserSetting } from './Settings';
import { getFromLocalStorage, saveToLocalStorage } from "@app/utils/LocalStorage";
import { getFromLocalStorage, saveToLocalStorage } from '@app/utils/LocalStorage';

export interface Location {
key: string;
Expand All @@ -51,18 +51,17 @@ export interface Location {
export class Locations {
static readonly BROWSER_SESSION: Location = {
key: 'Session (Browser Memory)',
description: 'Keep credentials in browser memory for the current session only. When you close this browser tab the credentials will be forgotten.'
description:
'Keep credentials in browser memory for the current session only. When you close this browser tab the credentials will be forgotten.',
};
static readonly BACKEND: Location = {
key: 'Backend',
description: 'Keep credentials in encrypted Cryostat backend storage. These credentials will be available to other users and will be used for Automated Rules.'
description:
'Keep credentials in encrypted Cryostat backend storage. These credentials will be available to other users and will be used for Automated Rules.',
};
}

const locations = [
Locations.BROWSER_SESSION,
Locations.BACKEND,
];
const locations = [Locations.BROWSER_SESSION, Locations.BACKEND];

function getLocation(key: string): Location {
for (let l of locations) {
Expand All @@ -74,47 +73,49 @@ function getLocation(key: string): Location {
}

const Component = () => {

const [isExpanded, setExpanded] = React.useState(false);
const [selection, setSelection] = React.useState(Locations.BROWSER_SESSION);

const handleSelect = React.useCallback((_, selection) => {
let location = getLocation(selection);
setSelection(location);
setExpanded(false);
saveToLocalStorage("JMX_CREDENTIAL_LOCATION", selection)
}, [getLocation, setSelection, setExpanded, saveToLocalStorage]);
const handleSelect = React.useCallback(
(_, selection) => {
let location = getLocation(selection);
setSelection(location);
setExpanded(false);
saveToLocalStorage('JMX_CREDENTIAL_LOCATION', selection);
},
[getLocation, setSelection, setExpanded, saveToLocalStorage]
);

React.useEffect(() => {
handleSelect(
undefined,
getFromLocalStorage("JMX_CREDENTIAL_LOCATION", Locations.BROWSER_SESSION)
);
handleSelect(undefined, getFromLocalStorage('JMX_CREDENTIAL_LOCATION', Locations.BROWSER_SESSION));
}, [handleSelect, getLocation, getFromLocalStorage]);

return (<>
<Select
variant={SelectVariant.single}
onToggle={setExpanded}
onSelect={handleSelect}
isOpen={isExpanded}
selections={selection.key}
>
{
locations.map(location => <SelectOption key={location.key} value={location.key} description={location.description} />)
}
</Select>
</>);
}
return (
<>
<Select
variant={SelectVariant.single}
onToggle={setExpanded}
onSelect={handleSelect}
isOpen={isExpanded}
selections={selection.key}
>
{locations.map((location) => (
<SelectOption key={location.key} value={location.key} description={location.description} />
))}
</Select>
</>
);
};

export const CredentialsStorage: UserSetting = {
title: 'JMX Credentials Storage',
description: <Text>
When you attempt to connect to a target application which requires authentication
you will see a prompt for credentials to present to the application and complete the
connection. You can choose where to persist these credentials. Any credentials added
through the <Link to="/security">Security</Link> panel will always be stored in Cryostat
backend encrypted storage.
</Text>,
description: (
<Text>
When you attempt to connect to a target application which requires authentication you will see a prompt for
credentials to present to the application and complete the connection. You can choose where to persist these
credentials. Any credentials added through the <Link to="/security">Security</Link> panel will always be stored in
Cryostat backend encrypted storage.
</Text>
),
content: Component,
}
};
13 changes: 4 additions & 9 deletions src/app/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,13 @@ import { WebSocketDebounce } from './WebSocketDebounce';
import { AutoRefresh } from './AutoRefresh';

export const Settings: React.FunctionComponent<{}> = () => {
const settings =
[
NotificationControl,
CredentialsStorage,
DeletionDialogControl,
WebSocketDebounce,
AutoRefresh,
].map(c => ({
const settings = [NotificationControl, CredentialsStorage, DeletionDialogControl, WebSocketDebounce, AutoRefresh].map(
(c) => ({
title: c.title,
description: c.description,
element: React.createElement(c.content, null),
}));
})
);
return (
<>
<BreadcrumbPage pageTitle="Settings">
Expand Down
5 changes: 1 addition & 4 deletions src/app/Shared/Services/JmxCredentials.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,10 @@ export interface Credential {
}

export class JmxCredentials {

// TODO replace with Redux?
private readonly store = new Map<string, Credential>();

constructor(
private readonly api: () => ApiService
) { }
constructor(private readonly api: () => ApiService) {}

setCredential(targetId: string, username: string, password: string): Observable<boolean> {
let location = getFromLocalStorage('JMX_CREDENTIAL_LOCATION', Locations.BROWSER_SESSION);
Expand Down
18 changes: 14 additions & 4 deletions src/app/Shared/Services/Login.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ export class LoginService {
private readonly sessionState = new ReplaySubject<SessionState>(1);
readonly authority: string;

constructor(private readonly target: TargetService, private readonly jmxCredentials: JmxCredentials, private readonly settings: SettingsService) {
constructor(
private readonly target: TargetService,
private readonly jmxCredentials: JmxCredentials,
private readonly settings: SettingsService
) {
let apiAuthority = process.env.CRYOSTAT_AUTHORITY;
if (!apiAuthority) {
apiAuthority = '';
Expand Down Expand Up @@ -154,10 +158,16 @@ export class LoginService {
}

getHeaders(): Observable<Headers> {
return combineLatest([this.getToken(), this.getAuthMethod(), this.target.target().pipe(map(target => target.connectUrl), concatMap(connect => this.jmxCredentials.getCredential(connect)))])
.pipe(
return combineLatest([
this.getToken(),
this.getAuthMethod(),
this.target.target().pipe(
map((target) => target.connectUrl),
concatMap((connect) => this.jmxCredentials.getCredential(connect))
),
]).pipe(
map((parts: [string, AuthMethod, Credential | undefined]) => this.getAuthHeaders(parts[0], parts[1], parts[2])),
first(),
first()
);
}

Expand Down
11 changes: 10 additions & 1 deletion src/app/Shared/Services/Services.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,16 @@ const notificationChannel = new NotificationChannel(NotificationsInstance, login
const reports = new ReportService(login, NotificationsInstance);
const targets = new TargetsService(api, NotificationsInstance, login, notificationChannel);

const defaultServices: Services = { target: TargetInstance, targets, api, jmxCredentials, notificationChannel, reports, settings, login };
const defaultServices: Services = {
target: TargetInstance,
targets,
api,
jmxCredentials,
notificationChannel,
reports,
settings,
login,
};

const ServiceContext: React.Context<Services> = React.createContext(defaultServices);

Expand Down

0 comments on commit ad1e169

Please sign in to comment.