diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
index 895a6e4c..e7e4308d 100644
--- a/damus.xcodeproj/project.pbxproj
+++ b/damus.xcodeproj/project.pbxproj
@@ -1494,6 +1494,7 @@
INFOPLIST_FILE = damus/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Damus;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ INFOPLIST_KEY_NSFaceIDUsageDescription = "Local authentication to access private key";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "Granting Damus access to your photos allows you to save images.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@@ -1535,6 +1536,7 @@
INFOPLIST_FILE = damus/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Damus;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ INFOPLIST_KEY_NSFaceIDUsageDescription = "Local authentication to access private key";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "Granting Damus access to your photos allows you to save images.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
diff --git a/damus/Views/ConfigView.swift b/damus/Views/ConfigView.swift
index 217469e4..81ad009c 100644
--- a/damus/Views/ConfigView.swift
+++ b/damus/Views/ConfigView.swift
@@ -7,6 +7,7 @@
import AVFoundation
import Kingfisher
import SwiftUI
+import LocalAuthentication
struct ConfigView: View {
let state: DamusState
@@ -14,6 +15,7 @@ struct ConfigView: View {
@State var confirm_logout: Bool = false
@State var confirm_delete_account: Bool = false
@State var show_privkey: Bool = false
+ @State var has_authenticated_locally: Bool = false
@State var show_libretranslate_api_key: Bool = false
@State var privkey: String
@State var privkey_copied: Bool = false
@@ -30,13 +32,45 @@ struct ConfigView: View {
_settings = ObservedObject(initialValue: state.settings)
}
+ func authenticateLocally(completion: @escaping (Bool) -> Void) {
+ // Need to authenticate only once while ConfigView is presented
+ guard !has_authenticated_locally else {
+ completion(true)
+ return
+ }
+ let context = LAContext()
+ if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) {
+ context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: NSLocalizedString("Local authentication to access private key", comment: "Face ID usage description shown when trying to access private key")) { success, error in
+ DispatchQueue.main.async {
+ has_authenticated_locally = success
+ completion(success)
+ }
+ }
+ } else {
+ // If there's no authentication set up on the device, let the user copy the key without it
+ has_authenticated_locally = true
+ completion(true)
+ }
+ }
+
// TODO: (jb55) could be more general but not gonna worry about it atm
func CopyButton(is_pk: Bool) -> some View {
return Button(action: {
- UIPasteboard.general.string = is_pk ? self.state.keypair.pubkey_bech32 : self.privkey
- self.privkey_copied = !is_pk
- self.pubkey_copied = is_pk
- generator.impactOccurred()
+ let copyKey = {
+ UIPasteboard.general.string = is_pk ? self.state.keypair.pubkey_bech32 : self.privkey
+ self.privkey_copied = !is_pk
+ self.pubkey_copied = is_pk
+ generator.impactOccurred()
+ }
+ if has_authenticated_locally {
+ copyKey()
+ } else {
+ authenticateLocally { success in
+ if success {
+ copyKey()
+ }
+ }
+ }
}) {
let copied = is_pk ? self.pubkey_copied : self.privkey_copied
Image(systemName: copied ? "checkmark.circle" : "doc.on.doc")
@@ -58,7 +92,7 @@ struct ConfigView: View {
if let sec = state.keypair.privkey_bech32 {
Section(NSLocalizedString("Secret Account Login Key", comment: "Section title for user's secret account login key.")) {
HStack {
- if show_privkey == false {
+ if show_privkey == false || !has_authenticated_locally {
SecureField(NSLocalizedString("Private Key", comment: "Title of the secure field that holds the user's private key."), text: $privkey)
.disabled(true)
} else {
@@ -70,6 +104,13 @@ struct ConfigView: View {
}
Toggle(NSLocalizedString("Show", comment: "Toggle to show or hide user's secret account login key."), isOn: $show_privkey)
+ .onChange(of: show_privkey) { newValue in
+ if newValue {
+ authenticateLocally { success in
+ show_privkey = success
+ }
+ }
+ }
}
}
diff --git a/translations/en-US.xcloc/Localized Contents/en-US.xliff b/translations/en-US.xcloc/Localized Contents/en-US.xliff
index 35fe4a41..aba43920 100644
--- a/translations/en-US.xcloc/Localized Contents/en-US.xliff
+++ b/translations/en-US.xcloc/Localized Contents/en-US.xliff
@@ -15,6 +15,11 @@
damusBundle name
+
+ Local authentication to access private key
+ Local authentication to access private key
+ Privacy - Face ID Usage Description
+ Granting Damus access to your photos allows you to save images.Granting Damus access to your photos allows you to save images.
@@ -444,6 +449,11 @@ Number of profiles a user is following.
FollowButton to follow a user.
+
+ Follow me on nostr
+ Follow me on nostr
+ No comment provided by engineer.
+ FollowersFollowers
@@ -540,6 +550,11 @@ Part of a larger sentence to describe how many profiles a user is following.Lightning Invoice
Indicates that the view is for paying a Lightning invoice.
+
+ Local authentication to access private key
+ Local authentication to access private key
+ Face ID usage description shown when trying to access private key
+ Local defaultLocal default
@@ -573,11 +588,6 @@ Part of a larger sentence to describe how many profiles a user is following.NIP-05 Verification
Label for NIP-05 Verification section of user profile form.
-
- No
- No
- Button to cancel out of posting a note after being alerted that it looks like they might be posting a private key.
- No block list found, create a new one? This will overwrite any previous block lists.No block list found, create a new one? This will overwrite any previous block lists.
@@ -588,11 +598,6 @@ Part of a larger sentence to describe how many profiles a user is following.None
Dropdown option for selecting no translation server.
-
- Note contains "nsec1" private key. Are you sure?
- Note contains "nsec1" private key. Are you sure?
- Alert user that they might be attempting to paste a private key and ask them to confirm.
- Nothing to see here. Check back later!Nothing to see here. Check back later!
@@ -714,6 +719,11 @@ Part of a larger sentence to describe how many profiles a user is following.Relays have been notified and clients will be able to use this information to filter content. Thank you!
Description of what was done as a result of sending a report to relay servers.
+
+ Remote Image Loading Policy
+ Remote Image Loading Policy
+ Section title for remote image loading policy
+ Remove allRemove all
@@ -796,6 +806,11 @@ Part of a larger sentence to describe how many profiles a user is following.Save Image
Context menu option to save an image.
+
+ Scan the code
+ Scan the code
+ No comment provided by engineer.
+ Search hashtag: #%@Search hashtag: #%@
@@ -1011,11 +1026,6 @@ Part of a larger sentence to describe how many profiles a user is following.Yes, Overwrite
Text of button that confirms to overwrite the existing mutelist.
-
- Yes, Post with Private Key
- Yes, Post with Private Key
- Button to proceed with posting a note even though it looks like they might be posting a private key.
- Your NameYour Name
@@ -1026,6 +1036,11 @@ Part of a larger sentence to describe how many profiles a user is following.Your report will be sent to the relays you are connected to
Footer text to inform user what will happen when the report is submitted.
+
+ Zaps
+ Zaps
+ Part of a larger sentence to describe how many zap payments there are on a post.
+ ZebedeeZebedee
@@ -1131,11 +1146,6 @@ Part of a larger sentence to describe how many profiles a user is following.you
You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself.
-
- zaps_count
- zaps_count
- Part of a larger sentence to describe how many zap payments there are on a post. (Key in .stringsdict)
- ⚡️ %@⚡️ %@
@@ -1281,17 +1291,17 @@ Part of a larger sentence to describe how many profiles a user is following.
%#@ZAPS@%#@ZAPS@
- Part of a larger sentence to describe how many zap payments there are on a post.
+ ZapZap
- Part of a larger sentence to describe how many zap payments there are on a post.
+ ZapsZaps
- Part of a larger sentence to describe how many zap payments there are on a post.
+