mirror of https://github.com/go-gitea/gitea.git
Move RepoTransfer from models to models/repo sub package (#32506)
`RepoTransfer` now is at models, but if we want to move it into `repo` model, it will depend on `Team`. So this PR also makes repo model depend on org model to make it possible. Just refactor, no code change. - [x] Move `DeleteOrganization` from `models/organization` to service layer - [x] Move `AccessibleTeamReposEnv` to `models/repo` - [x] Move `RepoTransfer` from `models` to `models/repo` - [x] Merge `getUserTeamIDs` and `GetUserTeamIDs`, Merge `GetUserTeams` and `getUserTeams`. - [x] Remove `Team`'s `Repos []*repo_model.Repository` to avoid dependency recycle.
This commit is contained in:
parent
b945742293
commit
e4c4629465
|
@ -511,7 +511,7 @@ func ActivityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.RequestedTeam != nil {
|
if opts.RequestedTeam != nil {
|
||||||
env := organization.OrgFromUser(opts.RequestedUser).AccessibleTeamReposEnv(ctx, opts.RequestedTeam)
|
env := repo_model.AccessibleTeamReposEnv(ctx, organization.OrgFromUser(opts.RequestedUser), opts.RequestedTeam)
|
||||||
teamRepoIDs, err := env.RepoIDs(1, opts.RequestedUser.NumRepos)
|
teamRepoIDs, err := env.RepoIDs(1, opts.RequestedUser.NumRepos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("GetTeamRepositories: %w", err)
|
return nil, fmt.Errorf("GetTeamRepositories: %w", err)
|
||||||
|
|
|
@ -72,48 +72,6 @@ func (err ErrDeleteLastAdminUser) Error() string {
|
||||||
return fmt.Sprintf("can not delete the last admin user [uid: %d]", err.UID)
|
return fmt.Sprintf("can not delete the last admin user [uid: %d]", err.UID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrNoPendingRepoTransfer is an error type for repositories without a pending
|
|
||||||
// transfer request
|
|
||||||
type ErrNoPendingRepoTransfer struct {
|
|
||||||
RepoID int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrNoPendingRepoTransfer) Error() string {
|
|
||||||
return fmt.Sprintf("repository doesn't have a pending transfer [repo_id: %d]", err.RepoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrNoPendingTransfer is an error type when a repository has no pending
|
|
||||||
// transfers
|
|
||||||
func IsErrNoPendingTransfer(err error) bool {
|
|
||||||
_, ok := err.(ErrNoPendingRepoTransfer)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrNoPendingRepoTransfer) Unwrap() error {
|
|
||||||
return util.ErrNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrRepoTransferInProgress represents the state of a repository that has an
|
|
||||||
// ongoing transfer
|
|
||||||
type ErrRepoTransferInProgress struct {
|
|
||||||
Uname string
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrRepoTransferInProgress checks if an error is a ErrRepoTransferInProgress.
|
|
||||||
func IsErrRepoTransferInProgress(err error) bool {
|
|
||||||
_, ok := err.(ErrRepoTransferInProgress)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrRepoTransferInProgress) Error() string {
|
|
||||||
return fmt.Sprintf("repository is already being transferred [uname: %s, name: %s]", err.Uname, err.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrRepoTransferInProgress) Unwrap() error {
|
|
||||||
return util.ErrAlreadyExist
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
|
// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
|
||||||
type ErrInvalidCloneAddr struct {
|
type ErrInvalidCloneAddr struct {
|
||||||
Host string
|
Host string
|
||||||
|
|
|
@ -9,11 +9,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
secret_model "code.gitea.io/gitea/models/secret"
|
|
||||||
"code.gitea.io/gitea/models/unit"
|
"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"
|
||||||
|
@ -407,33 +404,6 @@ func GetOrgByName(ctx context.Context, name string) (*Organization, error) {
|
||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteOrganization deletes models associated to an organization.
|
|
||||||
func DeleteOrganization(ctx context.Context, org *Organization) error {
|
|
||||||
if org.Type != user_model.UserTypeOrganization {
|
|
||||||
return fmt.Errorf("%s is a user not an organization", org.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.DeleteBeans(ctx,
|
|
||||||
&Team{OrgID: org.ID},
|
|
||||||
&OrgUser{OrgID: org.ID},
|
|
||||||
&TeamUser{OrgID: org.ID},
|
|
||||||
&TeamUnit{OrgID: org.ID},
|
|
||||||
&TeamInvite{OrgID: org.ID},
|
|
||||||
&secret_model.Secret{OwnerID: org.ID},
|
|
||||||
&user_model.Blocking{BlockerID: org.ID},
|
|
||||||
&actions_model.ActionRunner{OwnerID: org.ID},
|
|
||||||
&actions_model.ActionRunnerToken{OwnerID: org.ID},
|
|
||||||
); err != nil {
|
|
||||||
return fmt.Errorf("DeleteBeans: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := db.GetEngine(ctx).ID(org.ID).Delete(new(user_model.User)); err != nil {
|
|
||||||
return fmt.Errorf("Delete: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgUserMaxAuthorizeLevel returns highest authorize level of user in an organization
|
// GetOrgUserMaxAuthorizeLevel returns highest authorize level of user in an organization
|
||||||
func (org *Organization) GetOrgUserMaxAuthorizeLevel(ctx context.Context, uid int64) (perm.AccessMode, error) {
|
func (org *Organization) GetOrgUserMaxAuthorizeLevel(ctx context.Context, uid int64) (perm.AccessMode, error) {
|
||||||
var authorize perm.AccessMode
|
var authorize perm.AccessMode
|
||||||
|
@ -604,7 +574,9 @@ func RemoveOrgRepo(ctx context.Context, orgID, repoID int64) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (org *Organization) getUserTeams(ctx context.Context, userID int64, cols ...string) ([]*Team, error) {
|
// GetUserTeams returns all teams that belong to user,
|
||||||
|
// and that the user has joined.
|
||||||
|
func (org *Organization) GetUserTeams(ctx context.Context, userID int64, cols ...string) ([]*Team, error) {
|
||||||
teams := make([]*Team, 0, org.NumTeams)
|
teams := make([]*Team, 0, org.NumTeams)
|
||||||
return teams, db.GetEngine(ctx).
|
return teams, db.GetEngine(ctx).
|
||||||
Where("`team_user`.org_id = ?", org.ID).
|
Where("`team_user`.org_id = ?", org.ID).
|
||||||
|
@ -616,7 +588,8 @@ func (org *Organization) getUserTeams(ctx context.Context, userID int64, cols ..
|
||||||
Find(&teams)
|
Find(&teams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (org *Organization) getUserTeamIDs(ctx context.Context, userID int64) ([]int64, error) {
|
// GetUserTeamIDs returns of all team IDs of the organization that user is member of.
|
||||||
|
func (org *Organization) GetUserTeamIDs(ctx context.Context, userID int64) ([]int64, error) {
|
||||||
teamIDs := make([]int64, 0, org.NumTeams)
|
teamIDs := make([]int64, 0, org.NumTeams)
|
||||||
return teamIDs, db.GetEngine(ctx).
|
return teamIDs, db.GetEngine(ctx).
|
||||||
Table("team").
|
Table("team").
|
||||||
|
@ -640,175 +613,3 @@ func getUserTeamIDsQueryBuilder(orgID, userID int64) *builder.Builder {
|
||||||
func (org *Organization) TeamsWithAccessToRepo(ctx context.Context, repoID int64, mode perm.AccessMode) ([]*Team, error) {
|
func (org *Organization) TeamsWithAccessToRepo(ctx context.Context, repoID int64, mode perm.AccessMode) ([]*Team, error) {
|
||||||
return GetTeamsWithAccessToRepo(ctx, org.ID, repoID, mode)
|
return GetTeamsWithAccessToRepo(ctx, org.ID, repoID, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserTeamIDs returns of all team IDs of the organization that user is member of.
|
|
||||||
func (org *Organization) GetUserTeamIDs(ctx context.Context, userID int64) ([]int64, error) {
|
|
||||||
return org.getUserTeamIDs(ctx, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserTeams returns all teams that belong to user,
|
|
||||||
// and that the user has joined.
|
|
||||||
func (org *Organization) GetUserTeams(ctx context.Context, userID int64) ([]*Team, error) {
|
|
||||||
return org.getUserTeams(ctx, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessibleReposEnvironment operations involving the repositories that are
|
|
||||||
// accessible to a particular user
|
|
||||||
type AccessibleReposEnvironment interface {
|
|
||||||
CountRepos() (int64, error)
|
|
||||||
RepoIDs(page, pageSize int) ([]int64, error)
|
|
||||||
Repos(page, pageSize int) (repo_model.RepositoryList, error)
|
|
||||||
MirrorRepos() (repo_model.RepositoryList, error)
|
|
||||||
AddKeyword(keyword string)
|
|
||||||
SetSort(db.SearchOrderBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
type accessibleReposEnv struct {
|
|
||||||
org *Organization
|
|
||||||
user *user_model.User
|
|
||||||
team *Team
|
|
||||||
teamIDs []int64
|
|
||||||
ctx context.Context
|
|
||||||
keyword string
|
|
||||||
orderBy db.SearchOrderBy
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessibleReposEnv builds an AccessibleReposEnvironment for the repositories in `org`
|
|
||||||
// that are accessible to the specified user.
|
|
||||||
func AccessibleReposEnv(ctx context.Context, org *Organization, userID int64) (AccessibleReposEnvironment, error) {
|
|
||||||
var user *user_model.User
|
|
||||||
|
|
||||||
if userID > 0 {
|
|
||||||
u, err := user_model.GetUserByID(ctx, userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
user = u
|
|
||||||
}
|
|
||||||
|
|
||||||
teamIDs, err := org.getUserTeamIDs(ctx, userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &accessibleReposEnv{
|
|
||||||
org: org,
|
|
||||||
user: user,
|
|
||||||
teamIDs: teamIDs,
|
|
||||||
ctx: ctx,
|
|
||||||
orderBy: db.SearchOrderByRecentUpdated,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessibleTeamReposEnv an AccessibleReposEnvironment for the repositories in `org`
|
|
||||||
// that are accessible to the specified team.
|
|
||||||
func (org *Organization) AccessibleTeamReposEnv(ctx context.Context, team *Team) AccessibleReposEnvironment {
|
|
||||||
return &accessibleReposEnv{
|
|
||||||
org: org,
|
|
||||||
team: team,
|
|
||||||
ctx: ctx,
|
|
||||||
orderBy: db.SearchOrderByRecentUpdated,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) cond() builder.Cond {
|
|
||||||
cond := builder.NewCond()
|
|
||||||
if env.team != nil {
|
|
||||||
cond = cond.And(builder.Eq{"team_repo.team_id": env.team.ID})
|
|
||||||
} else {
|
|
||||||
if env.user == nil || !env.user.IsRestricted {
|
|
||||||
cond = cond.Or(builder.Eq{
|
|
||||||
"`repository`.owner_id": env.org.ID,
|
|
||||||
"`repository`.is_private": false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if len(env.teamIDs) > 0 {
|
|
||||||
cond = cond.Or(builder.In("team_repo.team_id", env.teamIDs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if env.keyword != "" {
|
|
||||||
cond = cond.And(builder.Like{"`repository`.lower_name", strings.ToLower(env.keyword)})
|
|
||||||
}
|
|
||||||
return cond
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) CountRepos() (int64, error) {
|
|
||||||
repoCount, err := db.GetEngine(env.ctx).
|
|
||||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
|
||||||
Where(env.cond()).
|
|
||||||
Distinct("`repository`.id").
|
|
||||||
Count(&repo_model.Repository{})
|
|
||||||
if err != nil {
|
|
||||||
return 0, fmt.Errorf("count user repositories in organization: %w", err)
|
|
||||||
}
|
|
||||||
return repoCount, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
|
|
||||||
if page <= 0 {
|
|
||||||
page = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
repoIDs := make([]int64, 0, pageSize)
|
|
||||||
return repoIDs, db.GetEngine(env.ctx).
|
|
||||||
Table("repository").
|
|
||||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
|
||||||
Where(env.cond()).
|
|
||||||
GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]).
|
|
||||||
OrderBy(string(env.orderBy)).
|
|
||||||
Limit(pageSize, (page-1)*pageSize).
|
|
||||||
Cols("`repository`.id").
|
|
||||||
Find(&repoIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) Repos(page, pageSize int) (repo_model.RepositoryList, error) {
|
|
||||||
repoIDs, err := env.RepoIDs(page, pageSize)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("GetUserRepositoryIDs: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, len(repoIDs))
|
|
||||||
if len(repoIDs) == 0 {
|
|
||||||
return repos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return repos, db.GetEngine(env.ctx).
|
|
||||||
In("`repository`.id", repoIDs).
|
|
||||||
OrderBy(string(env.orderBy)).
|
|
||||||
Find(&repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
|
||||||
repoIDs := make([]int64, 0, 10)
|
|
||||||
return repoIDs, db.GetEngine(env.ctx).
|
|
||||||
Table("repository").
|
|
||||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
|
||||||
Where(env.cond()).
|
|
||||||
GroupBy("`repository`.id, `repository`.updated_unix").
|
|
||||||
OrderBy(string(env.orderBy)).
|
|
||||||
Cols("`repository`.id").
|
|
||||||
Find(&repoIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) MirrorRepos() (repo_model.RepositoryList, error) {
|
|
||||||
repoIDs, err := env.MirrorRepoIDs()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("MirrorRepoIDs: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, len(repoIDs))
|
|
||||||
if len(repoIDs) == 0 {
|
|
||||||
return repos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return repos, db.GetEngine(env.ctx).
|
|
||||||
In("`repository`.id", repoIDs).
|
|
||||||
Find(&repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) AddKeyword(keyword string) {
|
|
||||||
env.keyword = keyword
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) SetSort(orderBy db.SearchOrderBy) {
|
|
||||||
env.orderBy = orderBy
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package organization
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetOrgRepositories get repos belonging to the given organization
|
|
||||||
func GetOrgRepositories(ctx context.Context, orgID int64) (repo_model.RepositoryList, error) {
|
|
||||||
var orgRepos []*repo_model.Repository
|
|
||||||
return orgRepos, db.GetEngine(ctx).Where("owner_id = ?", orgID).Find(&orgRepos)
|
|
||||||
}
|
|
|
@ -318,7 +318,7 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||||
testSuccess := func(userID, expectedCount int64) {
|
testSuccess := func(userID, expectedCount int64) {
|
||||||
env, err := organization.AccessibleReposEnv(db.DefaultContext, org, userID)
|
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
count, err := env.CountRepos()
|
count, err := env.CountRepos()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -332,7 +332,7 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||||
env, err := organization.AccessibleReposEnv(db.DefaultContext, org, userID)
|
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
repoIDs, err := env.RepoIDs(1, 100)
|
repoIDs, err := env.RepoIDs(1, 100)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -346,7 +346,7 @@ func TestAccessibleReposEnv_Repos(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||||
env, err := organization.AccessibleReposEnv(db.DefaultContext, org, userID)
|
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
repos, err := env.Repos(1, 100)
|
repos, err := env.Repos(1, 100)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -365,7 +365,7 @@ func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||||
env, err := organization.AccessibleReposEnv(db.DefaultContext, org, userID)
|
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
repos, err := env.MirrorRepos()
|
repos, err := env.MirrorRepos()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
"code.gitea.io/gitea/models/unit"
|
"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"
|
||||||
|
@ -78,9 +77,8 @@ type Team struct {
|
||||||
LowerName string
|
LowerName string
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
AccessMode perm.AccessMode `xorm:"'authorize'"`
|
AccessMode perm.AccessMode `xorm:"'authorize'"`
|
||||||
Repos []*repo_model.Repository `xorm:"-"`
|
Members []*user_model.User `xorm:"-"`
|
||||||
Members []*user_model.User `xorm:"-"`
|
|
||||||
NumRepos int
|
NumRepos int
|
||||||
NumMembers int
|
NumMembers int
|
||||||
Units []*TeamUnit `xorm:"-"`
|
Units []*TeamUnit `xorm:"-"`
|
||||||
|
@ -155,17 +153,6 @@ func (t *Team) IsMember(ctx context.Context, userID int64) bool {
|
||||||
return isMember
|
return isMember
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadRepositories returns paginated repositories in team of organization.
|
|
||||||
func (t *Team) LoadRepositories(ctx context.Context) (err error) {
|
|
||||||
if t.Repos != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
t.Repos, err = GetTeamRepositories(ctx, &SearchTeamRepoOptions{
|
|
||||||
TeamID: t.ID,
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadMembers returns paginated members in team of organization.
|
// LoadMembers returns paginated members in team of organization.
|
||||||
func (t *Team) LoadMembers(ctx context.Context) (err error) {
|
func (t *Team) LoadMembers(ctx context.Context) (err error) {
|
||||||
t.Members, err = GetTeamMembers(ctx, &SearchMembersOptions{
|
t.Members, err = GetTeamMembers(ctx, &SearchMembersOptions{
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
|
@ -98,11 +97,11 @@ func SearchTeam(ctx context.Context, opts *SearchTeamOptions) (TeamList, int64,
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRepoTeams gets the list of teams that has access to the repository
|
// GetRepoTeams gets the list of teams that has access to the repository
|
||||||
func GetRepoTeams(ctx context.Context, repo *repo_model.Repository) (teams TeamList, err error) {
|
func GetRepoTeams(ctx context.Context, orgID, repoID int64) (teams TeamList, err error) {
|
||||||
return teams, db.GetEngine(ctx).
|
return teams, db.GetEngine(ctx).
|
||||||
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||||
Where("team.org_id = ?", repo.OwnerID).
|
Where("team.org_id = ?", orgID).
|
||||||
And("team_repo.repo_id=?", repo.ID).
|
And("team_repo.repo_id=?", repoID).
|
||||||
OrderBy("CASE WHEN name LIKE '" + OwnerTeamName + "' THEN '' ELSE name END").
|
OrderBy("CASE WHEN name LIKE '" + OwnerTeamName + "' THEN '' ELSE name END").
|
||||||
Find(&teams)
|
Find(&teams)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
|
||||||
"xorm.io/builder"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TeamRepo represents an team-repository relation.
|
// TeamRepo represents an team-repository relation.
|
||||||
|
@ -32,29 +29,6 @@ func HasTeamRepo(ctx context.Context, orgID, teamID, repoID int64) bool {
|
||||||
return has
|
return has
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchTeamRepoOptions struct {
|
|
||||||
db.ListOptions
|
|
||||||
TeamID int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRepositories returns paginated repositories in team of organization.
|
|
||||||
func GetTeamRepositories(ctx context.Context, opts *SearchTeamRepoOptions) (repo_model.RepositoryList, error) {
|
|
||||||
sess := db.GetEngine(ctx)
|
|
||||||
if opts.TeamID > 0 {
|
|
||||||
sess = sess.In("id",
|
|
||||||
builder.Select("repo_id").
|
|
||||||
From("team_repo").
|
|
||||||
Where(builder.Eq{"team_id": opts.TeamID}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if opts.PageSize > 0 {
|
|
||||||
sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
|
|
||||||
}
|
|
||||||
var repos []*repo_model.Repository
|
|
||||||
return repos, sess.OrderBy("repository.name").
|
|
||||||
Find(&repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddTeamRepo adds a repo for an organization's team
|
// AddTeamRepo adds a repo for an organization's team
|
||||||
func AddTeamRepo(ctx context.Context, orgID, teamID, repoID int64) error {
|
func AddTeamRepo(ctx context.Context, orgID, teamID, repoID int64) error {
|
||||||
_, err := db.GetEngine(ctx).Insert(&TeamRepo{
|
_, err := db.GetEngine(ctx).Insert(&TeamRepo{
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -42,9 +43,12 @@ func TestTeam_GetRepositories(t *testing.T) {
|
||||||
|
|
||||||
test := func(teamID int64) {
|
test := func(teamID int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
|
||||||
assert.NoError(t, team.LoadRepositories(db.DefaultContext))
|
repos, err := repo_model.GetTeamRepositories(db.DefaultContext, &repo_model.SearchTeamRepoOptions{
|
||||||
assert.Len(t, team.Repos, team.NumRepos)
|
TeamID: team.ID,
|
||||||
for _, repo := range team.Repos {
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, repos, team.NumRepos)
|
||||||
|
for _, repo := range repos {
|
||||||
unittest.AssertExistsAndLoadBean(t, &organization.TeamRepo{TeamID: teamID, RepoID: repo.ID})
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamRepo{TeamID: teamID, RepoID: repo.ID})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
org_model "code.gitea.io/gitea/models/organization"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetOrgRepositories get repos belonging to the given organization
|
||||||
|
func GetOrgRepositories(ctx context.Context, orgID int64) (RepositoryList, error) {
|
||||||
|
var orgRepos []*Repository
|
||||||
|
return orgRepos, db.GetEngine(ctx).Where("owner_id = ?", orgID).Find(&orgRepos)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchTeamRepoOptions struct {
|
||||||
|
db.ListOptions
|
||||||
|
TeamID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepositories returns paginated repositories in team of organization.
|
||||||
|
func GetTeamRepositories(ctx context.Context, opts *SearchTeamRepoOptions) (RepositoryList, error) {
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
if opts.TeamID > 0 {
|
||||||
|
sess = sess.In("id",
|
||||||
|
builder.Select("repo_id").
|
||||||
|
From("team_repo").
|
||||||
|
Where(builder.Eq{"team_id": opts.TeamID}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if opts.PageSize > 0 {
|
||||||
|
sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
|
||||||
|
}
|
||||||
|
var repos []*Repository
|
||||||
|
return repos, sess.OrderBy("repository.name").
|
||||||
|
Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessibleReposEnvironment operations involving the repositories that are
|
||||||
|
// accessible to a particular user
|
||||||
|
type AccessibleReposEnvironment interface {
|
||||||
|
CountRepos() (int64, error)
|
||||||
|
RepoIDs(page, pageSize int) ([]int64, error)
|
||||||
|
Repos(page, pageSize int) (RepositoryList, error)
|
||||||
|
MirrorRepos() (RepositoryList, error)
|
||||||
|
AddKeyword(keyword string)
|
||||||
|
SetSort(db.SearchOrderBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
type accessibleReposEnv struct {
|
||||||
|
org *org_model.Organization
|
||||||
|
user *user_model.User
|
||||||
|
team *org_model.Team
|
||||||
|
teamIDs []int64
|
||||||
|
ctx context.Context
|
||||||
|
keyword string
|
||||||
|
orderBy db.SearchOrderBy
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessibleReposEnv builds an AccessibleReposEnvironment for the repositories in `org`
|
||||||
|
// that are accessible to the specified user.
|
||||||
|
func AccessibleReposEnv(ctx context.Context, org *org_model.Organization, userID int64) (AccessibleReposEnvironment, error) {
|
||||||
|
var user *user_model.User
|
||||||
|
|
||||||
|
if userID > 0 {
|
||||||
|
u, err := user_model.GetUserByID(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
user = u
|
||||||
|
}
|
||||||
|
|
||||||
|
teamIDs, err := org.GetUserTeamIDs(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &accessibleReposEnv{
|
||||||
|
org: org,
|
||||||
|
user: user,
|
||||||
|
teamIDs: teamIDs,
|
||||||
|
ctx: ctx,
|
||||||
|
orderBy: db.SearchOrderByRecentUpdated,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessibleTeamReposEnv an AccessibleReposEnvironment for the repositories in `org`
|
||||||
|
// that are accessible to the specified team.
|
||||||
|
func AccessibleTeamReposEnv(ctx context.Context, org *org_model.Organization, team *org_model.Team) AccessibleReposEnvironment {
|
||||||
|
return &accessibleReposEnv{
|
||||||
|
org: org,
|
||||||
|
team: team,
|
||||||
|
ctx: ctx,
|
||||||
|
orderBy: db.SearchOrderByRecentUpdated,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) cond() builder.Cond {
|
||||||
|
cond := builder.NewCond()
|
||||||
|
if env.team != nil {
|
||||||
|
cond = cond.And(builder.Eq{"team_repo.team_id": env.team.ID})
|
||||||
|
} else {
|
||||||
|
if env.user == nil || !env.user.IsRestricted {
|
||||||
|
cond = cond.Or(builder.Eq{
|
||||||
|
"`repository`.owner_id": env.org.ID,
|
||||||
|
"`repository`.is_private": false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(env.teamIDs) > 0 {
|
||||||
|
cond = cond.Or(builder.In("team_repo.team_id", env.teamIDs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if env.keyword != "" {
|
||||||
|
cond = cond.And(builder.Like{"`repository`.lower_name", strings.ToLower(env.keyword)})
|
||||||
|
}
|
||||||
|
return cond
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) CountRepos() (int64, error) {
|
||||||
|
repoCount, err := db.GetEngine(env.ctx).
|
||||||
|
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||||
|
Where(env.cond()).
|
||||||
|
Distinct("`repository`.id").
|
||||||
|
Count(&Repository{})
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("count user repositories in organization: %w", err)
|
||||||
|
}
|
||||||
|
return repoCount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
|
||||||
|
if page <= 0 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
repoIDs := make([]int64, 0, pageSize)
|
||||||
|
return repoIDs, db.GetEngine(env.ctx).
|
||||||
|
Table("repository").
|
||||||
|
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||||
|
Where(env.cond()).
|
||||||
|
GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]).
|
||||||
|
OrderBy(string(env.orderBy)).
|
||||||
|
Limit(pageSize, (page-1)*pageSize).
|
||||||
|
Cols("`repository`.id").
|
||||||
|
Find(&repoIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) Repos(page, pageSize int) (RepositoryList, error) {
|
||||||
|
repoIDs, err := env.RepoIDs(page, pageSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GetUserRepositoryIDs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repos := make([]*Repository, 0, len(repoIDs))
|
||||||
|
if len(repoIDs) == 0 {
|
||||||
|
return repos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return repos, db.GetEngine(env.ctx).
|
||||||
|
In("`repository`.id", repoIDs).
|
||||||
|
OrderBy(string(env.orderBy)).
|
||||||
|
Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
||||||
|
repoIDs := make([]int64, 0, 10)
|
||||||
|
return repoIDs, db.GetEngine(env.ctx).
|
||||||
|
Table("repository").
|
||||||
|
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
||||||
|
Where(env.cond()).
|
||||||
|
GroupBy("`repository`.id, `repository`.updated_unix").
|
||||||
|
OrderBy(string(env.orderBy)).
|
||||||
|
Cols("`repository`.id").
|
||||||
|
Find(&repoIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) MirrorRepos() (RepositoryList, error) {
|
||||||
|
repoIDs, err := env.MirrorRepoIDs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("MirrorRepoIDs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repos := make([]*Repository, 0, len(repoIDs))
|
||||||
|
if len(repoIDs) == 0 {
|
||||||
|
return repos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return repos, db.GetEngine(env.ctx).
|
||||||
|
In("`repository`.id", repoIDs).
|
||||||
|
Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) AddKeyword(keyword string) {
|
||||||
|
env.keyword = keyword
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) SetSort(orderBy db.SearchOrderBy) {
|
||||||
|
env.orderBy = orderBy
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package models
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -10,16 +10,58 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
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"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrNoPendingRepoTransfer is an error type for repositories without a pending
|
||||||
|
// transfer request
|
||||||
|
type ErrNoPendingRepoTransfer struct {
|
||||||
|
RepoID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrNoPendingRepoTransfer) Error() string {
|
||||||
|
return fmt.Sprintf("repository doesn't have a pending transfer [repo_id: %d]", err.RepoID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrNoPendingTransfer is an error type when a repository has no pending
|
||||||
|
// transfers
|
||||||
|
func IsErrNoPendingTransfer(err error) bool {
|
||||||
|
_, ok := err.(ErrNoPendingRepoTransfer)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrNoPendingRepoTransfer) Unwrap() error {
|
||||||
|
return util.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrRepoTransferInProgress represents the state of a repository that has an
|
||||||
|
// ongoing transfer
|
||||||
|
type ErrRepoTransferInProgress struct {
|
||||||
|
Uname string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrRepoTransferInProgress checks if an error is a ErrRepoTransferInProgress.
|
||||||
|
func IsErrRepoTransferInProgress(err error) bool {
|
||||||
|
_, ok := err.(ErrRepoTransferInProgress)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrRepoTransferInProgress) Error() string {
|
||||||
|
return fmt.Sprintf("repository is already being transferred [uname: %s, name: %s]", err.Uname, err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrRepoTransferInProgress) Unwrap() error {
|
||||||
|
return util.ErrAlreadyExist
|
||||||
|
}
|
||||||
|
|
||||||
// RepoTransfer is used to manage repository transfers
|
// RepoTransfer is used to manage repository transfers
|
||||||
type RepoTransfer struct {
|
type RepoTransfer struct { //nolint
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
DoerID int64
|
DoerID int64
|
||||||
Doer *user_model.User `xorm:"-"`
|
Doer *user_model.User `xorm:"-"`
|
||||||
|
@ -126,7 +168,7 @@ func GetPendingRepositoryTransfers(ctx context.Context, opts *PendingRepositoryT
|
||||||
|
|
||||||
// GetPendingRepositoryTransfer fetches the most recent and ongoing transfer
|
// GetPendingRepositoryTransfer fetches the most recent and ongoing transfer
|
||||||
// process for the repository
|
// process for the repository
|
||||||
func GetPendingRepositoryTransfer(ctx context.Context, repo *repo_model.Repository) (*RepoTransfer, error) {
|
func GetPendingRepositoryTransfer(ctx context.Context, repo *Repository) (*RepoTransfer, error) {
|
||||||
transfers, err := GetPendingRepositoryTransfers(ctx, &PendingRepositoryTransferOptions{RepoID: repo.ID})
|
transfers, err := GetPendingRepositoryTransfers(ctx, &PendingRepositoryTransferOptions{RepoID: repo.ID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -145,11 +187,11 @@ func DeleteRepositoryTransfer(ctx context.Context, repoID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestRepositoryReadyForTransfer make sure repo is ready to transfer
|
// TestRepositoryReadyForTransfer make sure repo is ready to transfer
|
||||||
func TestRepositoryReadyForTransfer(status repo_model.RepositoryStatus) error {
|
func TestRepositoryReadyForTransfer(status RepositoryStatus) error {
|
||||||
switch status {
|
switch status {
|
||||||
case repo_model.RepositoryBeingMigrated:
|
case RepositoryBeingMigrated:
|
||||||
return errors.New("repo is not ready, currently migrating")
|
return errors.New("repo is not ready, currently migrating")
|
||||||
case repo_model.RepositoryPendingTransfer:
|
case RepositoryPendingTransfer:
|
||||||
return ErrRepoTransferInProgress{}
|
return ErrRepoTransferInProgress{}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -159,7 +201,7 @@ func TestRepositoryReadyForTransfer(status repo_model.RepositoryStatus) error {
|
||||||
// it marks the repository transfer as "pending"
|
// it marks the repository transfer as "pending"
|
||||||
func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error {
|
func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error {
|
||||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
repo, err := repo_model.GetRepositoryByID(ctx, repoID)
|
repo, err := GetRepositoryByID(ctx, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -169,16 +211,16 @@ func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_m
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.Status = repo_model.RepositoryPendingTransfer
|
repo.Status = RepositoryPendingTransfer
|
||||||
if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil {
|
if err := UpdateRepositoryCols(ctx, repo, "status"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if new owner has repository with same name.
|
// Check if new owner has repository with same name.
|
||||||
if has, err := repo_model.IsRepositoryModelExist(ctx, newOwner, repo.Name); err != nil {
|
if has, err := IsRepositoryModelExist(ctx, newOwner, repo.Name); err != nil {
|
||||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
return repo_model.ErrRepoAlreadyExist{
|
return ErrRepoAlreadyExist{
|
||||||
Uname: newOwner.LowerName,
|
Uname: newOwner.LowerName,
|
||||||
Name: repo.Name,
|
Name: repo.Name,
|
||||||
}
|
}
|
|
@ -573,19 +573,19 @@ func GetTeamRepos(ctx *context.APIContext) {
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
team := ctx.Org.Team
|
team := ctx.Org.Team
|
||||||
teamRepos, err := organization.GetTeamRepositories(ctx, &organization.SearchTeamRepoOptions{
|
teamRepos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
TeamID: team.ID,
|
TeamID: team.ID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
|
ctx.Error(http.StatusInternalServerError, "GetTeamRepositories", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repos := make([]*api.Repository, len(teamRepos))
|
repos := make([]*api.Repository, len(teamRepos))
|
||||||
for i, repo := range teamRepos {
|
for i, repo := range teamRepos {
|
||||||
permission, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer)
|
permission, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
|
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repos[i] = convert.ToRepo(ctx, repo, permission)
|
repos[i] = convert.ToRepo(ctx, repo, permission)
|
||||||
|
|
|
@ -42,7 +42,7 @@ func ListTeams(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository)
|
teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
|
@ -108,7 +107,7 @@ func Transfer(ctx *context.APIContext) {
|
||||||
oldFullname := ctx.Repo.Repository.FullName()
|
oldFullname := ctx.Repo.Repository.FullName()
|
||||||
|
|
||||||
if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
|
if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
|
||||||
if models.IsErrRepoTransferInProgress(err) {
|
if repo_model.IsErrRepoTransferInProgress(err) {
|
||||||
ctx.Error(http.StatusConflict, "StartRepositoryTransfer", err)
|
ctx.Error(http.StatusConflict, "StartRepositoryTransfer", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -213,9 +212,9 @@ func RejectTransfer(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
|
func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
|
||||||
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
repoTransfer, err := repo_model.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrNoPendingTransfer(err) {
|
if repo_model.IsErrNoPendingTransfer(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,11 +410,15 @@ func TeamRepositories(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.Org.Team.LoadRepositories(ctx); err != nil {
|
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
||||||
ctx.ServerError("GetRepositories", err)
|
TeamID: ctx.Org.Team.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetTeamRepositories", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Units"] = unit_model.Units
|
ctx.Data["Units"] = unit_model.Units
|
||||||
|
ctx.Data["TeamRepos"] = repos
|
||||||
ctx.HTML(http.StatusOK, tplTeamRepositories)
|
ctx.HTML(http.StatusOK, tplTeamRepositories)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"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/organization"
|
||||||
|
@ -378,7 +377,7 @@ func Action(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
|
func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
|
||||||
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
repoTransfer, err := repo_model.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ func Collaboration(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
ctx.Data["Collaborators"] = users
|
ctx.Data["Collaborators"] = users
|
||||||
|
|
||||||
teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository)
|
teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetRepoTeams", err)
|
ctx.ServerError("GetRepoTeams", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -788,7 +788,7 @@ func SettingsPost(ctx *context.Context) {
|
||||||
if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, repo, nil); err != nil {
|
if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, repo, nil); err != nil {
|
||||||
if repo_model.IsErrRepoAlreadyExist(err) {
|
if repo_model.IsErrRepoAlreadyExist(err) {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
|
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
|
||||||
} else if models.IsErrRepoTransferInProgress(err) {
|
} else if repo_model.IsErrRepoTransferInProgress(err) {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.settings.transfer_in_progress"), tplSettingsOptions, nil)
|
ctx.RenderWithErr(ctx.Tr("repo.settings.transfer_in_progress"), tplSettingsOptions, nil)
|
||||||
} else if errors.Is(err, user_model.ErrBlockedUser) {
|
} else if errors.Is(err, user_model.ErrBlockedUser) {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.settings.transfer.blocked_user"), tplSettingsOptions, nil)
|
ctx.RenderWithErr(ctx.Tr("repo.settings.transfer.blocked_user"), tplSettingsOptions, nil)
|
||||||
|
@ -814,9 +814,9 @@ func SettingsPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
repoTransfer, err := repo_model.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrNoPendingTransfer(err) {
|
if repo_model.IsErrNoPendingTransfer(err) {
|
||||||
ctx.Flash.Error("repo.settings.transfer_abort_invalid")
|
ctx.Flash.Error("repo.settings.transfer_abort_invalid")
|
||||||
ctx.Redirect(repo.Link() + "/settings")
|
ctx.Redirect(repo.Link() + "/settings")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"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"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
|
@ -709,7 +708,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||||
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
|
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
|
||||||
|
|
||||||
if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer {
|
if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer {
|
||||||
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
repoTransfer, err := repo_model.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetPendingRepositoryTransfer", err)
|
ctx.ServerError("GetPendingRepositoryTransfer", err)
|
||||||
return cancel
|
return cancel
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
|
@ -158,8 +157,8 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||||
|
|
||||||
var transfer *api.RepoTransfer
|
var transfer *api.RepoTransfer
|
||||||
if repo.Status == repo_model.RepositoryPendingTransfer {
|
if repo.Status == repo_model.RepositoryPendingTransfer {
|
||||||
t, err := models.GetPendingRepositoryTransfer(ctx, repo)
|
t, err := repo_model.GetPendingRepositoryTransfer(ctx, repo)
|
||||||
if err != nil && !models.IsErrNoPendingTransfer(err) {
|
if err != nil && !repo_model.IsErrNoPendingTransfer(err) {
|
||||||
log.Warn("GetPendingRepositoryTransfer: %v", err)
|
log.Warn("GetPendingRepositoryTransfer: %v", err)
|
||||||
} else {
|
} else {
|
||||||
if err := t.LoadAttributes(ctx); err != nil {
|
if err := t.LoadAttributes(ctx); err != nil {
|
||||||
|
@ -248,7 +247,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToRepoTransfer convert a models.RepoTransfer to a structs.RepeTransfer
|
// ToRepoTransfer convert a models.RepoTransfer to a structs.RepeTransfer
|
||||||
func ToRepoTransfer(ctx context.Context, t *models.RepoTransfer) *api.RepoTransfer {
|
func ToRepoTransfer(ctx context.Context, t *repo_model.RepoTransfer) *api.RepoTransfer {
|
||||||
teams, _ := ToTeams(ctx, t.Teams, false)
|
teams, _ := ToTeams(ctx, t.Teams, false)
|
||||||
|
|
||||||
return &api.RepoTransfer{
|
return &api.RepoTransfer{
|
||||||
|
|
|
@ -8,16 +8,45 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
org_model "code.gitea.io/gitea/models/organization"
|
org_model "code.gitea.io/gitea/models/organization"
|
||||||
packages_model "code.gitea.io/gitea/models/packages"
|
packages_model "code.gitea.io/gitea/models/packages"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
secret_model "code.gitea.io/gitea/models/secret"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// deleteOrganization deletes models associated to an organization.
|
||||||
|
func deleteOrganization(ctx context.Context, org *org_model.Organization) error {
|
||||||
|
if org.Type != user_model.UserTypeOrganization {
|
||||||
|
return fmt.Errorf("%s is a user not an organization", org.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.DeleteBeans(ctx,
|
||||||
|
&org_model.Team{OrgID: org.ID},
|
||||||
|
&org_model.OrgUser{OrgID: org.ID},
|
||||||
|
&org_model.TeamUser{OrgID: org.ID},
|
||||||
|
&org_model.TeamUnit{OrgID: org.ID},
|
||||||
|
&org_model.TeamInvite{OrgID: org.ID},
|
||||||
|
&secret_model.Secret{OwnerID: org.ID},
|
||||||
|
&user_model.Blocking{BlockerID: org.ID},
|
||||||
|
&actions_model.ActionRunner{OwnerID: org.ID},
|
||||||
|
&actions_model.ActionRunnerToken{OwnerID: org.ID},
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("DeleteBeans: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := db.GetEngine(ctx).ID(org.ID).Delete(new(user_model.User)); err != nil {
|
||||||
|
return fmt.Errorf("Delete: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteOrganization completely and permanently deletes everything of organization.
|
// DeleteOrganization completely and permanently deletes everything of organization.
|
||||||
func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge bool) error {
|
func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge bool) error {
|
||||||
ctx, committer, err := db.TxContext(ctx)
|
ctx, committer, err := db.TxContext(ctx)
|
||||||
|
@ -48,7 +77,7 @@ func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge
|
||||||
return models.ErrUserOwnPackages{UID: org.ID}
|
return models.ErrUserOwnPackages{UID: org.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := org_model.DeleteOrganization(ctx, org); err != nil {
|
if err := deleteOrganization(ctx, org); err != nil {
|
||||||
return fmt.Errorf("DeleteOrganization: %w", err)
|
return fmt.Errorf("DeleteOrganization: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,11 +141,14 @@ func UpdateTeam(ctx context.Context, t *organization.Team, authChanged, includeA
|
||||||
|
|
||||||
// Update access for team members if needed.
|
// Update access for team members if needed.
|
||||||
if authChanged {
|
if authChanged {
|
||||||
if err = t.LoadRepositories(ctx); err != nil {
|
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
||||||
return fmt.Errorf("LoadRepositories: %w", err)
|
TeamID: t.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetTeamRepositories: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range t.Repos {
|
for _, repo := range repos {
|
||||||
if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
|
if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
|
||||||
return fmt.Errorf("recalculateTeamAccesses: %w", err)
|
return fmt.Errorf("recalculateTeamAccesses: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -172,10 +175,6 @@ func DeleteTeam(ctx context.Context, t *organization.Team) error {
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
if err := t.LoadRepositories(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := t.LoadMembers(ctx); err != nil {
|
if err := t.LoadMembers(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -301,8 +300,11 @@ func AddTeamMember(ctx context.Context, team *organization.Team, user *user_mode
|
||||||
// FIXME: Update watch repos batchly
|
// FIXME: Update watch repos batchly
|
||||||
if setting.Service.AutoWatchNewRepos {
|
if setting.Service.AutoWatchNewRepos {
|
||||||
// Get team and its repositories.
|
// Get team and its repositories.
|
||||||
if err := team.LoadRepositories(ctx); err != nil {
|
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
||||||
log.Error("team.LoadRepositories failed: %v", err)
|
TeamID: team.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetTeamRepositories failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: in the goroutine, it can't access the "ctx", it could only use db.DefaultContext at the moment
|
// FIXME: in the goroutine, it can't access the "ctx", it could only use db.DefaultContext at the moment
|
||||||
|
@ -312,7 +314,7 @@ func AddTeamMember(ctx context.Context, team *organization.Team, user *user_mode
|
||||||
log.Error("watch repo failed: %v", err)
|
log.Error("watch repo failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(team.Repos)
|
}(repos)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -332,7 +334,10 @@ func removeTeamMember(ctx context.Context, team *organization.Team, user *user_m
|
||||||
|
|
||||||
team.NumMembers--
|
team.NumMembers--
|
||||||
|
|
||||||
if err := team.LoadRepositories(ctx); err != nil {
|
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
||||||
|
TeamID: team.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +355,7 @@ func removeTeamMember(ctx context.Context, team *organization.Team, user *user_m
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete access to team repositories.
|
// Delete access to team repositories.
|
||||||
for _, repo := range team.Repos {
|
for _, repo := range repos {
|
||||||
if err := access_model.RecalculateUserAccess(ctx, repo, user.ID); err != nil {
|
if err := access_model.RecalculateUserAccess(ctx, repo, user.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,9 +189,12 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {
|
||||||
|
|
||||||
testTeamRepositories := func(teamID int64, repoIDs []int64) {
|
testTeamRepositories := func(teamID int64, repoIDs []int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
|
||||||
assert.NoError(t, team.LoadRepositories(db.DefaultContext), "%s: GetRepositories", team.Name)
|
repos, err := repo_model.GetTeamRepositories(db.DefaultContext, &repo_model.SearchTeamRepoOptions{
|
||||||
assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name)
|
TeamID: team.ID,
|
||||||
assert.Len(t, team.Repos, len(repoIDs), "%s: repo count", team.Name)
|
})
|
||||||
|
assert.NoError(t, err, "%s: GetTeamRepositories", team.Name)
|
||||||
|
assert.Len(t, repos, team.NumRepos, "%s: len repo", team.Name)
|
||||||
|
assert.Len(t, repos, len(repoIDs), "%s: repo count", team.Name)
|
||||||
for i, rid := range repoIDs {
|
for i, rid := range repoIDs {
|
||||||
if rid > 0 {
|
if rid > 0 {
|
||||||
assert.True(t, repo_service.HasRepository(db.DefaultContext, team, rid), "%s: HasRepository(%d) %d", rid, i)
|
assert.True(t, repo_service.HasRepository(db.DefaultContext, team, rid), "%s: HasRepository(%d) %d", rid, i)
|
||||||
|
@ -310,5 +313,5 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {
|
||||||
assert.NoError(t, repo_service.DeleteRepositoryDirectly(db.DefaultContext, user, rid), "DeleteRepository %d", i)
|
assert.NoError(t, repo_service.DeleteRepositoryDirectly(db.DefaultContext, user, rid), "DeleteRepository %d", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.NoError(t, organization.DeleteOrganization(db.DefaultContext, org), "DeleteOrganization")
|
assert.NoError(t, DeleteOrganization(db.DefaultContext, org, false), "DeleteOrganization")
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ func RemoveOrgUser(ctx context.Context, org *organization.Organization, user *us
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all repository accesses and unwatch them.
|
// Delete all repository accesses and unwatch them.
|
||||||
env, err := organization.AccessibleReposEnv(ctx, org, user.ID)
|
env, err := repo_model.AccessibleReposEnv(ctx, org, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("AccessibleReposEnv: %w", err)
|
return fmt.Errorf("AccessibleReposEnv: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ func addRepositoryToTeam(ctx context.Context, t *organization.Team, repo *repo_m
|
||||||
// If the team already has some repositories they will be left unchanged.
|
// If the team already has some repositories they will be left unchanged.
|
||||||
func AddAllRepositoriesToTeam(ctx context.Context, t *organization.Team) error {
|
func AddAllRepositoriesToTeam(ctx context.Context, t *organization.Team) error {
|
||||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
orgRepos, err := organization.GetOrgRepositories(ctx, t.OrgID)
|
orgRepos, err := repo_model.GetOrgRepositories(ctx, t.OrgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get org repos: %w", err)
|
return fmt.Errorf("get org repos: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -103,8 +103,15 @@ func RemoveAllRepositoriesFromTeam(ctx context.Context, t *organization.Team) (e
|
||||||
// Note: Shall not be called if team includes all repositories
|
// Note: Shall not be called if team includes all repositories
|
||||||
func removeAllRepositoriesFromTeam(ctx context.Context, t *organization.Team) (err error) {
|
func removeAllRepositoriesFromTeam(ctx context.Context, t *organization.Team) (err error) {
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
|
repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{
|
||||||
|
TeamID: t.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetTeamRepositories: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Delete all accesses.
|
// Delete all accesses.
|
||||||
for _, repo := range t.Repos {
|
for _, repo := range repos {
|
||||||
if err := access_model.RecalculateTeamAccesses(ctx, repo, t.ID); err != nil {
|
if err := access_model.RecalculateTeamAccesses(ctx, repo, t.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
|
@ -285,7 +284,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
|
||||||
wikiRenamed = true
|
wikiRenamed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteRepositoryTransfer(ctx, repo.ID); err != nil {
|
if err := repo_model.DeleteRepositoryTransfer(ctx, repo.ID); err != nil {
|
||||||
return fmt.Errorf("deleteRepositoryTransfer: %w", err)
|
return fmt.Errorf("deleteRepositoryTransfer: %w", err)
|
||||||
}
|
}
|
||||||
repo.Status = repo_model.RepositoryReady
|
repo.Status = repo_model.RepositoryReady
|
||||||
|
@ -388,7 +387,7 @@ func ChangeRepositoryName(ctx context.Context, doer *user_model.User, repo *repo
|
||||||
// StartRepositoryTransfer transfer a repo from one owner to a new one.
|
// StartRepositoryTransfer transfer a repo from one owner to a new one.
|
||||||
// it make repository into pending transfer state, if doer can not create repo for new owner.
|
// it make repository into pending transfer state, if doer can not create repo for new owner.
|
||||||
func StartRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
|
func StartRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
|
||||||
if err := models.TestRepositoryReadyForTransfer(repo.Status); err != nil {
|
if err := repo_model.TestRepositoryReadyForTransfer(repo.Status); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +424,7 @@ func StartRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.Use
|
||||||
|
|
||||||
// Make repo as pending for transfer
|
// Make repo as pending for transfer
|
||||||
repo.Status = repo_model.RepositoryPendingTransfer
|
repo.Status = repo_model.RepositoryPendingTransfer
|
||||||
if err := models.CreatePendingRepositoryTransfer(ctx, doer, newOwner, repo.ID, teams); err != nil {
|
if err := repo_model.CreatePendingRepositoryTransfer(ctx, doer, newOwner, repo.ID, teams); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +448,7 @@ func CancelRepositoryTransfer(ctx context.Context, repo *repo_model.Repository)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteRepositoryTransfer(ctx, repo.ID); err != nil {
|
if err := repo_model.DeleteRepositoryTransfer(ctx, repo.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"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"
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
|
@ -86,23 +85,23 @@ func TestRepositoryTransfer(t *testing.T) {
|
||||||
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
||||||
|
|
||||||
transfer, err := models.GetPendingRepositoryTransfer(db.DefaultContext, repo)
|
transfer, err := repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, transfer)
|
assert.NotNil(t, transfer)
|
||||||
|
|
||||||
// Cancel transfer
|
// Cancel transfer
|
||||||
assert.NoError(t, CancelRepositoryTransfer(db.DefaultContext, repo))
|
assert.NoError(t, CancelRepositoryTransfer(db.DefaultContext, repo))
|
||||||
|
|
||||||
transfer, err = models.GetPendingRepositoryTransfer(db.DefaultContext, repo)
|
transfer, err = repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, transfer)
|
assert.Nil(t, transfer)
|
||||||
assert.True(t, models.IsErrNoPendingTransfer(err))
|
assert.True(t, repo_model.IsErrNoPendingTransfer(err))
|
||||||
|
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
assert.NoError(t, models.CreatePendingRepositoryTransfer(db.DefaultContext, doer, user2, repo.ID, nil))
|
assert.NoError(t, repo_model.CreatePendingRepositoryTransfer(db.DefaultContext, doer, user2, repo.ID, nil))
|
||||||
|
|
||||||
transfer, err = models.GetPendingRepositoryTransfer(db.DefaultContext, repo)
|
transfer, err = repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, transfer.LoadAttributes(db.DefaultContext))
|
assert.NoError(t, transfer.LoadAttributes(db.DefaultContext))
|
||||||
assert.Equal(t, "user2", transfer.Recipient.Name)
|
assert.Equal(t, "user2", transfer.Recipient.Name)
|
||||||
|
@ -110,12 +109,12 @@ func TestRepositoryTransfer(t *testing.T) {
|
||||||
org6 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
org6 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
// Only transfer can be started at any given time
|
// Only transfer can be started at any given time
|
||||||
err = models.CreatePendingRepositoryTransfer(db.DefaultContext, doer, org6, repo.ID, nil)
|
err = repo_model.CreatePendingRepositoryTransfer(db.DefaultContext, doer, org6, repo.ID, nil)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, models.IsErrRepoTransferInProgress(err))
|
assert.True(t, repo_model.IsErrRepoTransferInProgress(err))
|
||||||
|
|
||||||
// Unknown user
|
// Unknown user
|
||||||
err = models.CreatePendingRepositoryTransfer(db.DefaultContext, doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil)
|
err = repo_model.CreatePendingRepositoryTransfer(db.DefaultContext, doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
// Cancel transfer
|
// Cancel transfer
|
||||||
|
|
|
@ -6,7 +6,6 @@ package user
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
org_model "code.gitea.io/gitea/models/organization"
|
org_model "code.gitea.io/gitea/models/organization"
|
||||||
|
@ -194,7 +193,7 @@ func unwatchRepos(ctx context.Context, watcher, repoOwner *user_model.User) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancelRepositoryTransfers(ctx context.Context, sender, recipient *user_model.User) error {
|
func cancelRepositoryTransfers(ctx context.Context, sender, recipient *user_model.User) error {
|
||||||
transfers, err := models.GetPendingRepositoryTransfers(ctx, &models.PendingRepositoryTransferOptions{
|
transfers, err := repo_model.GetPendingRepositoryTransfers(ctx, &repo_model.PendingRepositoryTransferOptions{
|
||||||
SenderID: sender.ID,
|
SenderID: sender.ID,
|
||||||
RecipientID: recipient.ID,
|
RecipientID: recipient.ID,
|
||||||
})
|
})
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui{{if not $canAddRemove}} top{{end}} attached segment">
|
<div class="ui{{if not $canAddRemove}} top{{end}} attached segment">
|
||||||
<div class="flex-list">
|
<div class="flex-list">
|
||||||
{{range .Team.Repos}}
|
{{range $.TeamRepos}}
|
||||||
<div class="flex-item tw-items-center">
|
<div class="flex-item tw-items-center">
|
||||||
<div class="flex-item-leading">
|
<div class="flex-item-leading">
|
||||||
{{template "repo/icon" .}}
|
{{template "repo/icon" .}}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
|
@ -42,7 +41,7 @@ func TestBlockUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
countRepositoryTransfers := func(t *testing.T, senderID, recipientID int64) int64 {
|
countRepositoryTransfers := func(t *testing.T, senderID, recipientID int64) int64 {
|
||||||
transfers, err := models.GetPendingRepositoryTransfers(db.DefaultContext, &models.PendingRepositoryTransferOptions{
|
transfers, err := repo_model.GetPendingRepositoryTransfers(db.DefaultContext, &repo_model.PendingRepositoryTransferOptions{
|
||||||
SenderID: senderID,
|
SenderID: senderID,
|
||||||
RecipientID: recipientID,
|
RecipientID: recipientID,
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue