Files
StarPilot/openpilot/starpilot/galaxy/web/js/auth-client.js
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

98 lines
4.0 KiB
JavaScript

// Browser-only Galaxy session boundary; never persists passwords or tokens.
import { requestJson } from "./startup.js"
export class LocalAuth {
constructor({ publish, fetcher = (...args) => fetch(...args) }) {
this.publish = publish
this.fetcher = fetcher
this.generation = 0
this.gatewayAccess = false
this.localAccess = false
this.mutationTail = Promise.resolve()
}
update(state, localAccess = false) {
this.localAccess = localAccess
this.publish({ ...state, localAccess })
}
mutate(operation) {
const pending = this.mutationTail.then(operation)
this.mutationTail = pending.then(() => {}, () => {})
return pending
}
async check() {
const generation = ++this.generation
try {
const result = await requestJson("./api/auth/session", { fetcher: this.fetcher })
if (generation !== this.generation) return
this.gatewayAccess = result.gatewayAccess === true
this.publish({ gatewayAccess: this.gatewayAccess })
if (result.state === "unavailable") this.update({ status: "unavailable", error: "Galaxy access is unavailable." })
else if (result.state === "setup_required") this.update({ status: "setup_required", error: "Remote Galaxy access is not configured." })
else if (result.state === "configured") this.update({ status: result.authenticated === true ? "authenticated" : this.gatewayAccess ? "gateway_login" : "login", error: "",
...(this.gatewayAccess ? { gatewayAccess: true } : {}) },
result.authenticated === true && result.localAccess === true)
else throw new Error("Invalid session state")
} catch {
if (generation === this.generation) this.update({ status: "unavailable", error: "Galaxy access could not be checked." })
}
}
login(password) {
if (this.localAccess || this.gatewayAccess) return Promise.resolve(false)
const generation = ++this.generation
return this.mutate(async () => {
try {
const response = await this.fetcher("./api/auth/login", {
method: "POST", credentials: "same-origin", cache: "no-store",
headers: { "Content-Type": "application/json" }, body: JSON.stringify({ password }),
})
if (generation !== this.generation) return false
if (!response.ok) {
if (response.status === 429) this.update({ status: "login", error: "Try again shortly." })
else if (response.status === 503) this.update({ status: "unavailable", error: "Galaxy access is unavailable." })
else this.update({ status: "login", error: "Sign in failed." })
return false
}
this.update({ status: "authenticated", error: "" })
return true
} catch {
if (generation === this.generation) this.update({ status: "login", error: "Sign in could not be completed." })
return false
}
})
}
logout() {
if (this.localAccess || this.gatewayAccess) return Promise.resolve(false)
const generation = ++this.generation
return this.mutate(async () => {
try {
const response = await this.fetcher("./api/auth/logout", {
method: "POST", credentials: "same-origin", cache: "no-store",
headers: { "Content-Type": "application/json" }, body: "{}",
})
if (generation !== this.generation) return false
if (response.status === 401 || response.status === 503) {
this.update({ status: response.status === 503 ? "unavailable" : "login", error: "" })
return false
}
if (!response.ok) throw new Error("Logout failed")
this.update({ status: "login", error: "" })
return true
} catch {
if (generation === this.generation) this.update({ status: "authenticated", error: "Sign out could not be completed." })
return false
}
})
}
expired() {
this.generation++
if (this.localAccess || this.gatewayAccess) this.update({ status: "checking", error: "" })
else this.update({ status: "login", error: "Your Galaxy session expired. Sign in again." })
}
}