From a4dac596434df0af7de28d9c1f4630ba32b10515 Mon Sep 17 00:00:00 2001 From: Edip Emre Bodur Date: Tue, 13 Aug 2024 05:53:43 +0300 Subject: [PATCH] Fixes for unreachable project issues when transfer repository from organization (#31770) When transferring repositories that have issues linked to a project board to another organization, the issues remain associated with the original project board. This causes the columns in the project board to become bugged, making it difficult to move other issues in or out of the affected columns. As a solution, I removed the issue relations since the other organization does not have this project table. Fix for #31538 Co-authored-by: Jason Song --- models/project/issue.go | 6 ++++++ models/project/project.go | 6 ++++++ options/locale/locale_en-US.ini | 1 + services/repository/transfer.go | 17 +++++++++++++++++ templates/repo/settings/options.tmpl | 3 ++- 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/models/project/issue.go b/models/project/issue.go index 1c31b154ce..b4347a9c2b 100644 --- a/models/project/issue.go +++ b/models/project/issue.go @@ -117,3 +117,9 @@ func (c *Column) moveIssuesToAnotherColumn(ctx context.Context, newColumn *Colum return nil }) } + +// DeleteAllProjectIssueByIssueIDsAndProjectIDs delete all project's issues by issue's and project's ids +func DeleteAllProjectIssueByIssueIDsAndProjectIDs(ctx context.Context, issueIDs, projectIDs []int64) error { + _, err := db.GetEngine(ctx).In("project_id", projectIDs).In("issue_id", issueIDs).Delete(&ProjectIssue{}) + return err +} diff --git a/models/project/project.go b/models/project/project.go index 8cebf34b5e..050ccf44e0 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -296,6 +296,12 @@ func GetProjectForRepoByID(ctx context.Context, repoID, id int64) (*Project, err return p, nil } +// GetAllProjectsIDsByOwnerID returns the all projects ids it owns +func GetAllProjectsIDsByOwnerIDAndType(ctx context.Context, ownerID int64, projectType Type) ([]int64, error) { + projects := make([]int64, 0) + return projects, db.GetEngine(ctx).Table(&Project{}).Where("owner_id=? AND type=?", ownerID, projectType).Cols("id").Find(&projects) +} + // UpdateProject updates project properties func UpdateProject(ctx context.Context, p *Project) error { if !IsCardTypeValid(p.CardType) { diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index b30504edd7..f3a7a38951 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2186,6 +2186,7 @@ settings.transfer_in_progress = There is currently an ongoing transfer. Please c settings.transfer_notices_1 = - You will lose access to the repository if you transfer it to an individual user. settings.transfer_notices_2 = - You will keep access to the repository if you transfer it to an organization that you (co-)own. settings.transfer_notices_3 = - If the repository is private and is transferred to an individual user, this action makes sure that the user does have at least read permission (and changes permissions if necessary). +settings.transfer_notices_4 = - If the repository belongs to an organization, and you transfer it to another organization or individual, you will lose the links between the repository's issues and the organization's project board. settings.transfer_owner = New Owner settings.transfer_perform = Perform Transfer settings.transfer_started = This repository has been marked for transfer and awaits confirmation from "%s" diff --git a/services/repository/transfer.go b/services/repository/transfer.go index 9e0ff7ae14..f48653072a 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" + project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -177,6 +178,22 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName } } + // Remove project's issues that belong to old organization's projects + if oldOwner.IsOrganization() { + projects, err := project_model.GetAllProjectsIDsByOwnerIDAndType(ctx, oldOwner.ID, project_model.TypeOrganization) + if err != nil { + return fmt.Errorf("Unable to find old org projects: %w", err) + } + issues, err := issues_model.GetIssueIDsByRepoID(ctx, repo.ID) + if err != nil { + return fmt.Errorf("Unable to find repo's issues: %w", err) + } + err = project_model.DeleteAllProjectIssueByIssueIDsAndProjectIDs(ctx, issues, projects) + if err != nil { + return fmt.Errorf("Unable to delete project's issues: %w", err) + } + } + if newOwner.IsOrganization() { teams, err := organization.FindOrgTeams(ctx, newOwner.ID) if err != nil { diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index f12bbbdf4a..8f71f0020f 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -957,7 +957,8 @@
{{ctx.Locale.Tr "repo.settings.transfer_notices_1"}}
{{ctx.Locale.Tr "repo.settings.transfer_notices_2"}}
- {{ctx.Locale.Tr "repo.settings.transfer_notices_3"}} + {{ctx.Locale.Tr "repo.settings.transfer_notices_3"}}
+ {{ctx.Locale.Tr "repo.settings.transfer_notices_4"}}
{{.CsrfTokenHtml}}