Skip to content

Commit 98c184d

Browse files
chore: clear session on launch if vpn unconfigured (#76)
1 parent f970cfc commit 98c184d

11 files changed

+64
-7
lines changed

Coder Desktop/Coder Desktop/Coder_DesktopApp.swift

+8
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
4949
name: .NEVPNStatusDidChange,
5050
object: nil
5151
)
52+
Task {
53+
// If there's no NE config, then the user needs to sign in.
54+
// However, they might have a session from a previous install, so we
55+
// need to clear it.
56+
if await !vpn.loadNetworkExtensionConfig() {
57+
state.clearSession()
58+
}
59+
}
5260
}
5361

5462
// This function MUST eventually call `NSApp.reply(toApplicationShouldTerminate: true)`

Coder Desktop/Coder Desktop/NetworkExtension.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ enum NetworkExtensionState: Equatable {
2424
/// An actor that handles configuring, enabling, and disabling the VPN tunnel via the
2525
/// NetworkExtension APIs.
2626
extension CoderVPNService {
27-
func loadNetworkExtensionConfig() async {
27+
// Attempts to load the NetworkExtension configuration, returning true if successful.
28+
func loadNetworkExtensionConfig() async -> Bool {
2829
do {
2930
let tm = try await getTunnelManager()
3031
neState = .disabled
3132
serverAddress = tm.protocolConfiguration?.serverAddress
33+
return true
3234
} catch {
3335
neState = .unconfigured
36+
return false
3437
}
3538
}
3639

Coder Desktop/Coder Desktop/VPNService.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ enum VPNServiceError: Error, Equatable {
3535
state.description
3636
}
3737
}
38+
39+
var localizedDescription: String { description }
3840
}
3941

4042
@MainActor
@@ -67,9 +69,6 @@ final class CoderVPNService: NSObject, VPNService {
6769
override init() {
6870
super.init()
6971
installSystemExtension()
70-
Task {
71-
await loadNetworkExtensionConfig()
72-
}
7372
}
7473

7574
deinit {

Coder Desktop/Coder Desktop/Views/LoginForm.swift

+2
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ enum LoginError: Error {
204204
"Could not authenticate with Coder deployment:\n\(err.description)"
205205
}
206206
}
207+
208+
var localizedDescription: String { description }
207209
}
208210

209211
enum LoginPage {

Coder Desktop/Coder Desktop/Views/VPNMenu.swift

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct VPNMenu<VPN: VPNService>: View {
8989
!state.hasSession ||
9090
vpn.state == .connecting ||
9191
vpn.state == .disconnecting ||
92+
// Prevent starting the VPN before the user has approved the system extension.
9293
vpn.state == .failed(.systemExtensionError(.needsUserApproval))
9394
}
9495
}

Coder Desktop/CoderSDK/Client.swift

+2
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,6 @@ public enum ClientError: Error {
134134
"Failed to encode body: \(error)"
135135
}
136136
}
137+
138+
public var localizedDescription: String { description }
137139
}

Coder Desktop/VPN/Manager.swift

+2
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ enum ManagerError: Error {
276276
"Failed to communicate with dylib over tunnel: \(err)"
277277
}
278278
}
279+
280+
var localizedDescription: String { description }
279281
}
280282

281283
func writeVpnLog(_ log: Vpn_Log) {

Coder Desktop/VPN/TunnelHandle.swift

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ enum TunnelHandleError: Error {
8282
case let .close(errs): "close tunnel: \(errs.map(\.localizedDescription).joined(separator: ", "))"
8383
}
8484
}
85+
86+
var localizedDescription: String { description }
8587
}
8688

8789
enum OpenTunnelError: Int32 {

Coder Desktop/VPNLib/Download.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public enum ValidationError: Error {
1111
case missingInfoPList
1212
case invalidVersion(version: String?)
1313

14-
public var errorDescription: String? {
14+
public var description: String {
1515
switch self {
1616
case .fileNotFound:
1717
"The file does not exist."
@@ -31,6 +31,8 @@ public enum ValidationError: Error {
3131
"Info.plist is not embedded within the dylib."
3232
}
3333
}
34+
35+
public var localizedDescription: String { description }
3436
}
3537

3638
public class SignatureValidator {
@@ -156,7 +158,7 @@ public enum DownloadError: Error {
156158
case networkError(any Error)
157159
case fileOpError(any Error)
158160

159-
var localizedDescription: String {
161+
public var description: String {
160162
switch self {
161163
case let .unexpectedStatusCode(code):
162164
"Unexpected HTTP status code: \(code)"
@@ -168,4 +170,6 @@ public enum DownloadError: Error {
168170
"Received non-HTTP response"
169171
}
170172
}
173+
174+
public var localizedDescription: String { description }
171175
}

Coder Desktop/VPNLib/Receiver.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,18 @@ actor Receiver<RecvMsg: Message> {
7575
}
7676
}
7777

78-
enum ReceiveError: Error {
78+
public enum ReceiveError: Error {
7979
case readError(String)
8080
case invalidLength
81+
82+
public var description: String {
83+
switch self {
84+
case let .readError(err): "read error: \(err)"
85+
case .invalidLength: "invalid message length"
86+
}
87+
}
88+
89+
public var localizedDescription: String { description }
8190
}
8291

8392
func deserializeLen(_ data: Data) throws -> UInt32 {

Coder Desktop/VPNLib/Speaker.swift

+25
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,19 @@ public enum HandshakeError: Error {
290290
case wrongRole(String)
291291
case invalidVersion(String)
292292
case unsupportedVersion([ProtoVersion])
293+
294+
public var description: String {
295+
switch self {
296+
case let .readError(err): "read error: \(err)"
297+
case let .writeError(err): "write error: \(err)"
298+
case let .invalidHeader(err): "invalid header: \(err)"
299+
case let .wrongRole(err): "wrong role: \(err)"
300+
case let .invalidVersion(err): "invalid version: \(err)"
301+
case let .unsupportedVersion(versions): "unsupported version: \(versions)"
302+
}
303+
}
304+
305+
public var localizedDescription: String { description }
293306
}
294307

295308
public struct RPCRequest<SendMsg: RPCMessage & Message, RecvMsg: RPCMessage & Sendable>: Sendable {
@@ -314,6 +327,18 @@ enum RPCError: Error {
314327
case notAResponse
315328
case unknownResponseID(UInt64)
316329
case shutdown
330+
331+
var description: String {
332+
switch self {
333+
case .missingRPC: "missing RPC field"
334+
case .notARequest: "not a request"
335+
case .notAResponse: "not a response"
336+
case let .unknownResponseID(id): "unknown response ID: \(id)"
337+
case .shutdown: "RPC secretary has been shutdown"
338+
}
339+
}
340+
341+
var localizedDescription: String { description }
317342
}
318343

319344
/// An actor to record outgoing RPCs and route their replies to the original sender

0 commit comments

Comments
 (0)