Add secure input view to handle key inputs

This commit is contained in:
Garth Vander Houwen 2024-08-12 14:42:47 -07:00
parent 9eb64bb3ed
commit 6926d857ff
4 changed files with 66 additions and 52 deletions

View file

@ -92,6 +92,7 @@
DD6193752862F6E600E59241 /* ExternalNotificationConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6193742862F6E600E59241 /* ExternalNotificationConfig.swift */; };
DD6193772862F90F00E59241 /* CannedMessagesConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6193762862F90F00E59241 /* CannedMessagesConfig.swift */; };
DD6193792863875F00E59241 /* SerialConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6193782863875F00E59241 /* SerialConfig.swift */; };
DD6F65722C6AB8EC0053C113 /* SecureInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F65712C6AB8EC0053C113 /* SecureInput.swift */; };
DD73FD1128750779000852D6 /* PositionLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD73FD1028750779000852D6 /* PositionLog.swift */; };
DD769E0328D18BF1001A3F05 /* DeviceMetricsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */; };
DD77093B2AA1ABB8007A8BF0 /* BluetoothTips.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD77093A2AA1ABB8007A8BF0 /* BluetoothTips.swift */; };
@ -345,6 +346,7 @@
DD6193762862F90F00E59241 /* CannedMessagesConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CannedMessagesConfig.swift; sourceTree = "<group>"; };
DD6193782863875F00E59241 /* SerialConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerialConfig.swift; sourceTree = "<group>"; };
DD68BAE72C417A74004C01A0 /* MeshtasticDataModelV 40.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 40.xcdatamodel"; sourceTree = "<group>"; };
DD6F65712C6AB8EC0053C113 /* SecureInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureInput.swift; sourceTree = "<group>"; };
DD73FD1028750779000852D6 /* PositionLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionLog.swift; sourceTree = "<group>"; };
DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceMetricsLog.swift; sourceTree = "<group>"; };
DD77093A2AA1ABB8007A8BF0 /* BluetoothTips.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothTips.swift; sourceTree = "<group>"; };
@ -912,6 +914,7 @@
DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */,
DDF45C332BC1A48E005ED5F2 /* MQTTIcon.swift */,
DD5E523D298F5A7D00D21B61 /* Weather */,
DD6F65712C6AB8EC0053C113 /* SecureInput.swift */,
);
path = Helpers;
sourceTree = "<group>";
@ -1281,6 +1284,7 @@
DD4A911E2708C65400501B7E /* AppSettings.swift in Sources */,
DD1BD0F32C63C65E008C0C70 /* SecurityConfig.swift in Sources */,
DD2160AF28C5552500C17253 /* MQTTConfig.swift in Sources */,
DD6F65722C6AB8EC0053C113 /* SecureInput.swift in Sources */,
DD13AA492AB73BF400BA0C98 /* PositionPopover.swift in Sources */,
6DEDA55C2A9592F900321D2E /* MessageEntityExtension.swift in Sources */,
DDDB444229F8A88700EE2349 /* Double.swift in Sources */,

View file

@ -842,6 +842,8 @@ func textMessageAppPacket(
}
if fetchedUsers.first(where: { $0.num == packet.from }) != nil {
newMessage.fromUser = fetchedUsers.first(where: { $0.num == packet.from })
newMessage.fromUser?.publicKey = packet.publicKey
newMessage.fromUser?.pkiEncrypted = packet.pkiEncrypted
if packet.rxTime > 0 {
newMessage.fromUser?.userNode?.lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
}

View file

@ -0,0 +1,57 @@
//
// SecureInput.swift
// Meshtastic
//
// Copyright(c) Garth Vander Houwen 8/12/24.
//
import SwiftUI
struct SecureInput: View {
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
@Binding private var text: String
@State private var isSecure: Bool = true
private var title: String
init(_ title: String, text: Binding<String>) {
self.title = title
self._text = text
}
var body: some View {
ZStack(alignment: .trailing) {
Group {
if isSecure {
SecureField(title, text: $text)
.font(idiom == .phone ? .caption : .callout)
.allowsTightening(true)
.monospaced()
.keyboardType(.alphabet)
.foregroundStyle(.tertiary)
.disableAutocorrection(true)
.textSelection(.enabled)
} else {
TextField(title, text: $text, axis: .vertical)
.font(idiom == .phone ? .caption : .callout)
.allowsTightening(true)
.monospaced()
.keyboardType(.alphabet)
.foregroundStyle(.tertiary)
.disableAutocorrection(true)
.textSelection(.enabled)
.lineLimit(...3)
}
}.padding(.trailing, 36)
if !text.isEmpty {
Button(action: {
isSecure.toggle()
}) {
Image(systemName: self.isSecure ? "eye.slash" : "eye")
.accentColor(.secondary)
}
}
}
}
}

View file

@ -38,70 +38,21 @@ struct SecurityConfig: View {
Section(header: Text("Admin & Direct Message Keys")) {
VStack(alignment: .leading) {
Label("Public Key", systemImage: "key")
TextField(
"Public Key",
text: $publicKey,
axis: .vertical
)
.font(idiom == .phone ? .caption : .callout)
.allowsTightening(true)
.monospaced()
.keyboardType(.alphabet)
.foregroundStyle(.tertiary)
.disableAutocorrection(true)
.textSelection(.enabled)
.background(
RoundedRectangle(cornerRadius: 10.0)
.stroke(true ? Color.clear : Color.red, lineWidth: 2.0)
)
SecureInput("Public Key", text: $publicKey)
Text("Sent out to other nodes on the mesh to allow them to compute a shared secret key.")
.foregroundStyle(.secondary)
.font(idiom == .phone ? .caption : .callout)
}
VStack(alignment: .leading) {
Label("Private Key", systemImage: "key.fill")
TextField(
"Private Key",
text: $privateKey,
axis: .vertical
)
.font(idiom == .phone ? .caption : .callout)
.allowsTightening(true)
.monospaced()
.disableAutocorrection(true)
.keyboardType(.alphabet)
.foregroundStyle(.tertiary)
.textSelection(.enabled)
.background(
RoundedRectangle(cornerRadius: 10.0)
.stroke(true ? Color.clear : Color.red, lineWidth: 2.0)
)
SecureInput("Private Key", text: $privateKey)
Text("Used to create a shared key with a remote device.")
.foregroundStyle(.secondary)
.font(idiom == .phone ? .caption : .callout)
}
VStack(alignment: .leading) {
Label("Admin Key", systemImage: "key.viewfinder")
TextField(
"Admin Key",
text: $adminKey,
axis: .vertical
)
.font(idiom == .phone ? .caption : .callout)
.allowsTightening(true)
.monospaced()
.disableAutocorrection(true)
.keyboardType(.alphabet)
.foregroundStyle(.tertiary)
.textSelection(.enabled)
.background(
RoundedRectangle(cornerRadius: 10.0)
.stroke(true ? Color.clear : Color.red, lineWidth: 2.0)
)
SecureInput("Private Key", text: $adminKey)
Text("The public key authorized to send admin messages to this node.")
.foregroundStyle(.secondary)
.font(idiom == .phone ? .caption : .callout)