mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 20:54:50 +00:00
refactor: improve sudo error handling to distinguish authentication failures and adjust scene view rotation speed.
This commit is contained in:
@@ -165,7 +165,7 @@ struct MoleSceneView: NSViewRepresentable {
|
||||
// Slower, majestic rotation
|
||||
// Auto Rotation Speed
|
||||
// Slower, majestic rotation normally. Fast when working.
|
||||
let baseRotation = parent.isRunning ? 0.05 : 0.002
|
||||
let baseRotation = parent.isRunning ? 0.12 : 0.006
|
||||
|
||||
// Drag Influence
|
||||
let dragInfluence = Double(parent.rotationVelocity.width) * 0.0005
|
||||
|
||||
@@ -24,11 +24,30 @@ class OptimizerService: ObservableObject {
|
||||
_ = try await ShellRunner.shared.runSudo(command, password: pw)
|
||||
return
|
||||
} catch {
|
||||
await MainActor.run { AuthContext.shared.clear() }
|
||||
print("Optimizer privilege error: \(error)")
|
||||
// Only clear password if it's an authentication failure
|
||||
if case ShellError.authenticationFailed = error {
|
||||
await MainActor.run { AuthContext.shared.clear() }
|
||||
|
||||
await MainActor.run {
|
||||
AuthContext.shared.needsPassword = true
|
||||
self.statusMessage = "Password Incorrect"
|
||||
}
|
||||
|
||||
struct AuthRequired: Error, LocalizedError {
|
||||
var errorDescription: String? { "Authentication Failed" }
|
||||
}
|
||||
throw AuthRequired()
|
||||
} else {
|
||||
// Command failed but password likely correct.
|
||||
// Do NOT clear password. Propagate error.
|
||||
print("Non-auth error in optimizer: \(error)")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no password or failed, prompt via Custom Sheet
|
||||
// If no password, prompt via Custom Sheet
|
||||
await MainActor.run {
|
||||
AuthContext.shared.needsPassword = true
|
||||
self.statusMessage = "Waiting for Password..."
|
||||
|
||||
@@ -144,12 +144,23 @@ class ScannerService: ObservableObject {
|
||||
do {
|
||||
_ = try await ShellRunner.shared.runSudo(fullCommand, password: sessionPw)
|
||||
} catch {
|
||||
print("Sudo command error: \(error)")
|
||||
print("Session password failed: \(error)")
|
||||
await MainActor.run { AuthContext.shared.clear() }
|
||||
// Trigger re-auth on failure
|
||||
|
||||
if case ShellError.authenticationFailed = error {
|
||||
await MainActor.run {
|
||||
AuthContext.shared.clear()
|
||||
AuthContext.shared.needsPassword = true
|
||||
self.currentLog = "Password Incorrect/Expired"
|
||||
self.isCleaning = false
|
||||
}
|
||||
return 0
|
||||
}
|
||||
// Ignore other errors (e.g. command execution failed)
|
||||
// but continue the flow or handle gracefully without clearing password
|
||||
print("Non-auth error in cleanup: \(error)")
|
||||
await MainActor.run {
|
||||
AuthContext.shared.needsPassword = true
|
||||
self.currentLog = "Password Incorrect/Expired"
|
||||
self.currentLog = "Error: \(error.localizedDescription)"
|
||||
self.isCleaning = false
|
||||
}
|
||||
return 0
|
||||
|
||||
@@ -3,11 +3,13 @@ import Foundation
|
||||
enum ShellError: Error, LocalizedError {
|
||||
case commandFailed(output: String)
|
||||
case executionError(error: Error)
|
||||
case authenticationFailed
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .commandFailed(let output): return output
|
||||
case .executionError(let error): return error.localizedDescription
|
||||
case .authenticationFailed: return "Authentication failed - incorrect password"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,10 +100,15 @@ class ShellRunner {
|
||||
if process.terminationStatus == 0 {
|
||||
continuation.resume(returning: output)
|
||||
} else {
|
||||
// If 1, it might be wrong password or command fail.
|
||||
// sudo usually complains to stderr.
|
||||
continuation.resume(
|
||||
throwing: ShellError.commandFailed(output: errorOutput.isEmpty ? output : errorOutput))
|
||||
// Check for password failure
|
||||
let combined = (output + errorOutput).lowercased()
|
||||
if combined.contains("try again") || combined.contains("incorrect") {
|
||||
continuation.resume(throwing: ShellError.authenticationFailed)
|
||||
} else {
|
||||
continuation.resume(
|
||||
throwing: ShellError.commandFailed(output: errorOutput.isEmpty ? output : errorOutput)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,4 +124,11 @@ class ShellRunner {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Escapes a string for safe use in bash commands
|
||||
private func bashEscape(_ str: String) -> String {
|
||||
// Use single quotes and escape any single quotes within the string
|
||||
let escaped = str.replacingOccurrences(of: "'", with: "'\"'\"'")
|
||||
return "'\(escaped)'"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user