aboutsummaryrefslogtreecommitdiffstats
path: root/tests/integration/api_actions_artifact_v4_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'tests/integration/api_actions_artifact_v4_test.go')
-rw-r--r--tests/integration/api_actions_artifact_v4_test.go275
1 files changed, 275 insertions, 0 deletions
diff --git a/tests/integration/api_actions_artifact_v4_test.go b/tests/integration/api_actions_artifact_v4_test.go
index 8821472801..3db8bbb82e 100644
--- a/tests/integration/api_actions_artifact_v4_test.go
+++ b/tests/integration/api_actions_artifact_v4_test.go
@@ -8,13 +8,20 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/xml"
+ "fmt"
"io"
"net/http"
"strings"
"testing"
"time"
+ auth_model "code.gitea.io/gitea/models/auth"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/storage"
+ api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/actions"
actions_service "code.gitea.io/gitea/services/actions"
@@ -334,6 +341,206 @@ func TestActionsArtifactV4DownloadSingle(t *testing.T) {
assert.Equal(t, body, resp.Body.String())
}
+func TestActionsArtifactV4RunDownloadSinglePublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed and found by name
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/runs/792/artifacts?name=artifact-v4-download", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, listResp.Entries[0].ArchiveDownloadURL)
+ assert.Equal(t, "artifact-v4-download", listResp.Entries[0].Name)
+
+ // confirm artifact blob storage url can be retrieved
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].ArchiveDownloadURL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusFound)
+
+ // confirm artifact can be downloaded and has expected content
+ req = NewRequestWithBody(t, "GET", resp.Header().Get("Location"), nil).
+ AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+
+ body := strings.Repeat("D", 1024)
+ assert.Equal(t, body, resp.Body.String())
+}
+
+func TestActionsArtifactV4DownloadSinglePublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed and found by name
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts?name=artifact-v4-download", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, listResp.Entries[0].ArchiveDownloadURL)
+ assert.Equal(t, "artifact-v4-download", listResp.Entries[0].Name)
+
+ // confirm artifact blob storage url can be retrieved
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].ArchiveDownloadURL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusFound)
+
+ blobLocation := resp.Header().Get("Location")
+
+ // confirm artifact can be downloaded without token and has expected content
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("D", 1024)
+ assert.Equal(t, body, resp.Body.String())
+
+ // confirm artifact can not be downloaded without query
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ req.URL.RawQuery = ""
+ _ = MakeRequest(t, req, http.StatusUnauthorized)
+}
+
+func TestActionsArtifactV4DownloadSinglePublicApiPrivateRepo(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed and found by name
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts?name=artifact-v4-download", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+ assert.Equal(t, int64(23), listResp.Entries[0].ID)
+ assert.NotEmpty(t, listResp.Entries[0].ArchiveDownloadURL)
+ assert.Equal(t, "artifact-v4-download", listResp.Entries[0].Name)
+
+ // confirm artifact blob storage url can be retrieved
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].ArchiveDownloadURL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusFound)
+
+ blobLocation := resp.Header().Get("Location")
+ // confirm artifact can be downloaded without token and has expected content
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("D", 1024)
+ assert.Equal(t, body, resp.Body.String())
+
+ // confirm artifact can not be downloaded without query
+ req = NewRequestWithBody(t, "GET", blobLocation, nil)
+ req.URL.RawQuery = ""
+ _ = MakeRequest(t, req, http.StatusUnauthorized)
+}
+
+func TestActionsArtifactV4ListAndGetPublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifact can be listed
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts", repo.FullName()), nil).
+ AddTokenAuth(token)
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp api.ActionArtifactsResponse
+ err := json.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.NoError(t, err)
+
+ for _, artifact := range listResp.Entries {
+ assert.Contains(t, artifact.URL, fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), artifact.ID))
+ assert.Contains(t, artifact.ArchiveDownloadURL, fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip", repo.FullName(), artifact.ID))
+ req = NewRequestWithBody(t, "GET", listResp.Entries[0].URL, nil).
+ AddTokenAuth(token)
+
+ resp = MakeRequest(t, req, http.StatusOK)
+ var artifactResp api.ActionArtifact
+ err := json.Unmarshal(resp.Body.Bytes(), &artifactResp)
+ assert.NoError(t, err)
+
+ assert.Equal(t, artifact.ID, artifactResp.ID)
+ assert.Equal(t, artifact.Name, artifactResp.Name)
+ assert.Equal(t, artifact.SizeInBytes, artifactResp.SizeInBytes)
+ assert.Equal(t, artifact.URL, artifactResp.URL)
+ assert.Equal(t, artifact.ArchiveDownloadURL, artifactResp.ArchiveDownloadURL)
+ }
+}
+
+func TestActionsArtifactV4GetArtifactMismatchedRepoNotFound(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts of wrong repo is not visible
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func TestActionsArtifactV4DownloadArtifactMismatchedRepoNotFound(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts of wrong repo is not visible
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func TestActionsArtifactV4DownloadArtifactCorrectRepoFound(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts of correct repo is visible
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusFound)
+}
+
+func TestActionsArtifactV4DownloadRawArtifactCorrectRepoMissingSignatureUnauthorized(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm cannot use the raw artifact endpoint even with a correct access token
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip/raw", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusUnauthorized)
+}
+
func TestActionsArtifactV4Delete(t *testing.T) {
defer prepareTestEnvActionsArtifacts(t)()
@@ -350,4 +557,72 @@ func TestActionsArtifactV4Delete(t *testing.T) {
var deleteResp actions.DeleteArtifactResponse
protojson.Unmarshal(resp.Body.Bytes(), &deleteResp)
assert.True(t, deleteResp.Ok)
+
+ // confirm artifact is no longer accessible by GetSignedArtifactURL
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/GetSignedArtifactURL", toProtoJSON(&actions.GetSignedArtifactURLRequest{
+ Name: "artifact-v4-download",
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).
+ AddTokenAuth(token)
+ _ = MakeRequest(t, req, http.StatusNotFound)
+
+ // confirm artifact is no longer enumerateable by ListArtifacts and returns length == 0 without error
+ req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/ListArtifacts", toProtoJSON(&actions.ListArtifactsRequest{
+ NameFilter: wrapperspb.String("artifact-v4-download"),
+ WorkflowRunBackendId: "792",
+ WorkflowJobRunBackendId: "193",
+ })).AddTokenAuth(token)
+ resp = MakeRequest(t, req, http.StatusOK)
+ var listResp actions.ListArtifactsResponse
+ protojson.Unmarshal(resp.Body.Bytes(), &listResp)
+ assert.Empty(t, listResp.Artifacts)
+}
+
+func TestActionsArtifactV4DeletePublicApi(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
+
+ // confirm artifacts exists
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusOK)
+
+ // delete artifact by id
+ req = NewRequestWithBody(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNoContent)
+
+ // confirm artifacts has been deleted
+ req = NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func TestActionsArtifactV4DeletePublicApiNotAllowedReadScope(t *testing.T) {
+ defer prepareTestEnvActionsArtifacts(t)()
+
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ session := loginUser(t, user.Name)
+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
+
+ // confirm artifacts exists
+ req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusOK)
+
+ // try delete artifact by id
+ req = NewRequestWithBody(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusForbidden)
+
+ // confirm artifacts has not been deleted
+ req = NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
+ AddTokenAuth(token)
+ MakeRequest(t, req, http.StatusOK)
}