mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-01-11 20:56:29 +00:00
fix: disable actions endpoints of repository if actions are disabled (#10726)
Some checks are pending
Integration tests for the release process / release-simulation (push) Waiting to run
/ release (push) Waiting to run
testing-integration / test-unit (push) Waiting to run
testing-integration / test-sqlite (push) Waiting to run
testing-integration / test-mariadb (v10.6) (push) Waiting to run
testing-integration / test-mariadb (v11.8) (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
Some checks are pending
Integration tests for the release process / release-simulation (push) Waiting to run
/ release (push) Waiting to run
testing-integration / test-unit (push) Waiting to run
testing-integration / test-sqlite (push) Waiting to run
testing-integration / test-mariadb (v10.6) (push) Waiting to run
testing-integration / test-mariadb (v11.8) (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
Some HTTP API endpoints related to Actions, like `/api/v1/repos/{owner}/{repository}/actions/runners`, were not disabled if Actions had been disabled on a repository. With this change, all endpoints related to Actions will be disabled if Actions are disabled.
## Checklist
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
### Tests
- I added test coverage for Go changes...
- [ ] in their respective `*_test.go` for unit tests.
- [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
### Documentation
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
### Release notes
- [ ] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10726
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
This commit is contained in:
parent
6eed310ae6
commit
ba2a6fbc41
4 changed files with 92 additions and 4 deletions
|
|
@ -436,9 +436,16 @@ func reqSiteAdmin() func(ctx *context.APIContext) {
|
|||
}
|
||||
}
|
||||
|
||||
// reqOwner user should be the owner of the repo or site admin.
|
||||
func reqOwner() func(ctx *context.APIContext) {
|
||||
// reqOwner requires that the current user is either the owner of the repository or an administrator. If one or more
|
||||
// unitTypes are given, it also requires that at least one the respective unitTypes is enabled.
|
||||
func reqOwner(unitTypes ...unit.Type) func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if len(unitTypes) > 0 && !slices.ContainsFunc(unitTypes, func(unitType unit.Type) bool {
|
||||
return ctx.Repo.Repository.UnitEnabled(ctx, unitType)
|
||||
}) {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
if !ctx.Repo.IsOwner() && !ctx.IsUserSiteAdmin() {
|
||||
ctx.Error(http.StatusForbidden, "reqOwner", "user should be the owner of the repo")
|
||||
return
|
||||
|
|
@ -466,7 +473,8 @@ func reqAdmin() func(ctx *context.APIContext) {
|
|||
}
|
||||
}
|
||||
|
||||
// reqRepoWriter user should have a permission to write to a repo, or be a site admin
|
||||
// reqRepoWriter requires that the current user has permission to write to a repository or that it is an administrator.
|
||||
// One or more unitTypes have to be specified, and at least one of them has to be enabled.
|
||||
func reqRepoWriter(unitTypes ...unit.Type) func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if !slices.ContainsFunc(unitTypes, func(unitType unit.Type) bool {
|
||||
|
|
@ -1145,7 +1153,7 @@ func Routes() *web.Route {
|
|||
}, reqToken())
|
||||
addActionsRoutes(
|
||||
m,
|
||||
reqOwner(),
|
||||
reqOwner(unit.TypeActions),
|
||||
repo.NewAction(),
|
||||
)
|
||||
m.Group("/hooks/git", func() {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
actions_model "forgejo.org/models/actions"
|
||||
auth_model "forgejo.org/models/auth"
|
||||
"forgejo.org/models/db"
|
||||
repo_model "forgejo.org/models/repo"
|
||||
unit_model "forgejo.org/models/unit"
|
||||
"forgejo.org/models/unittest"
|
||||
|
|
@ -20,6 +21,7 @@ import (
|
|||
api "forgejo.org/modules/structs"
|
||||
"forgejo.org/modules/webhook"
|
||||
"forgejo.org/routers/api/v1/shared"
|
||||
repo_service "forgejo.org/services/repository"
|
||||
files_service "forgejo.org/services/repository/files"
|
||||
"forgejo.org/tests"
|
||||
|
||||
|
|
@ -545,4 +547,25 @@ func TestAPIRepoActionsRunnerOperations(t *testing.T) {
|
|||
|
||||
assert.Equal(t, "token does not have at least one of required scope(s): [write:repository]", errorMessage.Message)
|
||||
})
|
||||
|
||||
t.Run("Endpoints disabled if Actions disabled", func(t *testing.T) {
|
||||
repository, _, cleanUp := tests.CreateDeclarativeRepo(t, user2, "no-actions",
|
||||
[]unit_model.Type{unit_model.TypeCode, unit_model.TypeActions}, []unit_model.Type{}, nil)
|
||||
defer cleanUp()
|
||||
|
||||
requestURL := fmt.Sprintf("/api/v1/repos/%s/actions/runners", repository.FullName())
|
||||
|
||||
request := NewRequest(t, "GET", requestURL)
|
||||
request.AddTokenAuth(readToken)
|
||||
MakeRequest(t, request, http.StatusOK)
|
||||
|
||||
enabledUnits := []repo_model.RepoUnit{{RepoID: repository.ID, Type: unit_model.TypeCode}}
|
||||
disabledUnits := []unit_model.Type{unit_model.TypeActions}
|
||||
err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repository, enabledUnits, disabledUnits)
|
||||
require.NoError(t, err)
|
||||
|
||||
request = NewRequest(t, "GET", requestURL)
|
||||
request.AddTokenAuth(readToken)
|
||||
MakeRequest(t, request, http.StatusNotFound)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,16 @@ import (
|
|||
"testing"
|
||||
|
||||
auth_model "forgejo.org/models/auth"
|
||||
"forgejo.org/models/db"
|
||||
repo_model "forgejo.org/models/repo"
|
||||
unit_model "forgejo.org/models/unit"
|
||||
"forgejo.org/models/unittest"
|
||||
user_model "forgejo.org/models/user"
|
||||
api "forgejo.org/modules/structs"
|
||||
repo_service "forgejo.org/services/repository"
|
||||
"forgejo.org/tests"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAPIRepoSecrets(t *testing.T) {
|
||||
|
|
@ -109,4 +114,25 @@ func TestAPIRepoSecrets(t *testing.T) {
|
|||
AddTokenAuth(token)
|
||||
MakeRequest(t, req, http.StatusBadRequest)
|
||||
})
|
||||
|
||||
t.Run("Endpoints disabled if Actions disabled", func(t *testing.T) {
|
||||
repository, _, cleanUp := tests.CreateDeclarativeRepo(t, user, "no-actions",
|
||||
[]unit_model.Type{unit_model.TypeCode, unit_model.TypeActions}, []unit_model.Type{}, nil)
|
||||
defer cleanUp()
|
||||
|
||||
getURL := fmt.Sprintf("/api/v1/repos/%s/actions/secrets", repository.FullName())
|
||||
|
||||
getRequest := NewRequest(t, "GET", getURL)
|
||||
getRequest.AddTokenAuth(token)
|
||||
MakeRequest(t, getRequest, http.StatusOK)
|
||||
|
||||
enabledUnits := []repo_model.RepoUnit{{RepoID: repository.ID, Type: unit_model.TypeCode}}
|
||||
disabledUnits := []unit_model.Type{unit_model.TypeActions}
|
||||
err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repository, enabledUnits, disabledUnits)
|
||||
require.NoError(t, err)
|
||||
|
||||
getRequest = NewRequest(t, "GET", getURL)
|
||||
getRequest.AddTokenAuth(token)
|
||||
MakeRequest(t, getRequest, http.StatusNotFound)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,17 @@ import (
|
|||
"testing"
|
||||
|
||||
auth_model "forgejo.org/models/auth"
|
||||
"forgejo.org/models/db"
|
||||
repo_model "forgejo.org/models/repo"
|
||||
unit_model "forgejo.org/models/unit"
|
||||
"forgejo.org/models/unittest"
|
||||
user_model "forgejo.org/models/user"
|
||||
api "forgejo.org/modules/structs"
|
||||
repo_service "forgejo.org/services/repository"
|
||||
"forgejo.org/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAPIRepoVariablesTestCreateRepositoryVariable(t *testing.T) {
|
||||
|
|
@ -234,3 +238,30 @@ func TestAPIRepoVariablesGetAllRepositoryVariables(t *testing.T) {
|
|||
assert.Equal(t, "SECOND", actionVariables[1].Name)
|
||||
assert.Equal(t, "Dolor sit amet", actionVariables[1].Data)
|
||||
}
|
||||
|
||||
func TestAPIRepoVariablesEndpointsDisabledIfActionsDisabled(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user2.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
|
||||
repository, _, cleanUp := tests.CreateDeclarativeRepo(t, user2, "no-actions",
|
||||
[]unit_model.Type{unit_model.TypeCode, unit_model.TypeActions}, []unit_model.Type{}, nil)
|
||||
defer cleanUp()
|
||||
|
||||
getURL := fmt.Sprintf("/api/v1/repos/%s/actions/variables", repository.FullName())
|
||||
|
||||
getRequest := NewRequest(t, "GET", getURL)
|
||||
getRequest.AddTokenAuth(token)
|
||||
MakeRequest(t, getRequest, http.StatusOK)
|
||||
|
||||
enabledUnits := []repo_model.RepoUnit{{RepoID: repository.ID, Type: unit_model.TypeCode}}
|
||||
disabledUnits := []unit_model.Type{unit_model.TypeActions}
|
||||
err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repository, enabledUnits, disabledUnits)
|
||||
require.NoError(t, err)
|
||||
|
||||
getRequest = NewRequest(t, "GET", getURL)
|
||||
getRequest.AddTokenAuth(token)
|
||||
MakeRequest(t, getRequest, http.StatusNotFound)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue