Rethink library architecture (#301)

This commit is contained in:
Davide De Rosa 2023-05-24 18:19:47 +02:00 committed by GitHub
parent b4ad8dea0d
commit 7ccb10febc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
223 changed files with 2948 additions and 1647 deletions

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "PassepartoutLibrary/Sources/PassepartoutServices/API"]
path = PassepartoutLibrary/Sources/PassepartoutServices/API
path = PassepartoutLibrary/Sources/PassepartoutProvidersImpl/API
url = https://github.com/passepartoutvpn/api

2
API
View File

@ -1 +1 @@
PassepartoutLibrary/Sources/PassepartoutServices/API/
PassepartoutLibrary/Sources/PassepartoutProvidersImpl/API/

View File

@ -103,6 +103,11 @@
0E71ACFD27C1321A00F85C4B /* ActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E71ACFC27C1321A00F85C4B /* ActivityView.swift */; };
0E7577D72816A3B200081CBE /* DestructiveButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7577D62816A3B200081CBE /* DestructiveButton.swift */; };
0E7577DF2817E22C00081CBE /* VPNToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7577DE2817E22C00081CBE /* VPNToggle.swift */; };
0E7A8C0A2A1D410500780F4B /* PersistenceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7A8C092A1D410400780F4B /* PersistenceManager.swift */; };
0E7A8C0C2A1D4A6100780F4B /* PassepartoutLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0E7A8C0B2A1D4A6100780F4B /* PassepartoutLibrary */; };
0E7A8C0E2A1D4A6E00780F4B /* PassepartoutLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0E7A8C0D2A1D4A6E00780F4B /* PassepartoutLibrary */; };
0E7A8C0F2A1D54DE00780F4B /* Picker+OpenVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7A8C072A1D40BA00780F4B /* Picker+OpenVPN.swift */; };
0E7A8C102A1D54DE00780F4B /* Picker+Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7A8C082A1D40BA00780F4B /* Picker+Network.swift */; };
0E90DFE627BACC1500EF5078 /* AddHostViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E90DFE527BACC1500EF5078 /* AddHostViewModel.swift */; };
0E92D7C627F103300033CB7B /* ProfileView+Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E92D7C527F103300033CB7B /* ProfileView+Configuration.swift */; };
0E92D7C927F1042A0033CB7B /* ProfileView+Extra.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E92D7C827F1042A0033CB7B /* ProfileView+Extra.swift */; };
@ -138,7 +143,6 @@
0EA1D84728805EAE00F3CA48 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0EA1D84628805EAE00F3CA48 /* Flags.xcassets */; };
0EA591162733DDDA0096F796 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 0EA591142733DDDA0096F796 /* Intents.intentdefinition */; };
0EA9030B287045F70087BC73 /* SystemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA9030A287045F70087BC73 /* SystemMenu.swift */; };
0EB13BBE290E835A003CB654 /* PassepartoutLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0EB13BBD290E835A003CB654 /* PassepartoutLibrary */; };
0EB13BC0290E8C8D003CB654 /* PassepartoutTestsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB13BBF290E8C8D003CB654 /* PassepartoutTestsApp.swift */; };
0EB17EA727D226B400D473B5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB17EA127D2263700D473B5 /* Constants.swift */; };
0EB17EA927D226C900D473B5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB17EA127D2263700D473B5 /* Constants.swift */; };
@ -159,7 +163,6 @@
0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBC075F27EC587900208AD9 /* SwiftGen+Strings.swift */; };
0EBE880F281B18DE0090D9E6 /* OrganizerView+ProfileRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE880E281B18DE0090D9E6 /* OrganizerView+ProfileRow.swift */; };
0ECB78E9285F5DE300B0E460 /* PassepartoutMac.bundle in Embed Plugins */ = {isa = PBXBuildFile; fileRef = 0ECB78DA285F52F700B0E460 /* PassepartoutMac.bundle */; platformFilter = maccatalyst; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
0ECB78EC2863A21600B0E460 /* PassepartoutLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */; };
0ECF71EE27B6A99300CDB528 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECF71ED27B6A99300CDB528 /* AccountView.swift */; };
0ED1D6DC27DBA41700983466 /* DiagnosticsView+OpenVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED1D6DB27DBA41700983466 /* DiagnosticsView+OpenVPN.swift */; };
0ED1D6DE27DBA42100983466 /* DiagnosticsView+WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED1D6DD27DBA42100983466 /* DiagnosticsView+WireGuard.swift */; };
@ -295,6 +298,7 @@
0E021D9B284E68580077EF5D /* AppContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppContext.swift; sourceTree = "<group>"; };
0E0392762818732D00827C10 /* BuildProducts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildProducts.swift; sourceTree = "<group>"; };
0E039278281890B100827C10 /* AddHostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddHostView.swift; sourceTree = "<group>"; };
0E0480372A1A4AE000462F2F /* Passepartout.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Passepartout.xctestplan; sourceTree = "<group>"; };
0E04F0052883462E00BFCE1C /* LightUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightUtils.swift; sourceTree = "<group>"; };
0E04F0082883466500BFCE1C /* DefaultLightUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultLightUtils.swift; sourceTree = "<group>"; };
0E065F102813269500062CAF /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = "<group>"; };
@ -390,6 +394,9 @@
0E71ACFC27C1321A00F85C4B /* ActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityView.swift; sourceTree = "<group>"; };
0E7577D62816A3B200081CBE /* DestructiveButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestructiveButton.swift; sourceTree = "<group>"; };
0E7577DE2817E22C00081CBE /* VPNToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNToggle.swift; sourceTree = "<group>"; };
0E7A8C072A1D40BA00780F4B /* Picker+OpenVPN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Picker+OpenVPN.swift"; sourceTree = "<group>"; };
0E7A8C082A1D40BA00780F4B /* Picker+Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Picker+Network.swift"; sourceTree = "<group>"; };
0E7A8C092A1D410400780F4B /* PersistenceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceManager.swift; sourceTree = "<group>"; };
0E90DFE527BACC1500EF5078 /* AddHostViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddHostViewModel.swift; sourceTree = "<group>"; };
0E92D7C527F103300033CB7B /* ProfileView+Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+Configuration.swift"; sourceTree = "<group>"; };
0E92D7C827F1042A0033CB7B /* ProfileView+Extra.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+Extra.swift"; sourceTree = "<group>"; };
@ -532,7 +539,7 @@
files = (
0E9C3B6F27FC573E00D0F02E /* CloudKit.framework in Frameworks */,
0E53249D27D28FC7002565C3 /* Kvitto in Frameworks */,
0ECB78EC2863A21600B0E460 /* PassepartoutLibrary in Frameworks */,
0E7A8C0C2A1D4A6100780F4B /* PassepartoutLibrary in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -540,7 +547,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0EB13BBE290E835A003CB654 /* PassepartoutLibrary in Frameworks */,
0E7A8C0E2A1D4A6E00780F4B /* PassepartoutLibrary in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -577,6 +584,7 @@
children = (
0E021D9A284E68580077EF5D /* CoreContext.swift */,
0E29385B285A8B30002A6E0E /* CoreContext+Shared.swift */,
0E7A8C092A1D410400780F4B /* PersistenceManager.swift */,
);
path = Context;
sourceTree = "<group>";
@ -792,6 +800,7 @@
children = (
0EE315DB2733104700F5D461 /* Packages */,
0E23B4A12298559800304C30 /* Config.xcconfig */,
0E0480372A1A4AE000462F2F /* Passepartout.xctestplan */,
0E9AA982259F7674003FAFF1 /* Passepartout */,
0EB13BAD290E825E003CB654 /* PassepartoutTests */,
0E57F63920C83FC5008323CF /* Products */,
@ -812,6 +821,15 @@
name = Products;
sourceTree = "<group>";
};
0E7A8C062A1D40BA00780F4B /* Pickers */ = {
isa = PBXGroup;
children = (
0E7A8C072A1D40BA00780F4B /* Picker+OpenVPN.swift */,
0E7A8C082A1D40BA00780F4B /* Picker+Network.swift */,
);
path = Pickers;
sourceTree = "<group>";
};
0E92781227E7CD530057BB81 /* InApp */ = {
isa = PBXGroup;
children = (
@ -875,6 +893,7 @@
0E92781227E7CD530057BB81 /* InApp */,
0EA591112733DD4E0096F796 /* Intents */,
0E5467F12867A52B00F74D1C /* Mac */,
0E7A8C062A1D40BA00780F4B /* Pickers */,
0E2C171C27CB6307007E8488 /* Reusable */,
0E35C0AE280EF8A80071FA35 /* Views */,
0E6059CA27FCC5DE003F4063 /* Assets.xcassets */,
@ -1076,7 +1095,7 @@
name = Passepartout;
packageProductDependencies = (
0E53249C27D28FC7002565C3 /* Kvitto */,
0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */,
0E7A8C0B2A1D4A6100780F4B /* PassepartoutLibrary */,
);
productName = Passepartout;
productReference = 0E57F63820C83FC5008323CF /* Passepartout.app */;
@ -1097,7 +1116,7 @@
);
name = PassepartoutTests;
packageProductDependencies = (
0EB13BBD290E835A003CB654 /* PassepartoutLibrary */,
0E7A8C0D2A1D4A6E00780F4B /* PassepartoutLibrary */,
);
productName = PassepartoutTests;
productReference = 0EB13BAC290E825E003CB654 /* PassepartoutTests.app */;
@ -1435,6 +1454,7 @@
0E04F0092883466500BFCE1C /* DefaultLightUtils.swift in Sources */,
0E5349C827C176D100C71BB3 /* EndpointView+WireGuard.swift in Sources */,
0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */,
0E7A8C0F2A1D54DE00780F4B /* Picker+OpenVPN.swift in Sources */,
0E0392772818732D00827C10 /* BuildProducts.swift in Sources */,
0E0F4C5C29C76B790022E884 /* SceneDelegate+Shortcuts.swift in Sources */,
0E5683B927C2825D00EAF1CD /* DiagnosticsView.swift in Sources */,
@ -1487,11 +1507,13 @@
0EF2212F27E66F60001D0BD7 /* AddProfileView.swift in Sources */,
0E96D2FC2871D94E005EFBCF /* DefaultLightProfileManager.swift in Sources */,
0EF0FAF627DD0211007EB181 /* PaywallView.swift in Sources */,
0E7A8C102A1D54DE00780F4B /* Picker+Network.swift in Sources */,
0E293851285A70AC002A6E0E /* AppPreference.swift in Sources */,
0E5349BE27C16A4500C71BB3 /* StyledPicker.swift in Sources */,
0E2C172B27CB63F9007E8488 /* Reviewer.swift in Sources */,
0E71ACDD27C0295C00F85C4B /* View+Extensions.swift in Sources */,
0E021D9C284E68580077EF5D /* CoreContext.swift in Sources */,
0E7A8C0A2A1D410500780F4B /* PersistenceManager.swift in Sources */,
A38D607728AFCFD20005C271 /* SettingsView.swift in Sources */,
0E34A2B627CAA8CC00C73B67 /* Core+L10n.swift in Sources */,
0E7577DF2817E22C00081CBE /* VPNToggle.swift in Sources */,
@ -2254,11 +2276,11 @@
package = 0E53249B27D28FC7002565C3 /* XCRemoteSwiftPackageReference "Kvitto" */;
productName = Kvitto;
};
0EB13BBD290E835A003CB654 /* PassepartoutLibrary */ = {
0E7A8C0B2A1D4A6100780F4B /* PassepartoutLibrary */ = {
isa = XCSwiftPackageProductDependency;
productName = PassepartoutLibrary;
};
0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */ = {
0E7A8C0D2A1D4A6E00780F4B /* PassepartoutLibrary */ = {
isa = XCSwiftPackageProductDependency;
productName = PassepartoutLibrary;
};

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1420"
version = "1.3">
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
@ -78,7 +78,53 @@
ReferencedContainer = "container:Passepartout.xcodeproj">
</BuildableReference>
</MacroExpansion>
<TestPlans>
<TestPlanReference
reference = "container:Passepartout.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutCoreTests"
BuildableName = "PassepartoutCoreTests"
BlueprintName = "PassepartoutCoreTests"
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutProvidersTests"
BuildableName = "PassepartoutProvidersTests"
BlueprintName = "PassepartoutProvidersTests"
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutServicesTests"
BuildableName = "PassepartoutServicesTests"
BlueprintName = "PassepartoutServicesTests"
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutVPNTests"
BuildableName = "PassepartoutVPNTests"
BlueprintName = "PassepartoutVPNTests"
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction

View File

@ -38,26 +38,6 @@
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibraryTests"
BuildableName = "PassepartoutLibraryTests"
BlueprintName = "PassepartoutLibraryTests"
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutProfilesTests"
BuildableName = "PassepartoutProfilesTests"
BlueprintName = "PassepartoutProfilesTests"
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
@ -78,16 +58,6 @@
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutUtilsTests"
BuildableName = "PassepartoutUtilsTests"
BlueprintName = "PassepartoutUtilsTests"
ReferencedContainer = "container:PassepartoutLibrary">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference

71
Passepartout.xctestplan Normal file
View File

@ -0,0 +1,71 @@
{
"configurations" : [
{
"id" : "38DB0D3B-F3E5-4BD4-B413-B9C92AE7A2F5",
"name" : "Configuration 1",
"options" : {
}
}
],
"defaultOptions" : {
"codeCoverage" : false,
"commandLineArgumentEntries" : [
{
"argument" : "-com.apple.CoreData.SQLDebug 0"
},
{
"argument" : "-com.apple.CoreData.Logging.stderr 0 "
},
{
"argument" : "-com.apple.CoreData.CloudKitDebug 0"
},
{
"argument" : "-com.apple.CoreData.ConcurrencyDebug 0"
},
{
"argument" : "-com.apple.CoreData.MigrationDebug 0"
}
],
"environmentVariableEntries" : [
{
"key" : "APP_TYPE",
"value" : "2"
},
{
"key" : "LOG_LEVEL",
"value" : "0"
}
],
"targetForVariableExpansion" : {
"containerPath" : "container:Passepartout.xcodeproj",
"identifier" : "0E57F63720C83FC5008323CF",
"name" : "Passepartout"
}
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:PassepartoutLibrary",
"identifier" : "PassepartoutCoreTests",
"name" : "PassepartoutCoreTests"
}
},
{
"target" : {
"containerPath" : "container:PassepartoutLibrary",
"identifier" : "PassepartoutProvidersTests",
"name" : "PassepartoutProvidersTests"
}
},
{
"enabled" : false,
"target" : {
"containerPath" : "container:PassepartoutLibrary",
"identifier" : "PassepartoutVPNTests",
"name" : "PassepartoutVPNTests"
}
}
],
"version" : 1
}

View File

@ -27,7 +27,7 @@ import Foundation
import PassepartoutLibrary
import UIKit
class AppDelegate: UIResponder, UIApplicationDelegate, ObservableObject {
final class AppDelegate: UIResponder, UIApplicationDelegate, ObservableObject {
private let mac = MacBundle.shared
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {

View File

@ -24,7 +24,7 @@
//
import Foundation
import SwiftyBeaver
import PassepartoutLibrary
import UniformTypeIdentifiers
extension Constants {
@ -154,7 +154,7 @@ extension Constants {
private static let parentPath = "Library/Caches"
static let level: SwiftyBeaver.Level = {
static let level: LoggerLevel = {
guard let levelString = ProcessInfo.processInfo.environment["LOG_LEVEL"], let levelNum = Int(levelString) else {
return .info
}

View File

@ -33,7 +33,3 @@ extension AppContext {
extension ProductManager {
static let shared = AppContext.shared.productManager
}
extension LogManager {
static let shared = AppContext.shared.logManager
}

View File

@ -28,9 +28,7 @@ import Foundation
import PassepartoutLibrary
@MainActor
class AppContext {
let logManager: LogManager
final class AppContext {
let productManager: ProductManager
private let reviewer: Reviewer
@ -38,12 +36,6 @@ class AppContext {
private var cancellables: Set<AnyCancellable> = []
init(coreContext: CoreContext) {
logManager = LogManager(logFile: Constants.Log.App.url)
logManager.logLevel = Constants.Log.level
logManager.logFormat = Constants.Log.App.format
logManager.configureLogging()
pp_log.info("Logging to: \(logManager.logFile!)")
productManager = ProductManager(
appType: Constants.InApp.appType,
buildProducts: Constants.InApp.buildProducts

View File

@ -35,7 +35,7 @@ enum ProductError: Error {
case beta
}
class ProductManager: NSObject, ObservableObject {
final class ProductManager: NSObject, ObservableObject {
enum AppType: Int {
case freemium = 0

View File

@ -27,7 +27,7 @@ import Foundation
import Intents
import PassepartoutLibrary
class IntentDispatcher {
final class IntentDispatcher {
private struct Groups {
static let vpn = "VPN"

View File

@ -30,7 +30,7 @@ import IntentsUI
import PassepartoutLibrary
@MainActor
class IntentsManager: NSObject, ObservableObject {
final class IntentsManager: NSObject, ObservableObject {
@Published private(set) var isReloadingShortcuts = false
@Published private(set) var shortcuts: [UUID: Shortcut] = [:]

View File

@ -25,7 +25,7 @@
import Foundation
class MacBundle {
final class MacBundle {
static let shared = MacBundle()
private var bridge: MacBridge!

View File

@ -25,7 +25,7 @@
import Foundation
class MacBundleDelegate: MacMenuDelegate {
final class MacBundleDelegate: MacMenuDelegate {
private weak var bundle: MacBundle?
@MainActor

View File

@ -27,7 +27,7 @@ import Combine
import Foundation
import PassepartoutLibrary
class DefaultLightProfile: LightProfile {
final class DefaultLightProfile: LightProfile {
let id: UUID
let name: String
@ -50,7 +50,7 @@ class DefaultLightProfile: LightProfile {
}
}
class DefaultLightProfileManager: LightProfileManager {
final class DefaultLightProfileManager: LightProfileManager {
private let profileManager = ProfileManager.shared
private let providerManager = ProviderManager.shared

View File

@ -27,7 +27,7 @@ import Combine
import Foundation
import PassepartoutLibrary
class DefaultLightProviderCategory: LightProviderCategory {
final class DefaultLightProviderCategory: LightProviderCategory {
let name: String
var locations: [LightProviderLocation]
@ -40,7 +40,7 @@ class DefaultLightProviderCategory: LightProviderCategory {
}
}
class DefaultLightProviderLocation: LightProviderLocation {
final class DefaultLightProviderLocation: LightProviderLocation {
let description: String
let id: String
@ -59,7 +59,7 @@ class DefaultLightProviderLocation: LightProviderLocation {
}
}
class DefaultLightProviderServer: LightProviderServer {
final class DefaultLightProviderServer: LightProviderServer {
let description: String
let longDescription: String
@ -79,7 +79,7 @@ class DefaultLightProviderServer: LightProviderServer {
}
}
class DefaultLightProviderManager: LightProviderManager {
final class DefaultLightProviderManager: LightProviderManager {
private let providerManager = ProviderManager.shared
private var subscriptions: Set<AnyCancellable> = []

View File

@ -26,7 +26,7 @@
import Foundation
import SwiftUI
class DefaultLightUtils: LightUtils {
final class DefaultLightUtils: LightUtils {
private let app: UIApplication
init() {

View File

@ -26,8 +26,9 @@
import Combine
import Foundation
import PassepartoutLibrary
import TunnelKitManager
class DefaultLightVPNManager: LightVPNManager {
final class DefaultLightVPNManager: LightVPNManager {
private let vpnManager = VPNManager.shared
private var subscriptions: Set<AnyCancellable> = []

View File

@ -24,11 +24,11 @@
//
import Foundation
import PassepartoutCore
import PassepartoutLibrary
import TunnelKitCore
extension Network.DNSSettings {
public static func availableConfigurationTypes(forVPNProtocol vpnProtocol: VPNProtocolType) -> [ConfigurationType] {
static func availableConfigurationTypes(forVPNProtocol vpnProtocol: VPNProtocolType) -> [ConfigurationType] {
switch vpnProtocol {
case .openVPN:
return [.plain, .https, .tls, .disabled]
@ -40,7 +40,7 @@ extension Network.DNSSettings {
}
extension Network.ProxySettings {
public static let availableConfigurationTypes: [ConfigurationType] = [
static let availableConfigurationTypes: [ConfigurationType] = [
.manual,
.pac,
.disabled
@ -48,5 +48,5 @@ extension Network.ProxySettings {
}
extension Network.MTUSettings {
public static let availableBytes: [Int] = [0, 1500, 1400, 1300, 1200]
static let availableBytes: [Int] = [0, 1500, 1400, 1300, 1200]
}

View File

@ -27,7 +27,7 @@ import Foundation
import TunnelKitOpenVPN
extension OpenVPN.Cipher {
public static let available: [OpenVPN.Cipher] = [
static let available: [OpenVPN.Cipher] = [
.aes256gcm,
.aes192gcm,
.aes128gcm,
@ -38,7 +38,7 @@ extension OpenVPN.Cipher {
}
extension OpenVPN.Digest {
public static let available: [OpenVPN.Digest] = [
static let available: [OpenVPN.Digest] = [
.sha1,
.sha224,
.sha256,
@ -48,7 +48,7 @@ extension OpenVPN.Digest {
}
extension OpenVPN.CompressionFraming {
public static let available: [OpenVPN.CompressionFraming] = [
static let available: [OpenVPN.CompressionFraming] = [
.disabled,
.compLZO,
.compress
@ -56,7 +56,7 @@ extension OpenVPN.CompressionFraming {
}
extension OpenVPN.CompressionAlgorithm {
public static let available: [OpenVPN.CompressionAlgorithm] = [
static let available: [OpenVPN.CompressionAlgorithm] = [
.disabled,
.LZO
]

View File

@ -115,7 +115,7 @@ struct LockableView<Content: View, LockedContent: View>: View {
}
}
private class Lock: ObservableObject {
private final class Lock: ObservableObject {
enum State {
case none

View File

@ -27,7 +27,7 @@ import MessageUI
import SwiftUI
struct MailComposerView: UIViewControllerRepresentable {
class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
final class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
@Binding private var isPresented: Bool
init(_ view: MailComposerView) {

View File

@ -26,7 +26,7 @@
import StoreKit
import UIKit
public class Reviewer: ObservableObject {
public final class Reviewer: ObservableObject {
private struct Keys {
static let eventCount = "Reviewer.EventCount"

View File

@ -26,7 +26,7 @@
import PassepartoutLibrary
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func sceneDidEnterBackground(_ scene: UIScene) {
ProfileManager.shared.persist()
#if targetEnvironment(macCatalyst)

View File

@ -27,7 +27,7 @@ import Foundation
import PassepartoutLibrary
extension AddProviderView {
class ViewModel: ObservableObject {
final class ViewModel: ObservableObject {
enum PendingOperation {
case index

View File

@ -154,7 +154,7 @@ extension DiagnosticsView.OpenVPNView {
}
private var appLogURL: URL? {
LogManager.shared.logFile
Passepartout.shared.logger.logFile
}
private var tunnelLogURL: URL? {

View File

@ -52,7 +52,7 @@ extension DiagnosticsView {
extension DiagnosticsView.WireGuardView {
private var appLogURL: URL? {
LogManager.shared.logFile
Passepartout.shared.logger.logFile
}
private var tunnelLogURL: URL? {

View File

@ -30,7 +30,8 @@ extension OnDemandView {
struct SSIDList: View {
@Binding var withSSIDs: [String: Bool]
@StateObject private var reader = SSIDReader()
// FIXME: arch, this is a candidate for DI
@StateObject private var reader = Wifi(observer: CoreLocationWifiObserver())
var body: some View {
EditableTextList(elements: allSSIDs, allowsDuplicates: false, mapping: mapElements) { text in
@ -73,7 +74,7 @@ extension OnDemandView {
private func requestSSID(_ text: Binding<String>) {
Task { @MainActor in
let ssid = try await reader.requestCurrentSSID()
let ssid = try await reader.currentSSID()
if !withSSIDs.keys.contains(ssid) {
text.wrappedValue = ssid
}

View File

@ -25,7 +25,6 @@
import PassepartoutLibrary
import SwiftUI
import SwiftyBeaver
extension View {
func withoutTitleBar() -> some View {
@ -106,7 +105,7 @@ extension View {
extension View {
func debugChanges() {
if SwiftyBeaver.destinations.first?.minLevel == .verbose {
if Passepartout.shared.logger.logLevel == .verbose {
Self._printChanges()
}
}

View File

@ -1 +1 @@
2022 Davide De Rosa
2023 Davide De Rosa

View File

@ -27,7 +27,7 @@ import Foundation
import PassepartoutLibrary
extension CoreContext {
static let shared = CoreContext(store: UserDefaultsStore(defaults: .standard))
static let shared = CoreContext(store: UserDefaultsStore(defaults: .standard, key: \.key))
}
extension UpgradeManager {

View File

@ -26,14 +26,16 @@
import Combine
import Foundation
import PassepartoutLibrary
import TunnelKitCore
import TunnelKitManager
@MainActor
class CoreContext {
final class CoreContext {
let store: KeyValueStore
private let profilesPersistence: Persistence
private let profilesPersistence: CoreDataPersistentStore
private let providersPersistence: Persistence
private let providersPersistence: CoreDataPersistentStore
var urlsForProfiles: [URL]? {
profilesPersistence.containerURLs
@ -56,6 +58,14 @@ class CoreContext {
init(store: KeyValueStore) {
self.store = store
let logger = SwiftyBeaverLogger(
logFile: Constants.Log.App.url,
logLevel: Constants.Log.level,
logFormat: Constants.Log.App.format
)
Passepartout.shared.logger = logger
pp_log.info("Logging to: \(logger.logFile!)")
let persistenceManager = PersistenceManager(store: store)
profilesPersistence = persistenceManager.profilesPersistence(
withName: Constants.Persistence.profilesContainerName
@ -64,29 +74,35 @@ class CoreContext {
withName: Constants.Persistence.providersContainerName
)
upgradeManager = UpgradeManager(store: store)
upgradeManager = UpgradeManager(
store: store,
strategy: DefaultUpgradeStrategy()
)
providerManager = ProviderManager(
let remoteProvidersStrategy = APIRemoteProvidersStrategy(
appBuild: Constants.Global.appBuildNumber,
bundleServices: DefaultWebServices.bundledServices(
bundleServices: APIWebServices.bundledServices(
withVersion: Constants.Services.version
),
webServices: DefaultWebServices(
remoteServices: APIWebServices(
Constants.Services.version,
Constants.Repos.api,
timeout: Constants.Services.connectivityTimeout
),
persistence: providersPersistence
webServicesRepository: PassepartoutPersistence.webServicesRepository(providersPersistence)
)
providerManager = ProviderManager(
localProvidersRepository: PassepartoutPersistence.localProvidersRepository(providersPersistence),
remoteProvidersStrategy: remoteProvidersStrategy
)
profileManager = ProfileManager(
store: store,
providerManager: providerManager,
appGroup: Constants.App.appGroupId,
keychainLabel: Unlocalized.Keychain.passwordLabel,
strategy: CoreDataProfileManagerStrategy(
persistence: profilesPersistence
)
profileRepository: PassepartoutPersistence.profileRepository(profilesPersistence),
keychain: KeychainSecretRepository(appGroup: Constants.App.appGroupId),
keychainEntry: Unlocalized.Keychain.passwordEntry,
keychainLabel: Unlocalized.Keychain.passwordLabel
)
#if targetEnvironment(simulator)
@ -94,17 +110,16 @@ class CoreContext {
#else
let vpn = NetworkExtensionVPN()
#endif
let strategy = TunnelKitVPNManagerStrategy(
let vpnManagerStrategy = TunnelKitVPNManagerStrategy(
appGroup: Constants.App.appGroupId,
tunnelBundleIdentifier: Constants.App.tunnelBundleId,
vpn: vpn
)
vpnManager = VPNManager(
appGroup: Constants.App.appGroupId,
store: store,
profileManager: profileManager,
providerManager: providerManager,
strategy: strategy
strategy: vpnManagerStrategy
)
// post

View File

@ -25,13 +25,12 @@
import CoreData
import Foundation
import PassepartoutCore
import PassepartoutUtils
import PassepartoutLibrary
public final class PersistenceManager {
final class PersistenceManager {
private let store: KeyValueStore
public init(store: KeyValueStore) {
init(store: KeyValueStore) {
self.store = store
// set once
@ -40,21 +39,19 @@ public final class PersistenceManager {
}
}
public func profilesPersistence(withName containerName: String) -> Persistence {
let model = PassepartoutDataModels.profiles
return Persistence(withCloudKitName: containerName, model: model, author: persistenceAuthor)
func profilesPersistence(withName containerName: String) -> CoreDataPersistentStore {
PassepartoutPersistence.profilesStore(withName: containerName, cloudKit: true, author: persistenceAuthor)
}
public func providersPersistence(withName containerName: String) -> Persistence {
let model = PassepartoutDataModels.providers
return Persistence(withLocalName: containerName, model: model, author: persistenceAuthor)
func providersPersistence(withName containerName: String) -> CoreDataPersistentStore {
PassepartoutPersistence.providersStore(withName: containerName, cloudKit: false, author: persistenceAuthor)
}
}
// MARK: KeyValueStore
extension PersistenceManager {
public private(set) var persistenceAuthor: String? {
private(set) var persistenceAuthor: String? {
get {
store.value(forLocation: StoreKey.persistenceAuthor)
}

View File

@ -56,8 +56,12 @@ enum Unlocalized {
}
enum Keychain {
static func passwordLabel(_ profileName: String, vpnProtocol: VPNProtocolType) -> String {
"\(Constants.Global.appName): \(profileName) (\(vpnProtocol.description))"
static func passwordEntry(_ profile: Profile) -> String {
"\(profile.id.uuidString):\(profile.currentVPNProtocol.keychainEntry):\(profile.account.username)"
}
static func passwordLabel(_ profile: Profile) -> String {
"\(Constants.Global.appName): \(profile.header.name) (\(profile.currentVPNProtocol.keychainEntry))"
}
}
@ -252,3 +256,15 @@ enum Unlocalized {
static let totp = "TOTP"
}
}
private extension VPNProtocolType {
var keychainEntry: String {
switch self {
case .openVPN:
return "OpenVPN"
case .wireGuard:
return "WireGuard"
}
}
}

View File

@ -26,7 +26,7 @@
import AppKit
import Foundation
class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
private let appURL = Constants.Launcher.appURL
private var isAppRunning: Bool {

View File

@ -25,7 +25,7 @@
import Foundation
class DefaultMacMenu: MacMenu {
final class DefaultMacMenu: MacMenu {
weak var delegate: MacMenuDelegate?
private lazy var menu: PassepartoutMenu = {

View File

@ -26,7 +26,7 @@
import AppKit
import Foundation
class DefaultMacUtils: MacUtils {
final class DefaultMacUtils: MacUtils {
private(set) lazy var isStartedByLauncher = NSApp.isHidden
private let transformer = ObservableProcessTransformer.shared

View File

@ -28,7 +28,7 @@ import Foundation
extension HostProfileItem {
@MainActor
class ViewModel {
final class ViewModel {
let profile: LightProfile
private let vpnManager: LightVPNManager

View File

@ -30,7 +30,7 @@ import ServiceManagement
extension LaunchOnLoginItem {
@MainActor
class ViewModel: ObservableObject {
final class ViewModel: ObservableObject {
let title: String
let utils: LightUtils

View File

@ -29,7 +29,7 @@ import Foundation
extension PassepartoutMenu {
@MainActor
class StatusButton {
final class StatusButton {
private lazy var statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
private lazy var statusButton: NSStatusBarButton = {

View File

@ -27,7 +27,7 @@ import AppKit
import Foundation
@MainActor
class PassepartoutMenu {
final class PassepartoutMenu {
private let macMenuDelegate: MacMenuDelegate
private let profileManager: LightProfileManager

View File

@ -28,7 +28,7 @@ import Foundation
extension ProviderLocationItem {
@MainActor
class ViewModel {
final class ViewModel {
private let profile: LightProfile
let location: LightProviderLocation

View File

@ -28,7 +28,7 @@ import Foundation
extension ProviderProfileItem {
@MainActor
class ViewModel {
final class ViewModel {
let profile: LightProfile
private let providerManager: LightProviderManager

View File

@ -28,7 +28,7 @@ import Foundation
extension ProviderServerItem {
@MainActor
class ViewModel {
final class ViewModel {
private let profile: LightProfile
let server: LightProviderServer

View File

@ -29,7 +29,7 @@ import Foundation
extension VPNItemGroup {
@MainActor
class ViewModel {
final class ViewModel {
private let vpnManager: LightVPNManager
private let toggleTitleBlock: (Bool) -> String

View File

@ -29,7 +29,7 @@ import Foundation
extension VisibilityItem {
@MainActor
class ViewModel {
final class ViewModel {
private let transformer: ObservableProcessTransformer
private let utils: LightUtils

View File

@ -25,7 +25,7 @@
import Foundation
class PassepartoutMac: NSObject, MacBridge {
final class PassepartoutMac: NSObject, MacBridge {
required override init() {
super.init()
}

View File

@ -26,7 +26,7 @@
import Combine
import Foundation
class ObservableProcessTransformer: ObservableObject {
final class ObservableProcessTransformer: ObservableObject {
static let shared = ObservableProcessTransformer()
private let transformer = ProcessTransformer()

View File

@ -27,7 +27,7 @@ import Combine
import Foundation
extension TextItem {
class ViewModel {
final class ViewModel {
let title: CurrentValueSubject<String, Never>
let state: CurrentValueSubject<State, Never>

View File

@ -26,7 +26,7 @@
import Foundation
import OpenVPNAppExtension
class PacketTunnelProvider: OpenVPNTunnelProvider {
final class PacketTunnelProvider: OpenVPNTunnelProvider {
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
appVersion = "\(Constants.Global.appName) \(Constants.Global.appVersionString)"
dnsTimeout = Constants.OpenVPNTunnel.dnsTimeout

View File

@ -26,5 +26,5 @@
import Foundation
import WireGuardAppExtension
class PacketTunnelProvider: WireGuardTunnelProvider {
final class PacketTunnelProvider: WireGuardTunnelProvider {
}

View File

@ -0,0 +1,45 @@
{
"configurations" : [
{
"id" : "2A4B150B-39A2-417B-98FD-1C5C74C26E3E",
"name" : "Test Scheme Action",
"options" : {
}
}
],
"defaultOptions" : {
"codeCoverage" : false
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:",
"identifier" : "PassepartoutCoreTests",
"name" : "PassepartoutCoreTests"
}
},
{
"target" : {
"containerPath" : "container:",
"identifier" : "PassepartoutProvidersTests",
"name" : "PassepartoutProvidersTests"
}
},
{
"target" : {
"containerPath" : "container:",
"identifier" : "PassepartoutServicesTests",
"name" : "PassepartoutServicesTests"
}
},
{
"target" : {
"containerPath" : "container:",
"identifier" : "PassepartoutVPNTests",
"name" : "PassepartoutVPNTests"
}
}
],
"version" : 1
}

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "OpenVPNAppExtension"
BuildableName = "OpenVPNAppExtension"
BlueprintName = "OpenVPNAppExtension"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "OpenVPNAppExtension"
BuildableName = "OpenVPNAppExtension"
BlueprintName = "OpenVPNAppExtension"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutCoreTests"
BuildableName = "PassepartoutCoreTests"
BlueprintName = "PassepartoutCoreTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,332 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibrary_PassepartoutVPNImpl"
BuildableName = "PassepartoutLibrary_PassepartoutVPNImpl"
BlueprintName = "PassepartoutLibrary_PassepartoutVPNImpl"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibrary_PassepartoutCoreTests"
BuildableName = "PassepartoutLibrary_PassepartoutCoreTests"
BlueprintName = "PassepartoutLibrary_PassepartoutCoreTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "OpenVPNAppExtension"
BuildableName = "OpenVPNAppExtension"
BlueprintName = "OpenVPNAppExtension"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutVPN"
BuildableName = "PassepartoutVPN"
BlueprintName = "PassepartoutVPN"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "WireGuardAppExtension"
BuildableName = "WireGuardAppExtension"
BlueprintName = "WireGuardAppExtension"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutCore"
BuildableName = "PassepartoutCore"
BlueprintName = "PassepartoutCore"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutProviders"
BuildableName = "PassepartoutProviders"
BlueprintName = "PassepartoutProviders"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutServices"
BuildableName = "PassepartoutServices"
BlueprintName = "PassepartoutServices"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutVPNImpl"
BuildableName = "PassepartoutVPNImpl"
BlueprintName = "PassepartoutVPNImpl"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutCoreTests"
BuildableName = "PassepartoutCoreTests"
BlueprintName = "PassepartoutCoreTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutProvidersTests"
BuildableName = "PassepartoutProvidersTests"
BlueprintName = "PassepartoutProvidersTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutServicesTests"
BuildableName = "PassepartoutServicesTests"
BlueprintName = "PassepartoutServicesTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutVPNTests"
BuildableName = "PassepartoutVPNTests"
BlueprintName = "PassepartoutVPNTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutServicesImpl"
BuildableName = "PassepartoutServicesImpl"
BlueprintName = "PassepartoutServicesImpl"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutProvidersImpl"
BuildableName = "PassepartoutProvidersImpl"
BlueprintName = "PassepartoutProvidersImpl"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibrary_PassepartoutProvidersImpl"
BuildableName = "PassepartoutLibrary_PassepartoutProvidersImpl"
BlueprintName = "PassepartoutLibrary_PassepartoutProvidersImpl"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibrary"
BuildableName = "PassepartoutLibrary"
BlueprintName = "PassepartoutLibrary"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutCoreTests"
BuildableName = "PassepartoutCoreTests"
BlueprintName = "PassepartoutCoreTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutProvidersTests"
BuildableName = "PassepartoutProvidersTests"
BlueprintName = "PassepartoutProvidersTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutServicesTests"
BuildableName = "PassepartoutServicesTests"
BlueprintName = "PassepartoutServicesTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutVPNTests"
BuildableName = "PassepartoutVPNTests"
BlueprintName = "PassepartoutVPNTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibrary_PassepartoutVPNImpl"
BuildableName = "PassepartoutLibrary_PassepartoutVPNImpl"
BlueprintName = "PassepartoutLibrary_PassepartoutVPNImpl"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibrary"
BuildableName = "PassepartoutLibrary"
BlueprintName = "PassepartoutLibrary"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:.swiftpm/PassepartoutLibrary.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutLibrary"
BuildableName = "PassepartoutLibrary"
BlueprintName = "PassepartoutLibrary"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutProvidersTests"
BuildableName = "PassepartoutProvidersTests"
BlueprintName = "PassepartoutProvidersTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "PassepartoutVPNTests"
BuildableName = "PassepartoutVPNTests"
BlueprintName = "PassepartoutVPNTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "WireGuardAppExtension"
BuildableName = "WireGuardAppExtension"
BlueprintName = "WireGuardAppExtension"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "WireGuardAppExtension"
BuildableName = "WireGuardAppExtension"
BlueprintName = "WireGuardAppExtension"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -32,58 +32,64 @@ let package = Package(
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
// MARK: Implementations
.target(
name: "PassepartoutLibrary",
dependencies: [
"PassepartoutVPN"
"PassepartoutVPNImpl",
"PassepartoutProvidersImpl"
]),
.target(
name: "PassepartoutVPNImpl",
dependencies: [
"PassepartoutVPN",
"SwiftyBeaver",
.product(name: "TunnelKitLZO", package: "TunnelKit")
],
resources: [
.process("Data/Profiles.xcdatamodeld")
]),
.target(
name: "PassepartoutProvidersImpl",
dependencies: [
"PassepartoutProviders",
"PassepartoutServices"
],
resources: [
.copy("API"),
.process("Data/Providers.xcdatamodeld")
]),
// MARK: Interfaces
.target(
name: "PassepartoutVPN",
dependencies: [
"PassepartoutProfiles",
.product(name: "TunnelKitLZO", package: "TunnelKit")
]),
.target(
name: "PassepartoutProfiles",
dependencies: [
"PassepartoutProviders"
],
resources: [
.process("DataModels/Profiles.xcdatamodeld")
"PassepartoutProviders",
.product(name: "TunnelKit", package: "TunnelKit"),
.product(name: "TunnelKitOpenVPN", package: "TunnelKit"), // FIXME: arch, drop this
.product(name: "TunnelKitWireGuard", package: "TunnelKit"), // FIXME: arch, drop this
]),
.target(
name: "PassepartoutProviders",
dependencies: [
"PassepartoutCore",
"PassepartoutServices"
],
resources: [
.process("DataModels/Providers.xcdatamodeld")
"PassepartoutCore"
]),
.target(
name: "PassepartoutServices",
dependencies: [
"PassepartoutCore"
]),
.target(
name: "PassepartoutCore",
dependencies: [
.product(name: "TunnelKit", package: "TunnelKit"),
.product(name: "TunnelKitOpenVPN", package: "TunnelKit"),
.product(name: "TunnelKitWireGuard", package: "TunnelKit"),
.product(name: "GenericJSON", package: "generic-json-swift")
.product(name: "GenericJSON", package: "generic-json-swift") // FIXME: arch, drop this
]),
//
.target(
name: "PassepartoutServices",
dependencies: [
"PassepartoutUtils"
],
resources: [
.copy("API")
]),
.target(
name: "PassepartoutUtils",
dependencies: [
.product(name: "GenericJSON", package: "generic-json-swift"),
"SwiftyBeaver"
]),
//
// MARK: App extensions
.target(
name: "OpenVPNAppExtension",
dependencies: [
@ -95,27 +101,18 @@ let package = Package(
dependencies: [
.product(name: "TunnelKitWireGuardAppExtension", package: "TunnelKit")
]),
.testTarget(
name: "PassepartoutLibraryTests",
dependencies: ["PassepartoutLibrary"]),
// MARK: Tests
.testTarget(
name: "PassepartoutVPNTests",
dependencies: ["PassepartoutVPN"]),
.testTarget(
name: "PassepartoutProfilesTests",
dependencies: ["PassepartoutProfiles"]),
dependencies: ["PassepartoutVPNImpl"]),
.testTarget(
name: "PassepartoutProvidersTests",
dependencies: ["PassepartoutProviders"]),
dependencies: ["PassepartoutProvidersImpl"]),
.testTarget(
name: "PassepartoutCoreTests",
dependencies: ["PassepartoutCore"]),
.testTarget(
name: "PassepartoutServicesTests",
dependencies: ["PassepartoutServices"]),
.testTarget(
name: "PassepartoutUtilsTests",
dependencies: ["PassepartoutUtils"],
dependencies: ["PassepartoutCore"],
resources: [
.process("Resources")
])

View File

@ -25,6 +25,7 @@
import Foundation
// FIXME: arch, provide a well-defined serialization property rather than .rawValue
public enum VPNProtocolType: String, CaseIterable, Codable {
case openVPN = "ovpn"
@ -34,15 +35,3 @@ public enum VPNProtocolType: String, CaseIterable, Codable {
public protocol VPNProtocolProviding {
var vpnProtocol: VPNProtocolType { get }
}
extension VPNProtocolType: CustomStringConvertible {
public var description: String {
switch self {
case .openVPN:
return "OpenVPN"
case .wireGuard:
return "WireGuard"
}
}
}

View File

@ -0,0 +1,3 @@
public var pp_log: Logger {
Passepartout.shared.logger
}

View File

@ -1,57 +0,0 @@
//
// Profile+Extensions.swift
// Passepartout
//
// Created by Davide De Rosa on 3/13/22.
// Copyright (c) 2023 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
extension Profile {
public var isProvider: Bool {
provider != nil
}
public var vpnProtocols: [VPNProtocolType] {
if isProvider {
return provider?.vpnProtocols ?? []
} else {
return host?.vpnProtocols ?? []
}
}
public var account: Profile.Account {
get {
if isProvider {
return providerAccount ?? .init()
} else {
return hostAccount ?? .init()
}
}
set {
if isProvider {
providerAccount = newValue
} else {
hostAccount = newValue
}
}
}
}

View File

@ -1,5 +1,5 @@
//
// PassepartoutError.swift
// Passepartout.swift
// Passepartout
//
// Created by Davide De Rosa on 6/12/18.
@ -25,6 +25,19 @@
import Foundation
// FIXME: arch, global variables here are not extensible, use dependency injection instead
public class Passepartout {
public static let shared = Passepartout()
private init() {
}
public var logger: Logger = DefaultLogger()
}
public enum PassepartoutPersistence {
}
public struct PassepartoutError: Error, Equatable {
private let string: String

View File

@ -1,5 +1,5 @@
//
// Persistence.swift
// CoreDataPersistentStore.swift
// Passepartout
//
// Created by Davide De Rosa on 3/14/22.
@ -27,24 +27,16 @@ import Combine
import CoreData
import Foundation
public class Persistence {
public final class CoreDataPersistentStore {
private let container: NSPersistentContainer
public var context: NSManagedObjectContext {
container.viewContext
}
public var coordinator: NSPersistentStoreCoordinator {
container.persistentStoreCoordinator
}
public convenience init(withLocalName containerName: String, model: NSManagedObjectModel, author: String?) {
let container = NSPersistentContainer(name: containerName, managedObjectModel: model)
self.init(withContainer: container, author: author)
}
public convenience init(withCloudKitName containerName: String, model: NSManagedObjectModel, author: String?) {
let container = NSPersistentCloudKitContainer(name: containerName, managedObjectModel: model)
public convenience init(withName containerName: String, model: NSManagedObjectModel, cloudKit: Bool, author: String?) {
let container: NSPersistentContainer
if cloudKit {
container = NSPersistentCloudKitContainer(name: containerName, managedObjectModel: model)
} else {
container = NSPersistentContainer(name: containerName, managedObjectModel: model)
}
self.init(withContainer: container, author: author)
}
@ -112,3 +104,13 @@ public class Persistence {
}
}
}
extension CoreDataPersistentStore {
public var context: NSManagedObjectContext {
container.viewContext
}
public var coordinator: NSPersistentStoreCoordinator {
container.persistentStoreCoordinator
}
}

View File

@ -1,8 +1,8 @@
//
// SSIDReader.swift
// CoreLocationWifiObserver.swift
// Passepartout
//
// Created by Davide De Rosa on 2/24/22.
// Created by Davide De Rosa on 5/21/23.
// Copyright (c) 2023 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
@ -26,38 +26,37 @@
import CoreLocation
import Foundation
@MainActor
public class SSIDReader: NSObject, ObservableObject {
private let manager = CLLocationManager()
public final class CoreLocationWifiObserver: NSObject, WifiObserver {
private let locationManager = CLLocationManager()
private var continuation: CheckedContinuation<String, Error>?
private func currentSSID() async -> String {
await Utils.currentWifiSSID() ?? ""
}
public func requestCurrentSSID() async throws -> String {
switch manager.authorizationStatus {
public func currentSSID() async throws -> String {
switch locationManager.authorizationStatus {
case .authorizedAlways, .authorizedWhenInUse, .denied:
return await currentSSID()
return await currentSSIDWithoutAuthorization()
default:
return try await withCheckedThrowingContinuation { continuation in
self.continuation = continuation
manager.delegate = self
manager.requestWhenInUseAuthorization()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
}
}
private func currentSSIDWithoutAuthorization() async -> String {
await Utils.currentWifiSSID() ?? ""
}
}
extension SSIDReader: CLLocationManagerDelegate {
extension CoreLocationWifiObserver: CLLocationManagerDelegate {
public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .authorizedWhenInUse, .authorizedAlways, .denied:
Task {
continuation?.resume(returning: await currentSSID())
continuation?.resume(returning: await currentSSIDWithoutAuthorization())
continuation = nil
}

View File

@ -27,7 +27,7 @@ import Combine
import CoreData
import Foundation
public class FetchedValueHolder<V>: NSObject, ValueHolder, NSFetchedResultsControllerDelegate {
public final class FetchedValueHolder<V>: NSObject, ValueHolder, NSFetchedResultsControllerDelegate {
@Published public var value: V
private let controller: NSFetchedResultsController<NSFetchRequestResult>

View File

@ -25,7 +25,7 @@
import Foundation
public class GenericWebParser {
public final class GenericWebParser {
private static let lmFormatter: DateFormatter = {
let fmt = DateFormatter()
fmt.locale = Locale(identifier: "en")

View File

@ -32,7 +32,7 @@ public protocol GenericWebServicesError: Error {
static var unknown: Self { get }
}
public class GenericWebServices<ErrorType: GenericWebServicesError> {
public final class GenericWebServices<ErrorType: GenericWebServicesError> {
private let version: String?
private let root: URL

View File

@ -36,7 +36,7 @@ public enum InAppError: Error {
case unknown
}
public class InApp<PID: Hashable & RawRepresentable>: NSObject,
public final class InApp<PID: Hashable & RawRepresentable>: NSObject,
SKProductsRequestDelegate, SKPaymentTransactionObserver
where PID.RawValue == String {

View File

@ -1,5 +1,5 @@
//
// Utils+Codable.swift
// JSON+Codable.swift
// Passepartout
//
// Created by Davide De Rosa on 3/13/22.

View File

@ -33,16 +33,16 @@ public protocol KeyStoreDomainLocation: KeyStoreLocation {
var domain: String { get }
}
public protocol KeyValueStore {
func setValue<L, V>(_ value: V?, forLocation location: L) where L: KeyStoreLocation
func value<L, V>(forLocation location: L) -> V? where L: KeyStoreLocation
func removeValue<L>(forLocation location: L) where L: KeyStoreLocation
}
extension KeyStoreDomainLocation {
public var key: String {
"\(domain).\(rawValue)"
}
}
public protocol KeyValueStore {
func setValue<L: KeyStoreLocation, V>(_ value: V?, forLocation location: L)
func value<L: KeyStoreLocation, V>(forLocation location: L) -> V?
func removeValue<L: KeyStoreLocation>(forLocation location: L)
}

View File

@ -25,7 +25,7 @@
import Foundation
public class KeyedCache<K: Hashable, V> {
public struct KeyedCache<K: Hashable, V> {
private let query: String
private var store: [K: V] = [:]
@ -42,15 +42,15 @@ public class KeyedCache<K: Hashable, V> {
self.query = query
}
public func set(_ store: [K: V]) {
public mutating func set(_ store: [K: V]) {
self.store = store
}
public func put(_ key: K, value: V) {
public mutating func put(_ key: K, value: V) {
store[key] = value
}
public func put(_ key: K, valueBlock: (K) -> V?) -> V? {
public mutating func put(_ key: K, valueBlock: (K) -> V?) -> V? {
if let cachedValue = store[key] {
return cachedValue
}
@ -62,18 +62,18 @@ public class KeyedCache<K: Hashable, V> {
return value
}
public func forget(where condition: (K) -> Bool) {
public mutating func forget(where condition: (K) -> Bool) {
let removedKeys = store.keys.filter(condition)
removedKeys.forEach {
store.removeValue(forKey: $0)
}
}
public func forget(_ key: K) {
public mutating func forget(_ key: K) {
store.removeValue(forKey: key)
}
public func clear() {
public mutating func clear() {
store.removeAll()
}
}

View File

@ -0,0 +1,102 @@
//
// Logger.swift
// Passepartout
//
// Created by Davide De Rosa on 6/15/22.
// Copyright (c) 2023 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 enum LoggerLevel: Int {
case verbose
case debug
case info
case warning
case error
}
public protocol Logger {
var logFile: URL? { get }
var logLevel: LoggerLevel { get set }
func verbose(_ message: Any)
func debug(_ message: Any)
func info(_ message: Any)
func warning(_ message: Any)
func error(_ message: Any)
}
final class DefaultLogger: Logger {
let logFile: URL? = nil
var logLevel: LoggerLevel = .debug
func verbose(_ message: Any) {
guard logLevel.rawValue >= LoggerLevel.verbose.rawValue else {
return
}
logMessage(message)
}
func debug(_ message: Any) {
guard logLevel.rawValue >= LoggerLevel.debug.rawValue else {
return
}
logMessage(message)
}
func info(_ message: Any) {
guard logLevel.rawValue >= LoggerLevel.info.rawValue else {
return
}
logMessage(message)
}
func warning(_ message: Any) {
guard logLevel.rawValue >= LoggerLevel.warning.rawValue else {
return
}
logMessage(message)
}
func error(_ message: Any) {
guard logLevel.rawValue >= LoggerLevel.error.rawValue else {
return
}
logMessage(message)
}
private func logMessage(_ message: Any) {
guard let string = message as? String else {
return
}
NSLog(string)
}
}

View File

@ -0,0 +1,43 @@
//
// Wifi.swift
// Passepartout
//
// Created by Davide De Rosa on 2/24/22.
// Copyright (c) 2023 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
@MainActor
public final class Wifi: ObservableObject {
private let observer: WifiObserver
public init(observer: WifiObserver) {
self.observer = observer
}
public func currentSSID() async throws -> String {
try await observer.currentSSID()
}
}
public protocol WifiObserver {
func currentSSID() async throws -> String
}

View File

@ -1,8 +1,5 @@
@_exported import PassepartoutCore
@_exported import PassepartoutProfiles
@_exported import PassepartoutProviders
@_exported import PassepartoutServices
@_exported import PassepartoutUtils
@_exported import PassepartoutProvidersImpl
@_exported import PassepartoutVPN
@_exported import TunnelKit
@_exported import TunnelKitCore
@_exported import PassepartoutVPNImpl

View File

@ -1,69 +0,0 @@
//
// CoreDataProfileManagerStrategy.swift
// Passepartout
//
// Created by Davide De Rosa on 4/9/22.
// Copyright (c) 2023 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 Combine
import Foundation
import PassepartoutCore
import PassepartoutUtils
public class CoreDataProfileManagerStrategy: ProfileManagerStrategy {
private let profileRepository: ProfileRepository
private let fetchedProfiles: FetchedValueHolder<[UUID: Profile]>
public init(persistence: Persistence) {
profileRepository = ProfileRepository(persistence.context)
fetchedProfiles = profileRepository.fetchedProfiles()
}
public var allProfiles: [UUID: Profile] {
fetchedProfiles.value
}
public func profiles() -> [Profile] {
profileRepository.profiles()
}
public func profile(withId id: UUID) -> Profile? {
profileRepository.profile(withId: id)
}
public func saveProfiles(_ profiles: [Profile]) {
do {
try profileRepository.saveProfiles(profiles)
} catch {
pp_log.error("Unable to save profile: \(error)")
}
}
public func removeProfiles(withIds ids: [UUID]) {
profileRepository.removeProfiles(withIds: ids)
}
public func willUpdateProfiles() -> AnyPublisher<[UUID: Profile], Never> {
fetchedProfiles.$value
.eraseToAnyPublisher()
}
}

View File

@ -1,119 +0,0 @@
//
// ProfileManager+Keychain.swift
// Passepartout
//
// Created by Davide De Rosa on 4/8/22.
// Copyright (c) 2023 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 PassepartoutCore
import PassepartoutUtils
import TunnelKitManager
extension ProfileManager {
public func savePassword(forProfile profile: Profile, newPassword: String? = nil) {
guard !profile.isPlaceholder else {
assertionFailure("Placeholder")
return
}
guard let keychainEntry = profile.keychainEntry else {
return
}
let password = newPassword ?? profile.account.password
guard !password.isEmpty else {
keychain.removePassword(
for: keychainEntry,
context: appGroup,
userDefined: profile.id.uuidString
)
return
}
do {
try keychain.set(
password: password,
for: keychainEntry,
context: appGroup,
userDefined: profile.id.uuidString,
label: keychainLabel(profile.header.name, profile.currentVPNProtocol)
)
} catch {
pp_log.error("Unable to save password to keychain: \(error)")
}
}
public func passwordReference(forProfile profile: Profile) -> Data? {
guard !profile.isPlaceholder else {
assertionFailure("Placeholder")
return nil
}
guard let keychainEntry = profile.keychainEntry else {
return nil
}
do {
return try keychain.passwordReference(
for: keychainEntry,
context: appGroup,
userDefined: profile.id.uuidString
)
} catch {
pp_log.debug("Unable to load password reference from keychain: \(error)")
return nil
}
}
}
private extension Profile {
var keychainEntry: String? {
"\(id.uuidString):\(currentVPNProtocol.description):\(account.username)"
}
}
extension Keychain {
func debugAllPasswords(matching id: UUID, context: String) {
var query = allPasswordsQuery(id, context)
query[kSecReturnAttributes as String] = true
var list: CFTypeRef?
switch SecItemCopyMatching(query as CFDictionary, &list) {
case errSecSuccess:
break
default:
return
}
guard let list = list else {
pp_log.debug("Keychain items: none")
return
}
pp_log.debug("Keychain items: \(list)")
}
func removeAllPasswords(matching id: UUID, context: String) {
_ = SecItemDelete(allPasswordsQuery(id, context) as CFDictionary)
}
private func allPasswordsQuery(_ id: UUID, _ context: String) -> [String: Any] {
var query = [String: Any]()
setScope(query: &query, context: context, userDefined: id.uuidString)
query[kSecClass as String] = kSecClassGenericPassword
return query
}
}

View File

@ -1,46 +0,0 @@
//
// CDInfrastructure+CoreDataProperties.swift
//
//
// Created by Davide De Rosa on 27/03/22.
//
// This file was automatically generated and should not be edited.
//
import CoreData
import Foundation
extension CDInfrastructure {
@nonobjc public class func fetchRequest() -> NSFetchRequest<CDInfrastructure> {
return NSFetchRequest<CDInfrastructure>(entityName: "CDInfrastructure")
}
@NSManaged public var lastUpdate: Date?
@NSManaged public var vpnProtocol: String?
@NSManaged public var categories: NSSet?
@NSManaged public var defaults: CDInfrastructureDefaultSettings?
@NSManaged public var provider: CDProvider?
}
// MARK: Generated accessors for categories
extension CDInfrastructure {
@objc(addCategoriesObject:)
@NSManaged public func addToCategories(_ value: CDInfrastructureCategory)
@objc(removeCategoriesObject:)
@NSManaged public func removeFromCategories(_ value: CDInfrastructureCategory)
@objc(addCategories:)
@NSManaged public func addToCategories(_ values: NSSet)
@objc(removeCategories:)
@NSManaged public func removeFromCategories(_ values: NSSet)
}
extension CDInfrastructure: Identifiable {
}

View File

@ -1,80 +0,0 @@
//
// CDInfrastructureCategory+CoreDataProperties.swift
//
//
// Created by Davide De Rosa on 27/03/22.
//
// This file was automatically generated and should not be edited.
//
import CoreData
import Foundation
extension CDInfrastructureCategory {
@nonobjc public class func fetchRequest() -> NSFetchRequest<CDInfrastructureCategory> {
return NSFetchRequest<CDInfrastructureCategory>(entityName: "CDInfrastructureCategory")
}
@NSManaged public var name: String?
@NSManaged public var infrastructure: CDInfrastructure?
@NSManaged public var locations: NSSet?
@NSManaged public var presets: NSSet?
@NSManaged public var servers: NSSet?
}
// MARK: Generated accessors for locations
extension CDInfrastructureCategory {
@objc(addLocationsObject:)
@NSManaged public func addToLocations(_ value: CDInfrastructureLocation)
@objc(removeLocationsObject:)
@NSManaged public func removeFromLocations(_ value: CDInfrastructureLocation)
@objc(addLocations:)
@NSManaged public func addToLocations(_ values: NSSet)
@objc(removeLocations:)
@NSManaged public func removeFromLocations(_ values: NSSet)
}
// MARK: Generated accessors for presets
extension CDInfrastructureCategory {
@objc(addPresetsObject:)
@NSManaged public func addToPresets(_ value: CDInfrastructurePreset)
@objc(removePresetsObject:)
@NSManaged public func removeFromPresets(_ value: CDInfrastructurePreset)
@objc(addPresets:)
@NSManaged public func addToPresets(_ values: NSSet)
@objc(removePresets:)
@NSManaged public func removeFromPresets(_ values: NSSet)
}
// MARK: Generated accessors for servers
extension CDInfrastructureCategory {
@objc(addServersObject:)
@NSManaged public func addToServers(_ value: CDInfrastructureServer)
@objc(removeServersObject:)
@NSManaged public func removeFromServers(_ value: CDInfrastructureServer)
@objc(addServers:)
@NSManaged public func addToServers(_ values: NSSet)
@objc(removeServers:)
@NSManaged public func removeFromServers(_ values: NSSet)
}
extension CDInfrastructureCategory: Identifiable {
}

View File

@ -1,47 +0,0 @@
//
// CDInfrastructurePreset+CoreDataProperties.swift
//
//
// Created by Davide De Rosa on 27/03/22.
//
// This file was automatically generated and should not be edited.
//
import CoreData
import Foundation
extension CDInfrastructurePreset {
@nonobjc public class func fetchRequest() -> NSFetchRequest<CDInfrastructurePreset> {
return NSFetchRequest<CDInfrastructurePreset>(entityName: "CDInfrastructurePreset")
}
@NSManaged public var comment: String?
@NSManaged public var id: String?
@NSManaged public var name: String?
@NSManaged public var vpnConfiguration: Data?
@NSManaged public var vpnProtocol: String?
@NSManaged public var category: NSSet?
}
// MARK: Generated accessors for category
extension CDInfrastructurePreset {
@objc(addCategoryObject:)
@NSManaged public func addToCategory(_ value: CDInfrastructureCategory)
@objc(removeCategoryObject:)
@NSManaged public func removeFromCategory(_ value: CDInfrastructureCategory)
@objc(addCategory:)
@NSManaged public func addToCategory(_ values: NSSet)
@objc(removeCategory:)
@NSManaged public func removeFromCategory(_ values: NSSet)
}
extension CDInfrastructurePreset: Identifiable {
}

View File

@ -1,35 +0,0 @@
//
// CDInfrastructureServer+CoreDataProperties.swift
//
//
// Created by Davide De Rosa on 27/03/22.
//
// This file was automatically generated and should not be edited.
//
import CoreData
import Foundation
extension CDInfrastructureServer {
@nonobjc public class func fetchRequest() -> NSFetchRequest<CDInfrastructureServer> {
return NSFetchRequest<CDInfrastructureServer>(entityName: "CDInfrastructureServer")
}
@NSManaged public var area: String?
@NSManaged public var countryCode: String?
@NSManaged public var extraCountryCodes: String?
@NSManaged public var hostname: String?
@NSManaged public var ipAddresses: String?
@NSManaged public var apiId: String?
@NSManaged public var serverIndex: Int16
@NSManaged public var tags: String?
@NSManaged public var uniqueId: String?
@NSManaged public var category: CDInfrastructureCategory?
@NSManaged public var location: CDInfrastructureLocation?
}
extension CDInfrastructureServer: Identifiable {
}

Some files were not shown because too many files have changed in this diff Show More