code.gitea.io/gitea@v1.21.7/routers/web/repo/issue_dependency.go (about)

     1  // Copyright 2018 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package repo
     5  
     6  import (
     7  	"net/http"
     8  
     9  	issues_model "code.gitea.io/gitea/models/issues"
    10  	access_model "code.gitea.io/gitea/models/perm/access"
    11  	"code.gitea.io/gitea/modules/context"
    12  	"code.gitea.io/gitea/modules/setting"
    13  )
    14  
    15  // AddDependency adds new dependencies
    16  func AddDependency(ctx *context.Context) {
    17  	issueIndex := ctx.ParamsInt64("index")
    18  	issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, issueIndex)
    19  	if err != nil {
    20  		ctx.ServerError("GetIssueByIndex", err)
    21  		return
    22  	}
    23  
    24  	// Check if the Repo is allowed to have dependencies
    25  	if !ctx.Repo.CanCreateIssueDependencies(ctx.Doer, issue.IsPull) {
    26  		ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
    27  		return
    28  	}
    29  
    30  	depID := ctx.FormInt64("newDependency")
    31  
    32  	if err = issue.LoadRepo(ctx); err != nil {
    33  		ctx.ServerError("LoadRepo", err)
    34  		return
    35  	}
    36  
    37  	// Redirect
    38  	defer ctx.Redirect(issue.Link())
    39  
    40  	// Dependency
    41  	dep, err := issues_model.GetIssueByID(ctx, depID)
    42  	if err != nil {
    43  		ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_issue_not_exist"))
    44  		return
    45  	}
    46  
    47  	// Check if both issues are in the same repo if cross repository dependencies is not enabled
    48  	if issue.RepoID != dep.RepoID {
    49  		if !setting.Service.AllowCrossRepositoryDependencies {
    50  			ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_not_same_repo"))
    51  			return
    52  		}
    53  		if err := dep.LoadRepo(ctx); err != nil {
    54  			ctx.ServerError("loadRepo", err)
    55  			return
    56  		}
    57  		// Can ctx.Doer read issues in the dep repo?
    58  		depRepoPerm, err := access_model.GetUserRepoPermission(ctx, dep.Repo, ctx.Doer)
    59  		if err != nil {
    60  			ctx.ServerError("GetUserRepoPermission", err)
    61  			return
    62  		}
    63  		if !depRepoPerm.CanReadIssuesOrPulls(dep.IsPull) {
    64  			// you can't see this dependency
    65  			return
    66  		}
    67  	}
    68  
    69  	// Check if issue and dependency is the same
    70  	if dep.ID == issue.ID {
    71  		ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_same_issue"))
    72  		return
    73  	}
    74  
    75  	err = issues_model.CreateIssueDependency(ctx.Doer, issue, dep)
    76  	if err != nil {
    77  		if issues_model.IsErrDependencyExists(err) {
    78  			ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_exists"))
    79  			return
    80  		} else if issues_model.IsErrCircularDependency(err) {
    81  			ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_cannot_create_circular"))
    82  			return
    83  		} else {
    84  			ctx.ServerError("CreateOrUpdateIssueDependency", err)
    85  			return
    86  		}
    87  	}
    88  }
    89  
    90  // RemoveDependency removes the dependency
    91  func RemoveDependency(ctx *context.Context) {
    92  	issueIndex := ctx.ParamsInt64("index")
    93  	issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, issueIndex)
    94  	if err != nil {
    95  		ctx.ServerError("GetIssueByIndex", err)
    96  		return
    97  	}
    98  
    99  	// Check if the Repo is allowed to have dependencies
   100  	if !ctx.Repo.CanCreateIssueDependencies(ctx.Doer, issue.IsPull) {
   101  		ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
   102  		return
   103  	}
   104  
   105  	depID := ctx.FormInt64("removeDependencyID")
   106  
   107  	if err = issue.LoadRepo(ctx); err != nil {
   108  		ctx.ServerError("LoadRepo", err)
   109  		return
   110  	}
   111  
   112  	// Dependency Type
   113  	depTypeStr := ctx.Req.PostForm.Get("dependencyType")
   114  
   115  	var depType issues_model.DependencyType
   116  
   117  	switch depTypeStr {
   118  	case "blockedBy":
   119  		depType = issues_model.DependencyTypeBlockedBy
   120  	case "blocking":
   121  		depType = issues_model.DependencyTypeBlocking
   122  	default:
   123  		ctx.Error(http.StatusBadRequest, "GetDependecyType")
   124  		return
   125  	}
   126  
   127  	// Dependency
   128  	dep, err := issues_model.GetIssueByID(ctx, depID)
   129  	if err != nil {
   130  		ctx.ServerError("GetIssueByID", err)
   131  		return
   132  	}
   133  
   134  	if err = issues_model.RemoveIssueDependency(ctx.Doer, issue, dep, depType); err != nil {
   135  		if issues_model.IsErrDependencyNotExists(err) {
   136  			ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_not_exist"))
   137  			return
   138  		}
   139  		ctx.ServerError("RemoveIssueDependency", err)
   140  		return
   141  	}
   142  
   143  	// Redirect
   144  	ctx.Redirect(issue.Link())
   145  }