This commit is contained in:
wxiaoguang 2024-05-06 12:50:26 +08:00
parent f586577008
commit 94cb84d16e
6 changed files with 34 additions and 154 deletions

View File

@ -5,7 +5,6 @@ package issues
import (
"context"
"fmt"
"code.gitea.io/gitea/models/db"
project_model "code.gitea.io/gitea/models/project"
@ -107,8 +106,15 @@ func IssueAssignOrRemoveProject(ctx context.Context, issue *Issue, doer *user_mo
if err != nil {
return err
}
if newProject.RepoID != issue.RepoID && newProject.OwnerID != issue.Repo.OwnerID {
return fmt.Errorf("issue's repository is not the same as project's repository")
if newColumnID == 0 {
newDefaultColumn, err := newProject.GetDefaultBoard(ctx)
if err != nil {
return err
}
newColumnID = newDefaultColumn.ID
}
if !newProject.CanBeAccessedByOwnerRepo(issue.Repo.OwnerID, issue.Repo.ID) {
return util.NewPermissionDeniedErrorf("issue %d can't be accessed by project %d", issue.ID, newProject.ID)
}
}
@ -128,9 +134,12 @@ func IssueAssignOrRemoveProject(ctx context.Context, issue *Issue, doer *user_mo
return err
}
}
if newProjectID == 0 || newColumnID == 0 {
if newProjectID == 0 {
return nil
}
if newColumnID == 0 {
panic("newColumnID must not be zero") // shouldn't happen
}
res := struct {
MaxSorting int64

View File

@ -161,6 +161,13 @@ func (p *Project) IsRepositoryProject() bool {
return p.Type == TypeRepository
}
func (p *Project) CanBeAccessedByOwnerRepo(ownerID, repoID int64) bool {
if p.Type == TypeOrganization {
return p.OwnerID == ownerID && p.RepoID == 0
}
return p.OwnerID == ownerID && p.RepoID == repoID
}
func init() {
db.RegisterModel(new(Project))
}

View File

@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"net/http"
"strconv"
"strings"
"code.gitea.io/gitea/models/db"
@ -390,96 +389,6 @@ func ViewProject(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplProjectsView)
}
func getActionIssues(ctx *context.Context) issues_model.IssueList {
commaSeparatedIssueIDs := ctx.FormString("issue_ids")
if len(commaSeparatedIssueIDs) == 0 {
return nil
}
issueIDs := make([]int64, 0, 10)
for _, stringIssueID := range strings.Split(commaSeparatedIssueIDs, ",") {
issueID, err := strconv.ParseInt(stringIssueID, 10, 64)
if err != nil {
ctx.ServerError("ParseInt", err)
return nil
}
issueIDs = append(issueIDs, issueID)
}
issues, err := issues_model.GetIssuesByIDs(ctx, issueIDs)
if err != nil {
ctx.ServerError("GetIssuesByIDs", err)
return nil
}
// Check access rights for all issues
issueUnitEnabled := ctx.Repo.CanRead(unit.TypeIssues)
prUnitEnabled := ctx.Repo.CanRead(unit.TypePullRequests)
for _, issue := range issues {
if issue.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound("some issue's RepoID is incorrect", errors.New("some issue's RepoID is incorrect"))
return nil
}
if issue.IsPull && !prUnitEnabled || !issue.IsPull && !issueUnitEnabled {
ctx.NotFound("IssueOrPullRequestUnitNotAllowed", nil)
return nil
}
if err = issue.LoadAttributes(ctx); err != nil {
ctx.ServerError("LoadAttributes", err)
return nil
}
}
return issues
}
// UpdateIssueProject change an issue's project
func UpdateIssueProject(ctx *context.Context) {
issues := getActionIssues(ctx)
if ctx.Written() {
return
}
if err := issues.LoadProjects(ctx); err != nil {
ctx.ServerError("LoadProjects", err)
return
}
projectID := ctx.FormInt64("id")
var dstColumnID int64
if projectID > 0 {
dstProject, err := project_model.GetProjectByID(ctx, projectID)
if err != nil {
ctx.ServerError("GetProjectByID", err)
return
}
if dstProject.OwnerID != ctx.ContextUser.ID {
ctx.JSON(http.StatusUnprocessableEntity, map[string]string{
"message": fmt.Sprintf("Project[%d] is not in Owner[%d] as expected", dstProject.ID, ctx.ContextUser.ID),
})
return
}
dstDefaultColumn, err := dstProject.GetDefaultBoard(ctx)
if err != nil {
ctx.ServerError("GetDefaultBoard", err)
return
}
dstColumnID = dstDefaultColumn.ID
}
for _, issue := range issues {
if issue.Project != nil {
if issue.Project.ID == projectID {
continue
}
}
if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, ctx.Doer, projectID, dstColumnID); err != nil {
ctx.ServerError("ChangeProjectAssign", err)
return
}
}
ctx.JSONOK()
}
// DeleteProjectBoard allows for the deletion of a project board
func DeleteProjectBoard(ctx *context.Context) {
if ctx.Doer == nil {

View File

@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
@ -389,36 +390,15 @@ func UpdateIssueProject(ctx *context.Context) {
}
projectID := ctx.FormInt64("id")
var dstColumnID int64
if projectID > 0 {
dstProject, err := project_model.GetProjectByID(ctx, projectID)
if err != nil {
ctx.ServerError("GetProjectByID", err)
return
}
for _, issue := range issues {
if dstProject.RepoID != ctx.Repo.Repository.ID && dstProject.OwnerID != issue.Repo.OwnerID {
ctx.Error(http.StatusBadRequest, "project doesn't belong to the repository")
return
}
}
dstDefaultColumn, err := dstProject.GetDefaultBoard(ctx)
if err != nil {
ctx.ServerError("GetDefaultBoard", err)
return
}
dstColumnID = dstDefaultColumn.ID
}
for _, issue := range issues {
if issue.Project != nil {
if issue.Project.ID == projectID {
if issue.Project != nil && issue.Project.ID == projectID {
continue
}
if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, ctx.Doer, projectID, 0); err != nil {
if errors.Is(err, util.ErrPermissionDenied) {
continue
}
}
if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, ctx.Doer, projectID, dstColumnID); err != nil {
ctx.ServerError("ChangeProjectAssign", err)
ctx.ServerError("IssueAssignOrRemoveProject", err)
return
}
}

View File

@ -20,7 +20,6 @@ import (
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
project_model "code.gitea.io/gitea/models/project"
pull_model "code.gitea.io/gitea/models/pull"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
@ -1330,28 +1329,12 @@ func CompareAndPullRequestPost(ctx *context.Context) {
return
}
if projectID > 0 {
if !ctx.Repo.CanWrite(unit.TypeProjects) {
ctx.Error(http.StatusBadRequest, "user hasn't the permission to write to projects")
return
}
dstProject, err := project_model.GetProjectByID(ctx, projectID)
if err != nil {
ctx.ServerError("GetProjectByID", err)
return
}
if dstProject.RepoID != ctx.Repo.Repository.ID && dstProject.OwnerID != repo.OwnerID {
ctx.Error(http.StatusBadRequest, "project doesn't belong to the repository")
return
}
dstDefaultColumn, err := dstProject.GetDefaultBoard(ctx)
if err != nil {
ctx.ServerError("GetDefaultBoard", err)
return
}
if err := issues_model.IssueAssignOrRemoveProject(ctx, pullIssue, ctx.Doer, projectID, dstDefaultColumn.ID); err != nil {
ctx.ServerError("ChangeProjectAssign", err)
return
if projectID > 0 && ctx.Repo.CanWrite(unit.TypeProjects) {
if err := issues_model.IssueAssignOrRemoveProject(ctx, pullIssue, ctx.Doer, projectID, 0); err != nil {
if !errors.Is(err, util.ErrPermissionDenied) {
ctx.ServerError("IssueAssignOrRemoveProject", err)
return
}
}
}

View File

@ -42,15 +42,7 @@ func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *issues_mo
}
}
if projectID > 0 {
project, err := project_model.GetProjectByID(ctx, projectID)
if err != nil {
return err
}
defaultBoard, err := project.GetDefaultBoard(ctx)
if err != nil {
return err
}
if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, issue.Poster, projectID, defaultBoard.ID); err != nil {
if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, issue.Poster, projectID, 0); err != nil {
return err
}
}