From fa8d75b3e5700239cab02013c4c58936a34bdccd Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Mon, 31 Mar 2025 09:43:46 +0000 Subject: [PATCH] [v11.0/forgejo] fix: validate input for default_{merge,update}_style (#7401) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/7395 - Add `binding:"In(...)"` to the `default_merge_style` and `default_update_style` fields to only accept recognized merge and update styles. - Resolves forgejo/forgejo#7389 - Added integration test for the API (`binding` works in the exact same way for the API and web routes). Co-authored-by: Gusted Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7401 Reviewed-by: Earl Warren Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- modules/structs/repo.go | 6 +- routers/web/repo/setting/setting.go | 4 + services/forms/repo_form.go | 4 +- templates/swagger/v1_json.tmpl | 2 +- tests/integration/api_repo_edit_test.go | 448 +++++++++++++----------- 5 files changed, 248 insertions(+), 216 deletions(-) diff --git a/modules/structs/repo.go b/modules/structs/repo.go index b5f54a2a7a..c9cd729cf3 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -224,10 +224,10 @@ type EditRepoOption struct { AllowRebaseUpdate *bool `json:"allow_rebase_update,omitempty"` // set to `true` to delete pr branch after merge by default DefaultDeleteBranchAfterMerge *bool `json:"default_delete_branch_after_merge,omitempty"` - // set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", "squash", or "fast-forward-only". - DefaultMergeStyle *string `json:"default_merge_style,omitempty"` + // set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", "squash", "fast-forward-only", "manually-merged", or "rebase-update-only". + DefaultMergeStyle *string `json:"default_merge_style,omitempty" binding:"In(merge,rebase,rebase-merge,squash,fast-forward-only,manually-merged,rebase-update-only)"` // set to a update style to be used by this repository: "rebase" or "merge" - DefaultUpdateStyle *string `json:"default_update_style,omitempty"` + DefaultUpdateStyle *string `json:"default_update_style,omitempty" binding:"In(merge,rebase)"` // set to `true` to allow edits from maintainers by default DefaultAllowMaintainerEdit *bool `json:"default_allow_maintainer_edit,omitempty"` // set to `true` to archive this repository. diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 2af2eef4a5..083cc4ae82 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -105,6 +105,10 @@ func Units(ctx *context.Context) { func UnitsPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.RepoUnitSettingForm) + if ctx.HasError() { + ctx.Redirect(ctx.Repo.Repository.Link() + "/settings/units") + return + } repo := ctx.Repo.Repository diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index bd2eb769c6..c39c6a7b36 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -188,8 +188,8 @@ type RepoUnitSettingForm struct { PullsAllowSquash bool PullsAllowFastForwardOnly bool PullsAllowManualMerge bool - PullsDefaultMergeStyle string - PullsDefaultUpdateStyle string + PullsDefaultMergeStyle string `binding:"In(merge,rebase,rebase-merge,squash,fast-forward-only,manually-merged,rebase-update-only)"` + PullsDefaultUpdateStyle string `binding:"In(merge,rebase)"` EnableAutodetectManualMerge bool PullsAllowRebaseUpdate bool DefaultDeleteBranchAfterMerge bool diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 231386e3aa..400c71af1a 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -23762,7 +23762,7 @@ "x-go-name": "DefaultDeleteBranchAfterMerge" }, "default_merge_style": { - "description": "set to a merge style to be used by this repository: \"merge\", \"rebase\", \"rebase-merge\", \"squash\", or \"fast-forward-only\".", + "description": "set to a merge style to be used by this repository: \"merge\", \"rebase\", \"rebase-merge\", \"squash\", \"fast-forward-only\", \"manually-merged\", or \"rebase-update-only\".", "type": "string", "x-go-name": "DefaultMergeStyle" }, diff --git a/tests/integration/api_repo_edit_test.go b/tests/integration/api_repo_edit_test.go index 288c645e37..341cb0961f 100644 --- a/tests/integration/api_repo_edit_test.go +++ b/tests/integration/api_repo_edit_test.go @@ -6,7 +6,6 @@ package integration import ( "fmt" "net/http" - "net/url" "testing" auth_model "forgejo.org/models/auth" @@ -16,6 +15,7 @@ import ( "forgejo.org/models/unittest" user_model "forgejo.org/models/user" api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -137,232 +137,260 @@ func getNewRepoEditOption(opts *api.EditRepoOption) *api.EditRepoOption { } func TestAPIRepoEdit(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - bFalse, bTrue := false, true + defer tests.PrepareTestEnv(t)() + bFalse, bTrue := false, true - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16 - org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the repo3, is an org - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // owner of neither repos - repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo - repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo - repo15 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) // empty repo - repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16 + org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the repo3, is an org + user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // owner of neither repos + repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo + repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo + repo15 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) // empty repo + repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo - // Get user2's token - session := loginUser(t, user2.Name) - token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - // Get user4's token - session = loginUser(t, user4.Name) - token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + // Get user2's token + session := loginUser(t, user2.Name) + token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + // Get user4's token + session = loginUser(t, user4.Name) + token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - // Test editing a repo1 which user2 owns, changing name and many properties - origRepoEditOption := getRepoEditOptionFromRepo(repo1) - repoEditOption := getNewRepoEditOption(origRepoEditOption) - req := NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). - AddTokenAuth(token2) - resp := MakeRequest(t, req, http.StatusOK) - var repo api.Repository - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check response - assert.Equal(t, *repoEditOption.Name, repo.Name) - assert.Equal(t, *repoEditOption.Description, repo.Description) - assert.Equal(t, *repoEditOption.Website, repo.Website) - assert.Equal(t, *repoEditOption.Archived, repo.Archived) - // check repo1 from database - repo1edited := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption := getRepoEditOptionFromRepo(repo1edited) - assert.Equal(t, *repoEditOption.Name, *repo1editedOption.Name) - assert.Equal(t, *repoEditOption.Description, *repo1editedOption.Description) - assert.Equal(t, *repoEditOption.Website, *repo1editedOption.Website) - assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) - assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) - assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) + // Test editing a repo1 which user2 owns, changing name and many properties + origRepoEditOption := getRepoEditOptionFromRepo(repo1) + repoEditOption := getNewRepoEditOption(origRepoEditOption) + req := NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). + AddTokenAuth(token2) + resp := MakeRequest(t, req, http.StatusOK) + var repo api.Repository + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check response + assert.Equal(t, *repoEditOption.Name, repo.Name) + assert.Equal(t, *repoEditOption.Description, repo.Description) + assert.Equal(t, *repoEditOption.Website, repo.Website) + assert.Equal(t, *repoEditOption.Archived, repo.Archived) + // check repo1 from database + repo1edited := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption := getRepoEditOptionFromRepo(repo1edited) + assert.Equal(t, *repoEditOption.Name, *repo1editedOption.Name) + assert.Equal(t, *repoEditOption.Description, *repo1editedOption.Description) + assert.Equal(t, *repoEditOption.Website, *repo1editedOption.Website) + assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) + assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) + assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) - // Test editing repo1 to use internal issue and wiki (default) - *repoEditOption.HasIssues = true - repoEditOption.ExternalTracker = nil - repoEditOption.InternalTracker = &api.InternalTracker{ - EnableTimeTracker: false, - AllowOnlyContributorsToTrackTime: false, - EnableIssueDependencies: false, - } - *repoEditOption.HasWiki = true - repoEditOption.ExternalWiki = nil - url := fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name) - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check repo1 was written to database - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.True(t, *repo1editedOption.HasIssues) - assert.Nil(t, repo1editedOption.ExternalTracker) - assert.Equal(t, *repo1editedOption.InternalTracker, *repoEditOption.InternalTracker) - assert.True(t, *repo1editedOption.HasWiki) - assert.Nil(t, repo1editedOption.ExternalWiki) + // Test editing repo1 to use internal issue and wiki (default) + *repoEditOption.HasIssues = true + repoEditOption.ExternalTracker = nil + repoEditOption.InternalTracker = &api.InternalTracker{ + EnableTimeTracker: false, + AllowOnlyContributorsToTrackTime: false, + EnableIssueDependencies: false, + } + *repoEditOption.HasWiki = true + repoEditOption.ExternalWiki = nil + url := fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name) + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check repo1 was written to database + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.True(t, *repo1editedOption.HasIssues) + assert.Nil(t, repo1editedOption.ExternalTracker) + assert.Equal(t, *repo1editedOption.InternalTracker, *repoEditOption.InternalTracker) + assert.True(t, *repo1editedOption.HasWiki) + assert.Nil(t, repo1editedOption.ExternalWiki) - // Test editing repo1 to use external issue and wiki - repoEditOption.ExternalTracker = &api.ExternalTracker{ - ExternalTrackerURL: "http://www.somewebsite.com", - ExternalTrackerFormat: "http://www.somewebsite.com/{user}/{repo}?issue={index}", - ExternalTrackerStyle: "alphanumeric", - } - repoEditOption.ExternalWiki = &api.ExternalWiki{ - ExternalWikiURL: "http://www.somewebsite.com", - } - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check repo1 was written to database - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.True(t, *repo1editedOption.HasIssues) - assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) - assert.True(t, *repo1editedOption.HasWiki) - assert.Equal(t, *repo1editedOption.ExternalWiki, *repoEditOption.ExternalWiki) + // Test editing repo1 to use external issue and wiki + repoEditOption.ExternalTracker = &api.ExternalTracker{ + ExternalTrackerURL: "http://www.somewebsite.com", + ExternalTrackerFormat: "http://www.somewebsite.com/{user}/{repo}?issue={index}", + ExternalTrackerStyle: "alphanumeric", + } + repoEditOption.ExternalWiki = &api.ExternalWiki{ + ExternalWikiURL: "http://www.somewebsite.com", + } + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check repo1 was written to database + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.True(t, *repo1editedOption.HasIssues) + assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) + assert.True(t, *repo1editedOption.HasWiki) + assert.Equal(t, *repo1editedOption.ExternalWiki, *repoEditOption.ExternalWiki) - repoEditOption.ExternalTracker.ExternalTrackerStyle = "regexp" - repoEditOption.ExternalTracker.ExternalTrackerRegexpPattern = `(\d+)` - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.True(t, *repo1editedOption.HasIssues) - assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) + repoEditOption.ExternalTracker.ExternalTrackerStyle = "regexp" + repoEditOption.ExternalTracker.ExternalTrackerRegexpPattern = `(\d+)` + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.True(t, *repo1editedOption.HasIssues) + assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) - // Do some tests with invalid URL for external tracker and wiki - repoEditOption.ExternalTracker.ExternalTrackerURL = "htp://www.somewebsite.com" - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusUnprocessableEntity) - repoEditOption.ExternalTracker.ExternalTrackerURL = "http://www.somewebsite.com" - repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user/{repo}?issue={index}" - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusUnprocessableEntity) - repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user}/{repo}?issue={index}" - repoEditOption.ExternalWiki.ExternalWikiURL = "htp://www.somewebsite.com" - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusUnprocessableEntity) + // Do some tests with invalid URL for external tracker and wiki + repoEditOption.ExternalTracker.ExternalTrackerURL = "htp://www.somewebsite.com" + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusUnprocessableEntity) + repoEditOption.ExternalTracker.ExternalTrackerURL = "http://www.somewebsite.com" + repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user/{repo}?issue={index}" + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusUnprocessableEntity) + repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user}/{repo}?issue={index}" + repoEditOption.ExternalWiki.ExternalWikiURL = "htp://www.somewebsite.com" + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusUnprocessableEntity) - // Test small repo change through API with issue and wiki option not set; They shall not be touched. - *repoEditOption.Description = "small change" - repoEditOption.HasIssues = nil - repoEditOption.ExternalTracker = nil - repoEditOption.HasWiki = nil - repoEditOption.ExternalWiki = nil - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check repo1 was written to database - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.Equal(t, *repo1editedOption.Description, *repoEditOption.Description) - assert.True(t, *repo1editedOption.HasIssues) - assert.NotNil(t, *repo1editedOption.ExternalTracker) - assert.True(t, *repo1editedOption.HasWiki) - assert.NotNil(t, *repo1editedOption.ExternalWiki) + // Test small repo change through API with issue and wiki option not set; They shall not be touched. + *repoEditOption.Description = "small change" + repoEditOption.HasIssues = nil + repoEditOption.ExternalTracker = nil + repoEditOption.HasWiki = nil + repoEditOption.ExternalWiki = nil + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check repo1 was written to database + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.Equal(t, *repo1editedOption.Description, *repoEditOption.Description) + assert.True(t, *repo1editedOption.HasIssues) + assert.NotNil(t, *repo1editedOption.ExternalTracker) + assert.True(t, *repo1editedOption.HasWiki) + assert.NotNil(t, *repo1editedOption.ExternalWiki) - // reset repo in db - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // reset repo in db + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test editing a non-existing repo - name := "repodoesnotexist" - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, name), &api.EditRepoOption{Name: &name}). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusNotFound) + // Test editing a non-existing repo + name := "repodoesnotexist" + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, name), &api.EditRepoOption{Name: &name}). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusNotFound) - // Test editing repo16 by user4 who does not have write access - origRepoEditOption = getRepoEditOptionFromRepo(repo16) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). - AddTokenAuth(token4) - MakeRequest(t, req, http.StatusNotFound) + // Test editing repo16 by user4 who does not have write access + origRepoEditOption = getRepoEditOptionFromRepo(repo16) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). + AddTokenAuth(token4) + MakeRequest(t, req, http.StatusNotFound) - // Tests a repo with no token given so will fail - origRepoEditOption = getRepoEditOptionFromRepo(repo16) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption) - _ = MakeRequest(t, req, http.StatusNotFound) + // Tests a repo with no token given so will fail + origRepoEditOption = getRepoEditOptionFromRepo(repo16) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption) + _ = MakeRequest(t, req, http.StatusNotFound) - // Test using access token for a private repo that the user of the token owns - origRepoEditOption = getRepoEditOptionFromRepo(repo16) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) - // reset repo in db - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test using access token for a private repo that the user of the token owns + origRepoEditOption = getRepoEditOptionFromRepo(repo16) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) + // reset repo in db + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test making a repo public that is private - repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) - assert.True(t, repo16.IsPrivate) - repoEditOption = &api.EditRepoOption{ - Private: &bFalse, - } - url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name) - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) - repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) - assert.False(t, repo16.IsPrivate) - // Make it private again - repoEditOption.Private = &bTrue - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test making a repo public that is private + repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) + assert.True(t, repo16.IsPrivate) + repoEditOption = &api.EditRepoOption{ + Private: &bFalse, + } + url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name) + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) + repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) + assert.False(t, repo16.IsPrivate) + // Make it private again + repoEditOption.Private = &bTrue + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test to change empty repo - assert.False(t, repo15.IsArchived) - url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo15.Name) - req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ - Archived: &bTrue, - }).AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) - repo15 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) - assert.True(t, repo15.IsArchived) - req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ - Archived: &bFalse, - }).AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test to change empty repo + assert.False(t, repo15.IsArchived) + url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo15.Name) + req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + Archived: &bTrue, + }).AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) + repo15 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) + assert.True(t, repo15.IsArchived) + req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + Archived: &bFalse, + }).AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test using org repo "org3/repo3" where user2 is a collaborator - origRepoEditOption = getRepoEditOptionFromRepo(repo3) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusOK) - // reset repo in db - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, *repoEditOption.Name), &origRepoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test using org repo "org3/repo3" where user2 is a collaborator + origRepoEditOption = getRepoEditOptionFromRepo(repo3) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusOK) + // reset repo in db + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, *repoEditOption.Name), &origRepoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test using org repo "org3/repo3" with no user token - origRepoEditOption = getRepoEditOptionFromRepo(repo3) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption) - MakeRequest(t, req, http.StatusNotFound) + // Test using org repo "org3/repo3" with no user token + origRepoEditOption = getRepoEditOptionFromRepo(repo3) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption) + MakeRequest(t, req, http.StatusNotFound) - // Test using repo "user2/repo1" where user4 is a NOT collaborator - origRepoEditOption = getRepoEditOptionFromRepo(repo1) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). - AddTokenAuth(token4) - MakeRequest(t, req, http.StatusForbidden) + // Test using repo "user2/repo1" where user4 is a NOT collaborator + origRepoEditOption = getRepoEditOptionFromRepo(repo1) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). + AddTokenAuth(token4) + MakeRequest(t, req, http.StatusForbidden) + + t.Run("Default merge style", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + updateStyle := "invalid" + MakeRequest(t, NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + DefaultUpdateStyle: &updateStyle, + }).AddTokenAuth(token2), http.StatusUnprocessableEntity) + + MakeRequest(t, NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + DefaultMergeStyle: &updateStyle, + }).AddTokenAuth(token2), http.StatusUnprocessableEntity) + + var apiRepo api.Repository + DecodeJSON(t, MakeRequest(t, NewRequest(t, "GET", url).AddTokenAuth(token2), http.StatusOK), &apiRepo) + assert.Equal(t, "merge", apiRepo.DefaultMergeStyle) + assert.Equal(t, "merge", apiRepo.DefaultUpdateStyle) + + updateStyle = "rebase" + MakeRequest(t, NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + DefaultMergeStyle: &updateStyle, + DefaultUpdateStyle: &updateStyle, + HasPullRequests: &bTrue, + }).AddTokenAuth(token2), http.StatusOK) + + DecodeJSON(t, MakeRequest(t, NewRequest(t, "GET", url).AddTokenAuth(token2), http.StatusOK), &apiRepo) + assert.Equal(t, "rebase", apiRepo.DefaultMergeStyle) + assert.Equal(t, "rebase", apiRepo.DefaultUpdateStyle) }) }