spb/zyquo-router Public MIT
One local endpoint, every AI provider — a private OpenAI-compatible LLM gateway for your Mac (170 models, 12 providers).
Swift 95.7%
Python 2.3%
Shell 1.2%
Makefile 0.9%
1//2// AuthMiddlewareTests.swift3// Zyquo Router4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// Local API key gate: open with no keys, valid / invalid / revoked tokens,9// malformed Authorization headers.10//1112import NIOHTTP113import XCTest14@testable import ZyquoRouter1516final class AuthMiddlewareTests: XCTestCase {17 private func request(authorization: String?) -> RouteRequest {18 var headers = HTTPHeaders()19 if let authorization {20 headers.add(name: "Authorization", value: authorization)21 }22 return RouteRequest(method: .POST, uri: "/v1/chat/completions", headers: headers, body: Data())23 }2425 func testOpenWhenNoKeysConfigured() {26 let auth = AuthMiddleware(keys: [])27 guard case .allowed(nil) = auth.authorize(request(authorization: nil)) else {28 return XCTFail("no keys ⇒ open on localhost")29 }30 }3132 func testTokenLifecycle() {33 var (record, token) = APIKeyRecord.generate(name: "test")34 let auth = AuthMiddleware(keys: [record])3536 guard case .allowed(let matched) = auth.authorize(request(authorization: "Bearer \(token)")),37 matched?.name == "test" else {38 return XCTFail("valid token must pass and carry its record")39 }40 guard case .unauthorized = auth.authorize(request(authorization: "Bearer zyquo-sk-wrong")) else {41 return XCTFail("unknown token must 401")42 }43 guard case .unauthorized = auth.authorize(request(authorization: nil)) else {44 return XCTFail("missing header must 401 when keys exist")45 }46 guard case .unauthorized = auth.authorize(request(authorization: "Basic abc")) else {47 return XCTFail("non-bearer scheme must 401")48 }4950 // Revocation (disabled key keeps its hash but must be rejected).51 record.enabled = false52 let revoked = AuthMiddleware(keys: [record])53 guard case .unauthorized(let message) = revoked.authorize(request(authorization: "Bearer \(token)")),54 message.contains("revoked") else {55 return XCTFail("revoked token must 401 with a revocation message")56 }57 }5859 func testTokenHashIsStoredNotPlaintext() {60 let (record, token) = APIKeyRecord.generate(name: "x")61 XCTAssertFalse(record.tokenHash.contains(token))62 XCTAssertEqual(record.tokenHash, APIKeyRecord.hash(token))63 XCTAssertEqual(record.tokenPrefix.count, 12)64 }65}66