Files
StarPilot/openpilot/starpilot/galaxy/tests/test_auth_client.mjs
T
firestar5683 fab3ec9aeb Galaxy UI
Add Galaxy web assets and client settings interfaces with their bundled vendor notices.

Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>

Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 19:56:17 -05:00

213 lines
9.7 KiB
JavaScript

import assert from "node:assert/strict"
import { LocalAuth } from "../web/js/auth-client.js"
import { MonitorFeed } from "../web/js/monitor-feed.js"
import { readFileSync } from "node:fs"
const states = [], calls = []
const responses = [
{ ok: true, body: { state: "configured", authenticated: false } },
{ ok: false, status: 401 },
{ ok: true, body: { authenticated: true } },
{ ok: true, body: { authenticated: false } },
]
const auth = new LocalAuth({ publish: (state) => states.push(state), fetcher: async (url, options) => {
calls.push({ url, options })
const response = responses.shift()
return { ok: response.ok, status: response.status ?? 200, json: async () => response.body }
} })
await auth.check()
assert.equal(states.at(-1).status, "login")
assert.equal(await auth.login("wrongpass"), false)
assert.equal(states.at(-1).error, "Sign in failed.")
assert.equal(await auth.login("correctpass"), true)
assert.equal(states.at(-1).status, "authenticated")
assert.equal(calls[2].options.credentials, "same-origin")
assert.equal(calls[2].options.headers["Content-Type"], "application/json")
assert.equal(await auth.logout(), true)
assert.equal(states.at(-1).status, "login")
assert.equal(calls[3].options.body, "{}")
const setup = new LocalAuth({ publish: (state) => states.push(state), fetcher: async () =>
({ ok: true, json: async () => ({ state: "setup_required", authenticated: false }) }) })
await setup.check()
assert.equal(states.at(-1).status, "setup_required")
const unavailable = new LocalAuth({ publish: (state) => states.push(state), fetcher: async () =>
({ ok: true, json: async () => ({ state: "unavailable", authenticated: false }) }) })
await unavailable.check()
assert.equal(states.at(-1).status, "unavailable")
let unauthorized = 0
const samples = []
const feed = new MonitorFeed({ mode: "local", publish: (state) => samples.push(state), unauthorized: () => unauthorized++,
fetcher: async () => ({ ok: false, status: 401 }) })
feed.start()
for (let i = 0; i < 5; i++) await Promise.resolve()
assert.equal(unauthorized, 1)
assert.equal(samples.at(-1).snapshot, null)
assert.equal(feed.stopped, true)
assert.equal(feed.timer, null)
const accessLostStates = []
let accessLost = 0
const accessLostFeed = new MonitorFeed({ mode: "local", publish: (state) => accessLostStates.push(state),
unauthorized: () => accessLost++, fetcher: async () => ({ ok: false, status: 503, json: async () => ({ code: "setup_required" }) }) })
accessLostFeed.start()
for (let i = 0; i < 5; i++) await Promise.resolve()
assert.equal(accessLost, 1)
assert.equal(accessLostStates.at(-1).snapshot, null)
assert.equal(accessLostFeed.stopped, true)
const lostLogoutStates = []
const lostLogout = new LocalAuth({ publish: (state) => lostLogoutStates.push(state), fetcher: async () => ({ ok: false, status: 401 }) })
assert.equal(await lostLogout.logout(), false)
assert.equal(lostLogoutStates.at(-1).status, "login")
const previewCalls = []
const preview = new MonitorFeed({ mode: "sample", publish: () => {}, fetcher: async (url) => {
previewCalls.push(url)
return { ok: false, status: 404 }
} })
preview.start()
for (let i = 0; i < 5; i++) await Promise.resolve()
assert.deepEqual(previewCalls, ["./data/system-monitor.sample.json"])
preview.stop()
const deferred = () => { let resolve; const promise = new Promise((done) => { resolve = done }); return { promise, resolve } }
const flush = async () => { for (let i = 0; i < 10; i++) await Promise.resolve() }
// A slow session check may not replace a completed sign-in.
const oldCheck = deferred(), raceStates = []
const race = new LocalAuth({ publish: (state) => raceStates.push(state), fetcher: (url) =>
url.endsWith("session") ? oldCheck.promise : Promise.resolve({ ok: true, json: async () => ({ authenticated: true }) }) })
const checking = race.check()
assert.equal(await race.login("password123"), true)
oldCheck.resolve({ ok: true, json: async () => ({ state: "configured", authenticated: false }) })
await checking
assert.equal(raceStates.at(-1).status, "authenticated")
// Two successful sign-ins execute in order and only the latest publishes state.
const first = deferred(), second = deferred(), signStates = []
let loginNumber = 0
const sign = new LocalAuth({ publish: (state) => signStates.push(state), fetcher: (url) => {
if (url.endsWith("login")) return ++loginNumber === 1 ? first.promise : second.promise
return Promise.resolve({ ok: true })
} })
const firstLogin = sign.login("first-password")
const secondLogin = sign.login("second-password")
await flush()
assert.equal(loginNumber, 1)
first.resolve({ ok: true })
assert.equal(await firstLogin, false)
await flush()
assert.equal(loginNumber, 2)
second.resolve({ ok: true })
assert.equal(await secondLogin, true)
assert.equal(signStates.at(-1).status, "authenticated")
const waitingLogin = deferred(), waitingLogout = deferred(), logoutStates = [], logoutCalls = []
const serialized = new LocalAuth({ publish: (state) => logoutStates.push(state), fetcher: (url) => {
logoutCalls.push(url)
return url.endsWith("login") ? waitingLogin.promise : waitingLogout.promise
} })
const pendingSignIn = serialized.login("password123")
const pendingSignOut = serialized.logout()
await flush()
assert.deepEqual(logoutCalls, ["./api/auth/login"])
waitingLogin.resolve({ ok: true })
await pendingSignIn
await flush()
assert.deepEqual(logoutCalls, ["./api/auth/login", "./api/auth/logout"])
waitingLogout.resolve({ ok: true })
assert.equal(await pendingSignOut, true)
assert.equal(logoutStates.at(-1).status, "login")
// A login requested while logout waits must run after logout's cookie mutation.
const queuedLogin1 = deferred(), queuedLogout = deferred(), queuedLogin2 = deferred()
const orderedCalls = [], orderedStates = []
let orderedLoginNumber = 0
const ordered = new LocalAuth({ publish: (state) => orderedStates.push(state), fetcher: (url) => {
orderedCalls.push(url)
if (url.endsWith("login")) return ++orderedLoginNumber === 1 ? queuedLogin1.promise : queuedLogin2.promise
return queuedLogout.promise
} })
const orderedFirst = ordered.login("first-password")
const orderedSignOut = ordered.logout()
const orderedSecond = ordered.login("second-password")
await flush()
assert.deepEqual(orderedCalls, ["./api/auth/login"])
queuedLogin1.resolve({ ok: true })
assert.equal(await orderedFirst, false)
await flush()
assert.deepEqual(orderedCalls, ["./api/auth/login", "./api/auth/logout"])
queuedLogout.resolve({ ok: true })
assert.equal(await orderedSignOut, false)
await flush()
assert.deepEqual(orderedCalls, ["./api/auth/login", "./api/auth/logout", "./api/auth/login"])
queuedLogin2.resolve({ ok: true })
assert.equal(await orderedSecond, true)
assert.deepEqual(orderedStates, [{ status: "authenticated", error: "", localAccess: false }])
const localStates = [], localCalls = []
let localSession = { state: "configured", authenticated: true, localAccess: true }
const local = new LocalAuth({ publish: (state) => localStates.push(state), fetcher: async (url) => {
localCalls.push(url)
return { ok: true, json: async () => localSession }
} })
await local.check()
assert.deepEqual(localStates.at(-1), { status: "authenticated", error: "", localAccess: true })
assert.equal(await local.login("unused"), false)
assert.equal(await local.logout(), false)
assert.deepEqual(localCalls, ["./api/auth/session"])
assert.equal(localStates.at(-1).status, "authenticated")
local.expired()
assert.deepEqual(localStates.at(-1), { status: "checking", error: "", localAccess: false })
await local.check()
assert.equal(localStates.at(-1).localAccess, true)
assert.equal(localStates.at(-1).status, "authenticated")
localSession = { state: "configured", authenticated: false, localAccess: false }
await local.check()
assert.deepEqual(localStates.at(-1), { status: "login", error: "", localAccess: false })
localSession = { state: "configured", authenticated: false, localAccess: true }
await local.check()
assert.equal(localStates.at(-1).status, "login")
assert.equal(localStates.at(-1).localAccess, false)
localSession = { state: "configured", authenticated: true, localAccess: "true" }
await local.check()
assert.equal(localStates.at(-1).localAccess, false)
const app = readFileSync(new URL("../web/js/app.js", import.meta.url), "utf8")
assert.match(app, /authState\.status === 'authenticated' && !authState\.localAccess/)
assert.match(app, /state\.monitorMode === 'local' && authState\.status !== 'authenticated'/)
assert.match(app, /sessionExpired\(\) \{ if \(initializing\) return; auth\.expired\(\); initialize\(\) \}/)
const oldMonitor = deferred(), nextMonitor = deferred(), lateStates = []
let lateUnauthorized = 0, monitorRequests = 0
const lateFeed = new MonitorFeed({ mode: "local", publish: (state) => lateStates.push(state),
unauthorized: () => lateUnauthorized++, fetcher: () => ++monitorRequests === 1 ? oldMonitor.promise : nextMonitor.promise })
lateFeed.start()
lateFeed.stop()
lateFeed.start()
oldMonitor.resolve({ ok: false, status: 401 })
await flush()
assert.equal(lateUnauthorized, 0)
assert.equal(lateFeed.stopped, false)
assert.equal(lateStates.length, 0)
lateFeed.stop()
console.log("Galaxy browser auth, expiry and static-preview isolation checks passed")
const gatewayStates = [], gatewayCalls = []
let gatewayAuthenticated = true
const gateway = new LocalAuth({ publish: value => gatewayStates.push(value), fetcher: async (path) => {
gatewayCalls.push(path)
return { ok: true, json: async () => ({ state: "configured", authenticated: gatewayAuthenticated, gatewayAccess: true }) }
} })
await gateway.check()
assert.equal(gatewayStates.at(-1).status, "authenticated")
assert.equal(gatewayStates.at(-1).gatewayAccess, true)
assert.equal(await gateway.login("never-submit-to-device"), false)
assert.equal(await gateway.logout(), false)
assert.deepEqual(gatewayCalls, ["./api/auth/session"])
gatewayAuthenticated = false
await gateway.check()
assert.equal(gatewayStates.at(-1).status, "gateway_login")