mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-09-27 18:48:00 +02:00
Pending request view (#821)
* Splitting out auth context stuff in preparation for batch * Add uncommitted authhandler rename * Split out auth/nonauth paths * Messy auth batching infra WIP * Restrict connectionAcceptedNotifications to creating filehandle * WIP * WIP * WIP * WIP * WIP * Reenable multilineinfoview * WIP * WIP * Fixing up tests * WIP * Return empty bind response on parse throw * JSON project * JSON Project * WIP * WIP * Almost done * Tests * Cleanup test calls * Fixme * Cleanup * Localized strings
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import Cocoa
|
||||
import OSLog
|
||||
import SecretKit
|
||||
import SecureEnclaveSecretKit
|
||||
import SmartCardSecretKit
|
||||
import SecretAgentKit
|
||||
import Brief
|
||||
import Observation
|
||||
import Common
|
||||
import SwiftUI
|
||||
import CertificateKit
|
||||
|
||||
@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
|
||||
}()
|
||||
@MainActor private let certificateStore: CertificateStore = CertificateStore()
|
||||
|
||||
private let updater = Updater(checkOnLaunch: true)
|
||||
private let notifier = Notifier()
|
||||
private let authenticationHandler = AuthenticationHandler()
|
||||
private let publicKeyFileStoreController = PublicKeyFileStoreController(publicKeysURL: URL.publicKeyDirectory, certificatesURL: URL.certificatesDirectory)
|
||||
|
||||
@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,
|
||||
certificateStore: certificateStore,
|
||||
authenticationHandler: authenticationHandler,
|
||||
witness: notifier
|
||||
)
|
||||
for await session in socketController.sessions {
|
||||
Task {
|
||||
do {
|
||||
let inputParser = try await XPCAgentInputParser()
|
||||
let hosts = try? await XPCHostsfileReader().read()
|
||||
for await message in session.messages {
|
||||
let request = try await inputParser.parse(data: message)
|
||||
let agentResponse = await agent.handle(request: request, provenance: session.provenance, hosts: hosts)
|
||||
try session.write(agentResponse)
|
||||
}
|
||||
} catch {
|
||||
try? session.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.task {
|
||||
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
||||
for await _ in NotificationCenter.default.notifications(named: .secretStoreReloaded) {
|
||||
try? publicKeyFileStoreController.generatePublicKeys(for: storeList.allSecrets, clear: true)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
let certsMigrator = CertificateMigrator(homeDirectory: URL.homeDirectory, certificateStore: certificateStore)
|
||||
try? certsMigrator.migrate()
|
||||
try? publicKeyFileStoreController.generateCertificates(for: certificateStore.certificates, clear: true)
|
||||
for await _ in NotificationCenter.default.notifications(named: .certificateStoreReloaded) {
|
||||
try? publicKeyFileStoreController.generateCertificates(for: certificateStore.certificates, clear: true)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
authenticationHandler.setPendingRequestHandler { @MainActor in
|
||||
openWindow(value: PendingRequestsViewIdentifier())
|
||||
}
|
||||
|
||||
}
|
||||
.task {
|
||||
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(for: PendingRequestsViewIdentifier.self) { _ in
|
||||
pendingView
|
||||
}
|
||||
.windowStyle(.hiddenTitleBar)
|
||||
.windowResizability(.contentSize)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var pendingView: some View {
|
||||
if !authenticationHandler.batchableRequests.isEmpty {
|
||||
PendingRequestsView(authenticationHandler: authenticationHandler)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct PendingRequestsViewIdentifier: Codable, Hashable {}
|
||||
Reference in New Issue
Block a user