fix(bot-mode): show profile-owned cronjobs
This commit is contained in:
@@ -6004,10 +6004,11 @@ async function invalidateRoutineOwner(profile) {
|
||||
function selectRoutineJobs(data, error, lastJobs, bot) {
|
||||
const live = Array.isArray(data?.jobs) ? data.jobs : null
|
||||
const all = live ?? (error ? lastJobs : [])
|
||||
const scopedToBot = normalizedProfileName(data?.scoped) === normalizedProfileName(bot)
|
||||
return {
|
||||
live,
|
||||
all,
|
||||
jobs: all.filter(job => routineBot(job) === bot)
|
||||
jobs: scopedToBot ? all : all.filter(job => routineBot(job) === bot)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,45 @@ test('unit: a live list is filtered to the current bot', () => {
|
||||
assert.equal(shown[0].job_id, '1')
|
||||
})
|
||||
|
||||
test('regression: a profile-scoped list shows every job owned by that bot profile', () => {
|
||||
const profileJobs = [
|
||||
{ name: 'ordinary profile cronjob', job_id: 'legacy' },
|
||||
{ name: '[bot:ops] Bot Mode routine', job_id: 'routine' }
|
||||
]
|
||||
const view = load().__api.selectRoutineJobs({ jobs: profileJobs, scoped: 'ops' }, null, [], 'ops')
|
||||
|
||||
assert.deepEqual(
|
||||
Array.from(view.jobs, job => job.job_id),
|
||||
['legacy', 'routine']
|
||||
)
|
||||
})
|
||||
|
||||
test('compatibility: an unmarked list keeps tag filtering for older gateways', () => {
|
||||
const profileJobs = [
|
||||
{ name: 'ordinary launch-profile cronjob', job_id: 'legacy' },
|
||||
{ name: '[bot:ops] Bot Mode routine', job_id: 'routine' }
|
||||
]
|
||||
const view = load().__api.selectRoutineJobs({ jobs: profileJobs }, null, [], 'ops')
|
||||
|
||||
assert.deepEqual(
|
||||
Array.from(view.jobs, job => job.job_id),
|
||||
['routine']
|
||||
)
|
||||
})
|
||||
|
||||
test('compatibility: a stale scope marker cannot leak another profile\'s jobs', () => {
|
||||
const profileJobs = [
|
||||
{ name: 'ordinary research cronjob', job_id: 'research' },
|
||||
{ name: '[bot:ops] Bot Mode routine', job_id: 'routine' }
|
||||
]
|
||||
const view = load().__api.selectRoutineJobs({ jobs: profileJobs, scoped: 'research' }, null, [], 'ops')
|
||||
|
||||
assert.deepEqual(
|
||||
Array.from(view.jobs, job => job.job_id),
|
||||
['routine']
|
||||
)
|
||||
})
|
||||
|
||||
test('unit: a failed refresh keeps the last good list', () => {
|
||||
const view = load().__api.selectRoutineJobs(undefined, new Error('down'), jobs, 'ops')
|
||||
assert.equal(view.live, null)
|
||||
|
||||
@@ -47,6 +47,7 @@ def test_cron_manage_profile_reads_that_profiles_store(tmp_path, monkeypatch):
|
||||
)
|
||||
|
||||
assert "result" in resp, resp
|
||||
assert resp["result"]["scoped"] == "botA"
|
||||
names = [j.get("name") for j in resp["result"]["jobs"]]
|
||||
assert "botA-only-job" in names
|
||||
|
||||
|
||||
@@ -1699,15 +1699,19 @@ def _(rid, params: dict) -> dict:
|
||||
if action == "list":
|
||||
# Paused jobs are excluded by default, which reads as deletion in
|
||||
# any UI with an enable/disable toggle — forward the flag.
|
||||
return _ok(
|
||||
rid,
|
||||
json.loads(
|
||||
cronjob(
|
||||
action="list",
|
||||
include_disabled=is_truthy_value(params.get("include_disabled", False)),
|
||||
)
|
||||
),
|
||||
result = json.loads(
|
||||
cronjob(
|
||||
action="list",
|
||||
include_disabled=is_truthy_value(params.get("include_disabled", False)),
|
||||
)
|
||||
)
|
||||
# This marker proves the gateway honored the optional profile
|
||||
# scope. New clients may therefore treat every returned job as
|
||||
# owned by that profile; older gateways omit it, preserving the
|
||||
# safe [bot:<name>] compatibility filter.
|
||||
if profile:
|
||||
result["scoped"] = profile
|
||||
return _ok(rid, result)
|
||||
if action == "add":
|
||||
return _ok(
|
||||
rid,
|
||||
|
||||
Reference in New Issue
Block a user