Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error messaging when installing the Privileged Helper Tool #103

Merged
merged 3 commits into from
Oct 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Mist/Helpers/PropertyListUpdater.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
/// Helper struct to update a Property List key-pair value.
struct PropertyListUpdater {

/// Edit a key-pair value in a Property List.
/// Update a key-pair value in a Property List.
///
/// - Parameters:
/// - url: The URL of the property list to be updated.
Expand Down
1 change: 1 addition & 0 deletions Mist/Model/FirmwareAlertType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ import SwiftUI
enum FirmwareAlertType: String {
case compatibility = "Compatiblity"
case helperTool = "Helper Tool"
case error = "Error"
}
1 change: 1 addition & 0 deletions Mist/Model/InstallerAlertType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ enum InstallerAlertType: String {
case helperTool = "Helper Tool"
case fullDiskAccess = "Full Disk Access"
case cacheDirectory = "Cache Directory"
case error = "Error"
}
27 changes: 24 additions & 3 deletions Mist/Views/List/ListRowFirmware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct ListRowFirmware: View {
@State private var showAlert: Bool = false
@State private var showSavePanel: Bool = false
@State private var downloading: Bool = false
@State private var error: Error?
private let length: CGFloat = 48
private let spacing: CGFloat = 5
private let padding: CGFloat = 3
Expand All @@ -34,6 +35,14 @@ struct ListRowFirmware: View {

return "This macOS Firmware download cannot be used to restore macOS on this \(architecture.description) Mac.\n\nAre you sure you want to continue?"
}
private var errorMessage: String {

if let error: BlessError = error as? BlessError {
return error.description
}

return error?.localizedDescription ?? ""
}

var body: some View {
HStack {
Expand Down Expand Up @@ -68,10 +77,16 @@ struct ListRowFirmware: View {
case .helperTool:
return Alert(
title: Text("Privileged Helper Tool not installed!"),
message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when downloading macOS Firmwares"),
primaryButton: .default(Text("Install...")) { installPrivilegedHelperTool() },
message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when downloading macOS Firmwares."),
primaryButton: .default(Text("Install...")) { Task { installPrivilegedHelperTool() } },
secondaryButton: .default(Text("Cancel"))
)
case .error:
return Alert(
title: Text("An error has occured!"),
message: Text(errorMessage),
dismissButton: .default(Text("OK"))
)
}
}
.onChange(of: showSavePanel) { boolean in
Expand Down Expand Up @@ -132,7 +147,13 @@ struct ListRowFirmware: View {
}

private func installPrivilegedHelperTool() {
try? PrivilegedHelperManager.shared.authorizeAndBless()
do {
try PrivilegedHelperManager.shared.authorizeAndBless()
} catch {
self.error = error
alertType = .error
showAlert = true
}
}
}

Expand Down
87 changes: 56 additions & 31 deletions Mist/Views/List/ListRowInstaller.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct ListRowInstaller: View {
@State private var showOpenPanel: Bool = false
@State private var exports: [InstallerExportType] = []
@State private var volume: InstallerVolume?
@State private var error: Error?
private let length: CGFloat = 48
private let spacing: CGFloat = 5
private let padding: CGFloat = 3
Expand All @@ -62,6 +63,14 @@ struct ListRowInstaller: View {
private var cacheDirectoryMessage: String {
"The cache directory has incorrect ownership and/or permissions, which will cause issues caching macOS Installers.\n\nRepair the cache directory ownership and/or permissions and try again."
}
private var errorMessage: String {

if let error: BlessError = error as? BlessError {
return error.description
}

return error?.localizedDescription ?? ""
}

var body: some View {
HStack {
Expand Down Expand Up @@ -97,36 +106,7 @@ struct ListRowInstaller: View {
.clipShape(Capsule())
}
.alert(isPresented: $showAlert) {
switch alertType {
case .compatibility:
return Alert(
title: Text("macOS Installer not compatible!"),
message: Text(compatibilityMessage),
primaryButton: .default(Text("Cancel")),
secondaryButton: .default(Text("Continue")) { Task { validate() } }
)
case .helperTool:
return Alert(
title: Text("Privileged Helper Tool not installed!"),
message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when creating macOS Installers."),
primaryButton: .default(Text("Install...")) { installPrivilegedHelperTool() },
secondaryButton: .default(Text("Cancel"))
)
case .fullDiskAccess:
return Alert(
title: Text("Full Disk Access required!"),
message: Text("Mist requires Full Disk Access to perform Administrator tasks when creating macOS Installers."),
primaryButton: .default(Text("Allow...")) { openFullDiskAccessPreferences() },
secondaryButton: .default(Text("Cancel"))
)
case .cacheDirectory:
return Alert(
title: Text("Cache directory settings incorrect!"),
message: Text(cacheDirectoryMessage),
primaryButton: .default(Text("Repair...")) { Task { try await repairCacheDirectoryOwnershipAndPermissions() } },
secondaryButton: .default(Text("Cancel"))
)
}
alert(for: alertType)
}
.onChange(of: showOpenPanel) { boolean in

Expand Down Expand Up @@ -309,7 +289,13 @@ struct ListRowInstaller: View {
}

private func installPrivilegedHelperTool() {
try? PrivilegedHelperManager.shared.authorizeAndBless()
do {
try PrivilegedHelperManager.shared.authorizeAndBless()
} catch {
self.error = error
alertType = .error
showAlert = true
}
}

private func openFullDiskAccessPreferences() {
Expand All @@ -326,6 +312,45 @@ struct ListRowInstaller: View {
let ownerAccountName: String = NSUserName()
try await FileAttributesUpdater.update(url: url, ownerAccountName: ownerAccountName)
}

private func alert(for alertType: InstallerAlertType) -> Alert {
switch alertType {
case .compatibility:
return Alert(
title: Text("macOS Installer not compatible!"),
message: Text(compatibilityMessage),
primaryButton: .default(Text("Cancel")),
secondaryButton: .default(Text("Continue")) { Task { validate() } }
)
case .helperTool:
return Alert(
title: Text("Privileged Helper Tool not installed!"),
message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when creating macOS Installers."),
primaryButton: .default(Text("Install...")) { Task { installPrivilegedHelperTool() } },
secondaryButton: .default(Text("Cancel"))
)
case .fullDiskAccess:
return Alert(
title: Text("Full Disk Access required!"),
message: Text("Mist requires Full Disk Access to perform Administrator tasks when creating macOS Installers."),
primaryButton: .default(Text("Allow...")) { openFullDiskAccessPreferences() },
secondaryButton: .default(Text("Cancel"))
)
case .cacheDirectory:
return Alert(
title: Text("Cache directory settings incorrect!"),
message: Text(cacheDirectoryMessage),
primaryButton: .default(Text("Repair...")) { Task { try await repairCacheDirectoryOwnershipAndPermissions() } },
secondaryButton: .default(Text("Cancel"))
)
case .error:
return Alert(
title: Text("An error has occured!"),
message: Text(errorMessage),
dismissButton: .default(Text("OK"))
)
}
}
}

struct ListRowInstaller_Previews: PreviewProvider {
Expand Down