From a4962a944002c3d3949520949f964aae7ff478ed Mon Sep 17 00:00:00 2001 From: Jimmy Praet Date: Fri, 13 Aug 2021 22:47:25 +0200 Subject: [PATCH] Add filter by owner and team to issue/pulls search endpoint (#16662) * Filter by owner and team in API issue/pulls search * Add integration test --- integrations/api_issue_test.go | 25 ++++++++++++++++++++-- models/fixtures/issue.yml | 12 +++++++++++ models/fixtures/repository.yml | 2 +- routers/api/v1/repo/issue.go | 39 ++++++++++++++++++++++++++++++++++ templates/swagger/v1_json.tmpl | 12 +++++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) diff --git a/integrations/api_issue_test.go b/integrations/api_issue_test.go index 74512cafa3f6..245ab76c7b6c 100644 --- a/integrations/api_issue_test.go +++ b/integrations/api_issue_test.go @@ -206,7 +206,7 @@ func TestAPISearchIssues(t *testing.T) { req = NewRequest(t, "GET", link.String()) resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &apiIssues) - assert.EqualValues(t, "14", resp.Header().Get("X-Total-Count")) + assert.EqualValues(t, "15", resp.Header().Get("X-Total-Count")) assert.Len(t, apiIssues, 10) //there are more but 10 is page item limit query.Add("limit", "20") @@ -214,7 +214,7 @@ func TestAPISearchIssues(t *testing.T) { req = NewRequest(t, "GET", link.String()) resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &apiIssues) - assert.Len(t, apiIssues, 14) + assert.Len(t, apiIssues, 15) query = url.Values{"assigned": {"true"}, "state": {"all"}} link.RawQuery = query.Encode() @@ -236,6 +236,27 @@ func TestAPISearchIssues(t *testing.T) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &apiIssues) assert.Len(t, apiIssues, 2) + + query = url.Values{"owner": {"user2"}} // user + link.RawQuery = query.Encode() + req = NewRequest(t, "GET", link.String()) + resp = session.MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &apiIssues) + assert.Len(t, apiIssues, 6) + + query = url.Values{"owner": {"user3"}} // organization + link.RawQuery = query.Encode() + req = NewRequest(t, "GET", link.String()) + resp = session.MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &apiIssues) + assert.Len(t, apiIssues, 3) + + query = url.Values{"owner": {"user3"}, "team": {"team1"}} // organization + team + link.RawQuery = query.Encode() + req = NewRequest(t, "GET", link.String()) + resp = session.MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &apiIssues) + assert.Len(t, apiIssues, 2) } func TestAPISearchIssuesWithLabels(t *testing.T) { diff --git a/models/fixtures/issue.yml b/models/fixtures/issue.yml index 946899d6ff03..d5738d5db43f 100644 --- a/models/fixtures/issue.yml +++ b/models/fixtures/issue.yml @@ -172,3 +172,15 @@ is_pull: false created_unix: 1602935696 updated_unix: 1602935696 + +- + id: 15 + repo_id: 5 + index: 1 + poster_id: 2 + name: issue in repo not linked to team1 + content: content + is_closed: false + is_pull: false + created_unix: 1602935696 + updated_unix: 1602935696 diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml index 492040316c10..6860d00b30e5 100644 --- a/models/fixtures/repository.yml +++ b/models/fixtures/repository.yml @@ -73,7 +73,7 @@ lower_name: repo5 name: repo5 is_private: true - num_issues: 0 + num_issues: 1 num_closed_issues: 0 num_pulls: 0 num_closed_pulls: 0 diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index ff003b840bf6..e8ef2f3d05fd 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -87,6 +87,14 @@ func SearchIssues(ctx *context.APIContext) { // in: query // description: filter pulls requesting your review, default is false // type: boolean + // - name: owner + // in: query + // description: filter by owner + // type: string + // - name: team + // in: query + // description: filter by team (requires organization owner parameter to be provided) + // type: string // - name: page // in: query // description: page number of results to return (1-based) @@ -130,6 +138,37 @@ func SearchIssues(ctx *context.APIContext) { opts.Private = true opts.AllLimited = true } + if ctx.FormString("owner") != "" { + owner, err := models.GetUserByName(ctx.FormString("owner")) + if err != nil { + if models.IsErrUserNotExist(err) { + ctx.Error(http.StatusBadRequest, "Owner not found", err) + } else { + ctx.Error(http.StatusInternalServerError, "GetUserByName", err) + } + return + } + opts.OwnerID = owner.ID + opts.AllLimited = false + opts.AllPublic = false + opts.Collaborate = util.OptionalBoolFalse + } + if ctx.FormString("team") != "" { + if ctx.FormString("owner") == "" { + ctx.Error(http.StatusBadRequest, "", "Owner organisation is required for filtering on team") + return + } + team, err := models.GetTeam(opts.OwnerID, ctx.FormString("team")) + if err != nil { + if models.IsErrTeamNotExist(err) { + ctx.Error(http.StatusBadRequest, "Team not found", err) + } else { + ctx.Error(http.StatusInternalServerError, "GetUserByName", err) + } + return + } + opts.TeamID = team.ID + } repoIDs, _, err := models.SearchRepositoryIDs(opts) if err != nil { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d23d09bcfdad..ee759ba6b171 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1939,6 +1939,18 @@ "name": "review_requested", "in": "query" }, + { + "type": "string", + "description": "filter by owner", + "name": "owner", + "in": "query" + }, + { + "type": "string", + "description": "filter by team (requires organization owner parameter to be provided)", + "name": "team", + "in": "query" + }, { "type": "integer", "description": "page number of results to return (1-based)",