forked from go-gitea/gitea
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Feature - go-gitea#5960 - API Endpoint for Repo Editing * Revert from merge * Adds integration testing * Updates to integration tests * Revert changes * Update year in file header * Misspell fix * XORM = test * XORM = test * revert XORM = file * Makes RepoUnit.ID be pk and autoincr * Fix to units * revert header * Remove print statement * Adds other responses * Improves swagger for creating repo * Fixes import order * Better Unit Type does not exist error * Adds editable repo properties to the response repo structure * Fix to api_repo_edit_test.go * Fixes repo test * Changes per review * Fixes typo and standardizes comments in the EditRepoOption struct for swagger * Fixes typo and standardizes comments in the EditRepoOption struct for swagger * Actually can unarchive through the API * Unlike delete, user doesn't have to be the owner of the org, just admin to the repo * Fix to swagger comments for field name change * Update to swagger docs * Update swagger * Changes allow_pull_requests to has_pull_requests
- Loading branch information
Showing
11 changed files
with
868 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
// Copyright 2019 The Gitea Authors. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package integrations | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
"testing" | ||
|
||
"code.gitea.io/gitea/models" | ||
api "code.gitea.io/gitea/modules/structs" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
// getRepoEditOptionFromRepo gets the options for an existing repo exactly as is | ||
func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { | ||
name := repo.Name | ||
description := repo.Description | ||
website := repo.Website | ||
private := repo.IsPrivate | ||
hasIssues := false | ||
if _, err := repo.GetUnit(models.UnitTypeIssues); err == nil { | ||
hasIssues = true | ||
} | ||
hasWiki := false | ||
if _, err := repo.GetUnit(models.UnitTypeWiki); err == nil { | ||
hasWiki = true | ||
} | ||
defaultBranch := repo.DefaultBranch | ||
hasPullRequests := false | ||
ignoreWhitespaceConflicts := false | ||
allowMerge := false | ||
allowRebase := false | ||
allowRebaseMerge := false | ||
allowSquash := false | ||
if unit, err := repo.GetUnit(models.UnitTypePullRequests); err == nil { | ||
config := unit.PullRequestsConfig() | ||
hasPullRequests = true | ||
ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts | ||
allowMerge = config.AllowMerge | ||
allowRebase = config.AllowRebase | ||
allowRebaseMerge = config.AllowRebaseMerge | ||
allowSquash = config.AllowSquash | ||
} | ||
archived := repo.IsArchived | ||
return &api.EditRepoOption{ | ||
Name: &name, | ||
Description: &description, | ||
Website: &website, | ||
Private: &private, | ||
HasIssues: &hasIssues, | ||
HasWiki: &hasWiki, | ||
DefaultBranch: &defaultBranch, | ||
HasPullRequests: &hasPullRequests, | ||
IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, | ||
AllowMerge: &allowMerge, | ||
AllowRebase: &allowRebase, | ||
AllowRebaseMerge: &allowRebaseMerge, | ||
AllowSquash: &allowSquash, | ||
Archived: &archived, | ||
} | ||
} | ||
|
||
// getNewRepoEditOption Gets the options to change everything about an existing repo by adding to strings or changing | ||
// the boolean | ||
func getNewRepoEditOption(opts *api.EditRepoOption) *api.EditRepoOption { | ||
// Gives a new property to everything | ||
name := *opts.Name + "renamed" | ||
description := "new description" | ||
website := "http://wwww.newwebsite.com" | ||
private := !*opts.Private | ||
hasIssues := !*opts.HasIssues | ||
hasWiki := !*opts.HasWiki | ||
defaultBranch := "master" | ||
hasPullRequests := !*opts.HasPullRequests | ||
ignoreWhitespaceConflicts := !*opts.IgnoreWhitespaceConflicts | ||
allowMerge := !*opts.AllowMerge | ||
allowRebase := !*opts.AllowRebase | ||
allowRebaseMerge := !*opts.AllowRebaseMerge | ||
allowSquash := !*opts.AllowSquash | ||
archived := !*opts.Archived | ||
|
||
return &api.EditRepoOption{ | ||
Name: &name, | ||
Description: &description, | ||
Website: &website, | ||
Private: &private, | ||
DefaultBranch: &defaultBranch, | ||
HasIssues: &hasIssues, | ||
HasWiki: &hasWiki, | ||
HasPullRequests: &hasPullRequests, | ||
IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, | ||
AllowMerge: &allowMerge, | ||
AllowRebase: &allowRebase, | ||
AllowRebaseMerge: &allowRebaseMerge, | ||
AllowSquash: &allowSquash, | ||
Archived: &archived, | ||
} | ||
} | ||
|
||
func TestAPIRepoEdit(t *testing.T) { | ||
onGiteaRun(t, func(t *testing.T, u *url.URL) { | ||
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) // owner of the repo1 & repo16 | ||
user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User) // owner of the repo3, is an org | ||
user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User) // owner of neither repos | ||
repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) // public repo | ||
repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository) // public repo | ||
repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo | ||
|
||
// Get user2's token | ||
session := loginUser(t, user2.Name) | ||
token2 := getTokenForLoggedInUser(t, session) | ||
session = emptyTestSession(t) | ||
// Get user4's token | ||
session = loginUser(t, user4.Name) | ||
token4 := getTokenForLoggedInUser(t, session) | ||
session = emptyTestSession(t) | ||
|
||
// Test editing a repo1 which user2 owns, changing name and many properties | ||
origRepoEditOption := getRepoEditOptionFromRepo(repo1) | ||
repoEditOption := getNewRepoEditOption(origRepoEditOption) | ||
url := fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, repo1.Name, token2) | ||
req := NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
resp := session.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 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) | ||
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) | ||
// reset repo in db | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, *repoEditOption.Name, token2) | ||
req = NewRequestWithJSON(t, "PATCH", url, &origRepoEditOption) | ||
resp = session.MakeRequest(t, req, http.StatusOK) | ||
|
||
// Test editing a non-existing repo | ||
name := "repodoesnotexist" | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, name, token2) | ||
req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{Name: &name}) | ||
resp = session.MakeRequest(t, req, http.StatusNotFound) | ||
|
||
// Test editing repo16 by user4 who does not have write access | ||
origRepoEditOption = getRepoEditOptionFromRepo(repo16) | ||
repoEditOption = getNewRepoEditOption(origRepoEditOption) | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, repo16.Name, token4) | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
session.MakeRequest(t, req, http.StatusNotFound) | ||
|
||
// Tests a repo with no token given so will fail | ||
origRepoEditOption = getRepoEditOptionFromRepo(repo16) | ||
repoEditOption = getNewRepoEditOption(origRepoEditOption) | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name) | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
resp = session.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) | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, repo16.Name, token2) | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
resp = session.MakeRequest(t, req, http.StatusOK) | ||
// reset repo in db | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, *repoEditOption.Name, token2) | ||
req = NewRequestWithJSON(t, "PATCH", url, &origRepoEditOption) | ||
resp = session.MakeRequest(t, req, http.StatusOK) | ||
|
||
// Test making a repo public that is private | ||
repo16 = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) | ||
assert.True(t, repo16.IsPrivate) | ||
private := false | ||
repoEditOption = &api.EditRepoOption{ | ||
Private: &private, | ||
} | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, repo16.Name, token2) | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
resp = session.MakeRequest(t, req, http.StatusOK) | ||
repo16 = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) | ||
assert.False(t, repo16.IsPrivate) | ||
// Make it private again | ||
private = true | ||
repoEditOption.Private = &private | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
resp = session.MakeRequest(t, req, http.StatusOK) | ||
|
||
// Test using org repo "user3/repo3" where user2 is a collaborator | ||
origRepoEditOption = getRepoEditOptionFromRepo(repo3) | ||
repoEditOption = getNewRepoEditOption(origRepoEditOption) | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user3.Name, repo3.Name, token2) | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
session.MakeRequest(t, req, http.StatusOK) | ||
// reset repo in db | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user3.Name, *repoEditOption.Name, token2) | ||
req = NewRequestWithJSON(t, "PATCH", url, &origRepoEditOption) | ||
resp = session.MakeRequest(t, req, http.StatusOK) | ||
|
||
// Test using org repo "user3/repo3" with no user token | ||
origRepoEditOption = getRepoEditOptionFromRepo(repo3) | ||
repoEditOption = getNewRepoEditOption(origRepoEditOption) | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s", user3.Name, repo3.Name) | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
session.MakeRequest(t, req, http.StatusNotFound) | ||
|
||
// Test using repo "user2/repo1" where user4 is a NOT collaborator | ||
origRepoEditOption = getRepoEditOptionFromRepo(repo1) | ||
repoEditOption = getNewRepoEditOption(origRepoEditOption) | ||
url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, repo1.Name, token4) | ||
req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | ||
session.MakeRequest(t, req, http.StatusForbidden) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.