macOS: Exclude private IPs
This commit is contained in:
parent
549f5de700
commit
226911715c
|
@ -547,6 +547,14 @@ class TunnelViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func asWgQuickConfig() -> String? {
|
||||||
|
let saveResult = save()
|
||||||
|
if case .saved(let tunnelConfiguration) = saveResult {
|
||||||
|
return tunnelConfiguration.asWgQuickConfig()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
func applyConfiguration(other: TunnelConfiguration) -> Changes {
|
func applyConfiguration(other: TunnelConfiguration) -> Changes {
|
||||||
// Replaces current data with data from other TunnelConfiguration, ignoring any changes in peer ordering.
|
// Replaces current data with data from other TunnelConfiguration, ignoring any changes in peer ordering.
|
||||||
|
|
|
@ -9,6 +9,7 @@ class ConfTextView: NSTextView {
|
||||||
|
|
||||||
@objc dynamic var hasError: Bool = false
|
@objc dynamic var hasError: Bool = false
|
||||||
@objc dynamic var privateKeyString: String?
|
@objc dynamic var privateKeyString: String?
|
||||||
|
@objc dynamic var singlePeerAllowedIPs: [String]?
|
||||||
|
|
||||||
override var string: String {
|
override var string: String {
|
||||||
didSet {
|
didSet {
|
||||||
|
@ -52,6 +53,13 @@ class ConfTextView: NSTextView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setConfText(_ text: String) {
|
||||||
|
let fullTextRange = NSRange(location: 0, length: (string as NSString).length)
|
||||||
|
if shouldChangeText(in: fullTextRange, replacementString: text) {
|
||||||
|
replaceCharacters(in: fullTextRange, with: text)
|
||||||
|
didChangeText()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConfTextView: NSTextViewDelegate {
|
extension ConfTextView: NSTextViewDelegate {
|
||||||
|
@ -64,6 +72,10 @@ extension ConfTextView: NSTextViewDelegate {
|
||||||
if privateKeyString != confTextStorage.privateKeyString {
|
if privateKeyString != confTextStorage.privateKeyString {
|
||||||
privateKeyString = confTextStorage.privateKeyString
|
privateKeyString = confTextStorage.privateKeyString
|
||||||
}
|
}
|
||||||
|
let updatedSinglePeerAllowedIPs = confTextStorage.hasOnePeer && !confTextStorage.hasError ? confTextStorage.lastOnePeerAllowedIPs : nil
|
||||||
|
if singlePeerAllowedIPs != updatedSinglePeerAllowedIPs {
|
||||||
|
singlePeerAllowedIPs = updatedSinglePeerAllowedIPs
|
||||||
|
}
|
||||||
needsDisplay = true
|
needsDisplay = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,14 @@ class TunnelEditViewController: NSViewController {
|
||||||
return scrollView
|
return scrollView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
let excludePrivateIPsCheckbox: NSButton = {
|
||||||
|
let checkbox = NSButton()
|
||||||
|
checkbox.title = tr("tunnelPeerExcludePrivateIPs")
|
||||||
|
checkbox.setButtonType(.switch)
|
||||||
|
checkbox.state = .off
|
||||||
|
return checkbox
|
||||||
|
}()
|
||||||
|
|
||||||
let discardButton: NSButton = {
|
let discardButton: NSButton = {
|
||||||
let button = NSButton()
|
let button = NSButton()
|
||||||
button.title = tr("macEditDiscard")
|
button.title = tr("macEditDiscard")
|
||||||
|
@ -86,6 +94,7 @@ class TunnelEditViewController: NSViewController {
|
||||||
|
|
||||||
var privateKeyObservationToken: AnyObject?
|
var privateKeyObservationToken: AnyObject?
|
||||||
var hasErrorObservationToken: AnyObject?
|
var hasErrorObservationToken: AnyObject?
|
||||||
|
var singlePeerAllowedIPsObservationToken: AnyObject?
|
||||||
|
|
||||||
init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer?) {
|
init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer?) {
|
||||||
self.tunnelsManager = tunnelsManager
|
self.tunnelsManager = tunnelsManager
|
||||||
|
@ -111,6 +120,8 @@ class TunnelEditViewController: NSViewController {
|
||||||
} else {
|
} else {
|
||||||
selectedActivateOnDemandOption = .none
|
selectedActivateOnDemandOption = .none
|
||||||
}
|
}
|
||||||
|
let singlePeer = tunnelConfiguration.peers.count == 1 ? tunnelConfiguration.peers.first : nil
|
||||||
|
updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: singlePeer?.allowedIPs.map { $0.stringRepresentation })
|
||||||
} else {
|
} else {
|
||||||
// Creating a new tunnel
|
// Creating a new tunnel
|
||||||
let privateKey = Curve25519.generatePrivateKey()
|
let privateKey = Curve25519.generatePrivateKey()
|
||||||
|
@ -133,6 +144,9 @@ class TunnelEditViewController: NSViewController {
|
||||||
hasErrorObservationToken = textView.observe(\.hasError) { [weak saveButton] textView, _ in
|
hasErrorObservationToken = textView.observe(\.hasError) { [weak saveButton] textView, _ in
|
||||||
saveButton?.isEnabled = !textView.hasError
|
saveButton?.isEnabled = !textView.hasError
|
||||||
}
|
}
|
||||||
|
singlePeerAllowedIPsObservationToken = textView.observe(\.singlePeerAllowedIPs) { [weak self] textView, _ in
|
||||||
|
self?.updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: textView.singlePeerAllowedIPs)
|
||||||
|
}
|
||||||
|
|
||||||
onDemandRow.valueOptions = activateOnDemandOptions.map { TunnelViewModel.activateOnDemandOptionText(for: $0) }
|
onDemandRow.valueOptions = activateOnDemandOptions.map { TunnelViewModel.activateOnDemandOptionText(for: $0) }
|
||||||
onDemandRow.selectedOptionIndex = activateOnDemandOptions.firstIndex(of: selectedActivateOnDemandOption)!
|
onDemandRow.selectedOptionIndex = activateOnDemandOptions.firstIndex(of: selectedActivateOnDemandOption)!
|
||||||
|
@ -149,6 +163,9 @@ class TunnelEditViewController: NSViewController {
|
||||||
discardButton.target = self
|
discardButton.target = self
|
||||||
discardButton.action = #selector(handleDiscardAction)
|
discardButton.action = #selector(handleDiscardAction)
|
||||||
|
|
||||||
|
excludePrivateIPsCheckbox.target = self
|
||||||
|
excludePrivateIPsCheckbox.action = #selector(excludePrivateIPsCheckboxToggled(sender:))
|
||||||
|
|
||||||
let margin: CGFloat = 20
|
let margin: CGFloat = 20
|
||||||
let internalSpacing: CGFloat = 10
|
let internalSpacing: CGFloat = 10
|
||||||
|
|
||||||
|
@ -159,6 +176,7 @@ class TunnelEditViewController: NSViewController {
|
||||||
|
|
||||||
let buttonRowStackView = NSStackView()
|
let buttonRowStackView = NSStackView()
|
||||||
buttonRowStackView.setViews([discardButton, saveButton], in: .trailing)
|
buttonRowStackView.setViews([discardButton, saveButton], in: .trailing)
|
||||||
|
buttonRowStackView.addView(excludePrivateIPsCheckbox, in: .leading)
|
||||||
buttonRowStackView.orientation = .horizontal
|
buttonRowStackView.orientation = .horizontal
|
||||||
buttonRowStackView.spacing = internalSpacing
|
buttonRowStackView.spacing = internalSpacing
|
||||||
|
|
||||||
|
@ -237,4 +255,27 @@ class TunnelEditViewController: NSViewController {
|
||||||
delegate?.tunnelEditingCancelled()
|
delegate?.tunnelEditingCancelled()
|
||||||
dismiss(self)
|
dismiss(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: [String]?) {
|
||||||
|
let shouldAllowExcludePrivateIPsControl: Bool
|
||||||
|
let excludePrivateIPsValue: Bool
|
||||||
|
if let singlePeerAllowedIPs = singlePeerAllowedIPs {
|
||||||
|
(shouldAllowExcludePrivateIPsControl, excludePrivateIPsValue) = TunnelViewModel.PeerData.excludePrivateIPsFieldStates(isSinglePeer: true, allowedIPs: Set<String>(singlePeerAllowedIPs))
|
||||||
|
} else {
|
||||||
|
(shouldAllowExcludePrivateIPsControl, excludePrivateIPsValue) = TunnelViewModel.PeerData.excludePrivateIPsFieldStates(isSinglePeer: false, allowedIPs: Set<String>())
|
||||||
|
}
|
||||||
|
excludePrivateIPsCheckbox.isHidden = !shouldAllowExcludePrivateIPsControl
|
||||||
|
excludePrivateIPsCheckbox.state = excludePrivateIPsValue ? .on : .off
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func excludePrivateIPsCheckboxToggled(sender: AnyObject?) {
|
||||||
|
guard let excludePrivateIPsCheckbox = sender as? NSButton else { return }
|
||||||
|
guard let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: textView.string, called: nameRow.value) else { return }
|
||||||
|
let isOn = excludePrivateIPsCheckbox.state == .on
|
||||||
|
let tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnelConfiguration)
|
||||||
|
tunnelViewModel.peersData.first?.excludePrivateIPsValueChanged(isOn: isOn, dnsServers: tunnelViewModel.interfaceData[.dns])
|
||||||
|
if let modifiedConfig = tunnelViewModel.asWgQuickConfig() {
|
||||||
|
textView.setConfText(modifiedConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue