mirror of
https://github.com/hansjone/dsh-ops-cron.git
synced 2026-10-08 23:20:45 +08:00
Make uds-auth optional: standalone local mode for cron.
Without udsAuth, trusted HTTP uses a synthetic __local__ viewer that sees all jobs; with uds-auth, keep multi-user empNo isolation and admin folders. Document that IM channels are not default UDS accounts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
1c504eb1fd
commit
933bad9201
8 changed files with 132 additions and 27 deletions
|
|
@ -916,6 +916,47 @@ test('GET /jobs claims unassigned jobs that match viewer cwd', async (t) => {
|
|||
assert.equal(listed.body.jobs[0].ownerEmpNo, 'tester')
|
||||
})
|
||||
|
||||
|
||||
test('HTTP works standalone without uds-auth (local mode)', async (t) => {
|
||||
const dir = await mkdtemp(join(tmpdir(), 'dsh-ops-cron-local-'))
|
||||
t.after(() => rm(dir, { recursive: true, force: true }))
|
||||
const service = createHostService({
|
||||
filePath: join(dir, 'store.json'),
|
||||
now: () => Date.parse('2026-08-24T01:00:00.000Z'),
|
||||
sessionPort: {
|
||||
async createAndPrompt() {
|
||||
return { sessionId: 'local-sess', status: 'succeeded', summary: 'ok' }
|
||||
},
|
||||
async archiveSession() {},
|
||||
},
|
||||
getUdsAuth: () => undefined,
|
||||
})
|
||||
const http = await listen(service)
|
||||
t.after(() => http.close())
|
||||
|
||||
const created = await jsonRequest(http.url, '/dsh-ops-cron/jobs', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name: 'local job',
|
||||
prompt: 'ping',
|
||||
schedule: { kind: 'cron', expr: '0 9 * * *', timezone: 'UTC' },
|
||||
}),
|
||||
})
|
||||
assert.equal(created.status, 200)
|
||||
assert.equal(created.body.job.name, 'local job')
|
||||
assert.ok(!created.body.job.ownerEmpNo || created.body.job.ownerEmpNo === '__unassigned__')
|
||||
|
||||
const listed = await jsonRequest(http.url, '/dsh-ops-cron/jobs')
|
||||
assert.equal(listed.status, 200)
|
||||
assert.equal(listed.body.viewer.mode, 'local')
|
||||
assert.equal(listed.body.viewer.canViewAll, true)
|
||||
assert.equal(listed.body.jobs.length, 1)
|
||||
|
||||
const ran = await jsonRequest(http.url, `/dsh-ops-cron/jobs/${created.body.job.id}/run`, { method: 'POST' })
|
||||
assert.equal(ran.status, 200)
|
||||
assert.equal(ran.body.run.sessionId, 'local-sess')
|
||||
})
|
||||
|
||||
test('migrateJobOwners assigns unassigned for legacy jobs', async () => {
|
||||
const { migrateJobOwners, UNASSIGNED_OWNER } = await import('../lib/ownership.js')
|
||||
const state = {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ import {
|
|||
filterJobsForIdentity,
|
||||
filterRunsForJobs,
|
||||
inferOwnerEmpNo,
|
||||
isMultiUserIdentity,
|
||||
jobVisibleToIdentity,
|
||||
LOCAL_EMP_NO,
|
||||
localIdentity,
|
||||
migrateJobOwners,
|
||||
UNASSIGNED_OWNER,
|
||||
viewerPayload,
|
||||
|
|
@ -73,6 +76,23 @@ test('viewerPayload', () => {
|
|||
assert.equal(v.empNo, 'u1')
|
||||
assert.equal(v.canViewAll, false)
|
||||
assert.equal(v.workspacePath, '/w/u1')
|
||||
assert.equal(v.mode, 'multi')
|
||||
})
|
||||
|
||||
test('standalone local identity sees all jobs including unassigned', () => {
|
||||
const local = localIdentity()
|
||||
assert.equal(isMultiUserIdentity(local), false)
|
||||
assert.equal(local.empNo, LOCAL_EMP_NO)
|
||||
assert.equal(canViewAllJobs(local), true)
|
||||
assert.equal(jobVisibleToIdentity({ ownerEmpNo: UNASSIGNED_OWNER }, local), true)
|
||||
assert.equal(jobVisibleToIdentity({ ownerEmpNo: 'u2' }, local), true)
|
||||
const payload = viewerPayload(local)
|
||||
assert.equal(payload.mode, 'local')
|
||||
assert.equal(payload.canViewAll, true)
|
||||
assert.deepEqual(
|
||||
filterJobsForIdentity([{ id: '1', ownerEmpNo: 'u1' }, { id: '2', ownerEmpNo: UNASSIGNED_OWNER }], local).map((j) => j.id),
|
||||
['1', '2'],
|
||||
)
|
||||
})
|
||||
|
||||
test('claimUnassignedForViewer claims by session owner or user-workspaces cwd', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue