mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-09-12 22:07:17 +00:00
Because the user:password is no longer automatically set as upstream origin, we have to set it manually if we want push to work.
218 lines
7.6 KiB
Go
218 lines
7.6 KiB
Go
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"forgejo.org/models/db"
|
|
issues_model "forgejo.org/models/issues"
|
|
repo_model "forgejo.org/models/repo"
|
|
unit_model "forgejo.org/models/unit"
|
|
"forgejo.org/models/unittest"
|
|
user_model "forgejo.org/models/user"
|
|
"forgejo.org/modules/git"
|
|
files_service "forgejo.org/services/repository/files"
|
|
"forgejo.org/tests"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func CodeOwnerTestCommon(t *testing.T, u *url.URL, codeownerTest CodeownerTest) {
|
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
|
|
// Create the repo.
|
|
repo, _, f := tests.CreateDeclarativeRepo(t, user2, codeownerTest.Name,
|
|
[]unit_model.Type{unit_model.TypePullRequests}, nil,
|
|
[]*files_service.ChangeRepoFile{
|
|
{
|
|
Operation: "create",
|
|
TreePath: codeownerTest.Path,
|
|
ContentReader: strings.NewReader("README.md @user5\ntest-file @user4"),
|
|
},
|
|
},
|
|
)
|
|
defer f()
|
|
|
|
dstPath := t.TempDir()
|
|
r := fmt.Sprintf("%suser2/%s.git", u.String(), repo.Name)
|
|
cloneURL, _ := url.Parse(r)
|
|
cloneURL.User = url.UserPassword("user2", userPassword)
|
|
require.NoError(t, git.CloneWithArgs(t.Context(), nil, cloneURL.String(), dstPath, git.CloneRepoOptions{}))
|
|
doGitSetRemoteURL(dstPath, "origin", cloneURL)(t)
|
|
|
|
t.Run("Normal", func(t *testing.T) {
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
err := os.WriteFile(path.Join(dstPath, "README.md"), []byte("## test content"), 0o666)
|
|
require.NoError(t, err)
|
|
|
|
err = git.AddChanges(dstPath, true)
|
|
require.NoError(t, err)
|
|
|
|
err = git.CommitChanges(dstPath, git.CommitChangesOptions{
|
|
Committer: &git.Signature{
|
|
Email: "user2@example.com",
|
|
Name: "user2",
|
|
When: time.Now(),
|
|
},
|
|
Author: &git.Signature{
|
|
Email: "user2@example.com",
|
|
Name: "user2",
|
|
When: time.Now(),
|
|
},
|
|
Message: "Add README.",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/main", "-o", "topic=codeowner-normal").Run(&git.RunOpts{Dir: dstPath})
|
|
require.NoError(t, err)
|
|
|
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadBranch: "user2/codeowner-normal"})
|
|
unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5})
|
|
})
|
|
|
|
t.Run("Forked repository", func(t *testing.T) {
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
session := loginUser(t, "user1")
|
|
testRepoFork(t, session, user2.Name, repo.Name, "user1", codeownerTest.Name)
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: codeownerTest.Name})
|
|
|
|
r := fmt.Sprintf("%suser1/%s.git", u.String(), codeownerTest.Name)
|
|
remoteURL, _ := url.Parse(r)
|
|
remoteURL.User = url.UserPassword("user2", userPassword)
|
|
doGitAddRemote(dstPath, "forked", remoteURL)(t)
|
|
|
|
err := git.NewCommand(git.DefaultContext, "push", "forked", "HEAD:refs/for/main", "-o", "topic=codeowner-forked").Run(&git.RunOpts{Dir: dstPath})
|
|
require.NoError(t, err)
|
|
|
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadBranch: "user2/codeowner-forked"})
|
|
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5})
|
|
})
|
|
|
|
t.Run("Out of date", func(t *testing.T) {
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
// Push the changes made from the previous subtest.
|
|
require.NoError(t, git.NewCommand(git.DefaultContext, "push", "origin").Run(&git.RunOpts{Dir: dstPath}))
|
|
|
|
// Reset the tree to the previous commit.
|
|
require.NoError(t, git.NewCommand(git.DefaultContext, "reset", "--hard", "HEAD~1").Run(&git.RunOpts{Dir: dstPath}))
|
|
|
|
err := os.WriteFile(path.Join(dstPath, "test-file"), []byte("## test content"), 0o666)
|
|
require.NoError(t, err)
|
|
|
|
err = git.AddChanges(dstPath, true)
|
|
require.NoError(t, err)
|
|
|
|
err = git.CommitChanges(dstPath, git.CommitChangesOptions{
|
|
Committer: &git.Signature{
|
|
Email: "user2@example.com",
|
|
Name: "user2",
|
|
When: time.Now(),
|
|
},
|
|
Author: &git.Signature{
|
|
Email: "user2@example.com",
|
|
Name: "user2",
|
|
When: time.Now(),
|
|
},
|
|
Message: "Add test-file.",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/main", "-o", "topic=codeowner-out-of-date").Run(&git.RunOpts{Dir: dstPath})
|
|
require.NoError(t, err)
|
|
|
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadBranch: "user2/codeowner-out-of-date"})
|
|
unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 4})
|
|
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5})
|
|
})
|
|
t.Run("From a forked repository", func(t *testing.T) {
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
session := loginUser(t, "user1")
|
|
|
|
r := fmt.Sprintf("%suser1/%s.git", u.String(), codeownerTest.Name)
|
|
remoteURL, _ := url.Parse(r)
|
|
remoteURL.User = url.UserPassword("user1", userPassword)
|
|
doGitAddRemote(dstPath, "forked-2", remoteURL)(t)
|
|
|
|
err := git.NewCommand(git.DefaultContext, "push", "forked-2", "HEAD:branch").Run(&git.RunOpts{Dir: dstPath})
|
|
require.NoError(t, err)
|
|
|
|
req := NewRequestWithValues(t, "POST", repo.FullName()+"/compare/main...user1/"+codeownerTest.Name+":branch", map[string]string{
|
|
"_csrf": GetCSRF(t, session, repo.FullName()+"/compare/main...user1/"+codeownerTest.Name+":branch"),
|
|
"title": "pull request",
|
|
})
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadBranch: "branch"})
|
|
unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 4})
|
|
})
|
|
|
|
t.Run("Codeowner user with no permission", func(t *testing.T) {
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
// Make repository private, only user2 (owner of repository) has now access to this repository.
|
|
repo.IsPrivate = true
|
|
_, err := db.GetEngine(db.DefaultContext).Cols("is_private").Update(repo)
|
|
require.NoError(t, err)
|
|
|
|
err = os.WriteFile(path.Join(dstPath, "README.md"), []byte("## very sensitive info"), 0o666)
|
|
require.NoError(t, err)
|
|
|
|
err = git.AddChanges(dstPath, true)
|
|
require.NoError(t, err)
|
|
|
|
err = git.CommitChanges(dstPath, git.CommitChangesOptions{
|
|
Committer: &git.Signature{
|
|
Email: "user2@example.com",
|
|
Name: "user2",
|
|
When: time.Now(),
|
|
},
|
|
Author: &git.Signature{
|
|
Email: "user2@example.com",
|
|
Name: "user2",
|
|
When: time.Now(),
|
|
},
|
|
Message: "Add secrets to the README.",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/main", "-o", "topic=codeowner-private").Run(&git.RunOpts{Dir: dstPath})
|
|
require.NoError(t, err)
|
|
|
|
// In CODEOWNERS file the codeowner for README.md is user5, but does not have access to this private repository.
|
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadBranch: "user2/codeowner-private"})
|
|
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5})
|
|
})
|
|
}
|
|
|
|
type CodeownerTest struct {
|
|
Name string
|
|
Path string
|
|
}
|
|
|
|
func TestCodeOwner(t *testing.T) {
|
|
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
|
tests := []CodeownerTest{
|
|
{Name: "root", Path: "CODEOWNERS"},
|
|
{Name: "docs", Path: "docs/CODEOWNERS"},
|
|
{Name: "gitea", Path: ".gitea/CODEOWNERS"},
|
|
{Name: "forgejo", Path: ".forgejo/CODEOWNERS"},
|
|
}
|
|
for _, test := range tests {
|
|
CodeOwnerTestCommon(t, u, test)
|
|
}
|
|
})
|
|
}
|