From 81f30218cf20e95c605513af3a6730dcf095e4a6 Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Tue, 31 Dec 2024 03:19:53 -0800
Subject: [PATCH] Use project's redirect url instead of composing url (#33058)

Fix #32992

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
(cherry picked from commit 20c7fba60157067252af49da41b6f8929a5ae31a)

Conflicts:
	routers/web/repo/issue_new.go
  the function is at routers/web/repo/issue.go in Forgejo
---
 models/project/project.go    | 12 ++++++++++--
 routers/web/org/projects.go  |  6 +++---
 routers/web/repo/issue.go    | 13 ++++++++++---
 routers/web/repo/projects.go |  6 +++---
 4 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/models/project/project.go b/models/project/project.go
index 245838abb5..beffffcdfc 100644
--- a/models/project/project.go
+++ b/models/project/project.go
@@ -126,6 +126,14 @@ func (p *Project) LoadRepo(ctx context.Context) (err error) {
 	return err
 }
 
+func ProjectLinkForOrg(org *user_model.User, projectID int64) string { //nolint
+	return fmt.Sprintf("%s/-/projects/%d", org.HomeLink(), projectID)
+}
+
+func ProjectLinkForRepo(repo *repo_model.Repository, projectID int64) string { //nolint
+	return fmt.Sprintf("%s/projects/%d", repo.Link(), projectID)
+}
+
 // Link returns the project's relative URL.
 func (p *Project) Link(ctx context.Context) string {
 	if p.OwnerID > 0 {
@@ -134,7 +142,7 @@ func (p *Project) Link(ctx context.Context) string {
 			log.Error("LoadOwner: %v", err)
 			return ""
 		}
-		return fmt.Sprintf("%s/-/projects/%d", p.Owner.HomeLink(), p.ID)
+		return ProjectLinkForOrg(p.Owner, p.ID)
 	}
 	if p.RepoID > 0 {
 		err := p.LoadRepo(ctx)
@@ -142,7 +150,7 @@ func (p *Project) Link(ctx context.Context) string {
 			log.Error("LoadRepo: %v", err)
 			return ""
 		}
-		return fmt.Sprintf("%s/projects/%d", p.Repo.Link(), p.ID)
+		return ProjectLinkForRepo(p.Repo, p.ID)
 	}
 	return ""
 }
diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go
index 64d233fc45..32eb6eeef1 100644
--- a/routers/web/org/projects.go
+++ b/routers/web/org/projects.go
@@ -209,7 +209,7 @@ func ChangeProjectStatus(ctx *context.Context) {
 		ctx.NotFoundOrServerError("ChangeProjectStatusByRepoIDAndID", project_model.IsErrProjectNotExist, err)
 		return
 	}
-	ctx.JSONRedirect(fmt.Sprintf("%s/-/projects/%d", ctx.ContextUser.HomeLink(), id))
+	ctx.JSONRedirect(project_model.ProjectLinkForOrg(ctx.ContextUser, id))
 }
 
 // DeleteProject delete a project
@@ -259,7 +259,7 @@ func RenderEditProject(ctx *context.Context) {
 	ctx.Data["redirect"] = ctx.FormString("redirect")
 	ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
 	ctx.Data["card_type"] = p.CardType
-	ctx.Data["CancelLink"] = fmt.Sprintf("%s/-/projects/%d", ctx.ContextUser.HomeLink(), p.ID)
+	ctx.Data["CancelLink"] = project_model.ProjectLinkForOrg(ctx.ContextUser, p.ID)
 
 	ctx.HTML(http.StatusOK, tplProjectsNew)
 }
@@ -273,7 +273,7 @@ func EditProjectPost(ctx *context.Context) {
 	ctx.Data["PageIsViewProjects"] = true
 	ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
 	ctx.Data["CardTypes"] = project_model.GetCardConfig()
-	ctx.Data["CancelLink"] = fmt.Sprintf("%s/-/projects/%d", ctx.ContextUser.HomeLink(), projectID)
+	ctx.Data["CancelLink"] = project_model.ProjectLinkForOrg(ctx.ContextUser, projectID)
 
 	shared_user.RenderUserHeader(ctx)
 
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index b537afdab5..61711095b9 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -1291,10 +1291,17 @@ func NewIssuePost(ctx *context.Context) {
 
 	log.Trace("Issue created: %d/%d", repo.ID, issue.ID)
 	if ctx.FormString("redirect_after_creation") == "project" && projectID > 0 {
-		ctx.JSONRedirect(ctx.Repo.RepoLink + "/projects/" + strconv.FormatInt(projectID, 10))
-	} else {
-		ctx.JSONRedirect(issue.Link())
+		project, err := project_model.GetProjectByID(ctx, projectID)
+		if err == nil {
+			if project.Type == project_model.TypeOrganization {
+				ctx.JSONRedirect(project_model.ProjectLinkForOrg(ctx.Repo.Owner, project.ID))
+			} else {
+				ctx.JSONRedirect(project_model.ProjectLinkForRepo(repo, project.ID))
+			}
+			return
+		}
 	}
+	ctx.JSONRedirect(issue.Link())
 }
 
 // roleDescriptor returns the role descriptor for a comment in/with the given repo, poster and issue
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index f4b027dae1..55a422453f 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -183,7 +183,7 @@ func ChangeProjectStatus(ctx *context.Context) {
 		ctx.NotFoundOrServerError("ChangeProjectStatusByRepoIDAndID", project_model.IsErrProjectNotExist, err)
 		return
 	}
-	ctx.JSONRedirect(fmt.Sprintf("%s/projects/%d", ctx.Repo.RepoLink, id))
+	ctx.JSONRedirect(project_model.ProjectLinkForRepo(ctx.Repo.Repository, id))
 }
 
 // DeleteProject delete a project
@@ -237,7 +237,7 @@ func RenderEditProject(ctx *context.Context) {
 	ctx.Data["content"] = p.Description
 	ctx.Data["card_type"] = p.CardType
 	ctx.Data["redirect"] = ctx.FormString("redirect")
-	ctx.Data["CancelLink"] = fmt.Sprintf("%s/projects/%d", ctx.Repo.Repository.Link(), p.ID)
+	ctx.Data["CancelLink"] = project_model.ProjectLinkForRepo(ctx.Repo.Repository, p.ID)
 
 	ctx.HTML(http.StatusOK, tplProjectsNew)
 }
@@ -251,7 +251,7 @@ func EditProjectPost(ctx *context.Context) {
 	ctx.Data["PageIsEditProjects"] = true
 	ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
 	ctx.Data["CardTypes"] = project_model.GetCardConfig()
-	ctx.Data["CancelLink"] = fmt.Sprintf("%s/projects/%d", ctx.Repo.Repository.Link(), projectID)
+	ctx.Data["CancelLink"] = project_model.ProjectLinkForRepo(ctx.Repo.Repository, projectID)
 
 	if ctx.HasError() {
 		ctx.HTML(http.StatusOK, tplProjectsNew)