Missing secrets help (#671)

This commit is contained in:
Max Goedjen 2025-09-04 01:10:50 -07:00 committed by GitHub
parent 902d5c4a1e
commit 558ae15b2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 107 additions and 15 deletions

View File

@ -2901,6 +2901,28 @@
} }
} }
}, },
"empty_store_modifiable_empty_os_warning_description" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "It looks like you may have recently updated macOS. Sometimes this puts the Secure Enclave into a weird state, and you might need to reboot your Mac before things start working again."
}
}
}
},
"empty_store_modifiable_empty_os_warning_title" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Missing Secrets?"
}
}
}
},
"empty_store_nonmodifiable_description" : { "empty_store_nonmodifiable_description" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {

View File

@ -30,6 +30,7 @@
504788F22E681F3A00B4556F /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F12E681F3A00B4556F /* Instructions.swift */; }; 504788F22E681F3A00B4556F /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F12E681F3A00B4556F /* Instructions.swift */; };
504788F42E681F6900B4556F /* ToolConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F32E681F6900B4556F /* ToolConfigurationView.swift */; }; 504788F42E681F6900B4556F /* ToolConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F32E681F6900B4556F /* ToolConfigurationView.swift */; };
504788F62E68206F00B4556F /* GettingStartedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F52E68206F00B4556F /* GettingStartedView.swift */; }; 504788F62E68206F00B4556F /* GettingStartedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F52E68206F00B4556F /* GettingStartedView.swift */; };
504789232E697DD300B4556F /* BoxBackgroundStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504789222E697DD300B4556F /* BoxBackgroundStyle.swift */; };
50571E0324393C2600F76F6C /* JustUpdatedChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */; }; 50571E0324393C2600F76F6C /* JustUpdatedChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */; };
50571E0524393D1500F76F6C /* LaunchAgentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0424393D1500F76F6C /* LaunchAgentController.swift */; }; 50571E0524393D1500F76F6C /* LaunchAgentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0424393D1500F76F6C /* LaunchAgentController.swift */; };
50617D8323FCE48E0099B055 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50617D8223FCE48E0099B055 /* App.swift */; }; 50617D8323FCE48E0099B055 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50617D8223FCE48E0099B055 /* App.swift */; };
@ -118,6 +119,7 @@
504788F12E681F3A00B4556F /* Instructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = "<group>"; }; 504788F12E681F3A00B4556F /* Instructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = "<group>"; };
504788F32E681F6900B4556F /* ToolConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolConfigurationView.swift; sourceTree = "<group>"; }; 504788F32E681F6900B4556F /* ToolConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolConfigurationView.swift; sourceTree = "<group>"; };
504788F52E68206F00B4556F /* GettingStartedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingStartedView.swift; sourceTree = "<group>"; }; 504788F52E68206F00B4556F /* GettingStartedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingStartedView.swift; sourceTree = "<group>"; };
504789222E697DD300B4556F /* BoxBackgroundStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxBackgroundStyle.swift; sourceTree = "<group>"; };
50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JustUpdatedChecker.swift; sourceTree = "<group>"; }; 50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JustUpdatedChecker.swift; sourceTree = "<group>"; };
50571E0424393D1500F76F6C /* LaunchAgentController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAgentController.swift; sourceTree = "<group>"; }; 50571E0424393D1500F76F6C /* LaunchAgentController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAgentController.swift; sourceTree = "<group>"; };
50617D7F23FCE48E0099B055 /* Secretive.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretive.app; sourceTree = BUILT_PRODUCTS_DIR; }; 50617D7F23FCE48E0099B055 /* Secretive.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretive.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -198,6 +200,7 @@
children = ( children = (
50CF4ABB2E601B0F005588DC /* ActionButtonStyle.swift */, 50CF4ABB2E601B0F005588DC /* ActionButtonStyle.swift */,
50BDCB732E6436C60072D2E7 /* ErrorStyle.swift */, 50BDCB732E6436C60072D2E7 /* ErrorStyle.swift */,
504789222E697DD300B4556F /* BoxBackgroundStyle.swift */,
5065E312295517C500E16645 /* ToolbarButtonStyle.swift */, 5065E312295517C500E16645 /* ToolbarButtonStyle.swift */,
); );
path = Styles; path = Styles;
@ -491,6 +494,7 @@
2C4A9D2F2636FFD3008CC8E2 /* EditSecretView.swift in Sources */, 2C4A9D2F2636FFD3008CC8E2 /* EditSecretView.swift in Sources */,
5091D2BC25183B830049FD9B /* ApplicationDirectoryController.swift in Sources */, 5091D2BC25183B830049FD9B /* ApplicationDirectoryController.swift in Sources */,
504788EC2E680DC800B4556F /* URLs.swift in Sources */, 504788EC2E680DC800B4556F /* URLs.swift in Sources */,
504789232E697DD300B4556F /* BoxBackgroundStyle.swift in Sources */,
5066A6C22516F303004B5A36 /* SetupView.swift in Sources */, 5066A6C22516F303004B5A36 /* SetupView.swift in Sources */,
5065E313295517C500E16645 /* ToolbarButtonStyle.swift in Sources */, 5065E313295517C500E16645 /* ToolbarButtonStyle.swift in Sources */,
50617D8523FCE48E0099B055 /* ContentView.swift in Sources */, 50617D8523FCE48E0099B055 /* ContentView.swift in Sources */,

View File

@ -25,6 +25,9 @@ extension EnvironmentValues {
}() }()
@Entry var updater: any UpdaterProtocol = _updater @Entry var updater: any UpdaterProtocol = _updater
private static let _justUpdatedChecker = JustUpdatedChecker()
@Entry var justUpdatedChecker: any JustUpdatedCheckerProtocol = _justUpdatedChecker
@MainActor var secretStoreList: SecretStoreList { @MainActor var secretStoreList: SecretStoreList {
EnvironmentValues._secretStoreList EnvironmentValues._secretStoreList
} }
@ -33,8 +36,8 @@ extension EnvironmentValues {
@main @main
struct Secretive: App { struct Secretive: App {
private let justUpdatedChecker = JustUpdatedChecker()
@Environment(\.agentStatusChecker) var agentStatusChecker @Environment(\.agentStatusChecker) var agentStatusChecker
@Environment(\.justUpdatedChecker) var justUpdatedChecker
@AppStorage("defaultsHasRunSetup") var hasRunSetup = false @AppStorage("defaultsHasRunSetup") var hasRunSetup = false
@State private var showingSetup = false @State private var showingSetup = false
@State private var showingIntegrations = false @State private var showingIntegrations = false
@ -52,7 +55,7 @@ struct Secretive: App {
.onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
guard hasRunSetup else { return } guard hasRunSetup else { return }
agentStatusChecker.check() agentStatusChecker.check()
if agentStatusChecker.running && justUpdatedChecker.justUpdated { if agentStatusChecker.running && justUpdatedChecker.justUpdatedBuild {
// Relaunch the agent, since it'll be running from earlier update still // Relaunch the agent, since it'll be running from earlier update still
reinstallAgent() reinstallAgent()
} else if !agentStatusChecker.running && !agentStatusChecker.developmentBuild { } else if !agentStatusChecker.running && !agentStatusChecker.developmentBuild {
@ -89,7 +92,6 @@ struct Secretive: App {
extension Secretive { extension Secretive {
private func reinstallAgent() { private func reinstallAgent() {
justUpdatedChecker.check()
Task { Task {
_ = await LaunchAgentController().install() _ = await LaunchAgentController().install()
try? await Task.sleep(for: .seconds(1)) try? await Task.sleep(for: .seconds(1))

View File

@ -1,23 +1,33 @@
import Foundation import Foundation
import AppKit import AppKit
protocol JustUpdatedCheckerProtocol: Observable { @MainActor protocol JustUpdatedCheckerProtocol: Observable {
var justUpdated: Bool { get } var justUpdatedBuild: Bool { get }
var justUpdatedOS: Bool { get }
} }
@Observable class JustUpdatedChecker: JustUpdatedCheckerProtocol { @Observable @MainActor class JustUpdatedChecker: JustUpdatedCheckerProtocol {
var justUpdated: Bool = false var justUpdatedBuild: Bool = false
var justUpdatedOS: Bool = false
init() { nonisolated init() {
Task { @MainActor in
check() check()
} }
}
func check() { private func check() {
let lastBuild = UserDefaults.standard.object(forKey: Constants.previousVersionUserDefaultsKey) as? String ?? "None" let lastBuild = UserDefaults.standard.object(forKey: Constants.previousVersionUserDefaultsKey) as? String
let lastOS = UserDefaults.standard.object(forKey: Constants.previousOSVersionUserDefaultsKey) as? String
let currentBuild = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String let currentBuild = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
let osRaw = ProcessInfo.processInfo.operatingSystemVersion
let currentOS = "\(osRaw.majorVersion).\(osRaw.minorVersion).\(osRaw.patchVersion)"
UserDefaults.standard.set(currentBuild, forKey: Constants.previousVersionUserDefaultsKey) UserDefaults.standard.set(currentBuild, forKey: Constants.previousVersionUserDefaultsKey)
justUpdated = lastBuild != currentBuild UserDefaults.standard.set(currentOS, forKey: Constants.previousOSVersionUserDefaultsKey)
justUpdatedBuild = lastBuild != currentBuild
// To prevent this showing on first lauch for every user, only show if lastBuild is non-nil.
justUpdatedOS = lastBuild != nil && lastOS != currentOS
} }
@ -28,6 +38,7 @@ extension JustUpdatedChecker {
enum Constants { enum Constants {
static let previousVersionUserDefaultsKey = "com.maxgoedjen.Secretive.lastBuild" static let previousVersionUserDefaultsKey = "com.maxgoedjen.Secretive.lastBuild"
static let previousOSVersionUserDefaultsKey = "com.maxgoedjen.Secretive.lastOS"
} }
} }

View File

@ -66,7 +66,7 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
Text(.createSecretBiometryCurrentWarning) Text(.createSecretBiometryCurrentWarning)
.padding(.horizontal, 10) .padding(.horizontal, 10)
.padding(.vertical, 3) .padding(.vertical, 3)
.background(.red.opacity(0.5), in: RoundedRectangle(cornerRadius: 5)) .boxBackground(color: .red)
} }
} }
@ -85,7 +85,7 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
Text(.createSecretMldsaWarning) Text(.createSecretMldsaWarning)
.padding(.horizontal, 10) .padding(.horizontal, 10)
.padding(.vertical, 3) .padding(.vertical, 3)
.background(.red.opacity(0.5), in: RoundedRectangle(cornerRadius: 5)) .boxBackground(color: .orange)
} }
} }
VStack(alignment: .leading) { VStack(alignment: .leading) {

View File

@ -28,6 +28,8 @@ struct EmptyStoreImmutableView: View {
struct EmptyStoreModifiableView: View { struct EmptyStoreModifiableView: View {
@Environment(\.justUpdatedChecker) var justUpdatedChecker
var body: some View { var body: some View {
GeometryReader { windowGeometry in GeometryReader { windowGeometry in
VStack { VStack {
@ -51,6 +53,21 @@ struct EmptyStoreModifiableView: View {
}.frame(height: (windowGeometry.size.height/2) - 20).padding() }.frame(height: (windowGeometry.size.height/2) - 20).padding()
Text(.emptyStoreModifiableClickHereTitle).bold() Text(.emptyStoreModifiableClickHereTitle).bold()
Text(.emptyStoreModifiableClickHereDescription) Text(.emptyStoreModifiableClickHereDescription)
if justUpdatedChecker.justUpdatedOS {
Spacer()
.frame(height: 20)
VStack(spacing: 10) {
Text(.emptyStoreModifiableEmptyOsWarningTitle)
.font(.title2)
.bold()
Text(.emptyStoreModifiableEmptyOsWarningDescription)
.fixedSize(horizontal: false, vertical: true)
.bold()
}
.padding()
.boxBackground(color: .orange)
.padding()
}
Spacer() Spacer()
}.frame(maxWidth: .infinity, maxHeight: .infinity) }.frame(maxWidth: .infinity, maxHeight: .infinity)
} }
@ -61,6 +78,10 @@ struct EmptyStoreModifiableView: View {
#Preview { #Preview {
EmptyStoreImmutableView() EmptyStoreImmutableView()
} }
#Preview {
EmptyStoreImmutableView()
// .environment(\.justUpdatedChecker, <#T##value: V##V#>)
}
#Preview { #Preview {
EmptyStoreModifiableView() EmptyStoreModifiableView()
} }

View File

@ -0,0 +1,32 @@
import SwiftUI
struct BoxBackgroundModifier: ViewModifier {
let color: Color
func body(content: Content) -> some View {
content
.background {
RoundedRectangle(cornerRadius: 5)
.fill(color.opacity(0.3))
.stroke(color, lineWidth: 1)
}
}
}
extension View {
func boxBackground(color: Color) -> some View {
modifier(BoxBackgroundModifier(color: color))
}
}
#Preview {
Text("Hello")
.boxBackground(color: .red)
.padding()
Text("Hello")
.boxBackground(color: .orange)
.padding()
}