Skip to content

Commit 687f946

Browse files
committed
chore: sign user out if token expired
1 parent 2094e9f commit 687f946

File tree

4 files changed

+47
-11
lines changed

4 files changed

+47
-11
lines changed

Coder Desktop/Coder Desktop/Coder_DesktopApp.swift

+15-5
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,21 @@ class AppDelegate: NSObject, NSApplicationDelegate {
3737
}
3838

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

Coder Desktop/Coder Desktop/State.swift

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

8+
@MainActor
79
class AppState: ObservableObject {
10+
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "AppState")
811
let appId = Bundle.main.bundleIdentifier!
912

1013
// Stored in UserDefaults
@@ -94,6 +97,9 @@ class AppState: ObservableObject {
9497
)
9598
if hasSession {
9699
_sessionToken = Published(initialValue: keychainGet(for: Keys.sessionToken))
100+
if sessionToken == nil || sessionToken!.isEmpty == true {
101+
clearSession()
102+
}
97103
}
98104
}
99105

@@ -104,6 +110,24 @@ class AppState: ObservableObject {
104110
reconfigure()
105111
}
106112

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+
107131
public func clearSession() {
108132
hasSession = false
109133
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
@@ -89,10 +89,12 @@ packages:
8989
url: https://github.com/SimplyDanny/SwiftLintPlugins
9090
from: 0.57.1
9191
FluidMenuBarExtra:
92-
# Forked so we can dynamically update the menu bar icon.
92+
# Forked to:
93+
# - Dynamically update the menu bar icon
94+
# - Set onAppear/disappear handlers.
9395
# The upstream repo has a purposefully limited API
9496
url: https://github.com/coder/fluid-menu-bar-extra
95-
revision: 020be37
97+
revision: 96a861a
9698
KeychainAccess:
9799
url: https://github.com/kishikawakatsumi/KeychainAccess
98100
branch: e0c7eebc5a4465a3c4680764f26b7a61f567cdaf

0 commit comments

Comments
 (0)