forgejo/tests/integration/api_org_secrets_test.go
zokki eeb47e3340 fix: actions variable and secret names validation (#10682)
Fixed action variables and secrets according to [Docu](https://forgejo.org/docs/next/user/actions/basic-concepts/#name-constraints):
> Variable names must not start with the FORGEJO_, GITHUB_ or GITEA_ prefix.
This wasn't correctly enforced, so I changed the regex

## 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...
  - [x] 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

- [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] 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.
- [x] 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/10682
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: zokki <zokki.softwareschmiede@gmail.com>
Co-committed-by: zokki <zokki.softwareschmiede@gmail.com>
2026-01-14 04:19:21 +01:00

160 lines
4.6 KiB
Go

// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package integration
import (
"fmt"
"net/http"
"strings"
"testing"
auth_model "forgejo.org/models/auth"
org_model "forgejo.org/models/organization"
secret_model "forgejo.org/models/secret"
"forgejo.org/models/unittest"
"forgejo.org/modules/keying"
api "forgejo.org/modules/structs"
"forgejo.org/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAPIOrgSecrets(t *testing.T) {
defer tests.PrepareTestEnv(t)()
org := unittest.AssertExistsAndLoadBean(t, &org_model.Organization{Name: "org3"})
session := loginUser(t, "user2")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
t.Run("List", func(t *testing.T) {
listURL := fmt.Sprintf("/api/v1/orgs/%s/actions/secrets", org.Name)
req := NewRequest(t, "GET", listURL).AddTokenAuth(token)
res := MakeRequest(t, req, http.StatusOK)
secrets := []*api.Secret{}
DecodeJSON(t, res, &secrets)
assert.Empty(t, secrets)
createData := api.CreateOrUpdateSecretOption{Data: "a secret to create"}
req = NewRequestWithJSON(t, "PUT", listURL+"/first", createData).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
req = NewRequestWithJSON(t, "PUT", listURL+"/sec2", createData).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
req = NewRequestWithJSON(t, "PUT", listURL+"/last", createData).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
req = NewRequest(t, "GET", listURL).AddTokenAuth(token)
res = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, res, &secrets)
assert.Len(t, secrets, 3)
expectedValues := []string{"FIRST", "SEC2", "LAST"}
for _, secret := range secrets {
assert.Contains(t, expectedValues, secret.Name)
}
})
t.Run("Create", func(t *testing.T) {
cases := []struct {
Name string
ExpectedStatus int
}{
{
Name: "",
ExpectedStatus: http.StatusMethodNotAllowed,
},
{
Name: "-",
ExpectedStatus: http.StatusBadRequest,
},
{
Name: "_",
ExpectedStatus: http.StatusCreated,
},
{
Name: "ci",
ExpectedStatus: http.StatusCreated,
},
{
Name: "secret",
ExpectedStatus: http.StatusCreated,
},
{
Name: "2secret",
ExpectedStatus: http.StatusBadRequest,
},
{
Name: "FORGEJO_secret",
ExpectedStatus: http.StatusBadRequest,
},
{
Name: "GITEA_secret",
ExpectedStatus: http.StatusBadRequest,
},
{
Name: "GITHUB_secret",
ExpectedStatus: http.StatusBadRequest,
},
}
for _, c := range cases {
req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/orgs/%s/actions/secrets/%s", org.Name, c.Name), api.CreateOrUpdateSecretOption{
Data: "data",
}).AddTokenAuth(token)
MakeRequest(t, req, c.ExpectedStatus)
}
})
t.Run("Update", func(t *testing.T) {
name := "update_org_secret_and_test_data"
url := fmt.Sprintf("/api/v1/orgs/%s/actions/secrets/%s", org.Name, name)
req := NewRequestWithJSON(t, "PUT", url, api.CreateOrUpdateSecretOption{
Data: "initial",
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
req = NewRequestWithJSON(t, "PUT", url, api.CreateOrUpdateSecretOption{
Data: "changed data",
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
secret := unittest.AssertExistsAndLoadBean(t, &secret_model.Secret{Name: strings.ToUpper(name)})
data, err := keying.ActionSecret.Decrypt(secret.Data, keying.ColumnAndID("data", secret.ID))
require.NoError(t, err)
assert.Equal(t, "changed data", string(data))
})
t.Run("Delete", func(t *testing.T) {
name := "delete_secret"
url := fmt.Sprintf("/api/v1/orgs/%s/actions/secrets/%s", org.Name, name)
req := NewRequestWithJSON(t, "PUT", url, api.CreateOrUpdateSecretOption{
Data: "initial",
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
req = NewRequest(t, "DELETE", url).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
req = NewRequest(t, "DELETE", url).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
})
t.Run("Delete with forbidden names", func(t *testing.T) {
secret, err := secret_model.InsertEncryptedSecret(t.Context(), org.ID, 0, "FORGEJO_FORBIDDEN", "illegal")
require.NoError(t, err)
url := fmt.Sprintf("/api/v1/orgs/%s/actions/secrets/%s", org.Name, secret.Name)
req := NewRequest(t, "DELETE", url).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
req = NewRequest(t, "DELETE", url).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
})
}