Refactor repository transfer (#33211)
- Both have `RejectTransfer` and `CancelTransfer` because the permission checks are not the same. `CancelTransfer` can be done by the doer or those who have admin permission to access this repository. `RejectTransfer` can be done by the receiver user if it's an individual or those who can create repositories if it's an organization. - Some tests are wrong, this PR corrects them. --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
48183d2b05
commit
f88dbf86b3
10 changed files with 302 additions and 222 deletions
|
@ -68,6 +68,7 @@ type RepoTransfer struct { //nolint
|
|||
RecipientID int64
|
||||
Recipient *user_model.User `xorm:"-"`
|
||||
RepoID int64
|
||||
Repo *Repository `xorm:"-"`
|
||||
TeamIDs []int64
|
||||
Teams []*organization.Team `xorm:"-"`
|
||||
|
||||
|
@ -79,48 +80,65 @@ func init() {
|
|||
db.RegisterModel(new(RepoTransfer))
|
||||
}
|
||||
|
||||
// LoadAttributes fetches the transfer recipient from the database
|
||||
func (r *RepoTransfer) LoadAttributes(ctx context.Context) error {
|
||||
func (r *RepoTransfer) LoadRecipient(ctx context.Context) error {
|
||||
if r.Recipient == nil {
|
||||
u, err := user_model.GetUserByID(ctx, r.RecipientID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Recipient = u
|
||||
}
|
||||
|
||||
if r.Recipient.IsOrganization() && len(r.TeamIDs) != len(r.Teams) {
|
||||
for _, v := range r.TeamIDs {
|
||||
team, err := organization.GetTeamByID(ctx, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if team.OrgID != r.Recipient.ID {
|
||||
return fmt.Errorf("team %d belongs not to org %d", v, r.Recipient.ID)
|
||||
}
|
||||
func (r *RepoTransfer) LoadRepo(ctx context.Context) error {
|
||||
if r.Repo == nil {
|
||||
repo, err := GetRepositoryByID(ctx, r.RepoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Repo = repo
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadAttributes fetches the transfer recipient from the database
|
||||
func (r *RepoTransfer) LoadAttributes(ctx context.Context) error {
|
||||
if err := r.LoadRecipient(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Recipient.IsOrganization() && r.Teams == nil {
|
||||
teamsMap, err := organization.GetTeamsByIDs(ctx, r.TeamIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, team := range teamsMap {
|
||||
r.Teams = append(r.Teams, team)
|
||||
}
|
||||
}
|
||||
|
||||
if err := r.LoadRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Doer == nil {
|
||||
u, err := user_model.GetUserByID(ctx, r.DoerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Doer = u
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanUserAcceptTransfer checks if the user has the rights to accept/decline a repo transfer.
|
||||
// CanUserAcceptOrRejectTransfer checks if the user has the rights to accept/decline a repo transfer.
|
||||
// For user, it checks if it's himself
|
||||
// For organizations, it checks if the user is able to create repos
|
||||
func (r *RepoTransfer) CanUserAcceptTransfer(ctx context.Context, u *user_model.User) bool {
|
||||
func (r *RepoTransfer) CanUserAcceptOrRejectTransfer(ctx context.Context, u *user_model.User) bool {
|
||||
if err := r.LoadAttributes(ctx); err != nil {
|
||||
log.Error("LoadAttributes: %v", err)
|
||||
return false
|
||||
|
@ -166,6 +184,10 @@ func GetPendingRepositoryTransfers(ctx context.Context, opts *PendingRepositoryT
|
|||
Find(&transfers)
|
||||
}
|
||||
|
||||
func IsRepositoryTransferExist(ctx context.Context, repoID int64) (bool, error) {
|
||||
return db.GetEngine(ctx).Where("repo_id = ?", repoID).Exist(new(RepoTransfer))
|
||||
}
|
||||
|
||||
// GetPendingRepositoryTransfer fetches the most recent and ongoing transfer
|
||||
// process for the repository
|
||||
func GetPendingRepositoryTransfer(ctx context.Context, repo *Repository) (*RepoTransfer, error) {
|
||||
|
@ -206,11 +228,26 @@ func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_m
|
|||
return err
|
||||
}
|
||||
|
||||
if _, err := user_model.GetUserByID(ctx, newOwner.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make sure repo is ready to transfer
|
||||
if err := TestRepositoryReadyForTransfer(repo.Status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exist, err := IsRepositoryTransferExist(ctx, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist {
|
||||
return ErrRepoTransferInProgress{
|
||||
Uname: repo.Owner.LowerName,
|
||||
Name: repo.Name,
|
||||
}
|
||||
}
|
||||
|
||||
repo.Status = RepositoryPendingTransfer
|
||||
if err := UpdateRepositoryCols(ctx, repo, "status"); err != nil {
|
||||
return err
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue