Protected tag is no internal server error (#30962)

Fixes #30959

Adds an API test for protected tags.
Fix existing tag in combination with fixtures.
This commit is contained in:
KN4CK3R 2024-05-14 08:48:21 +02:00 committed by GitHub
parent 9a577c62e4
commit b1d8f13bd0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 83 additions and 29 deletions

View File

@ -0,0 +1,24 @@
-
id: 1
repo_id: 4
name_pattern: /v.+/
allowlist_user_i_ds: []
allowlist_team_i_ds: []
created_unix: 1715596037
updated_unix: 1715596037
-
id: 2
repo_id: 1
name_pattern: v-*
allowlist_user_i_ds: []
allowlist_team_i_ds: []
created_unix: 1715596037
updated_unix: 1715596037
-
id: 3
repo_id: 1
name_pattern: v-1.1
allowlist_user_i_ds: [2]
allowlist_team_i_ds: []
created_unix: 1715596037
updated_unix: 1715596037

View File

@ -215,6 +215,9 @@ func CreateRelease(ctx *context.APIContext) {
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
// "409": // "409":
// "$ref": "#/responses/error" // "$ref": "#/responses/error"
// "422":
// "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateReleaseOption) form := web.GetForm(ctx).(*api.CreateReleaseOption)
if ctx.Repo.Repository.IsEmpty { if ctx.Repo.Repository.IsEmpty {
ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty")) ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty"))
@ -246,6 +249,8 @@ func CreateRelease(ctx *context.APIContext) {
if err := release_service.CreateRelease(ctx.Repo.GitRepo, rel, nil, ""); err != nil { if err := release_service.CreateRelease(ctx.Repo.GitRepo, rel, nil, ""); err != nil {
if repo_model.IsErrReleaseAlreadyExist(err) { if repo_model.IsErrReleaseAlreadyExist(err) {
ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err) ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err)
} else if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "ProtectedTagName", err)
} else { } else {
ctx.Error(http.StatusInternalServerError, "CreateRelease", err) ctx.Error(http.StatusInternalServerError, "CreateRelease", err)
} }
@ -386,8 +391,8 @@ func DeleteRelease(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
// "405": // "422":
// "$ref": "#/responses/empty" // "$ref": "#/responses/validationError"
id := ctx.ParamsInt64(":id") id := ctx.ParamsInt64(":id")
rel, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id) rel, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id)
@ -401,7 +406,7 @@ func DeleteRelease(ctx *context.APIContext) {
} }
if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, false); err != nil { if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) { if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return return
} }
ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err) ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)

View File

@ -92,8 +92,8 @@ func DeleteReleaseByTag(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
// "405": // "422":
// "$ref": "#/responses/empty" // "$ref": "#/responses/validationError"
tag := ctx.Params(":tag") tag := ctx.Params(":tag")
@ -114,7 +114,7 @@ func DeleteReleaseByTag(ctx *context.APIContext) {
if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil { if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) { if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return return
} }
ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err) ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)

View File

@ -184,6 +184,8 @@ func CreateTag(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
// "409": // "409":
// "$ref": "#/responses/conflict" // "$ref": "#/responses/conflict"
// "422":
// "$ref": "#/responses/validationError"
// "423": // "423":
// "$ref": "#/responses/repoArchivedError" // "$ref": "#/responses/repoArchivedError"
form := web.GetForm(ctx).(*api.CreateTagOption) form := web.GetForm(ctx).(*api.CreateTagOption)
@ -205,7 +207,7 @@ func CreateTag(ctx *context.APIContext) {
return return
} }
if models.IsErrProtectedTagName(err) { if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "CreateNewTag", "user not allowed to create protected tag") ctx.Error(http.StatusUnprocessableEntity, "CreateNewTag", "user not allowed to create protected tag")
return return
} }
@ -253,6 +255,8 @@ func DeleteTag(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
// "409": // "409":
// "$ref": "#/responses/conflict" // "$ref": "#/responses/conflict"
// "422":
// "$ref": "#/responses/validationError"
// "423": // "423":
// "$ref": "#/responses/repoArchivedError" // "$ref": "#/responses/repoArchivedError"
tagName := ctx.Params("*") tagName := ctx.Params("*")
@ -274,7 +278,7 @@ func DeleteTag(ctx *context.APIContext) {
if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil { if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil {
if models.IsErrProtectedTagName(err) { if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return return
} }
ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err) ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)

View File

@ -12831,6 +12831,9 @@
}, },
"409": { "409": {
"$ref": "#/responses/error" "$ref": "#/responses/error"
},
"422": {
"$ref": "#/responses/validationError"
} }
} }
} }
@ -12949,8 +12952,8 @@
"404": { "404": {
"$ref": "#/responses/notFound" "$ref": "#/responses/notFound"
}, },
"405": { "422": {
"$ref": "#/responses/empty" "$ref": "#/responses/validationError"
} }
} }
} }
@ -13035,8 +13038,8 @@
"404": { "404": {
"$ref": "#/responses/notFound" "$ref": "#/responses/notFound"
}, },
"405": { "422": {
"$ref": "#/responses/empty" "$ref": "#/responses/validationError"
} }
} }
}, },
@ -13886,6 +13889,9 @@
"409": { "409": {
"$ref": "#/responses/conflict" "$ref": "#/responses/conflict"
}, },
"422": {
"$ref": "#/responses/validationError"
},
"423": { "423": {
"$ref": "#/responses/repoArchivedError" "$ref": "#/responses/repoArchivedError"
} }
@ -13979,6 +13985,9 @@
"409": { "409": {
"$ref": "#/responses/conflict" "$ref": "#/responses/conflict"
}, },
"422": {
"$ref": "#/responses/validationError"
},
"423": { "423": {
"$ref": "#/responses/repoArchivedError" "$ref": "#/responses/repoArchivedError"
} }

View File

@ -154,6 +154,31 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
assert.EqualValues(t, rel.Note, newRelease.Note) assert.EqualValues(t, rel.Note, newRelease.Note)
} }
func TestAPICreateProtectedTagRelease(t *testing.T) {
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
writer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
session := loginUser(t, writer.LowerName)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
assert.NoError(t, err)
defer gitRepo.Close()
commit, err := gitRepo.GetBranchCommit("master")
assert.NoError(t, err)
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/releases", repo.OwnerName, repo.Name), &api.CreateReleaseOption{
TagName: "v0.0.1",
Title: "v0.0.1",
IsDraft: false,
IsPrerelease: false,
Target: commit.ID.String(),
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusUnprocessableEntity)
}
func TestAPICreateReleaseToDefaultBranch(t *testing.T) { func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()

View File

@ -26,22 +26,10 @@ func TestCreateNewTagProtected(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
t.Run("API", func(t *testing.T) { t.Run("Code", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1", "first tag") err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "t-first", "first tag")
assert.NoError(t, err)
err = git_model.InsertProtectedTag(db.DefaultContext, &git_model.ProtectedTag{
RepoID: repo.ID,
NamePattern: "v-*",
})
assert.NoError(t, err)
err = git_model.InsertProtectedTag(db.DefaultContext, &git_model.ProtectedTag{
RepoID: repo.ID,
NamePattern: "v-1.1",
AllowlistUserIDs: []int64{repo.OwnerID},
})
assert.NoError(t, err) assert.NoError(t, err)
err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag") err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag")
@ -54,13 +42,12 @@ func TestCreateNewTagProtected(t *testing.T) {
t.Run("Git", func(t *testing.T) { t.Run("Git", func(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { onGiteaRun(t, func(t *testing.T, u *url.URL) {
username := "user2" httpContext := NewAPITestContext(t, owner.Name, repo.Name)
httpContext := NewAPITestContext(t, username, "repo1")
dstPath := t.TempDir() dstPath := t.TempDir()
u.Path = httpContext.GitPath() u.Path = httpContext.GitPath()
u.User = url.UserPassword(username, userPassword) u.User = url.UserPassword(owner.Name, userPassword)
doGitClone(dstPath, u)(t) doGitClone(dstPath, u)(t)