From 1073af21305360bd33903c533cdac57e9f936294 Mon Sep 17 00:00:00 2001 From: Yuuta Liang Date: Tue, 28 Nov 2023 18:19:39 -0800 Subject: Move TUI and GUI into separate packages Signed-off-by: Yuuta Liang --- src/main/ui/gui/RevokeDialog.java | 184 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/main/ui/gui/RevokeDialog.java (limited to 'src/main/ui/gui/RevokeDialog.java') diff --git a/src/main/ui/gui/RevokeDialog.java b/src/main/ui/gui/RevokeDialog.java new file mode 100644 index 0000000..9cebc74 --- /dev/null +++ b/src/main/ui/gui/RevokeDialog.java @@ -0,0 +1,184 @@ +package ui.gui; + +import model.asn1.ASN1Object; +import model.asn1.UtcTime; +import model.pki.cert.Certificate; +import model.pki.crl.Reason; +import model.pki.crl.RevokedCertificate; +import ui.gui.widgets.GCBuilder; +import ui.gui.widgets.UIUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Arrays; + +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.WEST; +import static ui.gui.widgets.UIUtils.alert; + +/** + * A dialog that presents user with cert info, revocation reason, and revocation time. + * +----------------------------+ + * |Revoking: CN=xyz (Serial: 1)| + * |Reason: (Drop Down) | + * |Time: (ISO-8601 text) | + * | | + * | Revoke Cancel| + * +----------------------------+ + */ +public class RevokeDialog extends JDialog { + /** + * ISO8601 + */ + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + + /** + * The incoming certificate. + */ + private final Certificate crt; + + /** + * The result. + */ + private RevokedCertificate res; + + + /** + * Root pane + */ + private JPanel contentPane; + + /** + * OK button + */ + private JButton buttonOK; + + /** + * Cancel button + */ + private JButton buttonCancel; + + /** + * Reason + */ + private JComboBox comboBoxReason; + + /** + * Subject (not editable) + */ + private JTextField textFieldSubject; + + /** + * Time + */ + private JFormattedTextField formattedTextFieldTime; + + /** + * EFFECTS: Init GUI with the given cert. + */ + public RevokeDialog(Certificate crt) { + this.crt = crt; + + contentPane = new JPanel(); + contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.PAGE_AXIS)); + contentPane.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + contentPane.add(renderForm()); + + contentPane.add(UIUtils.createActionsPane(buttonOK = new JButton("Revoke"), + buttonCancel = new JButton("Cancel"))); + buttonOK.addActionListener(this::onOK); + buttonCancel.addActionListener(this::onCancel); + + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + + setTitle("Revoke certificate"); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + onCancel(null); + } + }); + + contentPane.registerKeyboardAction(this::onCancel, + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } + + /** + * EFFECTS: Init GUI. + * MODIFIES: this + */ + private JPanel renderForm() { + final JPanel panelForm = new JPanel(); + panelForm.setLayout(new GridBagLayout()); + + panelForm.add(new JLabel("Revoking: "), new GCBuilder().anchor(WEST).build()); + panelForm.add(new JLabel("Reason: "), new GCBuilder().gridY(1).anchor(WEST).build()); + panelForm.add(new JLabel("Time: "), new GCBuilder().gridY(2).anchor(WEST).build()); + + textFieldSubject = new JTextField(String.format("%s (Serial: %d)", + crt.getCertificate().getSubject().toString(), crt.getCertificate().getSerialNumber().getLong())); + textFieldSubject.setEditable(false); + panelForm.add(textFieldSubject, new GCBuilder().gridX(1).anchor(WEST).fill(HORIZONTAL).build()); + + comboBoxReason = new JComboBox<>(Arrays.stream(Reason.values()).map(Enum::toString).toArray(String[]::new)); + panelForm.add(comboBoxReason, new GCBuilder().gridXY(1, 1).anchor(WEST).fill(HORIZONTAL).build()); + + formattedTextFieldTime = new JFormattedTextField(DATE_FORMAT.toFormat()); + formattedTextFieldTime.setText(ZonedDateTime.now().format(DATE_FORMAT)); + panelForm.add(formattedTextFieldTime, new GCBuilder().gridXY(1, 2).anchor(WEST).fill(HORIZONTAL).build()); + + panelForm.add(new JPanel(), new GCBuilder().gridXY(1, 3).expandXY().fill(HORIZONTAL).build()); + return panelForm; + } + + /** + * EFFECTS: Validate form, set result, and close dialog. + * Time must be a valid ISO-8601 string with offset, and it will be converted into UTC. + * Reason must be supported. + * MODIFIES: this + */ + private void onOK(ActionEvent ev) { + try { + res = new RevokedCertificate(ASN1Object.TAG_SEQUENCE, null, + crt.getCertificate().getSerialNumber(), + new UtcTime(UtcTime.TAG, null, + ZonedDateTime.parse(formattedTextFieldTime.getText(), DATE_FORMAT) + .withZoneSameInstant(ZoneId.of("UTC"))), + Reason.valueOf(comboBoxReason.getSelectedItem().toString())); + dispose(); + } catch (DateTimeParseException e) { + alert(rootPane, "Revoke certificate", "Invalid time: " + formattedTextFieldTime.getText() + + ". It must be a valid ISO8601 time with offset, like '1919-08-10T11:45:14+09:00'."); + } catch (IllegalArgumentException e) { + alert(rootPane, "Revoke certificate", "Invalid reason."); + } + } + + /** + * EFFECTS: Clear the result and close dialog. + * MODIFIES: this + */ + private void onCancel(ActionEvent ev) { + res = null; + dispose(); + } + + /** + * EFFECTS: Get result. + */ + public RevokedCertificate getRes() { + return res; + } +} -- cgit v1.2.3