Revert to concrete-only managers

Abstraction was overcomplicated. Strategy pattern is enough.
This commit is contained in:
Davide De Rosa 2022-08-28 09:19:15 +02:00
parent ac0f994997
commit 4c4b3ee0c9
50 changed files with 90 additions and 411 deletions

View File

@ -29,7 +29,7 @@ import PassepartoutLibrary
protocol ProviderProfileAvailability { protocol ProviderProfileAvailability {
var profile: Profile { get } var profile: Profile { get }
var providerManager: Impl.ProviderManager { get } var providerManager: ProviderManager { get }
} }
extension ProviderProfileAvailability { extension ProviderProfileAvailability {

View File

@ -51,9 +51,9 @@ class DefaultLightProfile: LightProfile {
} }
class DefaultLightProfileManager: LightProfileManager { class DefaultLightProfileManager: LightProfileManager {
private let profileManager = Impl.ProfileManager.shared private let profileManager = ProfileManager.shared
private let providerManager = Impl.ProviderManager.shared private let providerManager = ProviderManager.shared
private var subscriptions: Set<AnyCancellable> = [] private var subscriptions: Set<AnyCancellable> = []

View File

@ -77,7 +77,7 @@ class DefaultLightProviderServer: LightProviderServer {
} }
class DefaultLightProviderManager: LightProviderManager { class DefaultLightProviderManager: LightProviderManager {
private let providerManager = Impl.ProviderManager.shared private let providerManager = ProviderManager.shared
private var subscriptions: Set<AnyCancellable> = [] private var subscriptions: Set<AnyCancellable> = []

View File

@ -28,7 +28,7 @@ import PassepartoutLibrary
import Combine import Combine
class DefaultLightVPNManager: LightVPNManager { class DefaultLightVPNManager: LightVPNManager {
private let vpnManager = Impl.VPNManager.shared private let vpnManager = VPNManager.shared
private var subscriptions: Set<AnyCancellable> = [] private var subscriptions: Set<AnyCancellable> = []

View File

@ -27,7 +27,7 @@ import SwiftUI
import PassepartoutLibrary import PassepartoutLibrary
struct AccountView: View { struct AccountView: View {
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
private let providerName: ProviderName? private let providerName: ProviderName?

View File

@ -30,7 +30,7 @@ import TunnelKitWireGuard
extension AddHostView { extension AddHostView {
struct NameView: View { struct NameView: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
private let url: URL private let url: URL

View File

@ -71,7 +71,7 @@ enum AddProfileView {
} }
struct AccountWrapperView: View { struct AccountWrapperView: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
@Binding private var profile: Profile @Binding private var profile: Profile

View File

@ -28,7 +28,7 @@ import PassepartoutLibrary
extension AddProviderView { extension AddProviderView {
struct NameView: View { struct NameView: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
@Binding private var profile: Profile @Binding private var profile: Profile

View File

@ -27,7 +27,7 @@ import SwiftUI
import PassepartoutLibrary import PassepartoutLibrary
struct AddProviderView: View { struct AddProviderView: View {
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
@ObservedObject private var productManager: ProductManager @ObservedObject private var productManager: ProductManager

View File

@ -37,9 +37,9 @@ extension DiagnosticsView {
} }
} }
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
@ObservedObject private var vpnManager: Impl.VPNManager @ObservedObject private var vpnManager: VPNManager
@ObservedObject private var currentVPNState: ObservableVPNState @ObservedObject private var currentVPNState: ObservableVPNState

View File

@ -29,7 +29,7 @@ import TunnelKitWireGuard
extension DiagnosticsView { extension DiagnosticsView {
struct WireGuardView: View { struct WireGuardView: View {
@ObservedObject private var vpnManager: Impl.VPNManager @ObservedObject private var vpnManager: VPNManager
private let providerName: ProviderName? private let providerName: ProviderName?

View File

@ -31,7 +31,7 @@ extension EndpointView {
struct OpenVPNView: View { struct OpenVPNView: View {
@Environment(\.presentationMode) private var presentationMode @Environment(\.presentationMode) private var presentationMode
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -53,7 +53,7 @@ extension EndpointView {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile) { init(currentProfile: ObservableProfile) {
let providerManager: Impl.ProviderManager = .shared let providerManager: ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile

View File

@ -29,7 +29,7 @@ import TunnelKitWireGuard
extension EndpointView { extension EndpointView {
struct WireGuardView: View { struct WireGuardView: View {
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -41,7 +41,7 @@ extension EndpointView {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile, isReadonly: Bool) { init(currentProfile: ObservableProfile, isReadonly: Bool) {
let providerManager: Impl.ProviderManager = .shared let providerManager: ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile

View File

@ -28,7 +28,7 @@ import PassepartoutLibrary
extension OrganizerView { extension OrganizerView {
struct ProfilesList: View { struct ProfilesList: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
init() { init() {
profileManager = .shared profileManager = .shared

View File

@ -30,9 +30,9 @@ extension OrganizerView {
struct SceneView: View { struct SceneView: View {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
@ObservedObject private var vpnManager: Impl.VPNManager @ObservedObject private var vpnManager: VPNManager
@ObservedObject private var productManager: ProductManager @ObservedObject private var productManager: ProductManager

View File

@ -81,7 +81,7 @@ struct OrganizerView: View {
.themePrimaryView() .themePrimaryView()
// VPN configuration error publisher (no need to observe VPNManager) // VPN configuration error publisher (no need to observe VPNManager)
.onReceive(Impl.VPNManager.shared.configurationError) { .onReceive(VPNManager.shared.configurationError) {
alertType = .error($0.profile.header.name, $0.error.localizedAppDescription) alertType = .error($0.profile.header.name, $0.error.localizedAppDescription)
} }
} }

View File

@ -28,7 +28,7 @@ import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct DiagnosticsSection: View { struct DiagnosticsSection: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -38,9 +38,9 @@ extension ProfileView {
} }
} }
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
@ObservedObject private var vpnManager: Impl.VPNManager @ObservedObject private var vpnManager: VPNManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -200,7 +200,7 @@ extension ProfileView {
} }
struct DuplicateButton: View { struct DuplicateButton: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
private let header: Profile.Header private let header: Profile.Header

View File

@ -28,7 +28,7 @@ import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct ProviderSection: View, ProviderProfileAvailability { struct ProviderSection: View, ProviderProfileAvailability {
@ObservedObject var providerManager: Impl.ProviderManager @ObservedObject var providerManager: ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -30,7 +30,7 @@ extension ProfileView {
struct RenameView: View { struct RenameView: View {
@Environment(\.presentationMode) private var presentationMode @Environment(\.presentationMode) private var presentationMode
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -28,7 +28,7 @@ import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct VPNSection: View { struct VPNSection: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
private let profileId: UUID private let profileId: UUID

View File

@ -56,7 +56,7 @@ struct ProfileView: View {
@State private var modalType: ModalType? @State private var modalType: ModalType?
init() { init() {
currentProfile = Impl.ProfileManager.shared.currentProfile currentProfile = ProfileManager.shared.currentProfile
} }
var body: some View { var body: some View {

View File

@ -27,7 +27,7 @@ import SwiftUI
import PassepartoutLibrary import PassepartoutLibrary
struct ProviderLocationView: View, ProviderProfileAvailability { struct ProviderLocationView: View, ProviderProfileAvailability {
@ObservedObject var providerManager: Impl.ProviderManager @ObservedObject var providerManager: ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -64,7 +64,7 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile, isEditable: Bool, isPresented: Binding<Bool>) { init(currentProfile: ObservableProfile, isEditable: Bool, isPresented: Binding<Bool>) {
let providerManager: Impl.ProviderManager = .shared let providerManager: ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile
@ -268,7 +268,7 @@ extension ProviderLocationView {
} }
struct ServerListView: View { struct ServerListView: View {
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
private let location: ProviderLocation private let location: ProviderLocation

View File

@ -29,7 +29,7 @@ import PassepartoutLibrary
struct ProviderPresetView: View { struct ProviderPresetView: View {
@Environment(\.presentationMode) private var presentationMode @Environment(\.presentationMode) private var presentationMode
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -39,7 +39,7 @@ struct ProviderPresetView: View {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile) { init(currentProfile: ObservableProfile) {
let providerManager: Impl.ProviderManager = .shared let providerManager: ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile

View File

@ -29,7 +29,7 @@ import PassepartoutLibrary
extension ShortcutsView { extension ShortcutsView {
struct AddView: View { struct AddView: View {
@ObservedObject private var providerManager: Impl.ProviderManager @ObservedObject private var providerManager: ProviderManager
@StateObject private var pendingProfile = ObservableProfile() @StateObject private var pendingProfile = ObservableProfile()

View File

@ -27,9 +27,9 @@ import SwiftUI
import PassepartoutLibrary import PassepartoutLibrary
struct VPNToggle: View { struct VPNToggle: View {
@ObservedObject private var profileManager: Impl.ProfileManager @ObservedObject private var profileManager: ProfileManager
@ObservedObject private var vpnManager: Impl.VPNManager @ObservedObject private var vpnManager: VPNManager
@ObservedObject private var currentVPNState: ObservableVPNState @ObservedObject private var currentVPNState: ObservableVPNState
@ -113,7 +113,7 @@ struct VPNToggle: View {
IntentDispatcher.donateDisableVPN() IntentDispatcher.donateDisableVPN()
IntentDispatcher.donateConnection( IntentDispatcher.donateConnection(
with: profile, with: profile,
providerManager: Impl.ProviderManager.shared providerManager: ProviderManager.shared
) )
} }
} }

View File

@ -36,15 +36,15 @@ extension UpgradeManager {
static let shared = CoreContext.shared.upgradeManager static let shared = CoreContext.shared.upgradeManager
} }
extension Impl.ProfileManager { extension ProfileManager {
static let shared = CoreContext.shared.profileManager static let shared = CoreContext.shared.profileManager
} }
extension Impl.ProviderManager { extension ProviderManager {
static let shared = CoreContext.shared.providerManager static let shared = CoreContext.shared.providerManager
} }
extension Impl.VPNManager { extension VPNManager {
static let shared = CoreContext.shared.vpnManager static let shared = CoreContext.shared.vpnManager
} }

View File

@ -27,14 +27,6 @@ import Foundation
import Combine import Combine
import PassepartoutLibrary import PassepartoutLibrary
enum Impl {
typealias ProfileManager = DefaultProfileManager
typealias ProviderManager = DefaultProviderManager
typealias VPNManager = DefaultVPNManager<DefaultProfileManager>
}
class CoreContext { class CoreContext {
let store: KeyValueStore let store: KeyValueStore
@ -52,11 +44,11 @@ class CoreContext {
let upgradeManager: UpgradeManager let upgradeManager: UpgradeManager
let providerManager: Impl.ProviderManager let providerManager: ProviderManager
let profileManager: Impl.ProfileManager let profileManager: ProfileManager
let vpnManager: Impl.VPNManager let vpnManager: VPNManager
private var cancellables: Set<AnyCancellable> = [] private var cancellables: Set<AnyCancellable> = []
@ -74,7 +66,7 @@ class CoreContext {
upgradeManager = UpgradeManager(store: store) upgradeManager = UpgradeManager(store: store)
providerManager = DefaultProviderManager( providerManager = ProviderManager(
appBuild: Constants.Global.appBuildNumber, appBuild: Constants.Global.appBuildNumber,
bundleServices: DefaultWebServices.bundledServices( bundleServices: DefaultWebServices.bundledServices(
withVersion: Constants.Services.version withVersion: Constants.Services.version
@ -87,7 +79,7 @@ class CoreContext {
persistence: providersPersistence persistence: providersPersistence
) )
profileManager = DefaultProfileManager( profileManager = ProfileManager(
store: store, store: store,
providerManager: providerManager, providerManager: providerManager,
appGroup: Constants.App.appGroupId, appGroup: Constants.App.appGroupId,
@ -105,7 +97,7 @@ class CoreContext {
tunnelBundleIdentifier: Constants.App.tunnelBundleId tunnelBundleIdentifier: Constants.App.tunnelBundleId
) )
#endif #endif
vpnManager = DefaultVPNManager( vpnManager = VPNManager(
appGroup: Constants.App.appGroupId, appGroup: Constants.App.appGroupId,
store: store, store: store,
profileManager: profileManager, profileManager: profileManager,

View File

@ -45,13 +45,6 @@ extension Profile {
provider?.name provider?.name
} }
public func providerServer(_ providerManager: ProviderManager) -> ProviderServer? {
guard let serverId = provider?.vpnSettings[currentVPNProtocol]?.serverId else {
return nil
}
return providerManager.server(withId: serverId)
}
public func providerServerId() -> String? { public func providerServerId() -> String? {
return provider?.vpnSettings[currentVPNProtocol]?.serverId return provider?.vpnSettings[currentVPNProtocol]?.serverId
} }

View File

@ -1,32 +0,0 @@
//
// CurrentProfileProviding.swift
// Passepartout
//
// Created by Davide De Rosa on 6/22/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
public protocol CurrentProfileProviding {
associatedtype WrappedType: WrappedProfile
var currentProfile: WrappedType { get }
}

View File

@ -1,32 +0,0 @@
//
// CurrentVPNStateProviding.swift
// Passepartout
//
// Created by Davide De Rosa on 6/22/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
public protocol CurrentVPNStateProviding {
associatedtype WrappedType: WrappedVPNState
var currentState: WrappedType { get }
}

View File

@ -1,72 +0,0 @@
//
// ProfileManager.swift
// Passepartout
//
// Created by Davide De Rosa on 6/20/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
import Combine
public protocol ProfileManager {
typealias ProfileEx = (profile: Profile, isReady: Bool)
var activeProfileId: UUID? { get }
var currentProfileId: UUID? { get set }
var didUpdateProfiles: PassthroughSubject<Void, Never> { get }
var didUpdateActiveProfile: PassthroughSubject<UUID?, Never> { get }
var didCreateProfile: PassthroughSubject<Profile, Never> { get }
var headers: [Profile.Header] { get }
var profiles: [Profile] { get }
func isExistingProfile(withId id: UUID) -> Bool
func isExistingProfile(withName name: String) -> Bool
func liveProfileEx(withId id: UUID) throws -> ProfileEx
func makeProfileReady(_ profile: Profile) async throws
func saveProfile(_ profile: Profile, isActive: Bool?, updateIfCurrent: Bool)
func savePassword(forProfile profile: Profile)
func passwordReference(forProfile profile: Profile) -> Data?
func removeProfiles(withIds ids: [UUID])
@available(*, deprecated, message: "only use for testing")
func removeAllProfiles()
func duplicateProfile(withId id: UUID, setAsCurrent: Bool)
func profile(withHeader header: Profile.Header, fromContents contents: String, originalURL: URL?, passphrase: String?) throws -> Profile
func persist()
func observeUpdates()
}

View File

@ -1,29 +0,0 @@
//
// ProfileManagerWithCurrentProfile.swift
// Passepartout
//
// Created by Davide De Rosa on 6/22/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
public protocol ProfileManagerWithCurrentProfile: ProfileManager, CurrentProfileProviding {
}

View File

@ -1,61 +0,0 @@
//
// ProviderManager.swift
// Passepartout
//
// Created by Davide De Rosa on 6/19/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
import Combine
public protocol ProviderManager {
var didUpdateProviders: PassthroughSubject<Void, Never> { get }
func allProviders() -> [ProviderMetadata]
func provider(withName name: ProviderName) -> ProviderMetadata?
func isAvailable(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> Bool
func defaultUsername(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> String?
func lastUpdate(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> Date?
func categories(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> [ProviderCategory]
func servers(forLocation location: ProviderLocation) -> [ProviderServer]
func server(_ name: ProviderName, vpnProtocol: VPNProtocolType, apiId: String) -> ProviderServer?
func anyDefaultServer(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> ProviderServer?
func server(withId id: String) -> ProviderServer?
func fetchProvidersIndexPublisher(priority: ProviderManagerFetchPriority) -> AnyPublisher<Void, Error>
func fetchProviderPublisher(
withName providerName: ProviderName,
vpnProtocol: VPNProtocolType,
priority: ProviderManagerFetchPriority
) -> AnyPublisher<Void, Error>
func reset()
}

View File

@ -1,61 +0,0 @@
//
// VPNManager.swift
// Passepartout
//
// Created by Davide De Rosa on 6/22/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
import Combine
public protocol VPNManager {
var lastError: Error? { get }
var configurationError: PassthroughSubject<VPNConfigurationError, Never> { get }
var tunnelLogPath: String? { get set }
var tunnelLogFormat: String? { get set }
var masksPrivateData: Bool { get set }
func connectWithActiveProfile(toServer newServerId: String?) async throws
@discardableResult
func connect(with profileId: UUID) async throws -> Profile
@discardableResult
func connect(with profileId: UUID, toServer newServerId: String) async throws -> Profile
func reconnect() async
func modifyActiveProfile(_ block: (inout Profile) -> Void) async throws
func disable() async
func uninstall() async
func serverConfiguration(forProtocol vpnProtocol: VPNProtocolType) -> Any?
func debugLogURL(forProtocol vpnProtocol: VPNProtocolType) -> URL?
func observeUpdates()
}

View File

@ -1,29 +0,0 @@
//
// VPNManagerWithCurrentState.swift
// Passepartout
//
// Created by Davide De Rosa on 6/22/22.
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
public protocol VPNManagerWithCurrentState: VPNManager, CurrentVPNStateProviding {
}

View File

@ -29,7 +29,7 @@ import SwiftyBeaver
import PassepartoutCore import PassepartoutCore
import PassepartoutUtils import PassepartoutUtils
public class UpgradeManager: ObservableObject { public final class UpgradeManager: ObservableObject {
// MARK: Initialization // MARK: Initialization

View File

@ -39,6 +39,13 @@ extension Profile {
} }
extension Profile { extension Profile {
public func providerServer(_ providerManager: ProviderManager) -> ProviderServer? {
guard let serverId = providerServerId() else {
return nil
}
return providerManager.server(withId: serverId)
}
public func providerOpenVPNSettings(withManager providerManager: ProviderManager) throws -> Profile.OpenVPNSettings { public func providerOpenVPNSettings(withManager providerManager: ProviderManager) throws -> Profile.OpenVPNSettings {
guard isProvider else { guard isProvider else {
fatalError("Not a provider") fatalError("Not a provider")

View File

@ -60,7 +60,7 @@ extension ProfileManager {
} }
} }
extension ProfileManagerWithCurrentProfile { extension ProfileManager {
public func isCurrentProfileActive() -> Bool { public func isCurrentProfileActive() -> Bool {
currentProfile.value.id == activeProfileId currentProfile.value.id == activeProfileId
} }

View File

@ -26,6 +26,7 @@
import Foundation import Foundation
import Combine import Combine
import PassepartoutCore import PassepartoutCore
import PassepartoutProviders
extension ProviderManager { extension ProviderManager {
public func fetchRemoteProviderPublisher(forProfile profile: Profile) -> AnyPublisher<Void, Error> { public func fetchRemoteProviderPublisher(forProfile profile: Profile) -> AnyPublisher<Void, Error> {

View File

@ -28,7 +28,7 @@ import CoreData
import PassepartoutCore import PassepartoutCore
import PassepartoutUtils import PassepartoutUtils
public class PersistenceManager { public final class PersistenceManager {
private let store: KeyValueStore private let store: KeyValueStore
public init(store: KeyValueStore) { public init(store: KeyValueStore) {

View File

@ -1,5 +1,5 @@
// //
// DefaultProfileManager+Keychain.swift // ProfileManager+Keychain.swift
// Passepartout // Passepartout
// //
// Created by Davide De Rosa on 4/8/22. // Created by Davide De Rosa on 4/8/22.
@ -28,7 +28,7 @@ import TunnelKitManager
import PassepartoutCore import PassepartoutCore
import PassepartoutUtils import PassepartoutUtils
extension DefaultProfileManager { extension ProfileManager {
public func savePassword(forProfile profile: Profile) { public func savePassword(forProfile profile: Profile) {
guard !profile.isPlaceholder else { guard !profile.isPlaceholder else {
assertionFailure("Placeholder") assertionFailure("Placeholder")

View File

@ -1,5 +1,5 @@
// //
// DefaultProfileManager+Processing.swift // ProfileManager+Processing.swift
// Passepartout // Passepartout
// //
// Created by Davide De Rosa on 4/7/22. // Created by Davide De Rosa on 4/7/22.
@ -28,7 +28,7 @@ import TunnelKitOpenVPN
import TunnelKitWireGuard import TunnelKitWireGuard
import PassepartoutCore import PassepartoutCore
extension DefaultProfileManager { extension ProfileManager {
public func profile(withHeader header: Profile.Header, fromContents contents: String, originalURL: URL?, passphrase: String?) throws -> Profile { public func profile(withHeader header: Profile.Header, fromContents contents: String, originalURL: URL?, passphrase: String?) throws -> Profile {
do { do {
let ovpn = try OpenVPN.ConfigurationParser.parsed(fromContents: contents, passphrase: passphrase, originalURL: originalURL) let ovpn = try OpenVPN.ConfigurationParser.parsed(fromContents: contents, passphrase: passphrase, originalURL: originalURL)

View File

@ -1,5 +1,5 @@
// //
// DefaultProfileManager.swift // ProfileManager.swift
// Passepartout // Passepartout
// //
// Created by Davide De Rosa on 2/25/22. // Created by Davide De Rosa on 2/25/22.
@ -27,10 +27,11 @@ import Foundation
import Combine import Combine
import TunnelKitManager import TunnelKitManager
import PassepartoutCore import PassepartoutCore
import PassepartoutCore
import PassepartoutUtils import PassepartoutUtils
import PassepartoutProviders
public class DefaultProfileManager: ProfileManagerWithCurrentProfile, ObservableObject { public final class ProfileManager: ObservableObject {
public typealias ProfileEx = (profile: Profile, isReady: Bool)
// MARK: Initialization // MARK: Initialization
@ -46,7 +47,7 @@ public class DefaultProfileManager: ProfileManagerWithCurrentProfile, Observable
private let strategy: ProfileManagerStrategy private let strategy: ProfileManagerStrategy
// MARK: Observables // MARK: State
@Published private var internalActiveProfileId: UUID? { @Published private var internalActiveProfileId: UUID? {
willSet { willSet {
@ -110,7 +111,7 @@ public class DefaultProfileManager: ProfileManagerWithCurrentProfile, Observable
// MARK: Index // MARK: Index
extension DefaultProfileManager { extension ProfileManager {
private var allHeaders: [UUID: Profile.Header] { private var allHeaders: [UUID: Profile.Header] {
strategy.allHeaders strategy.allHeaders
} }
@ -136,7 +137,7 @@ extension DefaultProfileManager {
// MARK: Profiles // MARK: Profiles
extension DefaultProfileManager { extension ProfileManager {
public func liveProfileEx(withId id: UUID) throws -> ProfileEx { public func liveProfileEx(withId id: UUID) throws -> ProfileEx {
guard let profile = liveProfile(withId: id) else { guard let profile = liveProfile(withId: id) else {
pp_log.error("Profile not found: \(id)") pp_log.error("Profile not found: \(id)")
@ -249,7 +250,7 @@ extension DefaultProfileManager {
// MARK: Observation // MARK: Observation
extension DefaultProfileManager { extension ProfileManager {
private func setCurrentProfile(_ profile: Profile) { private func setCurrentProfile(_ profile: Profile) {
guard !currentProfile.isLoading else { guard !currentProfile.isLoading else {
pp_log.warning("Already loading another profile") pp_log.warning("Already loading another profile")
@ -300,7 +301,7 @@ extension DefaultProfileManager {
} }
} }
extension DefaultProfileManager { extension ProfileManager {
public func observeUpdates() { public func observeUpdates() {
$internalActiveProfileId $internalActiveProfileId
.sink { .sink {
@ -393,7 +394,7 @@ extension DefaultProfileManager {
// MARK: Readiness // MARK: Readiness
extension DefaultProfileManager { extension ProfileManager {
private func isProfileReady(_ profile: Profile) -> Bool { private func isProfileReady(_ profile: Profile) -> Bool {
isProfileProviderAvailable(profile) isProfileProviderAvailable(profile)
} }
@ -433,7 +434,7 @@ extension DefaultProfileManager {
// MARK: KeyValueStore // MARK: KeyValueStore
extension DefaultProfileManager { extension ProfileManager {
public private(set) var activeProfileId: UUID? { public private(set) var activeProfileId: UUID? {
get { get {
guard let idString: String = store.value(forLocation: StoreKey.activeProfileId) else { guard let idString: String = store.value(forLocation: StoreKey.activeProfileId) else {
@ -459,7 +460,7 @@ extension DefaultProfileManager {
} }
} }
private extension DefaultProfileManager { private extension ProfileManager {
private enum StoreKey: String, KeyStoreDomainLocation { private enum StoreKey: String, KeyStoreDomainLocation {
case activeProfileId case activeProfileId

View File

@ -29,7 +29,7 @@ import PassepartoutCore
import PassepartoutServices import PassepartoutServices
import PassepartoutUtils import PassepartoutUtils
public class DefaultProviderManager: ProviderManager, ObservableObject, RateLimited { public final class ProviderManager: ObservableObject, RateLimited {
private let appBuild: Int private let appBuild: Int
private let bundleServices: WebServices private let bundleServices: WebServices

View File

@ -1,5 +1,5 @@
// //
// DefaultVPNManager+Actions.swift // VPNManager+Actions.swift
// Passepartout // Passepartout
// //
// Created by Davide De Rosa on 3/30/22. // Created by Davide De Rosa on 3/30/22.
@ -31,7 +31,7 @@ import PassepartoutUtils
// current profile, this must be updated too. this is done in // current profile, this must be updated too. this is done in
// ProfileManager.activateProfile() // ProfileManager.activateProfile()
extension DefaultVPNManager { extension VPNManager {
public func connectWithActiveProfile(toServer newServerId: String?) async throws { public func connectWithActiveProfile(toServer newServerId: String?) async throws {
guard currentState.vpnStatus != .connected else { guard currentState.vpnStatus != .connected else {
pp_log.warning("VPN is already connected") pp_log.warning("VPN is already connected")

View File

@ -1,5 +1,5 @@
// //
// DefaultVPNManager+Configuration.swift // VPNManager+Configuration.swift
// Passepartout // Passepartout
// //
// Created by Davide De Rosa on 3/12/22. // Created by Davide De Rosa on 3/12/22.
@ -27,7 +27,7 @@ import Foundation
import PassepartoutCore import PassepartoutCore
import PassepartoutUtils import PassepartoutUtils
extension DefaultVPNManager { extension VPNManager {
private var vpnPreferences: VPNPreferences { private var vpnPreferences: VPNPreferences {
DefaultVPNPreferences( DefaultVPNPreferences(
tunnelLogPath: tunnelLogPath, tunnelLogPath: tunnelLogPath,

View File

@ -1,5 +1,5 @@
// //
// DefaultVPNManager.swift // VPNManager.swift
// Passepartout // Passepartout
// //
// Created by Davide De Rosa on 2/9/22. // Created by Davide De Rosa on 2/9/22.
@ -29,9 +29,10 @@ import TunnelKitCore
import TunnelKitManager import TunnelKitManager
import PassepartoutCore import PassepartoutCore
import PassepartoutProfiles import PassepartoutProfiles
import PassepartoutProviders
import PassepartoutUtils import PassepartoutUtils
public class DefaultVPNManager<ProfileManagerType: ProfileManagerWithCurrentProfile>: VPNManagerWithCurrentState, ObservableObject where ProfileManagerType.WrappedType == ObservableProfile { public final class VPNManager: ObservableObject {
// MARK: Initialization // MARK: Initialization
@ -39,7 +40,7 @@ public class DefaultVPNManager<ProfileManagerType: ProfileManagerWithCurrentProf
private let store: KeyValueStore private let store: KeyValueStore
let profileManager: ProfileManagerType let profileManager: ProfileManager
let providerManager: ProviderManager let providerManager: ProviderManager
@ -73,7 +74,7 @@ public class DefaultVPNManager<ProfileManagerType: ProfileManagerWithCurrentProf
public init( public init(
appGroup: String, appGroup: String,
store: KeyValueStore, store: KeyValueStore,
profileManager: ProfileManagerType, profileManager: ProfileManager,
providerManager: ProviderManager, providerManager: ProviderManager,
strategy: VPNManagerStrategy strategy: VPNManagerStrategy
) { ) {
@ -138,7 +139,7 @@ public class DefaultVPNManager<ProfileManagerType: ProfileManagerWithCurrentProf
// MARK: Observation // MARK: Observation
extension DefaultVPNManager { extension VPNManager {
public func observeUpdates() { public func observeUpdates() {
observeStrategy() observeStrategy()
observeProfileManager() observeProfileManager()
@ -252,7 +253,7 @@ extension DefaultVPNManager {
// MARK: KeyValueStore // MARK: KeyValueStore
extension DefaultVPNManager { extension VPNManager {
public var tunnelLogPath: String? { public var tunnelLogPath: String? {
get { get {
store.value(forLocation: StoreKey.tunnelLogPath) store.value(forLocation: StoreKey.tunnelLogPath)
@ -283,7 +284,7 @@ extension DefaultVPNManager {
} }
} }
private extension DefaultVPNManager { private extension VPNManager {
private enum StoreKey: String, KeyStoreDomainLocation { private enum StoreKey: String, KeyStoreDomainLocation {
case tunnelLogPath case tunnelLogPath

View File

@ -45,7 +45,7 @@ class ProvidersTests: XCTestCase {
override func setUp() { override func setUp() {
pp_log.addDestination(ConsoleDestination()) pp_log.addDestination(ConsoleDestination())
manager = DefaultProviderManager( manager = ProviderManager(
appBuild: 10000, appBuild: 10000,
bundleServices: DefaultWebServices.bundledServices(withVersion: "v5"), bundleServices: DefaultWebServices.bundledServices(withVersion: "v5"),
webServices: DefaultWebServices("v5", URL(string: "https://passepartoutvpn.app/api/")!, timeout: nil), webServices: DefaultWebServices("v5", URL(string: "https://passepartoutvpn.app/api/")!, timeout: nil),
@ -133,7 +133,7 @@ class ProvidersTests: XCTestCase {
vpnProtocol: .openVPN, vpnProtocol: .openVPN,
categoryName: "", categoryName: "",
countryCode: "ES", countryCode: "ES",
onlyServer: nil servers: nil
) )
let servers = manager.servers(forLocation: location) let servers = manager.servers(forLocation: location)