163 lines
5.1 KiB
TypeScript
163 lines
5.1 KiB
TypeScript
import { Form, Formik } from 'formik';
|
|
import { Key } from 'lucide-react';
|
|
import { useState } from 'react';
|
|
import { SchemaOf, bool, object } from 'yup';
|
|
|
|
import { withHideOnExtension } from '@/react/hooks/withHideOnExtension';
|
|
|
|
import { Widget } from '@@/Widget';
|
|
import { LoadingButton } from '@@/buttons';
|
|
import {
|
|
file,
|
|
withFileExtension,
|
|
} from '@@/form-components/yup-file-validation';
|
|
import { TextTip } from '@@/Tip/TextTip';
|
|
import { FormControl } from '@@/form-components/FormControl';
|
|
import { FileUploadField } from '@@/form-components/FileUpload';
|
|
import { SwitchField } from '@@/form-components/SwitchField';
|
|
|
|
import { useUpdateSSLConfigMutation } from '../useUpdateSSLConfigMutation';
|
|
import { useSSLSettings } from '../../queries/useSSLSettings';
|
|
|
|
interface FormValues {
|
|
certFile?: File;
|
|
keyFile?: File;
|
|
forceHTTPS: boolean;
|
|
}
|
|
|
|
export const SSLSettingsPanelWrapper = withHideOnExtension(SSLSettingsPanel);
|
|
|
|
function SSLSettingsPanel() {
|
|
const settingsQuery = useSSLSettings();
|
|
const [reloadingPage, setReloadingPage] = useState(false);
|
|
const mutation = useUpdateSSLConfigMutation();
|
|
|
|
if (!settingsQuery.data) {
|
|
return null;
|
|
}
|
|
|
|
const initialValues: FormValues = {
|
|
certFile: undefined,
|
|
keyFile: undefined,
|
|
forceHTTPS: !settingsQuery.data.httpEnabled,
|
|
};
|
|
|
|
return (
|
|
<Widget>
|
|
<Widget.Title icon={Key} title="SSL certificate" />
|
|
<Widget.Body>
|
|
<Formik
|
|
initialValues={initialValues}
|
|
onSubmit={handleSubmit}
|
|
validationSchema={validation}
|
|
validateOnMount
|
|
>
|
|
{({ values, setFieldValue, isValid, errors, dirty }) => (
|
|
<Form className="form-horizontal">
|
|
<div className="form-group">
|
|
<div className="col-sm-12">
|
|
<TextTip color="orange">
|
|
Forcing HTTPs only will cause Portainer to stop listening on
|
|
the HTTP port. Any edge agent environment that is using HTTP
|
|
will no longer be available.
|
|
</TextTip>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<div className="col-sm-12">
|
|
<SwitchField
|
|
checked={values.forceHTTPS}
|
|
label="Force HTTPS only"
|
|
labelClass="col-sm-3 col-lg-2"
|
|
name="forceHTTPS"
|
|
onChange={(value) => setFieldValue('forceHTTPS', value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<div className="col-sm-12">
|
|
<TextTip color="blue">
|
|
Provide a new SSL Certificate to replace the existing one
|
|
that is used for HTTPS connections.
|
|
</TextTip>
|
|
</div>
|
|
</div>
|
|
|
|
<FormControl
|
|
label="SSL/TLS certificate"
|
|
tooltip="Select an X.509 certificate file, commonly a crt, cer or pem file."
|
|
inputId="ca-cert-field"
|
|
errors={errors.certFile}
|
|
>
|
|
<FileUploadField
|
|
inputId="ca-cert-field"
|
|
name="certFile"
|
|
onChange={(file) => setFieldValue('certFile', file)}
|
|
value={values.certFile}
|
|
/>
|
|
</FormControl>
|
|
|
|
<FormControl
|
|
label="SSL/TLS private key"
|
|
tooltip="Select a private key file, commonly a key, or pem file."
|
|
inputId="ca-cert-field"
|
|
errors={errors.keyFile}
|
|
>
|
|
<FileUploadField
|
|
inputId="ca-cert-field"
|
|
name="keyFile"
|
|
onChange={(file) => setFieldValue('keyFile', file)}
|
|
value={values.keyFile}
|
|
/>
|
|
</FormControl>
|
|
|
|
<div className="form-group">
|
|
<div className="col-sm-12">
|
|
<LoadingButton
|
|
isLoading={mutation.isLoading || reloadingPage}
|
|
disabled={!dirty || !isValid}
|
|
loadingText={reloadingPage ? 'Reloading' : 'Saving'}
|
|
className="!ml-0"
|
|
>
|
|
Save SSL settings
|
|
</LoadingButton>
|
|
</div>
|
|
</div>
|
|
</Form>
|
|
)}
|
|
</Formik>
|
|
</Widget.Body>
|
|
</Widget>
|
|
);
|
|
|
|
function handleSubmit({ certFile, forceHTTPS, keyFile }: FormValues) {
|
|
mutation.mutate(
|
|
{ certFile, httpEnabled: !forceHTTPS, keyFile },
|
|
{
|
|
async onSuccess() {
|
|
await new Promise((resolve) => {
|
|
setTimeout(resolve, 10000);
|
|
});
|
|
window.location.reload();
|
|
setReloadingPage(true);
|
|
},
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
function validation(): SchemaOf<FormValues> {
|
|
return object({
|
|
certFile: withFileExtension(file(), [
|
|
'pem',
|
|
'crt',
|
|
'cer',
|
|
'cert',
|
|
]).optional(),
|
|
keyFile: withFileExtension(file(), ['pem', 'key']).optional(),
|
|
forceHTTPS: bool().required(),
|
|
});
|
|
}
|