Skip to content

Commit 6e86c4c

Browse files
fix(actions): prevent bulk actions from affecting all runners (#38453) (#38457)
Backport #38453 Co-authored-by: xkm <fzc_study@163.com>
1 parent c32af04 commit 6e86c4c

4 files changed

Lines changed: 20 additions & 19 deletions

File tree

routers/web/shared/actions/runners.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -373,16 +373,18 @@ func RunnerBulkActionPost(ctx *context.Context) {
373373
return
374374
}
375375

376-
var runnerIDs []int64
377-
if rCtx.IsAdmin {
378-
// ATTENTION: it completely depends on the assumption that the doer is "site admin"
379-
// So it doesn't do extra permission check to the runner IDs
380-
// In the future, if you need to support such operation on non-admin pages, be careful!
381-
runnerIDs = ctx.FormStringInt64s("ids")
382-
} else {
376+
if !rCtx.IsAdmin {
383377
ctx.HTTPError(http.StatusForbidden, "bulk actions are admin-only")
384378
return
385379
}
380+
// ATTENTION: it completely depends on the assumption that the doer is "site admin"
381+
// So it doesn't do extra permission check to the runner IDs
382+
// In the future, if you need to support such operation on non-admin pages, be careful!
383+
runnerIDs := ctx.FormStringInt64s("ids")
384+
if len(runnerIDs) == 0 {
385+
ctx.HTTPError(http.StatusBadRequest, "missing runner IDs")
386+
return
387+
}
386388

387389
action := ctx.FormString("action")
388390
var successKey, failedKey string

templates/shared/actions/runner_list.tmpl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@
4444
<div class="ui attached segment tw-hidden" data-global-init="initRunnerBulkToolbar">
4545
<form action="{{$.Link}}/bulk" method="post" class="form-fetch-action">
4646
<input type="hidden" name="ids">
47-
<button class="ui small button" name="action" value="disable">{{ctx.Locale.Tr "actions.runners.disable_runner"}} <span class="runner-bulk-count"></span></button>
48-
<button class="ui small button" name="action" value="enable">{{ctx.Locale.Tr "actions.runners.enable_runner"}} <span class="runner-bulk-count"></span></button>
49-
<button class="ui small red button" name="action" value="delete"
47+
<button class="ui small button runner-bulk-action" name="action" value="disable">{{ctx.Locale.Tr "actions.runners.disable_runner"}} <span class="runner-bulk-count"></span></button>
48+
<button class="ui small button runner-bulk-action" name="action" value="enable">{{ctx.Locale.Tr "actions.runners.enable_runner"}} <span class="runner-bulk-count"></span></button>
49+
<button class="ui small red button runner-bulk-action" name="action" value="delete"
5050
data-modal-confirm-header="{{ctx.Locale.Tr "actions.runners.delete_runner_header"}}"
5151
data-modal-confirm-content="{{ctx.Locale.Tr "actions.runners.delete_runner_notice"}}"
5252
>{{ctx.Locale.Tr "actions.runners.delete_runner"}} <span class="runner-bulk-count"></span>

tests/integration/actions_runner_modify_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ func TestActionsRunnerModify(t *testing.T) {
196196
doBulk(t, sessionAdmin, "evict", allIDs, http.StatusBadRequest)
197197
})
198198

199+
t.Run("EmptyIDs", func(t *testing.T) {
200+
doBulk(t, sessionAdmin, "delete", nil, http.StatusBadRequest)
201+
for _, id := range allIDs {
202+
unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: id})
203+
}
204+
})
205+
199206
t.Run("DisableEnable", func(t *testing.T) {
200207
doBulk(t, sessionAdmin, "disable", allIDs, http.StatusOK)
201208
for _, id := range allIDs {

web_src/js/features/admin/common.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ function initAdminRunnerBulk(toolbar: HTMLElement) {
3636

3737
const refresh = () => {
3838
const checked = Array.from(rowCheckboxes).filter((c) => c.checked);
39+
formRunnerIds.value = checked.map((c) => c.getAttribute('data-runner-id')!).join(',');
3940
toggleElem(toolbar, checked.length > 0);
4041
for (const btn of actionButtons) {
4142
btn.querySelector<HTMLElement>('.runner-bulk-count')!.textContent = `(${checked.length})`;
@@ -50,15 +51,6 @@ function initAdminRunnerBulk(toolbar: HTMLElement) {
5051
});
5152
for (const cb of rowCheckboxes) cb.addEventListener('change', refresh);
5253
refresh();
53-
54-
const collectSelectedIds = () => {
55-
const ids = [];
56-
for (const cb of rowCheckboxes) {
57-
if (cb.checked) ids.push(cb.getAttribute('data-runner-id')!);
58-
}
59-
return ids.join(',');
60-
};
61-
formRunnerIds.value = collectSelectedIds();
6254
}
6355

6456
function initAdminUser() {

0 commit comments

Comments
 (0)