mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-05-08 08:28:58 +02:00
123 lines
5.3 KiB
Swift
123 lines
5.3 KiB
Swift
import Cocoa
|
|
import OSLog
|
|
import SecretKit
|
|
import SecureEnclaveSecretKit
|
|
import SmartCardSecretKit
|
|
import SecretAgentKit
|
|
import Brief
|
|
import Observation
|
|
import Common
|
|
import SwiftUI
|
|
|
|
@main
|
|
struct SecretAgent: App {
|
|
|
|
@MainActor private let storeList: SecretStoreList = {
|
|
let list = SecretStoreList()
|
|
let cryptoKit = SecureEnclave.Store()
|
|
let migrator = SecureEnclave.CryptoKitMigrator()
|
|
try? migrator.migrate(to: cryptoKit)
|
|
list.add(store: cryptoKit)
|
|
list.add(store: SmartCard.Store())
|
|
return list
|
|
}()
|
|
private let updater = Updater(checkOnLaunch: true)
|
|
private let notifier = Notifier()
|
|
private let authenticationHandler = AuthenticationHandler()
|
|
private let publicKeyFileStoreController = PublicKeyFileStoreController(directory: URL.publicKeyDirectory)
|
|
|
|
@State var pending: ([[SignatureRequest]], (Set<SignatureRequest>) async throws -> Void)?
|
|
@Environment(\.openWindow) var openWindow
|
|
|
|
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.secretagent", category: "App")
|
|
@SceneBuilder var body: some Scene {
|
|
MenuBarExtra(isInserted: .constant(false)) {
|
|
EmptyView()
|
|
} label: {
|
|
Image(systemName: "lock")
|
|
.task {
|
|
await notifier.registerPersistenceHandler {
|
|
try await authenticationHandler.persistAuthentication(secret: $0, forDuration: $1)
|
|
}
|
|
}
|
|
.task {
|
|
let socketController = SocketController(path: URL.socketPath)
|
|
let agent = Agent(storeList: storeList, authenticationHandler: authenticationHandler, witness: notifier)
|
|
for await session in socketController.sessions {
|
|
Task {
|
|
let inputParser = try await XPCAgentInputParser()
|
|
do {
|
|
for await message in session.messages {
|
|
let request = try await inputParser.parse(data: message)
|
|
let agentResponse = await agent.handle(request: request, provenance: session.provenance)
|
|
try session.write(agentResponse)
|
|
}
|
|
} catch {
|
|
try session.close()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// .task {
|
|
// let socketController = SocketController(path: URL.agentHomeURL.appendingPathComponent("socket-two.ssh").path())
|
|
// let socketController = SocketController(path: "/Users/max/Downloads/test.ssh")
|
|
// let agent = Agent(storeList: storeList, authenticationHandler: authenticationHandler, witness: notifier)
|
|
// for await session in socketController.sessions {
|
|
// Task {
|
|
// let inputParser = try await XPCAgentInputParser()
|
|
// do {
|
|
// for await message in session.messages {
|
|
// let request = try await inputParser.parse(data: message)
|
|
// let agentResponse = await agent.handle(request: request, provenance: session.provenance)
|
|
// try session.write(agentResponse)
|
|
// }
|
|
// } catch {
|
|
// try session.close()
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
.task {
|
|
for await _ in NotificationCenter.default.notifications(named: .secretStoreReloaded) {
|
|
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
|
}
|
|
}
|
|
.task {
|
|
await authenticationHandler.setBatchAuthHandler { @MainActor pending, authorize in
|
|
self.pending = (pending, authorize)
|
|
openWindow(id: String(describing: BatchedRequestsView.self))
|
|
}
|
|
|
|
}
|
|
.task {
|
|
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
|
notifier.prompt()
|
|
_ = withObservationTracking {
|
|
updater.update
|
|
} onChange: { [updater, notifier] in
|
|
Task {
|
|
guard !updater.currentVersion.isTestBuild else { return }
|
|
await notifier.notify(update: updater.update!) { release in
|
|
await updater.ignore(release: release)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
WindowGroup(id: String(describing: BatchedRequestsView.self)) {
|
|
pendingView
|
|
}
|
|
.windowStyle(.hiddenTitleBar)
|
|
.windowResizability(.contentSize)
|
|
}
|
|
|
|
@ViewBuilder
|
|
var pendingView: some View {
|
|
if let (requests, authorize) = pending {
|
|
BatchedRequestsView(pending: requests, review: authorize)
|
|
}
|
|
}
|
|
|
|
|
|
}
|