Skip to content

Commit

Permalink
Improve waitlist invite code checks (#2398)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/1199333091098016/1206460327917918/f
Tech Design URL:
CC:

Description:

This is the iOS PR for duckduckgo/BrowserServicesKit#639.

Steps to test this PR:

Check that NetP works and that you can toggle it off and on as expected
Ideally wipe your NetP state clean and then try to set it up again with a fresh invite code
  • Loading branch information
samsymons authored Jan 30, 2024
1 parent 590c586 commit bd2487c
Show file tree
Hide file tree
Showing 14 changed files with 31 additions and 25 deletions.
2 changes: 2 additions & 0 deletions Core/PixelEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ extension Pixel {
case networkProtectionKeychainErrorFailedToCastKeychainValueToData
case networkProtectionKeychainReadError
case networkProtectionKeychainWriteError
case networkProtectionKeychainUpdateError
case networkProtectionKeychainDeleteError

case networkProtectionWireguardErrorCannotLocateTunnelFileDescriptor
Expand Down Expand Up @@ -810,6 +811,7 @@ extension Pixel.Event {
case .networkProtectionKeychainErrorFailedToCastKeychainValueToData: return "m_netp_keychain_error_failed_to_cast_keychain_value_to_data"
case .networkProtectionKeychainReadError: return "m_netp_keychain_error_read_failed"
case .networkProtectionKeychainWriteError: return "m_netp_keychain_error_write_failed"
case .networkProtectionKeychainUpdateError: return "m_netp_keychain_error_update_failed"
case .networkProtectionKeychainDeleteError: return "m_netp_keychain_error_delete_failed"
case .networkProtectionWireguardErrorCannotLocateTunnelFileDescriptor: return "m_netp_wireguard_error_cannot_locate_tunnel_file_descriptor"
case .networkProtectionWireguardErrorInvalidState: return "m_netp_wireguard_error_invalid_state"
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9977,7 +9977,7 @@
repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 103.0.2;
version = 104.0.0;
};
};
C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/DuckDuckGo/BrowserServicesKit",
"state" : {
"revision" : "1f7a1b5fe1c404d331fe34e55c99296828107c1d",
"version" : "103.0.2"
"revision" : "872090e651ad8e26ca9903a95f3d094b21d48e23",
"version" : "104.0.0"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/AppDelegate+Waitlists.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ extension AppDelegate {
VPNWaitlist.shared.fetchInviteCodeIfAvailable { [weak self] error in
guard error == nil else {
#if !DEBUG
if error == .alreadyHasInviteCode {
if error == .alreadyHasInviteCode, UIApplication.shared.applicationState == .active {
// If the user already has an invite code but their auth token has gone missing, attempt to redeem it again.
let tokenStore = NetworkProtectionKeychainTokenStore()
let waitlistStorage = VPNWaitlist.shared.waitlistStorage
Expand Down
4 changes: 4 additions & 0 deletions DuckDuckGo/EventMapping+NetworkProtectionError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ extension EventMapping where Event == NetworkProtectionError {
pixelEvent = .networkProtectionKeychainWriteError
params[PixelParameters.keychainFieldName] = field
params[PixelParameters.keychainErrorCode] = String(status)
case .keychainUpdateError(field: let field, status: let status):
pixelEvent = .networkProtectionKeychainUpdateError
params[PixelParameters.keychainFieldName] = field
params[PixelParameters.keychainErrorCode] = String(status)
case .keychainDeleteError(status: let status):
pixelEvent = .networkProtectionKeychainDeleteError
params[PixelParameters.keychainErrorCode] = String(status)
Expand Down
10 changes: 9 additions & 1 deletion DuckDuckGo/KeychainItemsDebugViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ private struct KeychainItem {
let secClass: SecClass
let service: String?
let account: String?
let accessGroup: String?
let valueData: Data?
let creationDate: Any?
let modificationDate: Any?
Expand All @@ -39,6 +40,7 @@ private struct KeychainItem {
return """
Service: \(service ?? "nil")
Account: \(account ?? "nil")
Access Group: \(accessGroup ?? "nil")
Value as String: \(value ?? "nil")
Value data: \(String(describing: valueData))
Creation date: \(String(describing: creationDate))
Expand All @@ -54,7 +56,8 @@ private enum SecClass: CaseIterable {
case classCertificate
case classKey
case classIdentity

case accessGroup

var secClassCFString: CFString {
switch self {
case .internetPassword:
Expand All @@ -67,6 +70,8 @@ private enum SecClass: CaseIterable {
return kSecClassKey
case .classIdentity:
return kSecClassIdentity
case .accessGroup:
return kSecAttrAccessGroup
}
}

Expand All @@ -82,6 +87,8 @@ private enum SecClass: CaseIterable {
return "kSecClassKey"
case .classIdentity:
return "kSecClassIdentity"
case .accessGroup:
return "kSecAttrAccessGroup"
}
}

Expand All @@ -106,6 +113,7 @@ private enum SecClass: CaseIterable {
KeychainItem(secClass: self,
service: $0[kSecAttrService as String] as? String,
account: $0[kSecAttrAccount as String] as? String,
accessGroup: $0[kSecAttrAccessGroup as String] as? String,
valueData: $0[kSecValueData as String] as? Data,
creationDate: $0[kSecAttrCreationDate as String, default: "no creation"],
modificationDate: $0[kSecAttrModificationDate as String, default: "no modification"])
Expand Down
4 changes: 2 additions & 2 deletions DuckDuckGo/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ class MainViewController: UIViewController {
addLaunchTabNotificationObserver()
subscribeToEmailProtectionStatusNotifications()

#if NETWORK_PROTECTION
#if NETWORK_PROTECTION && SUBSCRIPTION
subscribeToNetworkProtectionSubscriptionEvents()
#endif

Expand Down Expand Up @@ -1238,7 +1238,7 @@ class MainViewController: UIViewController {
.store(in: &emailCancellables)
}

#if NETWORK_PROTECTION
#if NETWORK_PROTECTION && SUBSCRIPTION
private func subscribeToNetworkProtectionSubscriptionEvents() {
NotificationCenter.default.publisher(for: .accountDidSignIn)
.receive(on: DispatchQueue.main)
Expand Down
3 changes: 2 additions & 1 deletion DuckDuckGo/NetworkProtectionConvenienceInitialisers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ extension NetworkProtectionKeychainTokenStore {
}

extension NetworkProtectionCodeRedemptionCoordinator {
convenience init() {
convenience init(isManualCodeRedemptionFlow: Bool = false) {
let settings = VPNSettings(defaults: .networkProtectionGroupDefaults)
self.init(
environment: settings.selectedEnvironment,
tokenStore: NetworkProtectionKeychainTokenStore(),
isManualCodeRedemptionFlow: isManualCodeRedemptionFlow,
errorEvents: .networkProtectionAppDebugEvents
)
}
Expand Down
13 changes: 0 additions & 13 deletions DuckDuckGo/NetworkProtectionInviteViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,6 @@ final class NetworkProtectionInviteViewModel: ObservableObject {
completion()
}

// MARK: Dev only. Will be removed during https://app.asana.com/0/0/1205084446087078/f

@MainActor
func clear() async {
errorText = ""
do {
try NetworkProtectionKeychainTokenStore().deleteToken()
updateAuthenticatedText()
} catch {
errorText = "Could not clear token"
}
}

@Published var redeemedText: String?

private func updateAuthenticatedText() {
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/NetworkProtectionRootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct NetworkProtectionRootView: View {

var body: some View {
let inviteViewModel = NetworkProtectionInviteViewModel(
redemptionCoordinator: NetworkProtectionCodeRedemptionCoordinator(),
redemptionCoordinator: NetworkProtectionCodeRedemptionCoordinator(isManualCodeRedemptionFlow: true),
completion: inviteCompletion
)
switch model.initialViewKind {
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/DuckUI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ let package = Package(
targets: ["DuckUI"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "103.0.2"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "104.0.0"),
],
targets: [
.target(
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/SyncUI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let package = Package(
],
dependencies: [
.package(path: "../DuckUI"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "103.0.2"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "104.0.0"),
.package(url: "https://github.com/duckduckgo/DesignResourcesKit", exact: "2.0.0")
],
targets: [
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/Waitlist/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let package = Package(
targets: ["Waitlist", "WaitlistMocks"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "103.0.2"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "104.0.0"),
.package(url: "https://github.com/duckduckgo/DesignResourcesKit", exact: "2.0.0")
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider {
pixelEvent = .networkProtectionKeychainWriteError
params[PixelParameters.keychainFieldName] = field
params[PixelParameters.keychainErrorCode] = String(status)
case .keychainUpdateError(let field, let status):
pixelEvent = .networkProtectionKeychainUpdateError
params[PixelParameters.keychainFieldName] = field
params[PixelParameters.keychainErrorCode] = String(status)
case .keychainDeleteError(let status): // TODO: Check whether field needed here
pixelEvent = .networkProtectionKeychainDeleteError
params[PixelParameters.keychainErrorCode] = String(status)
Expand Down

0 comments on commit bd2487c

Please sign in to comment.