diff --git a/routers/api/v1/repo/issue_dependency.go b/routers/api/v1/repo/issue_dependency.go index 28cdbb3091..109395c400 100644 --- a/routers/api/v1/repo/issue_dependency.go +++ b/routers/api/v1/repo/issue_dependency.go @@ -500,7 +500,11 @@ func getParamsIssue(ctx *context.APIContext) *issues_model.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 { + // An empty owner/repo in the form means the dependency lives in the current + // repo, so default to it instead of looking up an empty ("", "") repository. + sameRepo := (form.Owner == "" || form.Owner == ctx.Repo.Repository.OwnerName) && + (form.Name == "" || form.Name == ctx.Repo.Repository.Name) + if !sameRepo { if !setting.Service.AllowCrossRepositoryDependencies { ctx.JSON(http.StatusBadRequest, "CrossRepositoryDependencies not enabled") return nil diff --git a/tests/integration/api_issue_dependency_test.go b/tests/integration/api_issue_dependency_test.go index fc2615be42..1776e8f821 100644 --- a/tests/integration/api_issue_dependency_test.go +++ b/tests/integration/api_issue_dependency_test.go @@ -90,6 +90,31 @@ func TestAPICreateIssueDependencyCrossRepoPermission(t *testing.T) { }) } +func TestAPICreateIssueDependencySameRepoOmitOwnerRepo(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + // Regression for #22: a same-repo dependency posted without owner/repo in the + // body must default to the current repo, not look up an empty ("", "") repo. + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + targetIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 1}) + dependencyIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 4}) + + enableRepoDependencies(t, repo.ID) + + url := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/dependencies", "user2", "repo1", targetIssue.Index) + // Owner and Name intentionally omitted — only the index is supplied. + dependencyMeta := &api.IssueMeta{Index: dependencyIssue.Index} + + writerToken := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteIssue) + req := NewRequestWithJSON(t, "POST", url, dependencyMeta). + AddTokenAuth(writerToken) + MakeRequest(t, req, http.StatusCreated) + unittest.AssertExistsAndLoadBean(t, &issues_model.IssueDependency{ + IssueID: targetIssue.ID, + DependencyID: dependencyIssue.ID, + }) +} + func TestAPIDeleteIssueDependencyCrossRepoPermission(t *testing.T) { defer tests.PrepareTestEnv(t)()