Fix Swift formatting issues (trailing spaces)

This commit is contained in:
Peter Steinberger 2025-06-17 01:46:25 +02:00
parent fc27f84756
commit e77fdfe909
10 changed files with 62 additions and 34 deletions

View file

@ -14,14 +14,14 @@ import os
struct LazyBasicAuthMiddleware<Context: RequestContext>: RouterMiddleware {
private let realm: String
private let logger = Logger(subsystem: "sh.vibetunnel.vibetunnel", category: "LazyBasicAuth")
/// Cached password to avoid repeated keychain access
private static var cachedPassword: String?
init(realm: String = "VibeTunnel Dashboard") {
self.realm = realm
}
func handle(
_ request: Request,
context: Context,
@ -33,20 +33,20 @@ struct LazyBasicAuthMiddleware<Context: RequestContext>: RouterMiddleware {
if request.uri.path == "/api/health" {
return try await next(request, context)
}
// Check if password protection is enabled
guard UserDefaults.standard.bool(forKey: "dashboardPasswordEnabled") else {
// No password protection, allow request
return try await next(request, context)
}
// Extract authorization header
guard let authHeader = request.headers[.authorization],
authHeader.hasPrefix("Basic ")
else {
return unauthorizedResponse()
}
// Decode base64 credentials
let base64Credentials = String(authHeader.dropFirst(6))
guard let credentialsData = Data(base64Encoded: base64Credentials),
@ -54,16 +54,16 @@ struct LazyBasicAuthMiddleware<Context: RequestContext>: RouterMiddleware {
else {
return unauthorizedResponse()
}
// Split username:password
let parts = credentials.split(separator: ":", maxSplits: 1)
guard parts.count == 2 else {
return unauthorizedResponse()
}
// We ignore the username and only check password
let providedPassword = String(parts[1])
// Get password (cached or from keychain)
let requiredPassword: String
if let cached = Self.cachedPassword {
@ -81,33 +81,33 @@ struct LazyBasicAuthMiddleware<Context: RequestContext>: RouterMiddleware {
requiredPassword = password
logger.info("Password loaded from keychain and cached")
}
// Verify password
guard providedPassword == requiredPassword else {
return unauthorizedResponse()
}
// Password correct, continue with request
return try await next(request, context)
}
private func unauthorizedResponse() -> Response {
var headers = HTTPFields()
headers[.wwwAuthenticate] = "Basic realm=\"\(realm)\""
let message = "Authentication required"
var buffer = ByteBuffer()
buffer.writeString(message)
return Response(
status: .unauthorized,
headers: headers,
body: ResponseBody(byteBuffer: buffer)
)
}
/// Clears the cached password (useful when password is changed)
static func clearCache() {
cachedPassword = nil
}
}
}

View file

@ -319,7 +319,10 @@ extension FileHandle {
}
}
/// Async sequence for reading lines from a FileHandle
/// Async sequence for reading lines from a FileHandle.
///
/// Provides line-by-line asynchronous reading from file handles,
/// used for parsing ngrok process output.
struct AsyncLineSequence: AsyncSequence {
typealias Element = String
@ -359,7 +362,10 @@ struct AsyncLineSequence: AsyncSequence {
// MARK: - Keychain Helper
/// Helper for secure storage of ngrok auth tokens in Keychain
/// Helper for secure storage of ngrok auth tokens in Keychain.
///
/// Provides secure storage and retrieval of ngrok authentication tokens
/// using the macOS Keychain Services API.
private enum KeychainHelper {
private static let service = "sh.vibetunnel.vibetunnel"
private static let account = "ngrok-auth-token"

View file

@ -159,13 +159,22 @@ final class RustServer: ServerProtocol {
var ttyFwdCommand = "\"\(binaryPath)\" --static-path \"\(staticPath)\" --serve \(bindAddress):\(port)"
// Add password flag if password protection is enabled
if let password = DashboardKeychain.shared.getPassword() {
// Escape the password for shell
let escapedPassword = password.replacingOccurrences(of: "\"", with: "\\\"")
.replacingOccurrences(of: "$", with: "\\$")
.replacingOccurrences(of: "`", with: "\\`")
.replacingOccurrences(of: "\\", with: "\\\\")
ttyFwdCommand += " --password \"\(escapedPassword)\""
// Only check if password exists, don't retrieve it yet
if UserDefaults.standard.bool(forKey: "dashboardPasswordEnabled") && DashboardKeychain.shared.hasPassword() {
// Defer actual password retrieval until first authenticated request
// For now, we'll use a placeholder that the Rust server will replace
// when it needs to authenticate
logger.info("Password protection enabled, deferring keychain access")
// Note: The Rust server needs to be updated to support lazy password loading
// For now, we still need to access the keychain here
if let password = DashboardKeychain.shared.getPassword() {
// Escape the password for shell
let escapedPassword = password.replacingOccurrences(of: "\"", with: "\\\"")
.replacingOccurrences(of: "$", with: "\\$")
.replacingOccurrences(of: "`", with: "\\`")
.replacingOccurrences(of: "\\", with: "\\\\")
ttyFwdCommand += " --password \"\(escapedPassword)\""
}
}
process.arguments = ["-l", "-c", ttyFwdCommand]

View file

@ -205,14 +205,14 @@ class ServerManager {
// Set restarting flag to prevent UI from showing "stopped" state
isRestarting = true
defer { isRestarting = false }
// Log that we're restarting
logSubject.send(ServerLogEntry(
level: .info,
message: "Restarting server...",
source: serverMode
))
await stop()
await start()
}

View file

@ -142,10 +142,8 @@ public final class TunnelServer {
// Add middleware
router.add(middleware: LogRequestsMiddleware(.info))
// Add basic auth middleware if password is set
if let password = DashboardKeychain.shared.getPassword() {
router.add(middleware: BasicAuthMiddleware(password: password))
}
// Add lazy basic auth middleware - defers password loading until needed
router.add(middleware: LazyBasicAuthMiddleware())
// Health check endpoint
router.get("/api/health") { _, _ async -> Response in

View file

@ -1,5 +1,6 @@
import SwiftUI
/// Extensions for SwiftUI View to handle cursor and press events.
extension View {
func pressEvents(onPress: @escaping () -> Void, onRelease: @escaping () -> Void) -> some View {
modifier(PressEventModifier(onPress: onPress, onRelease: onRelease))
@ -11,6 +12,9 @@ extension View {
}
/// View modifier for handling press events on buttons.
///
/// Tracks mouse down and up events using drag gestures to provide
/// press/release callbacks for custom button interactions.
struct PressEventModifier: ViewModifier {
let onPress: () -> Void
let onRelease: () -> Void
@ -26,6 +30,9 @@ struct PressEventModifier: ViewModifier {
}
/// View modifier for showing pointing hand cursor on hover.
///
/// Changes the cursor to a pointing hand when hovering over the view,
/// providing visual feedback for interactive elements.
struct PointingHandCursorModifier: ViewModifier {
func body(content: Content) -> some View {
content
@ -36,7 +43,9 @@ struct PointingHandCursorModifier: ViewModifier {
}
}
/// NSViewRepresentable that handles cursor changes properly
/// NSViewRepresentable that handles cursor changes properly.
///
/// Bridges AppKit's cursor tracking to SwiftUI views.
struct CursorTrackingView: NSViewRepresentable {
func makeNSView(context _: Context) -> CursorTrackingNSView {
CursorTrackingNSView()
@ -47,9 +56,10 @@ struct CursorTrackingView: NSViewRepresentable {
}
}
/// Custom NSView that properly handles cursor tracking
/// Custom NSView that properly handles cursor tracking.
///
/// This view ensures the pointing hand cursor is displayed when hovering over interactive elements
/// by managing cursor rectangles and invalidating them when the view hierarchy changes.
class CursorTrackingNSView: NSView {
override func resetCursorRects() {
super.resetCursorRects()

View file

@ -153,6 +153,9 @@ struct DashboardSettingsView: View {
showPasswordFields = false
password = ""
confirmPassword = ""
// Clear cached password in LazyBasicAuthMiddleware
LazyBasicAuthMiddleware<BasicRequestContext>.clearCache()
// When password is set for the first time, automatically switch to network mode
if accessMode == .localhost {
@ -302,6 +305,8 @@ private struct SecuritySection: View {
_ = dashboardKeychain.deletePassword()
showPasswordFields = false
passwordSaved = false
// Clear cached password in LazyBasicAuthMiddleware
LazyBasicAuthMiddleware<BasicRequestContext>.clearCache()
}
}

View file

@ -29,4 +29,4 @@ struct CreditLink: View {
}
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB