Skip to content

Commit 3f4a36d

Browse files
Gustedearl-warren
authored andcommitted
fix(sec): add tests for web route delete runner
Exhaustively test each combination of deleting and updating a action runner via the web route. Although updating an action runner was not impacted, its good to have a test nonetheless.
1 parent 0b17346 commit 3f4a36d

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
-
2+
id: 1001
3+
uuid: "43b5d4d3-401b-42f9-94df-a9d45b447b82"
4+
name: "User runner"
5+
owner_id: 2
6+
repo_id: 0
7+
deleted: 0
8+
9+
-
10+
id: 1002
11+
uuid: "bdc77f4f-2b2b-442d-bd44-e808f4306347"
12+
name: "Organisation runner"
13+
owner_id: 3
14+
repo_id: 0
15+
deleted: 0
16+
17+
-
18+
id: 1003
19+
uuid: "9268bc8c-efbf-4dbe-aeb5-945733cdd098"
20+
name: "Repository runner"
21+
owner_id: 0
22+
repo_id: 1
23+
deleted: 0
24+
25+
-
26+
id: 1004
27+
uuid: "fb857e63-c0ce-4571-a6c9-fde26c128073"
28+
name: "Global runner"
29+
owner_id: 0
30+
repo_id: 0
31+
deleted: 0

tests/integration/runner_test.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Copyright 2025 The Forgejo Authors. All rights reserved.
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
package integration
5+
6+
import (
7+
"fmt"
8+
"net/http"
9+
"testing"
10+
11+
actions_model "code.gitea.io/gitea/models/actions"
12+
repo_model "code.gitea.io/gitea/models/repo"
13+
"code.gitea.io/gitea/models/unittest"
14+
user_model "code.gitea.io/gitea/models/user"
15+
forgejo_context "code.gitea.io/gitea/services/context"
16+
"code.gitea.io/gitea/tests"
17+
18+
"github.com/stretchr/testify/assert"
19+
)
20+
21+
func TestRunnerModification(t *testing.T) {
22+
defer tests.AddFixtures("tests/integration/fixtures/TestRunnerModification")()
23+
defer tests.PrepareTestEnv(t)()
24+
25+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
26+
userRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1001, OwnerID: user.ID})
27+
userURL := "/user/settings/actions/runners"
28+
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
29+
orgRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1002, OwnerID: org.ID})
30+
orgURL := "/org/" + org.Name + "/settings/actions/runners"
31+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, OwnerID: user.ID})
32+
repoRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1003, RepoID: repo.ID})
33+
repoURL := "/" + repo.FullName() + "/settings/actions/runners"
34+
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true})
35+
globalRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1004}, "owner_id = 0 AND repo_id = 0")
36+
adminURL := "/admin/actions/runners"
37+
38+
adminSess := loginUser(t, admin.Name)
39+
adminCSRF := GetCSRF(t, adminSess, "/")
40+
sess := loginUser(t, user.Name)
41+
csrf := GetCSRF(t, sess, "/")
42+
43+
test := func(t *testing.T, fail bool, baseURL string, id int64) {
44+
defer tests.PrintCurrentTest(t, 1)()
45+
t.Helper()
46+
47+
sess := sess
48+
csrf := csrf
49+
if baseURL == adminURL {
50+
sess = adminSess
51+
csrf = adminCSRF
52+
}
53+
54+
req := NewRequestWithValues(t, "POST", baseURL+fmt.Sprintf("/%d", id), map[string]string{
55+
"_csrf": csrf,
56+
"description": "New Description",
57+
})
58+
if fail {
59+
sess.MakeRequest(t, req, http.StatusNotFound)
60+
} else {
61+
sess.MakeRequest(t, req, http.StatusSeeOther)
62+
flashCookie := sess.GetCookie(forgejo_context.CookieNameFlash)
63+
assert.NotNil(t, flashCookie)
64+
assert.EqualValues(t, "success%3DRunner%2Bupdated%2Bsuccessfully", flashCookie.Value)
65+
}
66+
67+
req = NewRequestWithValues(t, "POST", baseURL+fmt.Sprintf("/%d/delete", id), map[string]string{
68+
"_csrf": csrf,
69+
})
70+
if fail {
71+
sess.MakeRequest(t, req, http.StatusNotFound)
72+
} else {
73+
sess.MakeRequest(t, req, http.StatusOK)
74+
flashCookie := sess.GetCookie(forgejo_context.CookieNameFlash)
75+
assert.NotNil(t, flashCookie)
76+
assert.EqualValues(t, "success%3DRunner%2Bdeleted%2Bsuccessfully", flashCookie.Value)
77+
}
78+
}
79+
80+
t.Run("User runner", func(t *testing.T) {
81+
t.Run("Organisation", func(t *testing.T) {
82+
test(t, true, orgURL, userRunner.ID)
83+
})
84+
t.Run("Repository", func(t *testing.T) {
85+
test(t, true, repoURL, userRunner.ID)
86+
})
87+
t.Run("User", func(t *testing.T) {
88+
test(t, false, userURL, userRunner.ID)
89+
})
90+
})
91+
92+
t.Run("Organisation runner", func(t *testing.T) {
93+
t.Run("Repository", func(t *testing.T) {
94+
test(t, true, repoURL, orgRunner.ID)
95+
})
96+
t.Run("User", func(t *testing.T) {
97+
test(t, true, userURL, orgRunner.ID)
98+
})
99+
t.Run("Organisation", func(t *testing.T) {
100+
test(t, false, orgURL, orgRunner.ID)
101+
})
102+
})
103+
104+
t.Run("Repository runner", func(t *testing.T) {
105+
t.Run("Organisation", func(t *testing.T) {
106+
test(t, true, orgURL, repoRunner.ID)
107+
})
108+
t.Run("User", func(t *testing.T) {
109+
test(t, true, userURL, repoRunner.ID)
110+
})
111+
t.Run("Repository", func(t *testing.T) {
112+
test(t, false, repoURL, repoRunner.ID)
113+
})
114+
})
115+
116+
t.Run("Global runner", func(t *testing.T) {
117+
t.Run("Organisation", func(t *testing.T) {
118+
test(t, true, orgURL, globalRunner.ID)
119+
})
120+
t.Run("User", func(t *testing.T) {
121+
test(t, true, userURL, globalRunner.ID)
122+
})
123+
t.Run("Repository", func(t *testing.T) {
124+
test(t, true, repoURL, globalRunner.ID)
125+
})
126+
t.Run("Admin", func(t *testing.T) {
127+
test(t, false, adminURL, globalRunner.ID)
128+
})
129+
})
130+
}

0 commit comments

Comments
 (0)