mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-03 10:55:54 +00:00
Add local bypass
This commit is contained in:
parent
fff51301cf
commit
bb6934de5d
4 changed files with 84 additions and 21 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import Foundation
|
||||
import OSLog
|
||||
import CryptoKit
|
||||
|
||||
/// Server state enumeration
|
||||
enum ServerState {
|
||||
|
|
@ -44,6 +45,21 @@ final class BunServer {
|
|||
var port: String = ""
|
||||
|
||||
var bindAddress: String = "127.0.0.1"
|
||||
|
||||
/// Local authentication token for bypassing auth on localhost
|
||||
private let localAuthToken: String = {
|
||||
// Generate a secure random token for this session
|
||||
let randomData = Data((0..<32).map { _ in UInt8.random(in: 0...255) })
|
||||
return randomData.base64EncodedString()
|
||||
.replacingOccurrences(of: "+", with: "-")
|
||||
.replacingOccurrences(of: "/", with: "_")
|
||||
.replacingOccurrences(of: "=", with: "")
|
||||
}()
|
||||
|
||||
/// Get the local auth token for use in HTTP requests
|
||||
var localToken: String {
|
||||
localAuthToken
|
||||
}
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
|
|
@ -150,6 +166,13 @@ final class BunServer {
|
|||
// OS authentication is the default, no special flags needed
|
||||
break
|
||||
}
|
||||
|
||||
// Add local bypass authentication for the Mac app
|
||||
if authMode != "none" {
|
||||
// Enable local bypass with our generated token
|
||||
vibetunnelArgs += " --allow-local-bypass --local-auth-token \(localAuthToken)"
|
||||
logger.info("Local authentication bypass enabled for Mac app")
|
||||
}
|
||||
|
||||
// Create wrapper to run vibetunnel with a parent death signal
|
||||
// Using a subshell that monitors parent process and kills vibetunnel if parent dies
|
||||
|
|
|
|||
|
|
@ -224,6 +224,9 @@ class ServerManager {
|
|||
}
|
||||
|
||||
logger.info("Started server on port \(self.port)")
|
||||
|
||||
// Pass the local auth token to SessionMonitor
|
||||
SessionMonitor.shared.setLocalAuthToken(server.localToken)
|
||||
|
||||
// Trigger cleanup of old sessions after server starts
|
||||
await triggerInitialCleanup()
|
||||
|
|
@ -253,6 +256,9 @@ class ServerManager {
|
|||
await server.stop()
|
||||
bunServer = nil
|
||||
isRunning = false
|
||||
|
||||
// Clear the auth token from SessionMonitor
|
||||
SessionMonitor.shared.setLocalAuthToken(nil)
|
||||
|
||||
// Reset crash tracking when manually stopped
|
||||
consecutiveCrashes = 0
|
||||
|
|
@ -316,6 +322,11 @@ class ServerManager {
|
|||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.timeoutInterval = 10
|
||||
|
||||
// Add local auth token if available
|
||||
if let server = bunServer {
|
||||
request.setValue(server.localToken, forHTTPHeaderField: "X-VibeTunnel-Local")
|
||||
}
|
||||
|
||||
// Make the cleanup request
|
||||
let (data, response) = try await URLSession.shared.data(for: request)
|
||||
|
|
|
|||
|
|
@ -29,11 +29,17 @@ final class SessionMonitor {
|
|||
private var lastFetch: Date?
|
||||
private let cacheInterval: TimeInterval = 2.0
|
||||
private let serverPort: Int
|
||||
private var localAuthToken: String?
|
||||
|
||||
private init() {
|
||||
let port = UserDefaults.standard.integer(forKey: "serverPort")
|
||||
self.serverPort = port > 0 ? port : 4_020
|
||||
}
|
||||
|
||||
/// Set the local auth token for server requests
|
||||
func setLocalAuthToken(_ token: String?) {
|
||||
self.localAuthToken = token
|
||||
}
|
||||
|
||||
/// Number of running sessions
|
||||
var sessionCount: Int {
|
||||
|
|
@ -69,7 +75,13 @@ final class SessionMonitor {
|
|||
throw URLError(.badURL)
|
||||
}
|
||||
|
||||
let request = URLRequest(url: url, timeoutInterval: 3.0)
|
||||
var request = URLRequest(url: url, timeoutInterval: 3.0)
|
||||
|
||||
// Add local auth token if available
|
||||
if let token = localAuthToken {
|
||||
request.setValue(token, forHTTPHeaderField: "X-VibeTunnel-Local")
|
||||
}
|
||||
|
||||
let (data, response) = try await URLSession.shared.data(for: request)
|
||||
|
||||
guard let httpResponse = response as? HTTPURLResponse,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,43 @@ struct DashboardSettingsView: View {
|
|||
restartServerWithNewPort: restartServerWithNewPort,
|
||||
serverManager: serverManager
|
||||
)
|
||||
|
||||
// Dashboard URL display
|
||||
VStack(spacing: 4) {
|
||||
if accessMode == .localhost {
|
||||
HStack(spacing: 5) {
|
||||
Text("Dashboard available at")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
if let url = URL(string: "http://127.0.0.1:\(serverPort)") {
|
||||
Link(url.absoluteString, destination: url)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.blue)
|
||||
}
|
||||
}
|
||||
} else if accessMode == .network {
|
||||
if let ip = localIPAddress {
|
||||
HStack(spacing: 5) {
|
||||
Text("Dashboard available at")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
if let url = URL(string: "http://\(ip):\(serverPort)") {
|
||||
Link(url.absoluteString, destination: url)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.blue)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("Fetching local IP address...")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 8)
|
||||
|
||||
NgrokIntegrationSection(
|
||||
ngrokEnabled: $ngrokEnabled,
|
||||
|
|
@ -427,26 +464,6 @@ private struct AccessModeView: View {
|
|||
restartServerWithNewBindAddress()
|
||||
}
|
||||
}
|
||||
|
||||
if accessMode == .network {
|
||||
if let ip = localIPAddress {
|
||||
HStack {
|
||||
Text("Dashboard available at")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
if let url = URL(string: "http://\(ip):\(serverPort)") {
|
||||
Link(url.absoluteString, destination: url)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.blue)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("Fetching local IP address...")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue