mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-13 01:10:45 +08:00
63 lines
2.9 KiB
JavaScript
63 lines
2.9 KiB
JavaScript
/** Host shellEnv adapter. Values are rebuilt after ordinary environment entries. */
|
|
export function createTaskEnvironment({ getOwner, rolesStore, capabilities, getWebServer, allowRawCredentials }) {
|
|
const issued = new Map()
|
|
const release = execution => {
|
|
const key = execution?.token || execution
|
|
const row = issued.get(key)
|
|
if (!row) return
|
|
capabilities.revoke(row.id)
|
|
row.signal?.removeEventListener('abort', row.abort)
|
|
clearTimeout(row.timer)
|
|
row.off?.()
|
|
issued.delete(key)
|
|
}
|
|
const contributor = {
|
|
name: 'uds-auth',
|
|
variables: {
|
|
DSH_UDS_TASK_CAPABILITY: { description: 'Short-lived session-bound UDS capability; never print or persist.' },
|
|
DSH_UDS_AUTH_BASE: { description: 'Owned loopback uds-auth endpoint of this Host.' },
|
|
},
|
|
resolve(execution) {
|
|
release(execution)
|
|
const empty = { DSH_UDS_TASK_CAPABILITY: '', DSH_UDS_AUTH_BASE: '' }
|
|
const sid = execution?.agent?.session?.header?.id
|
|
const owner = sid ? getOwner(String(sid)) : null
|
|
const server = getWebServer()
|
|
const port = Number(server?.port)
|
|
if (!owner || rolesStore.isDisabled(owner) || !Number.isInteger(port) || port <= 0 || port > 65535
|
|
|| execution?.signal?.aborted) return empty
|
|
const scopes = typeof allowRawCredentials === 'function' && allowRawCredentials()
|
|
? ['outbound', 'credentials']
|
|
: ['outbound']
|
|
const cap = capabilities.mint({
|
|
empNo: owner, dshSessionId: String(sid), audience: 'uds-auth-agent',
|
|
scopes, ttlSeconds: 600, mintedBy: 'host:shellEnv',
|
|
})
|
|
const row = { id: cap.id, sessionId: String(sid), signal: execution.signal, abort: () => release(execution) }
|
|
issued.set(execution.token || execution, row)
|
|
row.signal?.addEventListener('abort', row.abort, { once: true })
|
|
row.timer = setTimeout(() => release(execution), cap.expiresAt - Date.now())
|
|
row.timer.unref?.()
|
|
return { DSH_UDS_TASK_CAPABILITY: cap.token, DSH_UDS_AUTH_BASE: `http://127.0.0.1:${port}/uds-auth` }
|
|
},
|
|
}
|
|
return { contributor, release, finish(execution, result, jobs) {
|
|
const row = issued.get(execution?.token || execution)
|
|
const value = result?.value
|
|
if (row && !result?.isError && ['background', 'promoted'].includes(value?.kind)
|
|
&& typeof value.jobId === 'string' && jobs?.events?.subscribe) {
|
|
const job = jobs.list(row.sessionId).find(job => job.id === value.jobId)
|
|
if (job && ['running', 'stopping'].includes(job.status)) {
|
|
row.signal?.removeEventListener('abort', row.abort)
|
|
row.signal = null
|
|
row.off = jobs.events.subscribe({ owner: row.sessionId }, event => {
|
|
if (event.job?.id === value.jobId && ['settled', 'stopping', 'removed'].includes(event.type)) release(execution)
|
|
})
|
|
return
|
|
}
|
|
}
|
|
release(execution)
|
|
}, dispose() {
|
|
for (const key of [...issued.keys()]) release({ token: key })
|
|
} }
|
|
}
|