mirror of
https://github.com/hansjone/dsh-ops-cron.git
synced 2026-10-10 03:20:46 +08:00
Stamp and reclaim chat-created cron jobs for the current user.
Tool creates often left ownerEmpNo unassigned so the sidebar hid them while runs still fired; infer identity from session/cwd, claim legacy orphans on list, and keep cron rows visible without leaking run sessions into the workspace list. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d298c77f3f
commit
a0dc070372
7 changed files with 254 additions and 25 deletions
56
lib/host.js
56
lib/host.js
|
|
@ -26,6 +26,7 @@ import {
|
|||
import {
|
||||
assertCanAccessJob,
|
||||
canViewAllJobs,
|
||||
claimUnassignedForViewer,
|
||||
filterJobsForIdentity,
|
||||
filterRunsForJobs,
|
||||
migrateJobOwners,
|
||||
|
|
@ -79,6 +80,40 @@ function parseCookieHeader(header, name) {
|
|||
}
|
||||
|
||||
|
||||
function empNoFromUserWorkspacePath(cwd) {
|
||||
const norm = String(cwd || '').replace(/\\/g, '/')
|
||||
const match = norm.match(/\/user-workspaces\/([^/]+)(?:\/|$)/)
|
||||
return match ? decodeURIComponent(match[1]) : null
|
||||
}
|
||||
|
||||
function inferIdentityFromJobInput(input, getUdsAuth) {
|
||||
const uds = typeof getUdsAuth === 'function' ? getUdsAuth() : null
|
||||
if (!uds) return null
|
||||
const origin = input?.origin
|
||||
const sessionId = origin?.kind === 'web' && typeof origin.sessionId === 'string'
|
||||
? origin.sessionId.trim()
|
||||
: ''
|
||||
if (sessionId && typeof uds.getSessionOwner === 'function') {
|
||||
const empNo = uds.getSessionOwner(sessionId)
|
||||
if (empNo) {
|
||||
return {
|
||||
empNo: String(empNo),
|
||||
displayName: String(empNo),
|
||||
permissions: {},
|
||||
}
|
||||
}
|
||||
}
|
||||
const fromCwd = empNoFromUserWorkspacePath(input?.cwd)
|
||||
if (fromCwd) {
|
||||
return {
|
||||
empNo: fromCwd,
|
||||
displayName: fromCwd,
|
||||
permissions: {},
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function browserEmpNo(request) {
|
||||
const cookie = request?.headers?.cookie || ''
|
||||
return parseCookieHeader(cookie, 'PORTALSSOUser')
|
||||
|
|
@ -137,6 +172,8 @@ function sanitizeJobCwd(cwd, identity, getUdsAuth, { forOwnerEmpNo } = {}) {
|
|||
: null
|
||||
if (!raw) return ownerPath || ''
|
||||
if (canViewAllJobs(identity)) return raw
|
||||
// Without uds-auth, keep the caller cwd (tools may stamp owner from path only).
|
||||
if (!uds) return raw
|
||||
if (owner && uds?.isUserPath?.(owner, raw)) return raw
|
||||
if (ownerPath) return ownerPath
|
||||
return ''
|
||||
|
|
@ -274,10 +311,11 @@ export function createHostService(options = {}) {
|
|||
const t = now()
|
||||
// Ignore client-supplied ids on create — otherwise POST/tools can overwrite.
|
||||
const { id: _ignoredId, ownerEmpNo: _ignoreOwner, ...safeInput } = input && typeof input === 'object' ? input : {}
|
||||
if (identity?.empNo) {
|
||||
safeInput.ownerEmpNo = identity.empNo
|
||||
safeInput.ownerDisplayName = identity.displayName || identity.empNo
|
||||
safeInput.cwd = sanitizeJobCwd(safeInput.cwd, identity, getUdsAuth, { forOwnerEmpNo: identity.empNo })
|
||||
let ownerIdentity = identity?.empNo ? identity : inferIdentityFromJobInput(safeInput, getUdsAuth)
|
||||
if (ownerIdentity?.empNo) {
|
||||
safeInput.ownerEmpNo = ownerIdentity.empNo
|
||||
safeInput.ownerDisplayName = ownerIdentity.displayName || ownerIdentity.empNo
|
||||
safeInput.cwd = sanitizeJobCwd(safeInput.cwd, ownerIdentity, getUdsAuth, { forOwnerEmpNo: ownerIdentity.empNo })
|
||||
} else if (safeInput.ownerEmpNo) {
|
||||
safeInput.ownerEmpNo = normalizeOwnerEmpNo(safeInput.ownerEmpNo)
|
||||
} else {
|
||||
|
|
@ -616,7 +654,15 @@ export function createHostService(options = {}) {
|
|||
if (path === `${API_PREFIX}/jobs` && method === 'GET') {
|
||||
const identity = await requireIdentity(req, write, getUdsAuth)
|
||||
if (!identity) return
|
||||
const state = await snapshot()
|
||||
const uds = getUdsAuth()
|
||||
const state = await withState((current) => {
|
||||
const { state: next, changed } = claimUnassignedForViewer(current, identity, {
|
||||
getSessionOwner: typeof uds?.getSessionOwner === 'function'
|
||||
? (sessionId) => uds.getSessionOwner(sessionId)
|
||||
: undefined,
|
||||
})
|
||||
return changed ? next : current
|
||||
})
|
||||
const jobs = filterJobsForIdentity(listJobs(state), identity).map(jobView)
|
||||
write(200, {
|
||||
ok: true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue