mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-04-09 18:57:22 +02:00
Compare commits
7 Commits
crowdin_co
...
log_err
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8cf0db1c5 | ||
|
|
412687467b | ||
|
|
416a7d5f40 | ||
|
|
c4605fb60e | ||
|
|
61eed5987c | ||
|
|
cbef7c6181 | ||
|
|
63a09390b8 |
21
.github/workflows/nightly.yml
vendored
21
.github/workflows/nightly.yml
vendored
@@ -3,10 +3,16 @@ name: Nightly
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 8 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# runs-on: macOS-latest
|
||||
runs-on: macos-15
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
attestations: write
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
@@ -30,22 +36,23 @@ jobs:
|
||||
sed -i '' -e "s/GITHUB_BUILD_URL/https:\/\/github.com\/maxgoedjen\/secretive\/actions\/runs\/$RUN_ID/g" Sources/Secretive/Credits.rtf
|
||||
- name: Build
|
||||
run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme Secretive -configuration Release -archivePath Archive.xcarchive archive
|
||||
- name: Create ZIPs
|
||||
- name: Create ZIP
|
||||
run: |
|
||||
ditto -c -k --sequesterRsrc --keepParent Archive.xcarchive/Products/Applications/Secretive.app ./Secretive.zip
|
||||
ditto -c -k --sequesterRsrc --keepParent Archive.xcarchive ./Archive.zip
|
||||
- name: Notarize
|
||||
env:
|
||||
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
|
||||
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
|
||||
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
||||
- name: Attest
|
||||
id: attest
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-path: 'Secretive.zip'
|
||||
- name: Upload App to Artifacts
|
||||
id: upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Secretive.zip
|
||||
path: Secretive.zip
|
||||
- name: Attest
|
||||
id: attest
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: "Secretive.zip"
|
||||
subject-digest: sha256:${{ steps.upload.outputs.artifact-digest }}
|
||||
|
||||
23
.github/workflows/release.yml
vendored
23
.github/workflows/release.yml
vendored
@@ -56,39 +56,34 @@ jobs:
|
||||
sed -i '' -e "s/GITHUB_BUILD_URL/https:\/\/github.com\/maxgoedjen\/secretive\/actions\/runs\/$RUN_ID/g" Sources/Secretive/Credits.rtf
|
||||
- name: Build
|
||||
run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme Secretive -configuration Release -archivePath Archive.xcarchive archive
|
||||
- name: Create ZIPs
|
||||
- name: Create ZIP
|
||||
run: |
|
||||
ditto -c -k --sequesterRsrc --keepParent Archive.xcarchive/Products/Applications/Secretive.app ./Secretive.zip
|
||||
ditto -c -k --sequesterRsrc --keepParent Archive.xcarchive ./Xcode_Archive.zip
|
||||
- name: Notarize
|
||||
env:
|
||||
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
|
||||
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
|
||||
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
||||
- name: Upload App to Artifacts
|
||||
id: upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Secretive.zip
|
||||
path: Secretive.zip
|
||||
- name: Attest
|
||||
id: attest
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-path: 'Secretive.zip, Xcode_Archive.zip'
|
||||
subject-name: "Secretive.zip"
|
||||
subject-digest: ${{ steps.upload.outputs.artifact-digest }}
|
||||
- name: Create Release
|
||||
run: |
|
||||
sed -i.tmp "s/RUN_ID/$RUN_ID/g" .github/templates/release.md
|
||||
sed -i.tmp "s/ATTESTATION_ID/$ATTESTATION_ID/g" .github/templates/release.md
|
||||
gh release create $TAG_NAME -d -F .github/templates/release.md
|
||||
gh release upload Secretive.zip
|
||||
gh release upload Xcode_Archive.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAG_NAME: ${{ github.ref }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
ATTESTATION_ID: ${{ steps.attest.outputs.attestation-id }}
|
||||
- name: Upload App to Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Secretive.zip
|
||||
path: Secretive.zip
|
||||
- name: Upload Archive to Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Xcode_Archive.zip
|
||||
path: Xcode_Archive.zip
|
||||
|
||||
@@ -3403,28 +3403,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"integrations_public_key_path_placeholder" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "YOUR_PUBLIC_KEY_PATH"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"integrations_public_key_placeholder" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "YOUR_PUBLIC_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"integrations_shell_section_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
|
||||
@@ -30,7 +30,7 @@ extension SecureEnclave {
|
||||
SecItemCopyMatching(privateAttributes, &privateUntyped)
|
||||
guard let privateTyped = privateUntyped as? [[CFString: Any]] else { return }
|
||||
let migratedPublicKeys = Set(store.secrets.map(\.publicKey))
|
||||
var migrated = false
|
||||
var migratedAny = false
|
||||
for key in privateTyped {
|
||||
let name = key[kSecAttrLabel] as? String ?? String(localized: .unnamedSecret)
|
||||
let id = key[kSecAttrApplicationLabel] as! Data
|
||||
@@ -45,20 +45,24 @@ extension SecureEnclave {
|
||||
// Best guess.
|
||||
let auth: AuthenticationRequirement = String(describing: accessControl)
|
||||
.contains("DeviceOwnerAuthentication") ? .presenceRequired : .unknown
|
||||
let parsed = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: tokenObjectID)
|
||||
let secret = Secret(id: UUID().uuidString, name: name, publicKey: parsed.publicKey.x963Representation, attributes: Attributes(keyType: .init(algorithm: .ecdsa, size: 256), authentication: auth))
|
||||
guard !migratedPublicKeys.contains(parsed.publicKey.x963Representation) else {
|
||||
logger.log("Skipping \(name), public key already present. Marking as migrated.")
|
||||
do {
|
||||
let parsed = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: tokenObjectID)
|
||||
let secret = Secret(id: UUID().uuidString, name: name, publicKey: parsed.publicKey.x963Representation, attributes: Attributes(keyType: .init(algorithm: .ecdsa, size: 256), authentication: auth))
|
||||
guard !migratedPublicKeys.contains(parsed.publicKey.x963Representation) else {
|
||||
logger.log("Skipping \(name), public key already present. Marking as migrated.")
|
||||
try markMigrated(secret: secret, oldID: id)
|
||||
continue
|
||||
}
|
||||
logger.log("Migrating \(name).")
|
||||
try store.saveKey(tokenObjectID, name: name, attributes: secret.attributes)
|
||||
logger.log("Migrated \(name).")
|
||||
try markMigrated(secret: secret, oldID: id)
|
||||
continue
|
||||
migratedAny = true
|
||||
} catch {
|
||||
logger.error("Failed to migrate \(name): \(error).")
|
||||
}
|
||||
logger.log("Migrating \(name).")
|
||||
try store.saveKey(tokenObjectID, name: name, attributes: secret.attributes)
|
||||
logger.log("Migrated \(name).")
|
||||
try markMigrated(secret: secret, oldID: id)
|
||||
migrated = true
|
||||
}
|
||||
if migrated {
|
||||
if migratedAny {
|
||||
store.reloadSecrets()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +146,6 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
CreateSecretView(store: Preview.StoreModifiable()) { _ in }
|
||||
}
|
||||
//#Preview {
|
||||
// CreateSecretView(store: Preview.StoreModifiable()) { _ in }
|
||||
//}
|
||||
|
||||
@@ -57,15 +57,10 @@ struct EmptyStoreModifiableView: View {
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct EmptyStoreModifiableView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group {
|
||||
EmptyStoreImmutableView()
|
||||
EmptyStoreModifiableView()
|
||||
}
|
||||
}
|
||||
#Preview {
|
||||
EmptyStoreImmutableView()
|
||||
}
|
||||
#Preview {
|
||||
EmptyStoreModifiableView()
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,12 +13,7 @@ struct NoStoresView: View {
|
||||
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct NoStoresView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NoStoresView()
|
||||
}
|
||||
#Preview {
|
||||
NoStoresView()
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,6 @@ struct SecretDetailView<SecretType: Secret>: View {
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
SecretDetailView(secret: Preview.Secret(name: "Demonstration Secret"))
|
||||
}
|
||||
//#Preview {
|
||||
// SecretDetailView(secret: Preview.Secret(name: "Demonstration Secret"))
|
||||
//}
|
||||
|
||||
@@ -143,11 +143,11 @@ struct AgentNotRunningView: View {
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
AgentStatusView()
|
||||
.environment(\.agentStatusChecker, PreviewAgentStatusChecker(running: false))
|
||||
}
|
||||
#Preview {
|
||||
AgentStatusView()
|
||||
.environment(\.agentStatusChecker, PreviewAgentStatusChecker(running: true, process: .current))
|
||||
}
|
||||
//#Preview {
|
||||
// AgentStatusView()
|
||||
// .environment(\.agentStatusChecker, PreviewAgentStatusChecker(running: false))
|
||||
//}
|
||||
//#Preview {
|
||||
// AgentStatusView()
|
||||
// .environment(\.agentStatusChecker, PreviewAgentStatusChecker(running: true, process: .current))
|
||||
//}
|
||||
|
||||
@@ -198,25 +198,17 @@ extension ContentView {
|
||||
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
|
||||
static var previews: some View {
|
||||
Group {
|
||||
// Empty on modifiable and nonmodifiable
|
||||
ContentView(showingCreation: .constant(false), runningSetup: .constant(false), hasRunSetup: .constant(true))
|
||||
.environment(Preview.storeList(stores: [Preview.Store(numberOfRandomSecrets: 0)], modifiableStores: [Preview.StoreModifiable(numberOfRandomSecrets: 0)]))
|
||||
.environment(PreviewUpdater())
|
||||
|
||||
// 5 items on modifiable and nonmodifiable
|
||||
ContentView(showingCreation: .constant(false), runningSetup: .constant(false), hasRunSetup: .constant(true))
|
||||
.environment(Preview.storeList(stores: [Preview.Store()], modifiableStores: [Preview.StoreModifiable()]))
|
||||
.environment(PreviewUpdater())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//#Preview {
|
||||
// // Empty on modifiable and nonmodifiable
|
||||
// ContentView(showingCreation: .constant(false), runningSetup: .constant(false), hasRunSetup: .constant(true))
|
||||
// .environment(Preview.storeList(stores: [Preview.Store(numberOfRandomSecrets: 0)], modifiableStores: [Preview.StoreModifiable(numberOfRandomSecrets: 0)]))
|
||||
// .environment(PreviewUpdater())
|
||||
//}
|
||||
//
|
||||
//#Preview {
|
||||
// // 5 items on modifiable and nonmodifiable
|
||||
// ContentView(showingCreation: .constant(false), runningSetup: .constant(false), hasRunSetup: .constant(true))
|
||||
// .environment(Preview.storeList(stores: [Preview.Store()], modifiableStores: [Preview.StoreModifiable()]))
|
||||
// .environment(PreviewUpdater())
|
||||
//}
|
||||
|
||||
@@ -163,17 +163,12 @@ fileprivate struct BackgroundViewModifier: ViewModifier {
|
||||
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct CopyableView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group {
|
||||
CopyableView(title: .secretDetailSha256FingerprintLabel, image: Image(systemName: "figure.wave"), text: "Hello world.")
|
||||
.padding()
|
||||
CopyableView(title: .secretDetailSha256FingerprintLabel, image: Image(systemName: "figure.wave"), text: "Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. ")
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
#Preview {
|
||||
CopyableView(title: .secretDetailSha256FingerprintLabel, image: Image(systemName: "figure.wave"), text: "Hello world.")
|
||||
.padding()
|
||||
}
|
||||
|
||||
#endif
|
||||
#Preview {
|
||||
CopyableView(title: .secretDetailSha256FingerprintLabel, image: Image(systemName: "figure.wave"), text: "Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. ")
|
||||
.padding()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user