mirror of
https://github.com/go-gitea/gitea
synced 2024-11-25 15:22:47 +01:00
Move AddCollabrator and CreateRepositoryByExample to service layer (#32419)
- [x] Move `CreateRepositoryByExample` to service layer - [x] Move `AddCollabrator` to service layer - [x] Add a new parameter for `AddCollabrator` so that changing mode immediately after that will become unnecessary.
This commit is contained in:
parent
913be9e8ac
commit
276500c314
19 changed files with 232 additions and 500 deletions
|
@ -60,3 +60,6 @@ func ParseAccessMode(permission string, allowed ...AccessMode) AccessMode {
|
||||||
}
|
}
|
||||||
return util.Iif(slices.Contains(allowed, m), m, AccessModeNone)
|
return util.Iif(slices.Contains(allowed, m), m, AccessModeNone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrInvalidAccessMode is returned when an invalid access mode is used
|
||||||
|
var ErrInvalidAccessMode = util.NewInvalidArgumentErrorf("Invalid access mode")
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
"code.gitea.io/gitea/models/perm"
|
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
|
||||||
|
|
||||||
"xorm.io/builder"
|
|
||||||
)
|
|
||||||
|
|
||||||
func AddCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
|
|
||||||
if err := repo.LoadOwner(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if user_model.IsUserBlockedBy(ctx, u, repo.OwnerID) || user_model.IsUserBlockedBy(ctx, repo.Owner, u.ID) {
|
|
||||||
return user_model.ErrBlockedUser
|
|
||||||
}
|
|
||||||
|
|
||||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
|
||||||
has, err := db.Exist[repo_model.Collaboration](ctx, builder.Eq{
|
|
||||||
"repo_id": repo.ID,
|
|
||||||
"user_id": u.ID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if has {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.Insert(ctx, &repo_model.Collaboration{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
UserID: u.ID,
|
|
||||||
Mode: perm.AccessModeWrite,
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return access_model.RecalculateUserAccess(ctx, repo, u.ID)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,280 +0,0 @@
|
||||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
"code.gitea.io/gitea/models/organization"
|
|
||||||
perm_model "code.gitea.io/gitea/models/perm"
|
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
"code.gitea.io/gitea/models/unit"
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRepository_AddCollaborator(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
testSuccess := func(repoID, userID int64) {
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
|
|
||||||
assert.NoError(t, repo.LoadOwner(db.DefaultContext))
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
|
|
||||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
|
||||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID})
|
|
||||||
}
|
|
||||||
testSuccess(1, 4)
|
|
||||||
testSuccess(1, 4)
|
|
||||||
testSuccess(3, 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRepoPermissionPublicNonOrgRepo(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
// public non-organization repo
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
|
||||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
|
||||||
|
|
||||||
// plain user
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.False(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// change to collaborator
|
|
||||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// collaborator
|
|
||||||
collaborator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, collaborator)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// owner
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// admin
|
|
||||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
// private non-organization repo
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
|
||||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
|
||||||
|
|
||||||
// plain user
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
|
||||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.False(t, perm.CanRead(unit.Type))
|
|
||||||
assert.False(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// change to collaborator to default write access
|
|
||||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.False(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// owner
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// admin
|
|
||||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRepoPermissionPublicOrgRepo(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
// public organization repo
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 32})
|
|
||||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
|
||||||
|
|
||||||
// plain user
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
|
||||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.False(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// change to collaborator to default write access
|
|
||||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.False(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// org member team owner
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// org member team tester
|
|
||||||
member := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, member)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
}
|
|
||||||
assert.True(t, perm.CanWrite(unit.TypeIssues))
|
|
||||||
assert.False(t, perm.CanWrite(unit.TypeCode))
|
|
||||||
|
|
||||||
// admin
|
|
||||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRepoPermissionPrivateOrgRepo(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
// private organization repo
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24})
|
|
||||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
|
||||||
|
|
||||||
// plain user
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
|
||||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.False(t, perm.CanRead(unit.Type))
|
|
||||||
assert.False(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// change to collaborator to default write access
|
|
||||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.False(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// org member team owner
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// update team information and then check permission
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5})
|
|
||||||
err = organization.UpdateTeamUnits(db.DefaultContext, team, nil)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
// org member team tester
|
|
||||||
tester := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, tester)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.True(t, perm.CanWrite(unit.TypeIssues))
|
|
||||||
assert.False(t, perm.CanWrite(unit.TypeCode))
|
|
||||||
assert.False(t, perm.CanRead(unit.TypeCode))
|
|
||||||
|
|
||||||
// org member team reviewer
|
|
||||||
reviewer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 20})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, reviewer)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, perm.CanRead(unit.TypeIssues))
|
|
||||||
assert.False(t, perm.CanWrite(unit.TypeCode))
|
|
||||||
assert.True(t, perm.CanRead(unit.TypeCode))
|
|
||||||
|
|
||||||
// admin
|
|
||||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
||||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, unit := range repo.Units {
|
|
||||||
assert.True(t, perm.CanRead(unit.Type))
|
|
||||||
assert.True(t, perm.CanWrite(unit.Type))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,160 +11,17 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
activities_model "code.gitea.io/gitea/models/activities"
|
activities_model "code.gitea.io/gitea/models/activities"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
"code.gitea.io/gitea/models/organization"
|
|
||||||
"code.gitea.io/gitea/models/perm"
|
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
|
||||||
"code.gitea.io/gitea/models/webhook"
|
|
||||||
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
|
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateRepositoryByExample creates a repository for the user/organization.
|
|
||||||
func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository, overwriteOrAdopt, isFork bool) (err error) {
|
|
||||||
if err = repo_model.IsUsableRepoName(repo.Name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
has, err := repo_model.IsRepositoryModelExist(ctx, u, repo.Name)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
|
||||||
} else if has {
|
|
||||||
return repo_model.ErrRepoAlreadyExist{
|
|
||||||
Uname: u.Name,
|
|
||||||
Name: repo.Name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repoPath := repo_model.RepoPath(u.Name, repo.Name)
|
|
||||||
isExist, err := util.IsExist(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !overwriteOrAdopt && isExist {
|
|
||||||
log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath)
|
|
||||||
return repo_model.ErrRepoFilesAlreadyExist{
|
|
||||||
Uname: u.Name,
|
|
||||||
Name: repo.Name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.Insert(ctx, repo); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = repo_model.DeleteRedirect(ctx, u.ID, repo.Name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert units for repo
|
|
||||||
defaultUnits := unit.DefaultRepoUnits
|
|
||||||
if isFork {
|
|
||||||
defaultUnits = unit.DefaultForkRepoUnits
|
|
||||||
}
|
|
||||||
units := make([]repo_model.RepoUnit, 0, len(defaultUnits))
|
|
||||||
for _, tp := range defaultUnits {
|
|
||||||
if tp == unit.TypeIssues {
|
|
||||||
units = append(units, repo_model.RepoUnit{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Type: tp,
|
|
||||||
Config: &repo_model.IssuesConfig{
|
|
||||||
EnableTimetracker: setting.Service.DefaultEnableTimetracking,
|
|
||||||
AllowOnlyContributorsToTrackTime: setting.Service.DefaultAllowOnlyContributorsToTrackTime,
|
|
||||||
EnableDependencies: setting.Service.DefaultEnableDependencies,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else if tp == unit.TypePullRequests {
|
|
||||||
units = append(units, repo_model.RepoUnit{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Type: tp,
|
|
||||||
Config: &repo_model.PullRequestsConfig{
|
|
||||||
AllowMerge: true, AllowRebase: true, AllowRebaseMerge: true, AllowSquash: true, AllowFastForwardOnly: true,
|
|
||||||
DefaultMergeStyle: repo_model.MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle),
|
|
||||||
AllowRebaseUpdate: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else if tp == unit.TypeProjects {
|
|
||||||
units = append(units, repo_model.RepoUnit{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Type: tp,
|
|
||||||
Config: &repo_model.ProjectsConfig{ProjectsMode: repo_model.ProjectsModeAll},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
units = append(units, repo_model.RepoUnit{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Type: tp,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.Insert(ctx, units); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember visibility preference.
|
|
||||||
u.LastRepoVisibility = repo.IsPrivate
|
|
||||||
if err = user_model.UpdateUserCols(ctx, u, "last_repo_visibility"); err != nil {
|
|
||||||
return fmt.Errorf("UpdateUserCols: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = user_model.IncrUserRepoNum(ctx, u.ID); err != nil {
|
|
||||||
return fmt.Errorf("IncrUserRepoNum: %w", err)
|
|
||||||
}
|
|
||||||
u.NumRepos++
|
|
||||||
|
|
||||||
// Give access to all members in teams with access to all repositories.
|
|
||||||
if u.IsOrganization() {
|
|
||||||
teams, err := organization.FindOrgTeams(ctx, u.ID)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("FindOrgTeams: %w", err)
|
|
||||||
}
|
|
||||||
for _, t := range teams {
|
|
||||||
if t.IncludesAllRepositories {
|
|
||||||
if err := models.AddRepository(ctx, t, repo); err != nil {
|
|
||||||
return fmt.Errorf("AddRepository: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isAdmin, err := access_model.IsUserRepoAdmin(ctx, repo, doer); err != nil {
|
|
||||||
return fmt.Errorf("IsUserRepoAdmin: %w", err)
|
|
||||||
} else if !isAdmin {
|
|
||||||
// Make creator repo admin if it wasn't assigned automatically
|
|
||||||
if err = AddCollaborator(ctx, repo, doer); err != nil {
|
|
||||||
return fmt.Errorf("AddCollaborator: %w", err)
|
|
||||||
}
|
|
||||||
if err = repo_model.ChangeCollaborationAccessMode(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil {
|
|
||||||
return fmt.Errorf("ChangeCollaborationAccessModeCtx: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if err = access_model.RecalculateAccesses(ctx, repo); err != nil {
|
|
||||||
// Organization automatically called this in AddRepository method.
|
|
||||||
return fmt.Errorf("RecalculateAccesses: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if setting.Service.AutoWatchNewRepos {
|
|
||||||
if err = repo_model.WatchRepo(ctx, doer, repo, true); err != nil {
|
|
||||||
return fmt.Errorf("WatchRepo: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = webhook.CopyDefaultWebhooksToRepo(ctx, repo.ID); err != nil {
|
|
||||||
return fmt.Errorf("CopyDefaultWebhooksToRepo: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
|
const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
|
||||||
|
|
||||||
// getDirectorySize returns the disk consumption for a given path
|
// getDirectorySize returns the disk consumption for a given path
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1172,7 +1172,7 @@ func Routes() *web.Router {
|
||||||
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
|
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
|
||||||
m.Group("/{collaborator}", func() {
|
m.Group("/{collaborator}", func() {
|
||||||
m.Combo("").Get(reqAnyRepoReader(), repo.IsCollaborator).
|
m.Combo("").Get(reqAnyRepoReader(), repo.IsCollaborator).
|
||||||
Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator).
|
Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddOrUpdateCollaborator).
|
||||||
Delete(reqAdmin(), repo.DeleteCollaborator)
|
Delete(reqAdmin(), repo.DeleteCollaborator)
|
||||||
m.Get("/permission", repo.GetRepoPermissions)
|
m.Get("/permission", repo.GetRepoPermissions)
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||||
|
@ -123,11 +122,11 @@ func IsCollaborator(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddCollaborator add a collaborator to a repository
|
// AddOrUpdateCollaborator add or update a collaborator to a repository
|
||||||
func AddCollaborator(ctx *context.APIContext) {
|
func AddOrUpdateCollaborator(ctx *context.APIContext) {
|
||||||
// swagger:operation PUT /repos/{owner}/{repo}/collaborators/{collaborator} repository repoAddCollaborator
|
// swagger:operation PUT /repos/{owner}/{repo}/collaborators/{collaborator} repository repoAddCollaborator
|
||||||
// ---
|
// ---
|
||||||
// summary: Add a collaborator to a repository
|
// summary: Add or Update a collaborator to a repository
|
||||||
// produces:
|
// produces:
|
||||||
// - application/json
|
// - application/json
|
||||||
// parameters:
|
// parameters:
|
||||||
|
@ -177,20 +176,18 @@ func AddCollaborator(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo_module.AddCollaborator(ctx, ctx.Repo.Repository, collaborator); err != nil {
|
p := perm.AccessModeWrite
|
||||||
if errors.Is(err, user_model.ErrBlockedUser) {
|
if form.Permission != nil {
|
||||||
ctx.Error(http.StatusForbidden, "AddCollaborator", err)
|
p = perm.ParseAccessMode(*form.Permission)
|
||||||
} else {
|
|
||||||
ctx.Error(http.StatusInternalServerError, "AddCollaborator", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if form.Permission != nil {
|
if err := repo_service.AddOrUpdateCollaborator(ctx, ctx.Repo.Repository, collaborator, p); err != nil {
|
||||||
if err := repo_model.ChangeCollaborationAccessMode(ctx, ctx.Repo.Repository, collaborator.ID, perm.ParseAccessMode(*form.Permission)); err != nil {
|
if errors.Is(err, user_model.ErrBlockedUser) {
|
||||||
ctx.Error(http.StatusInternalServerError, "ChangeCollaborationAccessMode", err)
|
ctx.Error(http.StatusForbidden, "AddOrUpdateCollaborator", err)
|
||||||
return
|
} else {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "AddOrUpdateCollaborator", err)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/services/context"
|
"code.gitea.io/gitea/services/context"
|
||||||
"code.gitea.io/gitea/services/mailer"
|
"code.gitea.io/gitea/services/mailer"
|
||||||
|
@ -100,12 +99,12 @@ func CollaborationPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = repo_module.AddCollaborator(ctx, ctx.Repo.Repository, u); err != nil {
|
if err = repo_service.AddOrUpdateCollaborator(ctx, ctx.Repo.Repository, u, perm.AccessModeWrite); err != nil {
|
||||||
if errors.Is(err, user_model.ErrBlockedUser) {
|
if errors.Is(err, user_model.ErrBlockedUser) {
|
||||||
ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator.blocked_user"))
|
ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator.blocked_user"))
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError("AddCollaborator", err)
|
ctx.ServerError("AddOrUpdateCollaborator", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo_module.CreateRepositoryByExample(ctx, doer, u, repo, true, false); err != nil {
|
if err := CreateRepositoryByExample(ctx, doer, u, repo, true, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,60 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func AddOrUpdateCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User, mode perm.AccessMode) error {
|
||||||
|
// only allow valid access modes, read, write and admin
|
||||||
|
if mode < perm.AccessModeRead || mode > perm.AccessModeAdmin {
|
||||||
|
return perm.ErrInvalidAccessMode
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := repo.LoadOwner(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_model.IsUserBlockedBy(ctx, u, repo.OwnerID) || user_model.IsUserBlockedBy(ctx, repo.Owner, u.ID) {
|
||||||
|
return user_model.ErrBlockedUser
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
|
collaboration, has, err := db.Get[repo_model.Collaboration](ctx, builder.Eq{
|
||||||
|
"repo_id": repo.ID,
|
||||||
|
"user_id": u.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if has {
|
||||||
|
if collaboration.Mode == mode {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if _, err = db.GetEngine(ctx).
|
||||||
|
Where("repo_id=?", repo.ID).
|
||||||
|
And("user_id=?", u.ID).
|
||||||
|
Cols("mode").
|
||||||
|
Update(&repo_model.Collaboration{
|
||||||
|
Mode: mode,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if err = db.Insert(ctx, &repo_model.Collaboration{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
UserID: u.ID,
|
||||||
|
Mode: mode,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return access_model.RecalculateUserAccess(ctx, repo, u.ID)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteCollaboration removes collaboration relation between the user and repository.
|
// DeleteCollaboration removes collaboration relation between the user and repository.
|
||||||
func DeleteCollaboration(ctx context.Context, repo *repo_model.Repository, collaborator *user_model.User) (err error) {
|
func DeleteCollaboration(ctx context.Context, repo *repo_model.Repository, collaborator *user_model.User) (err error) {
|
||||||
collaboration := &repo_model.Collaboration{
|
collaboration := &repo_model.Collaboration{
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -14,6 +15,21 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestRepository_AddCollaborator(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
testSuccess := func(repoID, userID int64) {
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
|
||||||
|
assert.NoError(t, repo.LoadOwner(db.DefaultContext))
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
|
||||||
|
assert.NoError(t, AddOrUpdateCollaborator(db.DefaultContext, repo, user, perm.AccessModeWrite))
|
||||||
|
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID})
|
||||||
|
}
|
||||||
|
testSuccess(1, 4)
|
||||||
|
testSuccess(1, 4)
|
||||||
|
testSuccess(3, 4)
|
||||||
|
}
|
||||||
|
|
||||||
func TestRepository_DeleteCollaboration(t *testing.T) {
|
func TestRepository_DeleteCollaboration(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,15 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -243,7 +249,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
|
||||||
var rollbackRepo *repo_model.Repository
|
var rollbackRepo *repo_model.Repository
|
||||||
|
|
||||||
if err := db.WithTx(ctx, func(ctx context.Context) error {
|
if err := db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
if err := repo_module.CreateRepositoryByExample(ctx, doer, u, repo, false, false); err != nil {
|
if err := CreateRepositoryByExample(ctx, doer, u, repo, false, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,3 +341,136 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
|
||||||
|
|
||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateRepositoryByExample creates a repository for the user/organization.
|
||||||
|
func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository, overwriteOrAdopt, isFork bool) (err error) {
|
||||||
|
if err = repo_model.IsUsableRepoName(repo.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
has, err := repo_model.IsRepositoryModelExist(ctx, u, repo.Name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
|
} else if has {
|
||||||
|
return repo_model.ErrRepoAlreadyExist{
|
||||||
|
Uname: u.Name,
|
||||||
|
Name: repo.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repoPath := repo_model.RepoPath(u.Name, repo.Name)
|
||||||
|
isExist, err := util.IsExist(repoPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !overwriteOrAdopt && isExist {
|
||||||
|
log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath)
|
||||||
|
return repo_model.ErrRepoFilesAlreadyExist{
|
||||||
|
Uname: u.Name,
|
||||||
|
Name: repo.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.Insert(ctx, repo); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = repo_model.DeleteRedirect(ctx, u.ID, repo.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert units for repo
|
||||||
|
defaultUnits := unit.DefaultRepoUnits
|
||||||
|
if isFork {
|
||||||
|
defaultUnits = unit.DefaultForkRepoUnits
|
||||||
|
}
|
||||||
|
units := make([]repo_model.RepoUnit, 0, len(defaultUnits))
|
||||||
|
for _, tp := range defaultUnits {
|
||||||
|
if tp == unit.TypeIssues {
|
||||||
|
units = append(units, repo_model.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: tp,
|
||||||
|
Config: &repo_model.IssuesConfig{
|
||||||
|
EnableTimetracker: setting.Service.DefaultEnableTimetracking,
|
||||||
|
AllowOnlyContributorsToTrackTime: setting.Service.DefaultAllowOnlyContributorsToTrackTime,
|
||||||
|
EnableDependencies: setting.Service.DefaultEnableDependencies,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else if tp == unit.TypePullRequests {
|
||||||
|
units = append(units, repo_model.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: tp,
|
||||||
|
Config: &repo_model.PullRequestsConfig{
|
||||||
|
AllowMerge: true, AllowRebase: true, AllowRebaseMerge: true, AllowSquash: true, AllowFastForwardOnly: true,
|
||||||
|
DefaultMergeStyle: repo_model.MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle),
|
||||||
|
AllowRebaseUpdate: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else if tp == unit.TypeProjects {
|
||||||
|
units = append(units, repo_model.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: tp,
|
||||||
|
Config: &repo_model.ProjectsConfig{ProjectsMode: repo_model.ProjectsModeAll},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
units = append(units, repo_model.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: tp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.Insert(ctx, units); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember visibility preference.
|
||||||
|
u.LastRepoVisibility = repo.IsPrivate
|
||||||
|
if err = user_model.UpdateUserCols(ctx, u, "last_repo_visibility"); err != nil {
|
||||||
|
return fmt.Errorf("UpdateUserCols: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = user_model.IncrUserRepoNum(ctx, u.ID); err != nil {
|
||||||
|
return fmt.Errorf("IncrUserRepoNum: %w", err)
|
||||||
|
}
|
||||||
|
u.NumRepos++
|
||||||
|
|
||||||
|
// Give access to all members in teams with access to all repositories.
|
||||||
|
if u.IsOrganization() {
|
||||||
|
teams, err := organization.FindOrgTeams(ctx, u.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("FindOrgTeams: %w", err)
|
||||||
|
}
|
||||||
|
for _, t := range teams {
|
||||||
|
if t.IncludesAllRepositories {
|
||||||
|
if err := models.AddRepository(ctx, t, repo); err != nil {
|
||||||
|
return fmt.Errorf("AddRepository: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isAdmin, err := access_model.IsUserRepoAdmin(ctx, repo, doer); err != nil {
|
||||||
|
return fmt.Errorf("IsUserRepoAdmin: %w", err)
|
||||||
|
} else if !isAdmin {
|
||||||
|
// Make creator repo admin if it wasn't assigned automatically
|
||||||
|
if err = AddOrUpdateCollaborator(ctx, repo, doer, perm.AccessModeAdmin); err != nil {
|
||||||
|
return fmt.Errorf("AddCollaborator: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if err = access_model.RecalculateAccesses(ctx, repo); err != nil {
|
||||||
|
// Organization automatically called this in AddRepository method.
|
||||||
|
return fmt.Errorf("RecalculateAccesses: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if setting.Service.AutoWatchNewRepos {
|
||||||
|
if err = repo_model.WatchRepo(ctx, doer, repo, true); err != nil {
|
||||||
|
return fmt.Errorf("WatchRepo: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = webhook.CopyDefaultWebhooksToRepo(ctx, repo.ID); err != nil {
|
||||||
|
return fmt.Errorf("CopyDefaultWebhooksToRepo: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = db.WithTx(ctx, func(txCtx context.Context) error {
|
err = db.WithTx(ctx, func(txCtx context.Context) error {
|
||||||
if err = repo_module.CreateRepositoryByExample(txCtx, doer, owner, repo, false, true); err != nil {
|
if err = CreateRepositoryByExample(txCtx, doer, owner, repo, false, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -343,7 +343,7 @@ func generateRepository(ctx context.Context, doer, owner *user_model.User, templ
|
||||||
ObjectFormatName: templateRepo.ObjectFormatName,
|
ObjectFormatName: templateRepo.ObjectFormatName,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = repo_module.CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil {
|
if err = CreateRepositoryByExample(ctx, doer, owner, generateRepo, false, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/globallock"
|
"code.gitea.io/gitea/modules/globallock"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
notify_service "code.gitea.io/gitea/services/notify"
|
notify_service "code.gitea.io/gitea/services/notify"
|
||||||
)
|
)
|
||||||
|
@ -419,10 +418,7 @@ func StartRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.Use
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !hasAccess {
|
if !hasAccess {
|
||||||
if err := repo_module.AddCollaborator(ctx, repo, newOwner); err != nil {
|
if err := AddOrUpdateCollaborator(ctx, repo, newOwner, perm.AccessModeRead); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := repo_model.ChangeCollaborationAccessMode(ctx, repo, newOwner.ID, perm.AccessModeRead); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
templates/swagger/v1_json.tmpl
generated
2
templates/swagger/v1_json.tmpl
generated
|
@ -5095,7 +5095,7 @@
|
||||||
"tags": [
|
"tags": [
|
||||||
"repository"
|
"repository"
|
||||||
],
|
],
|
||||||
"summary": "Add a collaborator to a repository",
|
"summary": "Add or Update a collaborator to a repository",
|
||||||
"operationId": "repoAddCollaborator",
|
"operationId": "repoAddCollaborator",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue