Hide unclaimed cron jobs from non-admin viewers.

Unassigned jobs are visible only to super_admin / fallback_admin (canViewAll). Regular users still reclaim jobs proven by session owner or their user-workspaces cwd.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-08 17:03:56 +08:00
parent 9a4662ca7c
commit d1127dba88
2 changed files with 11 additions and 26 deletions

View file

@ -23,14 +23,8 @@ export function jobVisibleToIdentity(job, identity) {
if (!identity?.empNo) return false
if (canViewAllJobs(identity)) return true
const owner = normalizeOwnerEmpNo(job?.ownerEmpNo)
// Legacy / tool-created rows often lack ownerEmpNo. Keep them visible so the
// sidebar is not empty, then claimUnassignedForViewer can adopt them — unless
// the cwd clearly belongs to another user.
if (owner === UNASSIGNED_OWNER) {
const pathOwner = empNoFromUserWorkspacePath(job?.cwd)
if (pathOwner && pathOwner !== String(identity.empNo)) return false
return true
}
// Unclaimed jobs are admin-only (super_admin / fallback_admin via canViewAll).
if (owner === UNASSIGNED_OWNER) return false
return owner === String(identity.empNo)
}
@ -140,23 +134,14 @@ export function claimUnassignedForViewer(state, identity, deps = {}) {
? job.origin.sessionId.trim()
: ''
let mine = false
// Prefer session ownership / user-workspaces cwd. Adopt web/legacy orphans when
// no other owner is known so chat-created jobs reappear in the sidebar.
// Only claim when evidence ties the job to this viewer. Remaining unassigned
// jobs stay admin-only until a super/fallback admin reassigns them.
if (sessionId && typeof deps.getSessionOwner === 'function') {
const sessionOwner = deps.getSessionOwner(sessionId)
if (sessionOwner && sessionOwner !== identity.empNo) return job
mine = !sessionOwner || sessionOwner === identity.empNo
mine = deps.getSessionOwner(sessionId) === identity.empNo
}
if (!mine && job.cwd) {
const norm = String(job.cwd).replace(/\\/g, '/')
const match = norm.match(/\/user-workspaces\/([^/]+)(?:\/|$)/)
if (match) {
if (decodeURIComponent(match[1]) === identity.empNo) mine = true
else return job
}
}
if (!mine && job.origin?.kind !== 'im') {
mine = true
const pathOwner = empNoFromUserWorkspacePath(job.cwd)
if (pathOwner === identity.empNo) mine = true
}
if (!mine) return job
changed = true