mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 20:36:07 +01:00 
			
		
		
		
	To avoid deadlock problem, almost database related functions should be have ctx as the first parameter. This PR do a refactor for some of these functions.
		
			
				
	
	
		
			599 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			599 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2016 The Gogs Authors. All rights reserved.
 | 
						|
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package repo
 | 
						|
 | 
						|
import (
 | 
						|
	"net/http"
 | 
						|
 | 
						|
	"code.gitea.io/gitea/models/db"
 | 
						|
	issues_model "code.gitea.io/gitea/models/issues"
 | 
						|
	access_model "code.gitea.io/gitea/models/perm/access"
 | 
						|
	repo_model "code.gitea.io/gitea/models/repo"
 | 
						|
	"code.gitea.io/gitea/modules/context"
 | 
						|
	"code.gitea.io/gitea/modules/setting"
 | 
						|
	api "code.gitea.io/gitea/modules/structs"
 | 
						|
	"code.gitea.io/gitea/modules/web"
 | 
						|
	"code.gitea.io/gitea/services/convert"
 | 
						|
)
 | 
						|
 | 
						|
// GetIssueDependencies list an issue's dependencies
 | 
						|
func GetIssueDependencies(ctx *context.APIContext) {
 | 
						|
	// swagger:operation GET /repos/{owner}/{repo}/issues/{index}/dependencies issue issueListIssueDependencies
 | 
						|
	// ---
 | 
						|
	// summary: List an issue's dependencies, i.e all issues that block this issue.
 | 
						|
	// produces:
 | 
						|
	// - application/json
 | 
						|
	// parameters:
 | 
						|
	// - name: owner
 | 
						|
	//   in: path
 | 
						|
	//   description: owner of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: repo
 | 
						|
	//   in: path
 | 
						|
	//   description: name of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: index
 | 
						|
	//   in: path
 | 
						|
	//   description: index of the issue
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: page
 | 
						|
	//   in: query
 | 
						|
	//   description: page number of results to return (1-based)
 | 
						|
	//   type: integer
 | 
						|
	// - name: limit
 | 
						|
	//   in: query
 | 
						|
	//   description: page size of results
 | 
						|
	//   type: integer
 | 
						|
	// responses:
 | 
						|
	//   "200":
 | 
						|
	//     "$ref": "#/responses/IssueList"
 | 
						|
 | 
						|
	// If this issue's repository does not enable dependencies then there can be no dependencies by default
 | 
						|
	if !ctx.Repo.Repository.IsDependenciesEnabled(ctx) {
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
 | 
						|
	if err != nil {
 | 
						|
		if issues_model.IsErrIssueNotExist(err) {
 | 
						|
			ctx.NotFound("IsErrIssueNotExist", err)
 | 
						|
		} else {
 | 
						|
			ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
 | 
						|
		}
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// 1. We must be able to read this issue
 | 
						|
	if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	page := ctx.FormInt("page")
 | 
						|
	if page <= 1 {
 | 
						|
		page = 1
 | 
						|
	}
 | 
						|
	limit := ctx.FormInt("limit")
 | 
						|
	if limit == 0 {
 | 
						|
		limit = setting.API.DefaultPagingNum
 | 
						|
	} else if limit > setting.API.MaxResponseItems {
 | 
						|
		limit = setting.API.MaxResponseItems
 | 
						|
	}
 | 
						|
 | 
						|
	canWrite := ctx.Repo.Permission.CanWriteIssuesOrPulls(issue.IsPull)
 | 
						|
 | 
						|
	blockerIssues := make([]*issues_model.Issue, 0, limit)
 | 
						|
 | 
						|
	// 2. Get the issues this issue depends on, i.e. the `<#b>`: `<issue> <- <#b>`
 | 
						|
	blockersInfo, err := issue.BlockedByDependencies(ctx, db.ListOptions{
 | 
						|
		Page:     page,
 | 
						|
		PageSize: limit,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		ctx.Error(http.StatusInternalServerError, "BlockedByDependencies", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	var lastRepoID int64
 | 
						|
	var lastPerm access_model.Permission
 | 
						|
	for _, blocker := range blockersInfo {
 | 
						|
		// Get the permissions for this repository
 | 
						|
		perm := lastPerm
 | 
						|
		if lastRepoID != blocker.Repository.ID {
 | 
						|
			if blocker.Repository.ID == ctx.Repo.Repository.ID {
 | 
						|
				perm = ctx.Repo.Permission
 | 
						|
			} else {
 | 
						|
				var err error
 | 
						|
				perm, err = access_model.GetUserRepoPermission(ctx, &blocker.Repository, ctx.Doer)
 | 
						|
				if err != nil {
 | 
						|
					ctx.ServerError("GetUserRepoPermission", err)
 | 
						|
					return
 | 
						|
				}
 | 
						|
			}
 | 
						|
			lastRepoID = blocker.Repository.ID
 | 
						|
		}
 | 
						|
 | 
						|
		// check permission
 | 
						|
		if !perm.CanReadIssuesOrPulls(blocker.Issue.IsPull) {
 | 
						|
			if !canWrite {
 | 
						|
				hiddenBlocker := &issues_model.DependencyInfo{
 | 
						|
					Issue: issues_model.Issue{
 | 
						|
						Title: "HIDDEN",
 | 
						|
					},
 | 
						|
				}
 | 
						|
				blocker = hiddenBlocker
 | 
						|
			} else {
 | 
						|
				confidentialBlocker := &issues_model.DependencyInfo{
 | 
						|
					Issue: issues_model.Issue{
 | 
						|
						RepoID:   blocker.Issue.RepoID,
 | 
						|
						Index:    blocker.Index,
 | 
						|
						Title:    blocker.Title,
 | 
						|
						IsClosed: blocker.IsClosed,
 | 
						|
						IsPull:   blocker.IsPull,
 | 
						|
					},
 | 
						|
					Repository: repo_model.Repository{
 | 
						|
						ID:        blocker.Issue.Repo.ID,
 | 
						|
						Name:      blocker.Issue.Repo.Name,
 | 
						|
						OwnerName: blocker.Issue.Repo.OwnerName,
 | 
						|
					},
 | 
						|
				}
 | 
						|
				confidentialBlocker.Issue.Repo = &confidentialBlocker.Repository
 | 
						|
				blocker = confidentialBlocker
 | 
						|
			}
 | 
						|
		}
 | 
						|
		blockerIssues = append(blockerIssues, &blocker.Issue)
 | 
						|
	}
 | 
						|
 | 
						|
	ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, blockerIssues))
 | 
						|
}
 | 
						|
 | 
						|
// CreateIssueDependency create a new issue dependencies
 | 
						|
func CreateIssueDependency(ctx *context.APIContext) {
 | 
						|
	// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/dependencies issue issueCreateIssueDependencies
 | 
						|
	// ---
 | 
						|
	// summary: Make the issue in the url depend on the issue in the form.
 | 
						|
	// produces:
 | 
						|
	// - application/json
 | 
						|
	// parameters:
 | 
						|
	// - name: owner
 | 
						|
	//   in: path
 | 
						|
	//   description: owner of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: repo
 | 
						|
	//   in: path
 | 
						|
	//   description: name of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: index
 | 
						|
	//   in: path
 | 
						|
	//   description: index of the issue
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: body
 | 
						|
	//   in: body
 | 
						|
	//   schema:
 | 
						|
	//     "$ref": "#/definitions/IssueMeta"
 | 
						|
	// responses:
 | 
						|
	//   "201":
 | 
						|
	//     "$ref": "#/responses/Issue"
 | 
						|
	//   "404":
 | 
						|
	//     description: the issue does not exist
 | 
						|
 | 
						|
	// We want to make <:index> depend on <Form>, i.e. <:index> is the target
 | 
						|
	target := getParamsIssue(ctx)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// and <Form> represents the dependency
 | 
						|
	form := web.GetForm(ctx).(*api.IssueMeta)
 | 
						|
	dependency := getFormIssue(ctx, form)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	dependencyPerm := getPermissionForRepo(ctx, target.Repo)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	createIssueDependency(ctx, target, dependency, ctx.Repo.Permission, *dependencyPerm)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, target))
 | 
						|
}
 | 
						|
 | 
						|
// RemoveIssueDependency remove an issue dependency
 | 
						|
func RemoveIssueDependency(ctx *context.APIContext) {
 | 
						|
	// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/dependencies issue issueRemoveIssueDependencies
 | 
						|
	// ---
 | 
						|
	// summary: Remove an issue dependency
 | 
						|
	// produces:
 | 
						|
	// - application/json
 | 
						|
	// parameters:
 | 
						|
	// - name: owner
 | 
						|
	//   in: path
 | 
						|
	//   description: owner of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: repo
 | 
						|
	//   in: path
 | 
						|
	//   description: name of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: index
 | 
						|
	//   in: path
 | 
						|
	//   description: index of the issue
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: body
 | 
						|
	//   in: body
 | 
						|
	//   schema:
 | 
						|
	//     "$ref": "#/definitions/IssueMeta"
 | 
						|
	// responses:
 | 
						|
	//   "200":
 | 
						|
	//     "$ref": "#/responses/Issue"
 | 
						|
 | 
						|
	// We want to make <:index> depend on <Form>, i.e. <:index> is the target
 | 
						|
	target := getParamsIssue(ctx)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// and <Form> represents the dependency
 | 
						|
	form := web.GetForm(ctx).(*api.IssueMeta)
 | 
						|
	dependency := getFormIssue(ctx, form)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	dependencyPerm := getPermissionForRepo(ctx, target.Repo)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	removeIssueDependency(ctx, target, dependency, ctx.Repo.Permission, *dependencyPerm)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, target))
 | 
						|
}
 | 
						|
 | 
						|
// GetIssueBlocks list issues that are blocked by this issue
 | 
						|
func GetIssueBlocks(ctx *context.APIContext) {
 | 
						|
	// swagger:operation GET /repos/{owner}/{repo}/issues/{index}/blocks issue issueListBlocks
 | 
						|
	// ---
 | 
						|
	// summary: List issues that are blocked by this issue
 | 
						|
	// produces:
 | 
						|
	// - application/json
 | 
						|
	// parameters:
 | 
						|
	// - name: owner
 | 
						|
	//   in: path
 | 
						|
	//   description: owner of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: repo
 | 
						|
	//   in: path
 | 
						|
	//   description: name of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: index
 | 
						|
	//   in: path
 | 
						|
	//   description: index of the issue
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: page
 | 
						|
	//   in: query
 | 
						|
	//   description: page number of results to return (1-based)
 | 
						|
	//   type: integer
 | 
						|
	// - name: limit
 | 
						|
	//   in: query
 | 
						|
	//   description: page size of results
 | 
						|
	//   type: integer
 | 
						|
	// responses:
 | 
						|
	//   "200":
 | 
						|
	//     "$ref": "#/responses/IssueList"
 | 
						|
 | 
						|
	// We need to list the issues that DEPEND on this issue not the other way round
 | 
						|
	// Therefore whether dependencies are enabled or not in this repository is potentially irrelevant.
 | 
						|
 | 
						|
	issue := getParamsIssue(ctx)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	page := ctx.FormInt("page")
 | 
						|
	if page <= 1 {
 | 
						|
		page = 1
 | 
						|
	}
 | 
						|
	limit := ctx.FormInt("limit")
 | 
						|
	if limit <= 1 {
 | 
						|
		limit = setting.API.DefaultPagingNum
 | 
						|
	}
 | 
						|
 | 
						|
	skip := (page - 1) * limit
 | 
						|
	max := page * limit
 | 
						|
 | 
						|
	deps, err := issue.BlockingDependencies(ctx)
 | 
						|
	if err != nil {
 | 
						|
		ctx.Error(http.StatusInternalServerError, "BlockingDependencies", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	var lastRepoID int64
 | 
						|
	var lastPerm access_model.Permission
 | 
						|
 | 
						|
	var issues []*issues_model.Issue
 | 
						|
	for i, depMeta := range deps {
 | 
						|
		if i < skip || i >= max {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		// Get the permissions for this repository
 | 
						|
		perm := lastPerm
 | 
						|
		if lastRepoID != depMeta.Repository.ID {
 | 
						|
			if depMeta.Repository.ID == ctx.Repo.Repository.ID {
 | 
						|
				perm = ctx.Repo.Permission
 | 
						|
			} else {
 | 
						|
				var err error
 | 
						|
				perm, err = access_model.GetUserRepoPermission(ctx, &depMeta.Repository, ctx.Doer)
 | 
						|
				if err != nil {
 | 
						|
					ctx.ServerError("GetUserRepoPermission", err)
 | 
						|
					return
 | 
						|
				}
 | 
						|
			}
 | 
						|
			lastRepoID = depMeta.Repository.ID
 | 
						|
		}
 | 
						|
 | 
						|
		if !perm.CanReadIssuesOrPulls(depMeta.Issue.IsPull) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		depMeta.Issue.Repo = &depMeta.Repository
 | 
						|
		issues = append(issues, &depMeta.Issue)
 | 
						|
	}
 | 
						|
 | 
						|
	ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues))
 | 
						|
}
 | 
						|
 | 
						|
// CreateIssueBlocking block the issue given in the body by the issue in path
 | 
						|
func CreateIssueBlocking(ctx *context.APIContext) {
 | 
						|
	// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/blocks issue issueCreateIssueBlocking
 | 
						|
	// ---
 | 
						|
	// summary: Block the issue given in the body by the issue in path
 | 
						|
	// produces:
 | 
						|
	// - application/json
 | 
						|
	// parameters:
 | 
						|
	// - name: owner
 | 
						|
	//   in: path
 | 
						|
	//   description: owner of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: repo
 | 
						|
	//   in: path
 | 
						|
	//   description: name of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: index
 | 
						|
	//   in: path
 | 
						|
	//   description: index of the issue
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: body
 | 
						|
	//   in: body
 | 
						|
	//   schema:
 | 
						|
	//     "$ref": "#/definitions/IssueMeta"
 | 
						|
	// responses:
 | 
						|
	//   "201":
 | 
						|
	//     "$ref": "#/responses/Issue"
 | 
						|
	//   "404":
 | 
						|
	//     description: the issue does not exist
 | 
						|
 | 
						|
	dependency := getParamsIssue(ctx)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	form := web.GetForm(ctx).(*api.IssueMeta)
 | 
						|
	target := getFormIssue(ctx, form)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	targetPerm := getPermissionForRepo(ctx, target.Repo)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	createIssueDependency(ctx, target, dependency, *targetPerm, ctx.Repo.Permission)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, dependency))
 | 
						|
}
 | 
						|
 | 
						|
// RemoveIssueBlocking unblock the issue given in the body by the issue in path
 | 
						|
func RemoveIssueBlocking(ctx *context.APIContext) {
 | 
						|
	// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/blocks issue issueRemoveIssueBlocking
 | 
						|
	// ---
 | 
						|
	// summary: Unblock the issue given in the body by the issue in path
 | 
						|
	// produces:
 | 
						|
	// - application/json
 | 
						|
	// parameters:
 | 
						|
	// - name: owner
 | 
						|
	//   in: path
 | 
						|
	//   description: owner of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: repo
 | 
						|
	//   in: path
 | 
						|
	//   description: name of the repo
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: index
 | 
						|
	//   in: path
 | 
						|
	//   description: index of the issue
 | 
						|
	//   type: string
 | 
						|
	//   required: true
 | 
						|
	// - name: body
 | 
						|
	//   in: body
 | 
						|
	//   schema:
 | 
						|
	//     "$ref": "#/definitions/IssueMeta"
 | 
						|
	// responses:
 | 
						|
	//   "200":
 | 
						|
	//     "$ref": "#/responses/Issue"
 | 
						|
 | 
						|
	dependency := getParamsIssue(ctx)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	form := web.GetForm(ctx).(*api.IssueMeta)
 | 
						|
	target := getFormIssue(ctx, form)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	targetPerm := getPermissionForRepo(ctx, target.Repo)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	removeIssueDependency(ctx, target, dependency, *targetPerm, ctx.Repo.Permission)
 | 
						|
	if ctx.Written() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, dependency))
 | 
						|
}
 | 
						|
 | 
						|
func getParamsIssue(ctx *context.APIContext) *issues_model.Issue {
 | 
						|
	issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
 | 
						|
	if err != nil {
 | 
						|
		if issues_model.IsErrIssueNotExist(err) {
 | 
						|
			ctx.NotFound("IsErrIssueNotExist", err)
 | 
						|
		} else {
 | 
						|
			ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
 | 
						|
		}
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	issue.Repo = ctx.Repo.Repository
 | 
						|
	return issue
 | 
						|
}
 | 
						|
 | 
						|
func getFormIssue(ctx *context.APIContext, form *api.IssueMeta) *issues_model.Issue {
 | 
						|
	var repo *repo_model.Repository
 | 
						|
	if form.Owner != ctx.Repo.Repository.OwnerName || form.Name != ctx.Repo.Repository.Name {
 | 
						|
		if !setting.Service.AllowCrossRepositoryDependencies {
 | 
						|
			ctx.JSON(http.StatusBadRequest, "CrossRepositoryDependencies not enabled")
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
		var err error
 | 
						|
		repo, err = repo_model.GetRepositoryByOwnerAndName(ctx, form.Owner, form.Name)
 | 
						|
		if err != nil {
 | 
						|
			if repo_model.IsErrRepoNotExist(err) {
 | 
						|
				ctx.NotFound("IsErrRepoNotExist", err)
 | 
						|
			} else {
 | 
						|
				ctx.Error(http.StatusInternalServerError, "GetRepositoryByOwnerAndName", err)
 | 
						|
			}
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		repo = ctx.Repo.Repository
 | 
						|
	}
 | 
						|
 | 
						|
	issue, err := issues_model.GetIssueByIndex(ctx, repo.ID, form.Index)
 | 
						|
	if err != nil {
 | 
						|
		if issues_model.IsErrIssueNotExist(err) {
 | 
						|
			ctx.NotFound("IsErrIssueNotExist", err)
 | 
						|
		} else {
 | 
						|
			ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
 | 
						|
		}
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	issue.Repo = repo
 | 
						|
	return issue
 | 
						|
}
 | 
						|
 | 
						|
func getPermissionForRepo(ctx *context.APIContext, repo *repo_model.Repository) *access_model.Permission {
 | 
						|
	if repo.ID == ctx.Repo.Repository.ID {
 | 
						|
		return &ctx.Repo.Permission
 | 
						|
	}
 | 
						|
 | 
						|
	perm, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer)
 | 
						|
	if err != nil {
 | 
						|
		ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	return &perm
 | 
						|
}
 | 
						|
 | 
						|
func createIssueDependency(ctx *context.APIContext, target, dependency *issues_model.Issue, targetPerm, dependencyPerm access_model.Permission) {
 | 
						|
	if target.Repo.IsArchived || !target.Repo.IsDependenciesEnabled(ctx) {
 | 
						|
		// The target's repository doesn't have dependencies enabled
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if !targetPerm.CanWriteIssuesOrPulls(target.IsPull) {
 | 
						|
		// We can't write to the target
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if !dependencyPerm.CanReadIssuesOrPulls(dependency.IsPull) {
 | 
						|
		// We can't read the dependency
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	err := issues_model.CreateIssueDependency(ctx.Doer, target, dependency)
 | 
						|
	if err != nil {
 | 
						|
		ctx.Error(http.StatusInternalServerError, "CreateIssueDependency", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func removeIssueDependency(ctx *context.APIContext, target, dependency *issues_model.Issue, targetPerm, dependencyPerm access_model.Permission) {
 | 
						|
	if target.Repo.IsArchived || !target.Repo.IsDependenciesEnabled(ctx) {
 | 
						|
		// The target's repository doesn't have dependencies enabled
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if !targetPerm.CanWriteIssuesOrPulls(target.IsPull) {
 | 
						|
		// We can't write to the target
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if !dependencyPerm.CanReadIssuesOrPulls(dependency.IsPull) {
 | 
						|
		// We can't read the dependency
 | 
						|
		ctx.NotFound()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	err := issues_model.RemoveIssueDependency(ctx.Doer, target, dependency, issues_model.DependencyTypeBlockedBy)
 | 
						|
	if err != nil {
 | 
						|
		ctx.Error(http.StatusInternalServerError, "CreateIssueDependency", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
}
 |