/* * Copyright (C) 2023 Red Hat, Inc. * SPDX-License-Identifier: LGPL-2.1-or-later */ import cockpit from "cockpit"; import React, { useState } from "react"; import { ActionList, ActionListItem } from "@patternfly/react-core/dist/esm/components/ActionList/index.js"; import { Alert } from "@patternfly/react-core/dist/esm/components/Alert/index.js"; import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js"; import { Form, FormGroup } from "@patternfly/react-core/dist/esm/components/Form/index.js"; import { InputGroup, InputGroupItem } from "@patternfly/react-core/dist/esm/components/InputGroup/index.js"; import { Modal, ModalBody, ModalFooter, ModalHeader } from "@patternfly/react-core/dist/esm/components/Modal/index.js"; import { TextInput } from "@patternfly/react-core/dist/esm/components/TextInput/index.js"; import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js"; import { EyeIcon } from "@patternfly/react-icons/dist/esm/icons/eye-icon"; import { EyeSlashIcon } from "@patternfly/react-icons/dist/esm/icons/eye-slash-icon"; import { LockIcon } from "@patternfly/react-icons/dist/esm/icons/lock-icon"; import { findExistingSystems, unlockDevice, } from "../../../apis/storage_devicetree.js"; import { getDevicesAction } from "../../../actions/storage-actions.js"; import { FormHelper } from "cockpit-components-form-helper.jsx"; import { InlineNotification } from "cockpit-components-inline-notification.jsx"; const _ = cockpit.gettext; const LockedDevices = ({ id, lockedEncryptedDevices }) => { return ( {lockedEncryptedDevices.map(device => ( {device} ))} ); }; export const EncryptedDevices = ({ dispatch, idPrefix, lockedEncryptedDevices }) => { const [showUnlockDialog, setShowUnlockDialog] = useState(false); return ( <> } > {_("Unlock encrypted partitions to keep existing data and show more installation methods.")} {showUnlockDialog && setShowUnlockDialog(false)} lockedEncryptedDevices={lockedEncryptedDevices} />} ); }; const UnlockDialog = ({ dispatch, lockedEncryptedDevices, onClose }) => { const [passphrase, setPassphrase] = useState(""); const [passphraseHidden, setPassphraseHidden] = useState(true); const [dialogWarning, setDialogWarning] = useState(); const [dialogSuccess, setDialogSuccess] = useState(); const [inProgress, setInProgress] = useState(false); const idPrefix = "unlock-device-dialog"; const onSubmit = () => { setInProgress(true); return Promise.allSettled( lockedEncryptedDevices.map(device => ( unlockDevice({ device, passphrase }) )) ).then( res => { if (res.every(r => r.status === "fulfilled")) { if (res.every(r => r.value)) { // Refresh the list of existing systems after unlocking the devices findExistingSystems({ onFail: exc => setDialogWarning(exc.message), onSuccess: () => { onClose(); dispatch(getDevicesAction()); }, }); } else { const unlockedDevs = res.reduce((acc, r, i) => { if (r.value) { acc.push(lockedEncryptedDevices[i]); } return acc; }, []); if (unlockedDevs.length > 0) { setDialogSuccess(cockpit.format(_("Successfully unlocked $0."), unlockedDevs.join(", "))); setDialogWarning(undefined); setPassphrase(""); } else { setDialogSuccess(undefined); setDialogWarning(_("Passphrase did not match any locked device")); } setInProgress(false); } // Blivet does not send a signal when a device is unlocked, // so we need to refresh the device data manually. dispatch(getDevicesAction()); } }, exc => { setDialogWarning(exc.message); setInProgress(false); } ); }; return ( onClose()} >
{ e.preventDefault(); onSubmit(); }}> {dialogSuccess && } setPassphrase(val)} />
); };