feat: require owner login and add onboarding
This commit is contained in:
@@ -4,7 +4,11 @@ type Snapshot = { configured: boolean; run: ResearchRun | null }
|
||||
type Subscribe = (listener: (snapshot: Snapshot) => void) => () => void
|
||||
|
||||
/** Subscribe to current state and subsequent changes; disconnect only this viewer. */
|
||||
export function researchEvents(request: Request, subscribe: Subscribe) {
|
||||
export function researchEvents(
|
||||
request: Request,
|
||||
subscribe: Subscribe,
|
||||
isAuthorized: () => boolean = () => true,
|
||||
) {
|
||||
const encoder = new TextEncoder()
|
||||
let dispose = () => {}
|
||||
let flushPending = () => {}
|
||||
@@ -14,7 +18,15 @@ export function researchEvents(request: Request, subscribe: Subscribe) {
|
||||
let closed = false
|
||||
let unsubscribe = () => {}
|
||||
let heartbeat: ReturnType<typeof setInterval> | undefined
|
||||
const checkSession = () => {
|
||||
if (closed) return false
|
||||
if (isAuthorized()) return true
|
||||
dispose()
|
||||
controller.close()
|
||||
return false
|
||||
}
|
||||
const flush = () => {
|
||||
if (!checkSession()) return
|
||||
if (
|
||||
!closed &&
|
||||
pending !== undefined &&
|
||||
@@ -46,7 +58,12 @@ export function researchEvents(request: Request, subscribe: Subscribe) {
|
||||
pending = `data: ${JSON.stringify(snapshot)}\n\n`
|
||||
flush()
|
||||
})
|
||||
if (closed) {
|
||||
unsubscribe()
|
||||
return
|
||||
}
|
||||
heartbeat = setInterval(() => {
|
||||
if (!checkSession()) return
|
||||
if (
|
||||
!closed &&
|
||||
pending === undefined &&
|
||||
|
||||
@@ -81,3 +81,25 @@ it('bounds a slow viewer buffer while retaining the latest state', async () => {
|
||||
)
|
||||
await reader.cancel()
|
||||
})
|
||||
|
||||
it('stops sending updates when its login session is revoked', async () => {
|
||||
let authorized = true
|
||||
let emit = (_value: { configured: boolean; run: null }) => {}
|
||||
const unsubscribe = vi.fn()
|
||||
const response = researchEvents(
|
||||
new Request('http://127.0.0.1/events'),
|
||||
(listener) => {
|
||||
emit = listener
|
||||
listener({ configured: false, run: null })
|
||||
return unsubscribe
|
||||
},
|
||||
() => authorized,
|
||||
)
|
||||
const reader = response.body?.getReader()
|
||||
expect.assert.isDefined(reader)
|
||||
await reader.read()
|
||||
authorized = false
|
||||
emit({ configured: true, run: null })
|
||||
expect((await reader.read()).done).toBe(true)
|
||||
expect(unsubscribe).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user