Skip to content

Commit a4962a9

Browse files
authored
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
1 parent 3a6edd3 commit a4962a9

File tree

5 files changed

+87
-3
lines changed

5 files changed

+87
-3
lines changed

integrations/api_issue_test.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,15 @@ func TestAPISearchIssues(t *testing.T) {
206206
req = NewRequest(t, "GET", link.String())
207207
resp = session.MakeRequest(t, req, http.StatusOK)
208208
DecodeJSON(t, resp, &apiIssues)
209-
assert.EqualValues(t, "14", resp.Header().Get("X-Total-Count"))
209+
assert.EqualValues(t, "15", resp.Header().Get("X-Total-Count"))
210210
assert.Len(t, apiIssues, 10) //there are more but 10 is page item limit
211211

212212
query.Add("limit", "20")
213213
link.RawQuery = query.Encode()
214214
req = NewRequest(t, "GET", link.String())
215215
resp = session.MakeRequest(t, req, http.StatusOK)
216216
DecodeJSON(t, resp, &apiIssues)
217-
assert.Len(t, apiIssues, 14)
217+
assert.Len(t, apiIssues, 15)
218218

219219
query = url.Values{"assigned": {"true"}, "state": {"all"}}
220220
link.RawQuery = query.Encode()
@@ -236,6 +236,27 @@ func TestAPISearchIssues(t *testing.T) {
236236
resp = session.MakeRequest(t, req, http.StatusOK)
237237
DecodeJSON(t, resp, &apiIssues)
238238
assert.Len(t, apiIssues, 2)
239+
240+
query = url.Values{"owner": {"user2"}} // user
241+
link.RawQuery = query.Encode()
242+
req = NewRequest(t, "GET", link.String())
243+
resp = session.MakeRequest(t, req, http.StatusOK)
244+
DecodeJSON(t, resp, &apiIssues)
245+
assert.Len(t, apiIssues, 6)
246+
247+
query = url.Values{"owner": {"user3"}} // organization
248+
link.RawQuery = query.Encode()
249+
req = NewRequest(t, "GET", link.String())
250+
resp = session.MakeRequest(t, req, http.StatusOK)
251+
DecodeJSON(t, resp, &apiIssues)
252+
assert.Len(t, apiIssues, 3)
253+
254+
query = url.Values{"owner": {"user3"}, "team": {"team1"}} // organization + team
255+
link.RawQuery = query.Encode()
256+
req = NewRequest(t, "GET", link.String())
257+
resp = session.MakeRequest(t, req, http.StatusOK)
258+
DecodeJSON(t, resp, &apiIssues)
259+
assert.Len(t, apiIssues, 2)
239260
}
240261

241262
func TestAPISearchIssuesWithLabels(t *testing.T) {

models/fixtures/issue.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,15 @@
172172
is_pull: false
173173
created_unix: 1602935696
174174
updated_unix: 1602935696
175+
176+
-
177+
id: 15
178+
repo_id: 5
179+
index: 1
180+
poster_id: 2
181+
name: issue in repo not linked to team1
182+
content: content
183+
is_closed: false
184+
is_pull: false
185+
created_unix: 1602935696
186+
updated_unix: 1602935696

models/fixtures/repository.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
lower_name: repo5
7474
name: repo5
7575
is_private: true
76-
num_issues: 0
76+
num_issues: 1
7777
num_closed_issues: 0
7878
num_pulls: 0
7979
num_closed_pulls: 0

routers/api/v1/repo/issue.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ func SearchIssues(ctx *context.APIContext) {
8787
// in: query
8888
// description: filter pulls requesting your review, default is false
8989
// type: boolean
90+
// - name: owner
91+
// in: query
92+
// description: filter by owner
93+
// type: string
94+
// - name: team
95+
// in: query
96+
// description: filter by team (requires organization owner parameter to be provided)
97+
// type: string
9098
// - name: page
9199
// in: query
92100
// description: page number of results to return (1-based)
@@ -130,6 +138,37 @@ func SearchIssues(ctx *context.APIContext) {
130138
opts.Private = true
131139
opts.AllLimited = true
132140
}
141+
if ctx.FormString("owner") != "" {
142+
owner, err := models.GetUserByName(ctx.FormString("owner"))
143+
if err != nil {
144+
if models.IsErrUserNotExist(err) {
145+
ctx.Error(http.StatusBadRequest, "Owner not found", err)
146+
} else {
147+
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
148+
}
149+
return
150+
}
151+
opts.OwnerID = owner.ID
152+
opts.AllLimited = false
153+
opts.AllPublic = false
154+
opts.Collaborate = util.OptionalBoolFalse
155+
}
156+
if ctx.FormString("team") != "" {
157+
if ctx.FormString("owner") == "" {
158+
ctx.Error(http.StatusBadRequest, "", "Owner organisation is required for filtering on team")
159+
return
160+
}
161+
team, err := models.GetTeam(opts.OwnerID, ctx.FormString("team"))
162+
if err != nil {
163+
if models.IsErrTeamNotExist(err) {
164+
ctx.Error(http.StatusBadRequest, "Team not found", err)
165+
} else {
166+
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
167+
}
168+
return
169+
}
170+
opts.TeamID = team.ID
171+
}
133172

134173
repoIDs, _, err := models.SearchRepositoryIDs(opts)
135174
if err != nil {

templates/swagger/v1_json.tmpl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,18 @@
19391939
"name": "review_requested",
19401940
"in": "query"
19411941
},
1942+
{
1943+
"type": "string",
1944+
"description": "filter by owner",
1945+
"name": "owner",
1946+
"in": "query"
1947+
},
1948+
{
1949+
"type": "string",
1950+
"description": "filter by team (requires organization owner parameter to be provided)",
1951+
"name": "team",
1952+
"in": "query"
1953+
},
19421954
{
19431955
"type": "integer",
19441956
"description": "page number of results to return (1-based)",

0 commit comments

Comments
 (0)