mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	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
This commit is contained in:
		@@ -206,7 +206,7 @@ func TestAPISearchIssues(t *testing.T) {
 | 
				
			|||||||
	req = NewRequest(t, "GET", link.String())
 | 
						req = NewRequest(t, "GET", link.String())
 | 
				
			||||||
	resp = session.MakeRequest(t, req, http.StatusOK)
 | 
						resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
	DecodeJSON(t, resp, &apiIssues)
 | 
						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
 | 
						assert.Len(t, apiIssues, 10) //there are more but 10 is page item limit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	query.Add("limit", "20")
 | 
						query.Add("limit", "20")
 | 
				
			||||||
@@ -214,7 +214,7 @@ func TestAPISearchIssues(t *testing.T) {
 | 
				
			|||||||
	req = NewRequest(t, "GET", link.String())
 | 
						req = NewRequest(t, "GET", link.String())
 | 
				
			||||||
	resp = session.MakeRequest(t, req, http.StatusOK)
 | 
						resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
	DecodeJSON(t, resp, &apiIssues)
 | 
						DecodeJSON(t, resp, &apiIssues)
 | 
				
			||||||
	assert.Len(t, apiIssues, 14)
 | 
						assert.Len(t, apiIssues, 15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	query = url.Values{"assigned": {"true"}, "state": {"all"}}
 | 
						query = url.Values{"assigned": {"true"}, "state": {"all"}}
 | 
				
			||||||
	link.RawQuery = query.Encode()
 | 
						link.RawQuery = query.Encode()
 | 
				
			||||||
@@ -236,6 +236,27 @@ func TestAPISearchIssues(t *testing.T) {
 | 
				
			|||||||
	resp = session.MakeRequest(t, req, http.StatusOK)
 | 
						resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
	DecodeJSON(t, resp, &apiIssues)
 | 
						DecodeJSON(t, resp, &apiIssues)
 | 
				
			||||||
	assert.Len(t, apiIssues, 2)
 | 
						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) {
 | 
					func TestAPISearchIssuesWithLabels(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,3 +172,15 @@
 | 
				
			|||||||
  is_pull: false
 | 
					  is_pull: false
 | 
				
			||||||
  created_unix: 1602935696
 | 
					  created_unix: 1602935696
 | 
				
			||||||
  updated_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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,7 @@
 | 
				
			|||||||
  lower_name: repo5
 | 
					  lower_name: repo5
 | 
				
			||||||
  name: repo5
 | 
					  name: repo5
 | 
				
			||||||
  is_private: true
 | 
					  is_private: true
 | 
				
			||||||
  num_issues: 0
 | 
					  num_issues: 1
 | 
				
			||||||
  num_closed_issues: 0
 | 
					  num_closed_issues: 0
 | 
				
			||||||
  num_pulls: 0
 | 
					  num_pulls: 0
 | 
				
			||||||
  num_closed_pulls: 0
 | 
					  num_closed_pulls: 0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,14 @@ func SearchIssues(ctx *context.APIContext) {
 | 
				
			|||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: filter pulls requesting your review, default is false
 | 
						//   description: filter pulls requesting your review, default is false
 | 
				
			||||||
	//   type: boolean
 | 
						//   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
 | 
						// - name: page
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: page number of results to return (1-based)
 | 
						//   description: page number of results to return (1-based)
 | 
				
			||||||
@@ -130,6 +138,37 @@ func SearchIssues(ctx *context.APIContext) {
 | 
				
			|||||||
		opts.Private = true
 | 
							opts.Private = true
 | 
				
			||||||
		opts.AllLimited = 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)
 | 
						repoIDs, _, err := models.SearchRepositoryIDs(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1939,6 +1939,18 @@
 | 
				
			|||||||
            "name": "review_requested",
 | 
					            "name": "review_requested",
 | 
				
			||||||
            "in": "query"
 | 
					            "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",
 | 
					            "type": "integer",
 | 
				
			||||||
            "description": "page number of results to return (1-based)",
 | 
					            "description": "page number of results to return (1-based)",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user