Expand parsing + bug fixes for cert UI (#802)

* Expand parsing and display of cert types, some additional cleanup

* Tweak cert
This commit is contained in:
Max Goedjen
2026-05-06 20:01:40 -07:00
committed by GitHub
parent 9bdf9775d2
commit 437386b87e
24 changed files with 363 additions and 100 deletions

View File

@@ -1,11 +1,12 @@
import SwiftUI
import SecretKit
import Common
import CertificateKit
import SSHProtocolKit
import CryptoKit
struct CertificateDetailView: View {
let certificate: OpenSSHCertificate
let certificate: Certificate
var body: some View {
ScrollView {
@@ -25,6 +26,26 @@ struct CertificateDetailView: View {
)
Spacer()
.frame(height: 20)
CopyableView(
title: .secretDetailSha256FingerprintLabel,
image: Image(systemName: "touchid"),
text: OpenSSHCertificateWriter().openSSHSHA256KeyFingerprint(publicKey: certificate.publicKey)
)
Spacer()
.frame(height: 20)
CopyableView(
title: .secretDetailSha256FingerprintLabel,
image: Image(systemName: "touchid"),
text: OpenSSHCertificateWriter().openSSHSHA256KeyFingerprint(publicKey: certificate.signingKey)
)
Spacer()
.frame(height: 20)
CopyableView(
title: .certificateDetailPathLabel,
image: Image(systemName: "checkmark.seal.text.page"),
text: URL.certificatePath(for: certificate.id, in: URL.certificatesDirectory),
showRevealInFinder: true
)
if let validityRange = certificate.validityRange {
let epoch = Date(timeIntervalSince1970: 0)
let end = Date(timeIntervalSince1970: TimeInterval(UInt64.max))
@@ -32,30 +53,34 @@ struct CertificateDetailView: View {
case (epoch, end):
EmptyView()
case (epoch, let otherEnd):
Spacer()
.frame(height: 20)
MultilineInfoView(title: .certificateDetailValidUntilLabel, image: Image(systemName: "calendar.badge.clock"), items: [otherEnd.formatted()])
Spacer()
.frame(height: 20)
case (let otherStart, end):
Spacer()
.frame(height: 20)
MultilineInfoView(title: .certificateDetailValidAfterLabel, image: Image(systemName: "calendar.badge.clock"), items: [otherStart.formatted()])
Spacer()
.frame(height: 20)
default:
MultilineInfoView(title: .certificateDetailValidityRangeLabel, image: Image(systemName: "calendar.badge.clock"), items: [validityRange.formatted()])
Spacer()
.frame(height: 20)
MultilineInfoView(title: .certificateDetailValidityRangeLabel, image: Image(systemName: "calendar.badge.clock"), items: [validityRange.formatted()])
}
}
if !certificate.principals.isEmpty {
MultilineInfoView(title: .certificateDetailPrincipalsLabel, image: Image(systemName: "person.2"), items: certificate.principals)
Spacer()
.frame(height: 20)
MultilineInfoView(title: .certificateDetailPrincipalsLabel, image: Image(systemName: "person.2"), items: certificate.principals)
}
if !certificate.criticalOptions.isEmpty {
Spacer()
.frame(height: 20)
MultilineInfoView(title: .certificateDetailCriticalOptionsLabel, image: Image(systemName: "person.2"), items: certificate.criticalOptions)
}
if !certificate.extensions.isEmpty {
Spacer()
.frame(height: 20)
MultilineInfoView(title: .certificateDetailExtensionsLabel, image: Image(systemName: "person.2"), items: certificate.extensions)
}
CopyableView(
title: .certificateDetailPathLabel,
image: Image(systemName: "checkmark.seal.text.page"),
text: URL.certificatePath(for: certificate, in: URL.certificatesDirectory),
showRevealInFinder: true
)
Spacer()
}
}

View File

@@ -6,13 +6,13 @@ struct CertificateListItemView: View {
@Environment(\.certificateStore) private var store
var certificate: OpenSSHCertificate
var certificate: Certificate
@State var isDeleting: Bool = false
@State var isRenaming: Bool = false
var deletedCertificate: (OpenSSHCertificate) -> Void
var renamedCertificate: (OpenSSHCertificate) -> Void
var deletedCertificate: (Certificate) -> Void
var renamedCertificate: (Certificate) -> Void
var body: some View {
NavigationLink(value: certificate) {

View File

@@ -4,7 +4,7 @@ import SSHProtocolKit
extension View {
func showingDeleteConfirmation(isPresented: Binding<Bool>, _ certificate: OpenSSHCertificate, _ store: CertificateStore, dismissalBlock: @escaping (Bool) -> ()) -> some View {
func showingDeleteConfirmation(isPresented: Binding<Bool>, _ certificate: Certificate, _ store: CertificateStore, dismissalBlock: @escaping (Bool) -> ()) -> some View {
modifier(DeleteCertificateConfirmationModifier(isPresented: isPresented, certificate: certificate, store: store, dismissalBlock: dismissalBlock))
}
@@ -13,7 +13,7 @@ extension View {
struct DeleteCertificateConfirmationModifier: ViewModifier {
var isPresented: Binding<Bool>
var certificate: OpenSSHCertificate
var certificate: Certificate
var store: CertificateStore
var dismissalBlock: (Bool) -> ()
@State var confirmedSecretName = ""

View File

@@ -5,14 +5,14 @@ import CertificateKit
struct EditCertificateView: View {
let store: CertificateStore
let certificate: OpenSSHCertificate
let certificate: Certificate
@State private var name: String
@State var errorText: String?
@Environment(\.dismiss) var dismiss
init(store: CertificateStore, certificate: OpenSSHCertificate) {
init(store: CertificateStore, certificate: Certificate) {
self.store = store
self.certificate = certificate
name = certificate.name
@@ -49,7 +49,7 @@ struct EditCertificateView: View {
Task {
do {
var updated = certificate
updated.name = name
updated.openSSHCertificate.name = name
try store.update(certificate: updated)
dismiss()
} catch {

View File

@@ -1,13 +1,14 @@
import SwiftUI
import SecretKit
import Common
import CertificateKit
import SSHProtocolKit
struct SecretDetailView<SecretType: Secret>: View {
let secret: SecretType
let certificates: [OpenSSHCertificate]
let navigateToCertificate: ((OpenSSHCertificate) -> Void)?
let certificates: [Certificate]
let navigateToCertificate: ((Certificate) -> Void)?
private let keyWriter = OpenSSHPublicKeyWriter()

View File

@@ -1,12 +1,13 @@
import SwiftUI
import SecretKit
import SSHProtocolKit
import CertificateKit
struct StoreListView: View {
enum StoreListSelection: Hashable {
case secret(AnySecret)
case certificate(OpenSSHCertificate)
case certificate(Certificate)
}
@Binding var selection: StoreListSelection?