1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 03:50:08 +02:00

Add FakeValetInteractor

This commit is contained in:
2022-12-13 23:21:15 +01:00
parent cb98d40bef
commit 912d9e7423
8 changed files with 97 additions and 71 deletions

View File

@ -91,7 +91,7 @@
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "--configuration:~/.phpmon_fconf_working.json" argument = "--configuration:~/.phpmon_fconf_working.json"
isEnabled = "NO"> isEnabled = "YES">
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "--configuration:~/.phpmon_fconf_broken.json" argument = "--configuration:~/.phpmon_fconf_broken.json"

View File

@ -26,6 +26,8 @@ public struct TestableConfiguration: Codable {
ActiveCommand.useTestable(commandOutput) ActiveCommand.useTestable(commandOutput)
Log.info("Applying fake scanner...") Log.info("Applying fake scanner...")
ValetScanners.useFake() ValetScanners.useFake()
Log.info("Applying fake Valet domain interactor...")
ValetInteractor.useFake()
} }
func toJson(pretty: Bool = false) -> String { func toJson(pretty: Bool = false) -> String {

View File

@ -72,6 +72,7 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate {
App.shared.domainListWindowController?.contentVC.setUIBusy() App.shared.domainListWindowController?.contentVC.setUIBusy()
Task { // Ensure we proxy the site asynchronously and reload UI on main thread again Task { // Ensure we proxy the site asynchronously and reload UI on main thread again
#warning("Creating a proxy should happen via the ValetInteractor")
await Shell.quiet("\(Paths.valet) proxy \(domain) \(proxyName)\(secure)") await Shell.quiet("\(Paths.valet) proxy \(domain) \(proxyName)\(secure)")
await Actions.restartNginx() await Actions.restartNginx()

View File

@ -71,6 +71,7 @@ class AddSiteVC: NSViewController, NSTextFieldDelegate {
// Adding `valet links` is a workaround for Valet malforming the config.json file // Adding `valet links` is a workaround for Valet malforming the config.json file
// TODO: I will have to investigate and report this behaviour if possible // TODO: I will have to investigate and report this behaviour if possible
#warning("Linking a site should happen via the ValetInteractor")
Task { await Shell.quiet("cd '\(path)' && \(Paths.valet) link '\(name)' && valet links") } Task { await Shell.quiet("cd '\(path)' && \(Paths.valet) link '\(name)' && valet links") }
dismissView(outcome: .OK) dismissView(outcome: .OK)

View File

@ -68,7 +68,7 @@ extension DomainListVC {
@objc func toggleSecure() { @objc func toggleSecure() {
if selected is ValetSite { if selected is ValetSite {
Task { toggleSecureForSite() } Task { await toggleSecureForSite() }
} else { } else {
Task { await toggleSecureForProxy() } Task { await toggleSecureForProxy() }
} }
@ -78,74 +78,33 @@ extension DomainListVC {
guard let proxy = selectedProxy else { return } guard let proxy = selectedProxy else { return }
do { do {
// Toggle secure // Recreate proxy as secure or unsecured proxy
try await proxy.toggleSecure() try await proxy.toggleSecure()
// Send a notification about the new status (if applicable) // Send a notification about the new status (if applicable)
LocalNotification.send( self.notifyAboutModifiedSecureStatus(domain: proxy.domain, secured: proxy.secured)
title: "domain_list.alerts_status_changed.title".localized,
subtitle: "domain_list.alerts_status_changed.desc"
.localized(
// 1. The domain that was secured is listed
"\(proxy.domain).\(Valet.shared.config.tld)",
// 2. What the domain is is listed (secure / unsecure)
proxy.secured
? "domain_list.alerts_status_secure".localized
: "domain_list.alerts_status_secure".localized
),
preference: .notifyAboutSecureToggle
)
// Reload the UI (do this last so we don't invalidate the proxy) // Reload the UI (do this last so we don't invalidate the proxy)
self.reloadSelectedRow() self.reloadSelectedRow()
} catch { } catch {
// Notify the user about a failed command
let error = error as! ValetInteractionError let error = error as! ValetInteractionError
self.notifyAboutFailedSecureStatus(command: error.command)
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()
} }
} }
func toggleSecureForSite() { func toggleSecureForSite() async {
let rowToReload = tableView.selectedRow guard let site = selectedSite else { return }
let originalSecureStatus = selectedSite!.secured
let action = selectedSite!.secured ? "unsecure" : "secure"
let selectedSite = selectedSite!
let command = "cd '\(selectedSite.absolutePath)' && sudo \(Paths.valet) \(action) && exit;"
waitAndExecute { do {
await Shell.quiet(command) // Instruct Valet to secure or unsecure a site
} completion: { [self] in try await site.toggleSecure()
selectedSite.determineSecured() // Send a notification about the new status (if applicable)
if selectedSite.secured == originalSecureStatus { self.notifyAboutModifiedSecureStatus(domain: site.name, secured: site.secured)
BetterAlert() // Reload the UI (do this last so we don't invalidate the proxy)
.withInformation( self.reloadSelectedRow()
title: "domain_list.alerts_status_not_changed.title".localized, } catch {
subtitle: "domain_list.alerts_status_not_changed.desc".localized(command) // Notify the user about a failed command
) let error = error as! ValetInteractionError
.withPrimary(text: "OK") self.notifyAboutFailedSecureStatus(command: error.command)
.show()
} else {
let newState = selectedSite.secured ? "secured" : "unsecured"
LocalNotification.send(
title: "domain_list.alerts_status_changed.title".localized,
subtitle: "domain_list.alerts_status_changed.desc"
.localized(
"\(selectedSite.name).\(Valet.shared.config.tld)",
newState
),
preference: .notifyAboutSecureToggle
)
}
tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0, 1, 2, 3, 4])
tableView.deselectRow(rowToReload)
tableView.selectRowIndexes([rowToReload], byExtendingSelection: true)
} }
} }
@ -223,4 +182,32 @@ extension DomainListVC {
} }
) )
} }
// MARK: - Alerts & Modals
private func notifyAboutModifiedSecureStatus(domain: String, secured: Bool) {
LocalNotification.send(
title: "domain_list.alerts_status_changed.title".localized,
subtitle: "domain_list.alerts_status_changed.desc"
.localized(
// 1. The domain that was secured is listed
"\(domain).\(Valet.shared.config.tld)",
// 2. What the domain is is listed (secure / unsecure)
secured
? "domain_list.alerts_status_secure".localized
: "domain_list.alerts_status_unsecure".localized
),
preference: .notifyAboutSecureToggle
)
}
private func notifyAboutFailedSecureStatus(command: String) {
BetterAlert()
.withInformation(
title: "domain_list.alerts_status_not_changed.title".localized,
subtitle: "domain_list.alerts_status_not_changed.desc".localized(command)
)
.withPrimary(text: "OK")
.show()
}
} }

View File

@ -15,11 +15,31 @@ struct ValetInteractionError: Error {
#warning("ValetInteractor needs to be implemented and used") #warning("ValetInteractor needs to be implemented and used")
class ValetInteractor { class ValetInteractor {
public static func toggleSecure(site: ValetSite) async throws { static var shared = ValetInteractor()
// TODO
public static func useFake() {
ValetInteractor.shared = FakeValetInteractor()
} }
public static func toggleSecure(proxy: ValetProxy) async throws { public func toggleSecure(site: ValetSite) async throws {
// Keep track of the original status (secure or not?)
let originalSecureStatus = site.secured
// Keep track of the command we wish to run
let action = site.secured ? "unsecure" : "secure"
let command = "cd '\(site.absolutePath)' && sudo \(Paths.valet) \(action) && exit;"
// Run the command
await Shell.quiet(command)
// Check if the secured status has actually changed
site.determineSecured()
if site.secured == originalSecureStatus {
throw ValetInteractionError(command: command)
}
}
public func toggleSecure(proxy: ValetProxy) async throws {
// Keep track of the original status (secure or not?) // Keep track of the original status (secure or not?)
let originalSecureStatus = proxy.secured let originalSecureStatus = proxy.secured
@ -33,6 +53,7 @@ class ValetInteractor {
: "\(Paths.valet) proxy \(proxy.domain) \(proxy.target) --secure" : "\(Paths.valet) proxy \(proxy.domain) \(proxy.target) --secure"
] ]
// Run the commands
for command in commands { for command in commands {
await Shell.quiet(command) await Shell.quiet(command)
} }
@ -49,15 +70,29 @@ class ValetInteractor {
await Actions.restartNginx() await Actions.restartNginx()
} }
public static func isolate(site: ValetSite, version: PhpVersionNumber) async throws { public func isolate(site: ValetSite, version: PhpVersionNumber) async throws {
// TODO // TODO
} }
public static func unlink(site: ValetSite) async throws { public func unlink(site: ValetSite) async throws {
// TODO // TODO
} }
public static func remove(proxy: ValetProxy) async throws { public func remove(proxy: ValetProxy) async throws {
await Shell.quiet("valet unproxy '\(proxy.domain)'") await Shell.quiet("valet unproxy '\(proxy.domain)'")
} }
} }
class FakeValetInteractor: ValetInteractor {
override func toggleSecure(proxy: ValetProxy) async throws {
proxy.secured = !proxy.secured
}
override func toggleSecure(site: ValetSite) async throws {
site.secured = !site.secured
}
override func remove(proxy: ValetProxy) async throws {
fatalError("This should remove the proxy")
}
}

View File

@ -58,10 +58,10 @@ class ValetProxy: ValetListable {
} }
func toggleSecure() async throws { func toggleSecure() async throws {
try await ValetInteractor.toggleSecure(proxy: self) try await ValetInteractor.shared.toggleSecure(proxy: self)
} }
func remove() async { func remove() async {
try! await ValetInteractor.remove(proxy: self) try! await ValetInteractor.shared.remove(proxy: self)
} }
} }

View File

@ -266,14 +266,14 @@ class ValetSite: ValetListable {
// MARK: - Interactions // MARK: - Interactions
func toggleSecure() async throws { func toggleSecure() async throws {
try await ValetInteractor.toggleSecure(site: self) try await ValetInteractor.shared.toggleSecure(site: self)
} }
func isolate(version: PhpVersionNumber) async throws { func isolate(version: PhpVersionNumber) async throws {
try await ValetInteractor.isolate(site: self, version: version) try await ValetInteractor.shared.isolate(site: self, version: version)
} }
func unlink() async throws { func unlink() async throws {
try await ValetInteractor.unlink(site: self) try await ValetInteractor.shared.unlink(site: self)
} }
} }