From 1f165058b20cde0738bdec618a54f9dbeac00f0f Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Tue, 13 Dec 2022 22:56:36 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rework=20interaction=20wit?= =?UTF-8?q?h=20Valet=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcschemes/PHP Monitor DEV.xcscheme | 2 +- .../DomainList/DomainListVC+Actions.swift | 154 ++++++++++-------- .../Valet/Domains/ValetInteractor.swift | 37 ++++- .../Valet/Proxies/ValetProxy.swift | 10 +- 4 files changed, 133 insertions(+), 70 deletions(-) diff --git a/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor DEV.xcscheme b/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor DEV.xcscheme index b0a4d86..8642ae0 100644 --- a/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor DEV.xcscheme +++ b/PHP Monitor.xcodeproj/xcshareddata/xcschemes/PHP Monitor DEV.xcscheme @@ -91,7 +91,7 @@ + isEnabled = "NO"> Void) { + let rowToReload = tableView.selectedRow + + waitAndExecute { + await Shell.quiet(command) + } completion: { [self] in + beforeCellReload() + tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0, 1, 2, 3, 4]) + tableView.deselectRow(rowToReload) + tableView.selectRowIndexes([rowToReload], byExtendingSelection: true) } } - func toggleSecureForProxy() { - let originalSecureStatus = selectedProxy!.secured - let selectedProxy = selectedProxy! + private func reloadSelectedRow() { + tableView.reloadData(forRowIndexes: [tableView.selectedRow], columnIndexes: [0, 1, 2, 3, 4]) + tableView.deselectRow(tableView.selectedRow) + tableView.selectRowIndexes([tableView.selectedRow], byExtendingSelection: true) + } - self.waitAndExecute { - // 1. Remove the original proxy - await Shell.quiet("\(Paths.valet) unproxy \(selectedProxy.domain)") + // MARK: - Interactions with `valet` or terminal - // 2. Add a new proxy, which is either secured/unsecured - let secure = originalSecureStatus ? "" : " --secure" - await Shell.quiet("\(Paths.valet) proxy \(selectedProxy.domain) \(selectedProxy.target)\(secure)") + @objc func toggleSecure() { + if selected is ValetSite { + Task { toggleSecureForSite() } + } else { + Task { await toggleSecureForProxy() } + } + } - // 3. Restart nginx - await Actions.restartNginx() + func toggleSecureForProxy() async { + guard let proxy = selectedProxy else { return } - // 4. Reload site list - Task { @MainActor in - App.shared.domainListWindowController?.pressedReload(nil) - } + do { + // Toggle secure + try await proxy.toggleSecure() + + // Reload the UI + self.reloadSelectedRow() + + // Send a notification about the new status (if applicable) + LocalNotification.send( + title: "domain_list.alerts_status_changed.title".localized, + subtitle: "domain_list.alerts_status_changed.desc" + .localized( + "\(proxy.domain).\(Valet.shared.config.tld)", + proxy.secured + ), + preference: .notifyAboutSecureToggle + ) + } catch { + let error = error as! ValetInteractionError + + BetterAlert() + .withInformation( + title: "domain_list.alerts_status_not_changed.title".localized, + subtitle: "domain_list.alerts_status_not_changed.desc".localized(error.command) + ) + .withPrimary(text: "OK") + .show() } } @@ -79,38 +145,6 @@ extension DomainListVC { } } - @objc func openInBrowser() { - guard let selected = self.selected else { - return - } - - guard let url = selected.getListableUrl() else { - BetterAlert() - .withInformation( - title: "domain_list.alert.invalid_folder_name".localized, - subtitle: "domain_list.alert.invalid_folder_name_desc".localized - ) - .withPrimary(text: "OK") - .show() - return - } - - NSWorkspace.shared.open(url) - } - - @objc func openInFinder() async { - await Shell.quiet("open '\(selectedSite!.absolutePath)'") - } - - @objc func openInTerminal() async { - await Shell.quiet("open -b com.apple.terminal '\(selectedSite!.absolutePath)'") - } - - @objc func openWithEditor(sender: EditorMenuItem) async { - guard let editor = sender.editor else { return } - await editor.openDirectory(file: selectedSite!.absolutePath) - } - @objc func isolateSite(sender: PhpMenuItem) { let command = "sudo \(Paths.valet) isolate php@\(sender.version) --site '\(self.selectedSite!.name)' && exit;" @@ -178,25 +212,11 @@ extension DomainListVC { style: .critical, onFirstButtonPressed: { self.waitAndExecute { - Task { await Shell.quiet("valet unproxy '\(proxy.domain)'") } + Task { await proxy.remove() } } completion: { Task { await self.reloadDomains() } } } ) } - - private func performAction(command: String, beforeCellReload: @escaping () -> Void) { - let rowToReload = tableView.selectedRow - - waitAndExecute { - await Shell.quiet(command) - } completion: { [self] in - beforeCellReload() - tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0, 1, 2, 3, 4]) - tableView.deselectRow(rowToReload) - tableView.selectRowIndexes([rowToReload], byExtendingSelection: true) - } - } - } diff --git a/phpmon/Domain/Integrations/Valet/Domains/ValetInteractor.swift b/phpmon/Domain/Integrations/Valet/Domains/ValetInteractor.swift index 0e90616..318b942 100644 --- a/phpmon/Domain/Integrations/Valet/Domains/ValetInteractor.swift +++ b/phpmon/Domain/Integrations/Valet/Domains/ValetInteractor.swift @@ -8,6 +8,11 @@ import Foundation +struct ValetInteractionError: Error { + /// The command the user should try (and failed). + var command: String +} + #warning("ValetInteractor needs to be implemented and used") class ValetInteractor { public static func toggleSecure(site: ValetSite) async throws { @@ -15,7 +20,33 @@ class ValetInteractor { } public static func toggleSecure(proxy: ValetProxy) async throws { - // TODO + // Keep track of the original status (secure or not?) + let originalSecureStatus = proxy.secured + + // Build the list of commands we will need to run + let commands: [String] = [ + // Unproxy the given domain + "\(Paths.valet) unproxy \(proxy.domain)", + // Re-create the proxy (with the inverse secured status) + originalSecureStatus + ? "\(Paths.valet) proxy \(proxy.domain) \(proxy.target)" + : "\(Paths.valet) proxy \(proxy.domain) \(proxy.target) --secure" + ] + + for command in commands { + await Shell.quiet(command) + } + + // Check if the secured status has actually changed + proxy.determineSecured() + if proxy.secured == originalSecureStatus { + throw ValetInteractionError( + command: commands.joined(separator: " && ") + ) + } + + // Restart nginx to load the new configuration + await Actions.restartNginx() } public static func isolate(site: ValetSite, version: PhpVersionNumber) async throws { @@ -25,4 +56,8 @@ class ValetInteractor { public static func unlink(site: ValetSite) async throws { // TODO } + + public static func remove(proxy: ValetProxy) async throws { + await Shell.quiet("valet unproxy '\(proxy.domain)'") + } } diff --git a/phpmon/Domain/Integrations/Valet/Proxies/ValetProxy.swift b/phpmon/Domain/Integrations/Valet/Proxies/ValetProxy.swift index d0ea2ab..ce118e1 100644 --- a/phpmon/Domain/Integrations/Valet/Proxies/ValetProxy.swift +++ b/phpmon/Domain/Integrations/Valet/Proxies/ValetProxy.swift @@ -18,7 +18,7 @@ class ValetProxy: ValetListable { self.domain = configuration.domain self.tld = configuration.tld self.target = configuration.proxy! - self.secured = FileSystem.fileExists("~/.config/valet/Certificates/\(self.domain).\(self.tld).key") + self.determineSecured() } // MARK: - ValetListable Protocol @@ -53,7 +53,15 @@ class ValetProxy: ValetListable { // MARK: - Interactions + func determineSecured() { + self.secured = FileSystem.fileExists("~/.config/valet/Certificates/\(self.domain).\(self.tld).key") + } + func toggleSecure() async throws { try await ValetInteractor.toggleSecure(proxy: self) } + + func remove() async { + try! await ValetInteractor.remove(proxy: self) + } }