Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

227 lines
6.6 KiB

import { FC, useCallback, useMemo, useRef, useState } from 'react';
import { Grid } from '@mui/material';
import ActionGroup from '../ActionGroup';
import api from '../../lib/api';
import handleAPIError from '../../lib/handleAPIError';
import MessageGroup, { MessageGroupForwardedRefContent } from '../MessageGroup';
import OutlinedInputWithLabel from '../OutlinedInputWithLabel';
import UncontrolledInput from '../UncontrolledInput';
import useFormikUtils from '../../hooks/useFormikUtils';
import Spinner from '../Spinner';
import schema from './testAccessSchema';
import { BodyText } from '../Text';
const TestAccessForm: FC<TestAccessFormProps> = (props) => {
const { setResponse, tools } = props;
const messageGroupRef = useRef<MessageGroupForwardedRefContent>(null);
const [loadingInquiry, setLoadingInquiry] = useState<boolean>(false);
const [moreActions, setMoreActions] = useState<ContainedButtonProps[]>([]);
const setApiMessage = useCallback(
(message?: Message) =>
messageGroupRef.current?.setMessage?.call(null, 'api', message),
[],
);
const { disabledSubmit, formik, formikErrors, handleChange } =
useFormikUtils<TestAccessFormikValues>({
initialValues: {
ip: '',
password: '',
},
onSubmit: (values, { setSubmitting }) => {
setApiMessage();
setLoadingInquiry(true);
setMoreActions([]);
setResponse(undefined);
const { ip, password } = values;
api
.put<APICommandInquireHostResponseBody>('/command/inquire-host', {
ipAddress: ip,
password,
})
.then(({ data }) => {
const { badSshKeys, isConnected } = data;
if (badSshKeys) {
setApiMessage({
children: (
<>
Host identification at {ip} changed. If this is valid,
please delete the conflicting SSH host key.
</>
),
type: 'warning',
});
setMoreActions([
{
background: 'red',
children: 'Delete keys',
onClick: () => {
tools.confirm.prepare({
actionProceedText: 'Delete',
content: (
<BodyText>
There&apos;s a different host key on {ip}, which could
mean a MITM attack. But if this change is expected,
you can delete the known host key(s) to resolve the
conflict.
</BodyText>
),
onProceedAppend: () => {
tools.confirm.loading(true);
api
.delete('/ssh-key/conflict', {
data: badSshKeys,
})
.then(() => {
tools.confirm.finish('Success', {
children: (
<>Started job to delete host key(s) for {ip}.</>
),
});
setMoreActions([]);
})
.catch((error) => {
const emsg = handleAPIError(error);
emsg.children = (
<>Failed to delete host key(s). {emsg.children}</>
);
tools.confirm.finish('Error', emsg);
});
},
proceedColour: 'red',
titleText: `Delete all known SSH host key(s) for ${ip}?`,
});
tools.confirm.open(true);
},
type: 'button',
},
]);
return;
}
if (!isConnected) {
setApiMessage({
children: (
<>
Failed to connect. Please make sure the credentials are
correct, and the host is reachable from this striker.
</>
),
type: 'warning',
});
return;
}
setResponse({
...data,
hostIpAddress: ip,
hostPassword: password,
});
setApiMessage();
})
.catch((error) => {
const emsg = handleAPIError(error);
emsg.children = (
<>
Failed to access {ip}. {emsg.children}
</>
);
setApiMessage(emsg);
})
.finally(() => {
setSubmitting(false);
setLoadingInquiry(false);
});
},
validationSchema: schema,
});
const ipChain = useMemo<string>(() => 'ip', []);
const passwordChain = useMemo<string>(() => 'password', []);
return (
<Grid
component="form"
container
columns={{ xs: 1, sm: 2 }}
onSubmit={(event) => {
event.preventDefault();
formik.submitForm();
}}
spacing="1em"
>
<Grid item xs={1}>
<UncontrolledInput
input={
<OutlinedInputWithLabel
disableAutofill
id={ipChain}
label="IP address"
name={ipChain}
onChange={handleChange}
required
value={formik.values.ip}
/>
}
/>
</Grid>
<Grid item xs={1}>
<UncontrolledInput
input={
<OutlinedInputWithLabel
disableAutofill
id={passwordChain}
label="Password"
name={passwordChain}
onChange={handleChange}
required
type="password"
value={formik.values.password}
/>
}
/>
</Grid>
<Grid item width="100%">
<MessageGroup count={1} messages={formikErrors} ref={messageGroupRef} />
</Grid>
<Grid item width="100%">
{loadingInquiry ? (
<Spinner mt={0} />
) : (
<ActionGroup
actions={[
...moreActions,
{
background: 'blue',
children: 'Test access',
disabled: disabledSubmit,
type: 'submit',
},
]}
/>
)}
</Grid>
</Grid>
);
};
export default TestAccessForm;