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/tui/JCA.java | 220 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 src/main/ui/tui/JCA.java (limited to 'src/main/ui/tui/JCA.java') diff --git a/src/main/ui/tui/JCA.java b/src/main/ui/tui/JCA.java new file mode 100644 index 0000000..c23d610 --- /dev/null +++ b/src/main/ui/tui/JCA.java @@ -0,0 +1,220 @@ +package ui.tui; + +import model.asn1.exceptions.InvalidDBException; +import model.asn1.exceptions.ParseException; +import model.ca.CertificationAuthority; +import persistence.Decoder; +import persistence.FS; +import ui.Utils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.util.Scanner; + +/** + * Main program + */ +public class JCA { + /** + * Default db file (./data/ca.json) + */ + private static final Path PATH_DEFAULT = Path.of("data", "ca.json"); + + /** + * Instances of the five screens; + */ + private final UIHandler mainScreen; + private final UIHandler mgmtScreen; + private final UIHandler issueScreen; + private final UIHandler templatesScreen; + private final UIHandler templateSetScreen; + /** + * The CA + */ + private CertificationAuthority ca; + /** + * The current screen. + */ + private UIHandler screen; + + /** + * There are unsaved changes. + */ + private boolean unsaved = false; + + /** + * EFFECTS: Init with main screen and empty CA. No private key and no CA cert. + * Throws {@link NoSuchAlgorithmException} when crypto issue happens. + */ + public JCA() throws NoSuchAlgorithmException, InvalidKeySpecException { + this.mainScreen = new MainScreen(this); + this.mgmtScreen = new MgmtScreen(this); + this.issueScreen = new IssueScreen(this); + this.templatesScreen = new TemplatesScreen(this); + this.templateSetScreen = new TemplateSetScreen(this); + + setScreen(Screen.MAIN); + + this.ca = new CertificationAuthority(); + } + + /** + * EFFECT: Checks if the CA is installed or not (according to the desired state) and print if not matching. Returns + * true if matching. + */ + public boolean checkCA(boolean requireInstalled) { + if (requireInstalled && ca.getCertificate() == null) { + System.out.println("No CA installed"); + return false; + } else if (!requireInstalled && ca.getCertificate() != null) { + System.out.println("CA already installed"); + return false; + } + return true; + } + + /** + * EFFECTS: Read PEM from stdin, matched the given tag. + * Throws {@link ParseException} if the input is incorrect. + */ + public Byte[] handleInputPEM(String desiredTag) throws ParseException { + final Scanner scanner = new Scanner(System.in); + StringBuilder in = new StringBuilder(); + while (true) { + final String line = scanner.nextLine(); + in.append(line); + in.append("\n"); + if (line.matches("-----END .*-----")) { + break; + } + } + return Utils.parsePEM(Utils.byteToByte(in.toString().getBytes(StandardCharsets.UTF_8)), desiredTag); + } + + /** + * EFFECT: Set the current screen with optional args. Exit the program when mode is null. + * MODIFIES: this + */ + public void setScreen(Screen mode, Object... args) { + if (mode == null) { + System.exit(0); + } + switch (mode) { + case MAIN: + this.screen = mainScreen; + break; + case MGMT: + this.screen = mgmtScreen; + break; + case ISSUE: + this.screen = issueScreen; + break; + case TEMPLATES: + this.screen = templatesScreen; + break; + case TEMPLATE_SET: + this.screen = templateSetScreen; + break; + } + screen.enter(args); + } + + /** + * EFFECTS: Read the database file and replace all local states. + * MODIFIES: this + */ + private void load() { + if (unsaved) { + System.out.println("Current database is not saved yet."); + return; + } + try { + this.ca = Decoder.decodeCA(FS.read(PATH_DEFAULT)); + } catch (InvalidDBException | NoSuchAlgorithmException e) { + System.out.println(e.getMessage()); + if (e.getCause() != null) { + System.out.println(e.getCause().getMessage()); + e.getCause().printStackTrace(); + } + } + } + + /** + * EFFECTS: Handle input line + * MODIFIES: this + */ + private void handleLine(String... args) { + if (args[0].equals("log")) { + ca.getLogs().forEach(System.out::println); + return; + } + if ("help".equals(args[0])) { + screen.help(); + System.out.println("log\tView audit logs"); + System.out.println("load\tLoad database"); + System.out.println("save\tSave database"); + } else if ("commit".equals(args[0])) { + screen.commit(); + } else if ("show".equals(args[0])) { + screen.show(); + } else if ("exit".equals(args[0])) { + setScreen(screen.exit()); + } else if ("save".equals(args[0])) { + save(); + } else if ("load".equals(args[0])) { + load(); + } else { + screen.command(args); + } + printPS1(); + } + + /** + * EFFECTS: Print the '*user@JCA PS1' line + */ + private void printPS1() { + System.out.printf("%s%s@JCA %s ", + unsaved ? "*" : "", + ca.getUser(), + screen.getPS1()); + } + + /** + * EFFECTS: Save the DB + */ + public void save() { + try { + FS.write(PATH_DEFAULT, Decoder.encodeCA(ca)); + unsaved = false; + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + + /** + * EFFECTS: Run the program + */ + public void run() { + printPS1(); + final Scanner scanner = new Scanner(System.in); + while (true) { + String[] args = scanner.nextLine().split(" "); + if (args.length <= 0 || args[0].isBlank()) { + printPS1(); + continue; + } + handleLine(args); + } + } + + public void setUnsaved(boolean unsaved) { + this.unsaved = unsaved; + } + + public CertificationAuthority getCa() { + return ca; + } +} -- cgit v1.2.3