Skip to content

Commit c244963

Browse files
committed
chore: sign user out if token expired
1 parent 6947811 commit c244963

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed

Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift

+15-5
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,21 @@ class AppDelegate: NSObject, NSApplicationDelegate {
4040
}
4141

4242
func applicationDidFinishLaunching(_: Notification) {
43-
menuBar = .init(menuBarExtra: FluidMenuBarExtra(title: "Coder Desktop", image: "MenuBarIcon") {
44-
VPNMenu<CoderVPNService>().frame(width: 256)
45-
.environmentObject(self.vpn)
46-
.environmentObject(self.state)
47-
})
43+
menuBar = .init(menuBarExtra: FluidMenuBarExtra(
44+
title: "Coder Desktop",
45+
image: "MenuBarIcon",
46+
onAppear: {
47+
// If the VPN is enabled, it's likely the token isn't expired
48+
guard case .disabled = self.vpn.state, self.state.hasSession else { return }
49+
Task { @MainActor in
50+
await self.state.handleTokenExpiry()
51+
}
52+
}, content: {
53+
VPNMenu<CoderVPNService>().frame(width: 256)
54+
.environmentObject(self.vpn)
55+
.environmentObject(self.state)
56+
}
57+
))
4858
// Subscribe to system VPN updates
4959
NotificationCenter.default.addObserver(
5060
self,

Coder-Desktop/Coder-Desktop/State.swift

+23
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import CoderSDK
22
import Foundation
33
import KeychainAccess
44
import NetworkExtension
5+
import os
56
import SwiftUI
67

78
@MainActor
89
class AppState: ObservableObject {
10+
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "AppState")
911
let appId = Bundle.main.bundleIdentifier!
1012

1113
// Stored in UserDefaults
@@ -95,6 +97,9 @@ class AppState: ObservableObject {
9597
)
9698
if hasSession {
9799
_sessionToken = Published(initialValue: keychainGet(for: Keys.sessionToken))
100+
if sessionToken == nil || sessionToken!.isEmpty == true {
101+
clearSession()
102+
}
98103
}
99104
}
100105

@@ -105,6 +110,24 @@ class AppState: ObservableObject {
105110
reconfigure()
106111
}
107112

113+
public func handleTokenExpiry() async {
114+
if hasSession {
115+
let client = Client(url: baseAccessURL!, token: sessionToken!)
116+
do {
117+
_ = try await client.user("me")
118+
} catch let ClientError.api(apiErr) {
119+
// Expired token
120+
if apiErr.statusCode == 401 {
121+
clearSession()
122+
}
123+
} catch {
124+
// Some other failure, we'll show an error if they try and do something
125+
logger.error("failed to check token validity: \(error)")
126+
return
127+
}
128+
}
129+
}
130+
108131
public func clearSession() {
109132
hasSession = false
110133
sessionToken = nil

Coder-Desktop/CoderSDK/Client.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,10 @@ public struct Client {
104104
}
105105

106106
public struct APIError: Decodable, Sendable {
107-
let response: Response
108-
let statusCode: Int
109-
let method: String
110-
let url: URL
107+
public let response: Response
108+
public let statusCode: Int
109+
public let method: String
110+
public let url: URL
111111

112112
var description: String {
113113
var components = ["\(method) \(url.absoluteString)\nUnexpected status code \(statusCode):\n\(response.message)"]

Coder-Desktop/project.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,12 @@ packages:
9292
url: https://github.com/SimplyDanny/SwiftLintPlugins
9393
from: 0.57.1
9494
FluidMenuBarExtra:
95-
# Forked so we can dynamically update the menu bar icon.
95+
# Forked to:
96+
# - Dynamically update the menu bar icon
97+
# - Set onAppear/disappear handlers.
9698
# The upstream repo has a purposefully limited API
9799
url: https://github.com/coder/fluid-menu-bar-extra
98-
revision: 020be37
100+
revision: 96a861a
99101
KeychainAccess:
100102
url: https://github.com/kishikawakatsumi/KeychainAccess
101103
branch: e0c7eebc5a4465a3c4680764f26b7a61f567cdaf

0 commit comments

Comments
 (0)