mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 01:34:27 +00:00 
			
		
		
		
	[API] generalize list header (#16551)
* Add info about list endpoints to CONTRIBUTING.md * Let all list endpoints return X-Total-Count header * Add TODOs for GetCombinedCommitStatusByRef * Fix models/issue_stopwatch.go * Rrefactor models.ListDeployKeys * Introduce helper func and use them for SetLinkHeader related func
This commit is contained in:
		@@ -207,6 +207,10 @@ In general, HTTP methods are chosen as follows:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
An endpoint which changes/edits an object expects all fields to be optional (except ones to identify the object, which are required).
 | 
					An endpoint which changes/edits an object expects all fields to be optional (except ones to identify the object, which are required).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Endpoints returning lists should
 | 
				
			||||||
 | 
					 * support pagination (`page` & `limit` options in query)
 | 
				
			||||||
 | 
					 * set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Developer Certificate of Origin (DCO)
 | 
					## Developer Certificate of Origin (DCO)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ func TestAPIGetTrackedTimes(t *testing.T) {
 | 
				
			|||||||
	resp := session.MakeRequest(t, req, http.StatusOK)
 | 
						resp := session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
	var apiTimes api.TrackedTimeList
 | 
						var apiTimes api.TrackedTimeList
 | 
				
			||||||
	DecodeJSON(t, resp, &apiTimes)
 | 
						DecodeJSON(t, resp, &apiTimes)
 | 
				
			||||||
	expect, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{IssueID: issue2.ID})
 | 
						expect, err := models.GetTrackedTimes(&models.FindTrackedTimesOptions{IssueID: issue2.ID})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, apiTimes, 3)
 | 
						assert.Len(t, apiTimes, 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ package integrations
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -15,6 +16,38 @@ import (
 | 
				
			|||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPITopicSearch(t *testing.T) {
 | 
				
			||||||
 | 
						defer prepareTestEnv(t)()
 | 
				
			||||||
 | 
						searchURL, _ := url.Parse("/api/v1/topics/search")
 | 
				
			||||||
 | 
						var topics struct {
 | 
				
			||||||
 | 
							TopicNames []*api.TopicResponse `json:"topics"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						query := url.Values{"page": []string{"1"}, "limit": []string{"4"}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						searchURL.RawQuery = query.Encode()
 | 
				
			||||||
 | 
						res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
 | 
				
			||||||
 | 
						DecodeJSON(t, res, &topics)
 | 
				
			||||||
 | 
						assert.Len(t, topics.TopicNames, 4)
 | 
				
			||||||
 | 
						assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						query.Add("q", "topic")
 | 
				
			||||||
 | 
						searchURL.RawQuery = query.Encode()
 | 
				
			||||||
 | 
						res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
 | 
				
			||||||
 | 
						DecodeJSON(t, res, &topics)
 | 
				
			||||||
 | 
						assert.Len(t, topics.TopicNames, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						query.Set("q", "database")
 | 
				
			||||||
 | 
						searchURL.RawQuery = query.Encode()
 | 
				
			||||||
 | 
						res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
 | 
				
			||||||
 | 
						DecodeJSON(t, res, &topics)
 | 
				
			||||||
 | 
						if assert.Len(t, topics.TopicNames, 1) {
 | 
				
			||||||
 | 
							assert.EqualValues(t, 2, topics.TopicNames[0].ID)
 | 
				
			||||||
 | 
							assert.EqualValues(t, "database", topics.TopicNames[0].Name)
 | 
				
			||||||
 | 
							assert.EqualValues(t, 1, topics.TopicNames[0].RepoCount)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAPIRepoTopic(t *testing.T) {
 | 
					func TestAPIRepoTopic(t *testing.T) {
 | 
				
			||||||
	defer prepareTestEnv(t)()
 | 
						defer prepareTestEnv(t)()
 | 
				
			||||||
	user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) // owner of repo2
 | 
						user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) // owner of repo2
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -246,7 +246,7 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, ignTeamID int64) (err
 | 
				
			|||||||
		return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
 | 
							return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = repo.Owner.getTeams(e); err != nil {
 | 
						if err = repo.Owner.loadTeams(e); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -159,7 +159,7 @@ func getLatestCommitStatus(e Engine, repoID int64, sha string, listOptions ListO
 | 
				
			|||||||
	if len(ids) == 0 {
 | 
						if len(ids) == 0 {
 | 
				
			||||||
		return statuses, nil
 | 
							return statuses, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return statuses, x.In("id", ids).Find(&statuses)
 | 
						return statuses, e.In("id", ids).Find(&statuses)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
 | 
					// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,6 +71,11 @@ func listGPGKeys(e Engine, uid int64, listOptions ListOptions) ([]*GPGKey, error
 | 
				
			|||||||
	return keys, sess.Find(&keys)
 | 
						return keys, sess.Find(&keys)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountUserGPGKeys return number of gpg keys a user own
 | 
				
			||||||
 | 
					func CountUserGPGKeys(userID int64) (int64, error) {
 | 
				
			||||||
 | 
						return x.Where("owner_id=? AND primary_key_id=''", userID).Count(&GPGKey{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetGPGKeyByID returns public key by given ID.
 | 
					// GetGPGKeyByID returns public key by given ID.
 | 
				
			||||||
func GetGPGKeyByID(keyID int64) (*GPGKey, error) {
 | 
					func GetGPGKeyByID(keyID int64) (*GPGKey, error) {
 | 
				
			||||||
	key := new(GPGKey)
 | 
						key := new(GPGKey)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,7 +89,7 @@ func init() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (issue *Issue) loadTotalTimes(e Engine) (err error) {
 | 
					func (issue *Issue) loadTotalTimes(e Engine) (err error) {
 | 
				
			||||||
	opts := FindTrackedTimesOptions{IssueID: issue.ID}
 | 
						opts := FindTrackedTimesOptions{IssueID: issue.ID}
 | 
				
			||||||
	issue.TotalTrackedTime, err = opts.ToSession(e).SumInt(&TrackedTime{}, "time")
 | 
						issue.TotalTrackedTime, err = opts.toSession(e).SumInt(&TrackedTime{}, "time")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -214,7 +214,7 @@ func (issue *Issue) loadCommentsByType(e Engine, tp CommentType) (err error) {
 | 
				
			|||||||
	if issue.Comments != nil {
 | 
						if issue.Comments != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	issue.Comments, err = findComments(e, FindCommentsOptions{
 | 
						issue.Comments, err = findComments(e, &FindCommentsOptions{
 | 
				
			||||||
		IssueID: issue.ID,
 | 
							IssueID: issue.ID,
 | 
				
			||||||
		Type:    tp,
 | 
							Type:    tp,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -999,7 +999,7 @@ func (opts *FindCommentsOptions) toConds() builder.Cond {
 | 
				
			|||||||
	return cond
 | 
						return cond
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func findComments(e Engine, opts FindCommentsOptions) ([]*Comment, error) {
 | 
					func findComments(e Engine, opts *FindCommentsOptions) ([]*Comment, error) {
 | 
				
			||||||
	comments := make([]*Comment, 0, 10)
 | 
						comments := make([]*Comment, 0, 10)
 | 
				
			||||||
	sess := e.Where(opts.toConds())
 | 
						sess := e.Where(opts.toConds())
 | 
				
			||||||
	if opts.RepoID > 0 {
 | 
						if opts.RepoID > 0 {
 | 
				
			||||||
@@ -1019,10 +1019,19 @@ func findComments(e Engine, opts FindCommentsOptions) ([]*Comment, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindComments returns all comments according options
 | 
					// FindComments returns all comments according options
 | 
				
			||||||
func FindComments(opts FindCommentsOptions) ([]*Comment, error) {
 | 
					func FindComments(opts *FindCommentsOptions) ([]*Comment, error) {
 | 
				
			||||||
	return findComments(x, opts)
 | 
						return findComments(x, opts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountComments count all comments according options by ignoring pagination
 | 
				
			||||||
 | 
					func CountComments(opts *FindCommentsOptions) (int64, error) {
 | 
				
			||||||
 | 
						sess := x.Where(opts.toConds())
 | 
				
			||||||
 | 
						if opts.RepoID > 0 {
 | 
				
			||||||
 | 
							sess.Join("INNER", "issue", "issue.id = comment.issue_id")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sess.Count(&Comment{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateComment updates information of comment.
 | 
					// UpdateComment updates information of comment.
 | 
				
			||||||
func UpdateComment(c *Comment, doer *User) error {
 | 
					func UpdateComment(c *Comment, doer *User) error {
 | 
				
			||||||
	sess := x.NewSession()
 | 
						sess := x.NewSession()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -444,6 +444,11 @@ func GetLabelsByRepoID(repoID int64, sortType string, listOptions ListOptions) (
 | 
				
			|||||||
	return getLabelsByRepoID(x, repoID, sortType, listOptions)
 | 
						return getLabelsByRepoID(x, repoID, sortType, listOptions)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountLabelsByRepoID count number of all labels that belong to given repository by ID.
 | 
				
			||||||
 | 
					func CountLabelsByRepoID(repoID int64) (int64, error) {
 | 
				
			||||||
 | 
						return x.Where("repo_id = ?", repoID).Count(&Label{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ________
 | 
					// ________
 | 
				
			||||||
// \_____  \_______  ____
 | 
					// \_____  \_______  ____
 | 
				
			||||||
//  /   |   \_  __ \/ ___\
 | 
					//  /   |   \_  __ \/ ___\
 | 
				
			||||||
@@ -556,6 +561,11 @@ func GetLabelsByOrgID(orgID int64, sortType string, listOptions ListOptions) ([]
 | 
				
			|||||||
	return getLabelsByOrgID(x, orgID, sortType, listOptions)
 | 
						return getLabelsByOrgID(x, orgID, sortType, listOptions)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountLabelsByOrgID count all labels that belong to given organization by ID.
 | 
				
			||||||
 | 
					func CountLabelsByOrgID(orgID int64) (int64, error) {
 | 
				
			||||||
 | 
						return x.Where("org_id = ?", orgID).Count(&Label{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// .___
 | 
					// .___
 | 
				
			||||||
// |   | ______ ________ __   ____
 | 
					// |   | ______ ________ __   ____
 | 
				
			||||||
// |   |/  ___//  ___/  |  \_/ __ \
 | 
					// |   |/  ___//  ___/  |  \_/ __ \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -380,24 +380,33 @@ type GetMilestonesOption struct {
 | 
				
			|||||||
	SortType string
 | 
						SortType string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetMilestones returns milestones filtered by GetMilestonesOption's
 | 
					func (opts GetMilestonesOption) toCond() builder.Cond {
 | 
				
			||||||
func GetMilestones(opts GetMilestonesOption) (MilestoneList, error) {
 | 
						cond := builder.NewCond()
 | 
				
			||||||
	sess := x.Where("repo_id = ?", opts.RepoID)
 | 
						if opts.RepoID != 0 {
 | 
				
			||||||
 | 
							cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch opts.State {
 | 
						switch opts.State {
 | 
				
			||||||
	case api.StateClosed:
 | 
						case api.StateClosed:
 | 
				
			||||||
		sess = sess.And("is_closed = ?", true)
 | 
							cond = cond.And(builder.Eq{"is_closed": true})
 | 
				
			||||||
	case api.StateAll:
 | 
						case api.StateAll:
 | 
				
			||||||
		break
 | 
							break
 | 
				
			||||||
	// api.StateOpen:
 | 
						// api.StateOpen:
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		sess = sess.And("is_closed = ?", false)
 | 
							cond = cond.And(builder.Eq{"is_closed": false})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(opts.Name) != 0 {
 | 
						if len(opts.Name) != 0 {
 | 
				
			||||||
		sess = sess.And(builder.Like{"name", opts.Name})
 | 
							cond = cond.And(builder.Like{"name", opts.Name})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cond
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetMilestones returns milestones filtered by GetMilestonesOption's
 | 
				
			||||||
 | 
					func GetMilestones(opts GetMilestonesOption) (MilestoneList, int64, error) {
 | 
				
			||||||
 | 
						sess := x.Where(opts.toCond())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if opts.Page != 0 {
 | 
						if opts.Page != 0 {
 | 
				
			||||||
		sess = opts.setSessionPagination(sess)
 | 
							sess = opts.setSessionPagination(sess)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -420,7 +429,8 @@ func GetMilestones(opts GetMilestonesOption) (MilestoneList, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	miles := make([]*Milestone, 0, opts.PageSize)
 | 
						miles := make([]*Milestone, 0, opts.PageSize)
 | 
				
			||||||
	return miles, sess.Find(&miles)
 | 
						total, err := sess.FindAndCount(&miles)
 | 
				
			||||||
 | 
						return miles, total, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SearchMilestones search milestones
 | 
					// SearchMilestones search milestones
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
 | 
				
			|||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	test := func(repoID int64, state api.StateType) {
 | 
						test := func(repoID int64, state api.StateType) {
 | 
				
			||||||
		repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
 | 
							repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
 | 
				
			||||||
		milestones, err := GetMilestones(GetMilestonesOption{
 | 
							milestones, _, err := GetMilestones(GetMilestonesOption{
 | 
				
			||||||
			RepoID: repo.ID,
 | 
								RepoID: repo.ID,
 | 
				
			||||||
			State:  state,
 | 
								State:  state,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
@@ -87,7 +87,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
 | 
				
			|||||||
	test(3, api.StateClosed)
 | 
						test(3, api.StateClosed)
 | 
				
			||||||
	test(3, api.StateAll)
 | 
						test(3, api.StateAll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	milestones, err := GetMilestones(GetMilestonesOption{
 | 
						milestones, _, err := GetMilestones(GetMilestonesOption{
 | 
				
			||||||
		RepoID: NonexistentID,
 | 
							RepoID: NonexistentID,
 | 
				
			||||||
		State:  api.StateOpen,
 | 
							State:  api.StateOpen,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -100,7 +100,7 @@ func TestGetMilestones(t *testing.T) {
 | 
				
			|||||||
	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
 | 
						repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
 | 
				
			||||||
	test := func(sortType string, sortCond func(*Milestone) int) {
 | 
						test := func(sortType string, sortCond func(*Milestone) int) {
 | 
				
			||||||
		for _, page := range []int{0, 1} {
 | 
							for _, page := range []int{0, 1} {
 | 
				
			||||||
			milestones, err := GetMilestones(GetMilestonesOption{
 | 
								milestones, _, err := GetMilestones(GetMilestonesOption{
 | 
				
			||||||
				ListOptions: ListOptions{
 | 
									ListOptions: ListOptions{
 | 
				
			||||||
					Page:     page,
 | 
										Page:     page,
 | 
				
			||||||
					PageSize: setting.UI.IssuePagingNum,
 | 
										PageSize: setting.UI.IssuePagingNum,
 | 
				
			||||||
@@ -117,7 +117,7 @@ func TestGetMilestones(t *testing.T) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			assert.True(t, sort.IntsAreSorted(values))
 | 
								assert.True(t, sort.IntsAreSorted(values))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			milestones, err = GetMilestones(GetMilestonesOption{
 | 
								milestones, _, err = GetMilestones(GetMilestonesOption{
 | 
				
			||||||
				ListOptions: ListOptions{
 | 
									ListOptions: ListOptions{
 | 
				
			||||||
					Page:     page,
 | 
										Page:     page,
 | 
				
			||||||
					PageSize: setting.UI.IssuePagingNum,
 | 
										PageSize: setting.UI.IssuePagingNum,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,11 @@ func GetUserStopwatches(userID int64, listOptions ListOptions) ([]*Stopwatch, er
 | 
				
			|||||||
	return sws, nil
 | 
						return sws, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountUserStopwatches return count of all stopwatches of a user
 | 
				
			||||||
 | 
					func CountUserStopwatches(userID int64) (int64, error) {
 | 
				
			||||||
 | 
						return x.Where("user_id = ?", userID).Count(&Stopwatch{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StopwatchExists returns true if the stopwatch exists
 | 
					// StopwatchExists returns true if the stopwatch exists
 | 
				
			||||||
func StopwatchExists(userID, issueID int64) bool {
 | 
					func StopwatchExists(userID, issueID int64) bool {
 | 
				
			||||||
	_, exists, _ := getStopwatch(x, userID, issueID)
 | 
						_, exists, _ := getStopwatch(x, userID, issueID)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,8 +79,8 @@ type FindTrackedTimesOptions struct {
 | 
				
			|||||||
	CreatedBeforeUnix int64
 | 
						CreatedBeforeUnix int64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToCond will convert each condition into a xorm-Cond
 | 
					// toCond will convert each condition into a xorm-Cond
 | 
				
			||||||
func (opts *FindTrackedTimesOptions) ToCond() builder.Cond {
 | 
					func (opts *FindTrackedTimesOptions) toCond() builder.Cond {
 | 
				
			||||||
	cond := builder.NewCond().And(builder.Eq{"tracked_time.deleted": false})
 | 
						cond := builder.NewCond().And(builder.Eq{"tracked_time.deleted": false})
 | 
				
			||||||
	if opts.IssueID != 0 {
 | 
						if opts.IssueID != 0 {
 | 
				
			||||||
		cond = cond.And(builder.Eq{"issue_id": opts.IssueID})
 | 
							cond = cond.And(builder.Eq{"issue_id": opts.IssueID})
 | 
				
			||||||
@@ -103,14 +103,14 @@ func (opts *FindTrackedTimesOptions) ToCond() builder.Cond {
 | 
				
			|||||||
	return cond
 | 
						return cond
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required
 | 
					// toSession will convert the given options to a xorm Session by using the conditions from toCond and joining with issue table if required
 | 
				
			||||||
func (opts *FindTrackedTimesOptions) ToSession(e Engine) Engine {
 | 
					func (opts *FindTrackedTimesOptions) toSession(e Engine) Engine {
 | 
				
			||||||
	sess := e
 | 
						sess := e
 | 
				
			||||||
	if opts.RepositoryID > 0 || opts.MilestoneID > 0 {
 | 
						if opts.RepositoryID > 0 || opts.MilestoneID > 0 {
 | 
				
			||||||
		sess = e.Join("INNER", "issue", "issue.id = tracked_time.issue_id")
 | 
							sess = e.Join("INNER", "issue", "issue.id = tracked_time.issue_id")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sess = sess.Where(opts.ToCond())
 | 
						sess = sess.Where(opts.toCond())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if opts.Page != 0 {
 | 
						if opts.Page != 0 {
 | 
				
			||||||
		sess = opts.setEnginePagination(sess)
 | 
							sess = opts.setEnginePagination(sess)
 | 
				
			||||||
@@ -119,18 +119,27 @@ func (opts *FindTrackedTimesOptions) ToSession(e Engine) Engine {
 | 
				
			|||||||
	return sess
 | 
						return sess
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getTrackedTimes(e Engine, options FindTrackedTimesOptions) (trackedTimes TrackedTimeList, err error) {
 | 
					func getTrackedTimes(e Engine, options *FindTrackedTimesOptions) (trackedTimes TrackedTimeList, err error) {
 | 
				
			||||||
	err = options.ToSession(e).Find(&trackedTimes)
 | 
						err = options.toSession(e).Find(&trackedTimes)
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetTrackedTimes returns all tracked times that fit to the given options.
 | 
					// GetTrackedTimes returns all tracked times that fit to the given options.
 | 
				
			||||||
func GetTrackedTimes(opts FindTrackedTimesOptions) (TrackedTimeList, error) {
 | 
					func GetTrackedTimes(opts *FindTrackedTimesOptions) (TrackedTimeList, error) {
 | 
				
			||||||
	return getTrackedTimes(x, opts)
 | 
						return getTrackedTimes(x, opts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountTrackedTimes returns count of tracked times that fit to the given options.
 | 
				
			||||||
 | 
					func CountTrackedTimes(opts *FindTrackedTimesOptions) (int64, error) {
 | 
				
			||||||
 | 
						sess := x.Where(opts.toCond())
 | 
				
			||||||
 | 
						if opts.RepositoryID > 0 || opts.MilestoneID > 0 {
 | 
				
			||||||
 | 
							sess = sess.Join("INNER", "issue", "issue.id = tracked_time.issue_id")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sess.Count(&TrackedTime{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getTrackedSeconds(e Engine, opts FindTrackedTimesOptions) (trackedSeconds int64, err error) {
 | 
					func getTrackedSeconds(e Engine, opts FindTrackedTimesOptions) (trackedSeconds int64, err error) {
 | 
				
			||||||
	return opts.ToSession(e).SumInt(&TrackedTime{}, "time")
 | 
						return opts.toSession(e).SumInt(&TrackedTime{}, "time")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetTrackedSeconds return sum of seconds
 | 
					// GetTrackedSeconds return sum of seconds
 | 
				
			||||||
@@ -188,7 +197,7 @@ func addTime(e Engine, user *User, issue *Issue, amount int64, created time.Time
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TotalTimes returns the spent time for each user by an issue
 | 
					// TotalTimes returns the spent time for each user by an issue
 | 
				
			||||||
func TotalTimes(options FindTrackedTimesOptions) (map[*User]string, error) {
 | 
					func TotalTimes(options *FindTrackedTimesOptions) (map[*User]string, error) {
 | 
				
			||||||
	trackedTimes, err := GetTrackedTimes(options)
 | 
						trackedTimes, err := GetTrackedTimes(options)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -288,7 +297,7 @@ func deleteTimes(e Engine, opts FindTrackedTimesOptions) (removedTime int64, err
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = opts.ToSession(e).Table("tracked_time").Cols("deleted").Update(&TrackedTime{Deleted: true})
 | 
						_, err = opts.toSession(e).Table("tracked_time").Cols("deleted").Update(&TrackedTime{Deleted: true})
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,27 +38,27 @@ func TestGetTrackedTimes(t *testing.T) {
 | 
				
			|||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// by Issue
 | 
						// by Issue
 | 
				
			||||||
	times, err := GetTrackedTimes(FindTrackedTimesOptions{IssueID: 1})
 | 
						times, err := GetTrackedTimes(&FindTrackedTimesOptions{IssueID: 1})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, times, 1)
 | 
						assert.Len(t, times, 1)
 | 
				
			||||||
	assert.Equal(t, int64(400), times[0].Time)
 | 
						assert.Equal(t, int64(400), times[0].Time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	times, err = GetTrackedTimes(FindTrackedTimesOptions{IssueID: -1})
 | 
						times, err = GetTrackedTimes(&FindTrackedTimesOptions{IssueID: -1})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, times, 0)
 | 
						assert.Len(t, times, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// by User
 | 
						// by User
 | 
				
			||||||
	times, err = GetTrackedTimes(FindTrackedTimesOptions{UserID: 1})
 | 
						times, err = GetTrackedTimes(&FindTrackedTimesOptions{UserID: 1})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, times, 3)
 | 
						assert.Len(t, times, 3)
 | 
				
			||||||
	assert.Equal(t, int64(400), times[0].Time)
 | 
						assert.Equal(t, int64(400), times[0].Time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	times, err = GetTrackedTimes(FindTrackedTimesOptions{UserID: 3})
 | 
						times, err = GetTrackedTimes(&FindTrackedTimesOptions{UserID: 3})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, times, 0)
 | 
						assert.Len(t, times, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// by Repo
 | 
						// by Repo
 | 
				
			||||||
	times, err = GetTrackedTimes(FindTrackedTimesOptions{RepositoryID: 2})
 | 
						times, err = GetTrackedTimes(&FindTrackedTimesOptions{RepositoryID: 2})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, times, 3)
 | 
						assert.Len(t, times, 3)
 | 
				
			||||||
	assert.Equal(t, int64(1), times[0].Time)
 | 
						assert.Equal(t, int64(1), times[0].Time)
 | 
				
			||||||
@@ -66,11 +66,11 @@ func TestGetTrackedTimes(t *testing.T) {
 | 
				
			|||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Equal(t, issue.RepoID, int64(2))
 | 
						assert.Equal(t, issue.RepoID, int64(2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	times, err = GetTrackedTimes(FindTrackedTimesOptions{RepositoryID: 1})
 | 
						times, err = GetTrackedTimes(&FindTrackedTimesOptions{RepositoryID: 1})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, times, 5)
 | 
						assert.Len(t, times, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	times, err = GetTrackedTimes(FindTrackedTimesOptions{RepositoryID: 10})
 | 
						times, err = GetTrackedTimes(&FindTrackedTimesOptions{RepositoryID: 10})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, times, 0)
 | 
						assert.Len(t, times, 0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -78,7 +78,7 @@ func TestGetTrackedTimes(t *testing.T) {
 | 
				
			|||||||
func TestTotalTimes(t *testing.T) {
 | 
					func TestTotalTimes(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	total, err := TotalTimes(FindTrackedTimesOptions{IssueID: 1})
 | 
						total, err := TotalTimes(&FindTrackedTimesOptions{IssueID: 1})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, total, 1)
 | 
						assert.Len(t, total, 1)
 | 
				
			||||||
	for user, time := range total {
 | 
						for user, time := range total {
 | 
				
			||||||
@@ -86,7 +86,7 @@ func TestTotalTimes(t *testing.T) {
 | 
				
			|||||||
		assert.Equal(t, "6min 40s", time)
 | 
							assert.Equal(t, "6min 40s", time)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	total, err = TotalTimes(FindTrackedTimesOptions{IssueID: 2})
 | 
						total, err = TotalTimes(&FindTrackedTimesOptions{IssueID: 2})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, total, 2)
 | 
						assert.Len(t, total, 2)
 | 
				
			||||||
	for user, time := range total {
 | 
						for user, time := range total {
 | 
				
			||||||
@@ -99,7 +99,7 @@ func TestTotalTimes(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	total, err = TotalTimes(FindTrackedTimesOptions{IssueID: 5})
 | 
						total, err = TotalTimes(&FindTrackedTimesOptions{IssueID: 5})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, total, 1)
 | 
						assert.Len(t, total, 1)
 | 
				
			||||||
	for user, time := range total {
 | 
						for user, time := range total {
 | 
				
			||||||
@@ -107,7 +107,7 @@ func TestTotalTimes(t *testing.T) {
 | 
				
			|||||||
		assert.Equal(t, "1s", time)
 | 
							assert.Equal(t, "1s", time)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	total, err = TotalTimes(FindTrackedTimesOptions{IssueID: 4})
 | 
						total, err = TotalTimes(&FindTrackedTimesOptions{IssueID: 4})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, total, 2)
 | 
						assert.Len(t, total, 2)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -125,6 +125,11 @@ func GetNotifications(opts *FindNotificationOptions) (NotificationList, error) {
 | 
				
			|||||||
	return getNotifications(x, opts)
 | 
						return getNotifications(x, opts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountNotifications count all notifications that fit to the given options and ignore pagination.
 | 
				
			||||||
 | 
					func CountNotifications(opts *FindNotificationOptions) (int64, error) {
 | 
				
			||||||
 | 
						return x.Where(opts.ToCond()).Count(&Notification{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CreateRepoTransferNotification creates  notification for the user a repository was transferred to
 | 
					// CreateRepoTransferNotification creates  notification for the user a repository was transferred to
 | 
				
			||||||
func CreateRepoTransferNotification(doer, newOwner *User, repo *Repository) error {
 | 
					func CreateRepoTransferNotification(doer, newOwner *User, repo *Repository) error {
 | 
				
			||||||
	sess := x.NewSession()
 | 
						sess := x.NewSession()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -269,7 +269,7 @@ func DeleteOAuth2Application(id, userid int64) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListOAuth2Applications returns a list of oauth2 applications belongs to given user.
 | 
					// ListOAuth2Applications returns a list of oauth2 applications belongs to given user.
 | 
				
			||||||
func ListOAuth2Applications(uid int64, listOptions ListOptions) ([]*OAuth2Application, error) {
 | 
					func ListOAuth2Applications(uid int64, listOptions ListOptions) ([]*OAuth2Application, int64, error) {
 | 
				
			||||||
	sess := x.
 | 
						sess := x.
 | 
				
			||||||
		Where("uid=?", uid).
 | 
							Where("uid=?", uid).
 | 
				
			||||||
		Desc("id")
 | 
							Desc("id")
 | 
				
			||||||
@@ -278,11 +278,13 @@ func ListOAuth2Applications(uid int64, listOptions ListOptions) ([]*OAuth2Applic
 | 
				
			|||||||
		sess = listOptions.setSessionPagination(sess)
 | 
							sess = listOptions.setSessionPagination(sess)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		apps := make([]*OAuth2Application, 0, listOptions.PageSize)
 | 
							apps := make([]*OAuth2Application, 0, listOptions.PageSize)
 | 
				
			||||||
		return apps, sess.Find(&apps)
 | 
							total, err := sess.FindAndCount(&apps)
 | 
				
			||||||
 | 
							return apps, total, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apps := make([]*OAuth2Application, 0, 5)
 | 
						apps := make([]*OAuth2Application, 0, 5)
 | 
				
			||||||
	return apps, sess.Find(&apps)
 | 
						total, err := sess.FindAndCount(&apps)
 | 
				
			||||||
 | 
						return apps, total, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//////////////////////////////////////////////////////
 | 
					//////////////////////////////////////////////////////
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,7 +52,7 @@ func (org *User) GetOwnerTeam() (*Team, error) {
 | 
				
			|||||||
	return org.getOwnerTeam(x)
 | 
						return org.getOwnerTeam(x)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (org *User) getTeams(e Engine) error {
 | 
					func (org *User) loadTeams(e Engine) error {
 | 
				
			||||||
	if org.Teams != nil {
 | 
						if org.Teams != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -62,13 +62,9 @@ func (org *User) getTeams(e Engine) error {
 | 
				
			|||||||
		Find(&org.Teams)
 | 
							Find(&org.Teams)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetTeams returns paginated teams that belong to organization.
 | 
					// LoadTeams load teams if not loaded.
 | 
				
			||||||
func (org *User) GetTeams(opts *SearchTeamOptions) error {
 | 
					func (org *User) LoadTeams() error {
 | 
				
			||||||
	if opts.Page != 0 {
 | 
						return org.loadTeams(x)
 | 
				
			||||||
		return org.getTeams(opts.getPaginatedSession())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return org.getTeams(x)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetMembers returns all members of organization.
 | 
					// GetMembers returns all members of organization.
 | 
				
			||||||
@@ -87,7 +83,7 @@ type FindOrgMembersOpts struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CountOrgMembers counts the organization's members
 | 
					// CountOrgMembers counts the organization's members
 | 
				
			||||||
func CountOrgMembers(opts FindOrgMembersOpts) (int64, error) {
 | 
					func CountOrgMembers(opts *FindOrgMembersOpts) (int64, error) {
 | 
				
			||||||
	sess := x.Where("org_id=?", opts.OrgID)
 | 
						sess := x.Where("org_id=?", opts.OrgID)
 | 
				
			||||||
	if opts.PublicOnly {
 | 
						if opts.PublicOnly {
 | 
				
			||||||
		sess.And("is_public = ?", true)
 | 
							sess.And("is_public = ?", true)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -790,16 +790,6 @@ func GetTeamMembers(teamID int64) ([]*User, error) {
 | 
				
			|||||||
	return getTeamMembers(x, teamID)
 | 
						return getTeamMembers(x, teamID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getUserTeams(e Engine, userID int64, listOptions ListOptions) (teams []*Team, err error) {
 | 
					 | 
				
			||||||
	sess := e.
 | 
					 | 
				
			||||||
		Join("INNER", "team_user", "team_user.team_id = team.id").
 | 
					 | 
				
			||||||
		Where("team_user.uid=?", userID)
 | 
					 | 
				
			||||||
	if listOptions.Page != 0 {
 | 
					 | 
				
			||||||
		sess = listOptions.setSessionPagination(sess)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return teams, sess.Find(&teams)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getUserOrgTeams(e Engine, orgID, userID int64) (teams []*Team, err error) {
 | 
					func getUserOrgTeams(e Engine, orgID, userID int64) (teams []*Team, err error) {
 | 
				
			||||||
	return teams, e.
 | 
						return teams, e.
 | 
				
			||||||
		Join("INNER", "team_user", "team_user.team_id = team.id").
 | 
							Join("INNER", "team_user", "team_user.team_id = team.id").
 | 
				
			||||||
@@ -823,11 +813,6 @@ func GetUserOrgTeams(orgID, userID int64) ([]*Team, error) {
 | 
				
			|||||||
	return getUserOrgTeams(x, orgID, userID)
 | 
						return getUserOrgTeams(x, orgID, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetUserTeams returns all teams that user belongs across all organizations.
 | 
					 | 
				
			||||||
func GetUserTeams(userID int64, listOptions ListOptions) ([]*Team, error) {
 | 
					 | 
				
			||||||
	return getUserTeams(x, userID, listOptions)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// AddTeamMember adds new membership of given team to given organization,
 | 
					// AddTeamMember adds new membership of given team to given organization,
 | 
				
			||||||
// the user will have membership to given organization automatically when needed.
 | 
					// the user will have membership to given organization automatically when needed.
 | 
				
			||||||
func AddTeamMember(team *Team, userID int64) error {
 | 
					func AddTeamMember(team *Team, userID int64) error {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -286,7 +286,7 @@ func TestGetTeamMembers(t *testing.T) {
 | 
				
			|||||||
func TestGetUserTeams(t *testing.T) {
 | 
					func TestGetUserTeams(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	test := func(userID int64) {
 | 
						test := func(userID int64) {
 | 
				
			||||||
		teams, err := GetUserTeams(userID, ListOptions{})
 | 
							teams, _, err := SearchTeam(&SearchTeamOptions{UserID: userID})
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		for _, team := range teams {
 | 
							for _, team := range teams {
 | 
				
			||||||
			AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
 | 
								AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,7 @@ func TestUser_GetOwnerTeam(t *testing.T) {
 | 
				
			|||||||
func TestUser_GetTeams(t *testing.T) {
 | 
					func TestUser_GetTeams(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	org := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User)
 | 
						org := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User)
 | 
				
			||||||
	assert.NoError(t, org.GetTeams(&SearchTeamOptions{}))
 | 
						assert.NoError(t, org.LoadTeams())
 | 
				
			||||||
	if assert.Len(t, org.Teams, 4) {
 | 
						if assert.Len(t, org.Teams, 4) {
 | 
				
			||||||
		assert.Equal(t, int64(1), org.Teams[0].ID)
 | 
							assert.Equal(t, int64(1), org.Teams[0].ID)
 | 
				
			||||||
		assert.Equal(t, int64(2), org.Teams[1].ID)
 | 
							assert.Equal(t, int64(2), org.Teams[1].ID)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1125,8 +1125,8 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, overwriteO
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Give access to all members in teams with access to all repositories.
 | 
						// Give access to all members in teams with access to all repositories.
 | 
				
			||||||
	if u.IsOrganization() {
 | 
						if u.IsOrganization() {
 | 
				
			||||||
		if err := u.getTeams(ctx.e); err != nil {
 | 
							if err := u.loadTeams(ctx.e); err != nil {
 | 
				
			||||||
			return fmt.Errorf("GetTeams: %v", err)
 | 
								return fmt.Errorf("loadTeams: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for _, t := range u.Teams {
 | 
							for _, t := range u.Teams {
 | 
				
			||||||
			if t.IncludesAllRepositories {
 | 
								if t.IncludesAllRepositories {
 | 
				
			||||||
@@ -1439,7 +1439,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if org.IsOrganization() {
 | 
						if org.IsOrganization() {
 | 
				
			||||||
		if err = org.getTeams(sess); err != nil {
 | 
							if err = org.loadTeams(sess); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1453,7 +1453,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete Deploy Keys
 | 
						// Delete Deploy Keys
 | 
				
			||||||
	deployKeys, err := listDeployKeys(sess, repo.ID, ListOptions{})
 | 
						deployKeys, err := listDeployKeys(sess, &ListDeployKeysOptions{RepoID: repoID})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return fmt.Errorf("listDeployKeys: %v", err)
 | 
							return fmt.Errorf("listDeployKeys: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,6 +102,11 @@ func (repo *Repository) GetCollaborators(listOptions ListOptions) ([]*Collaborat
 | 
				
			|||||||
	return repo.getCollaborators(x, listOptions)
 | 
						return repo.getCollaborators(x, listOptions)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountCollaborators returns total number of collaborators for a repository
 | 
				
			||||||
 | 
					func (repo *Repository) CountCollaborators() (int64, error) {
 | 
				
			||||||
 | 
						return x.Where("repo_id = ? ", repo.ID).Count(&Collaboration{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (repo *Repository) getCollaboration(e Engine, uid int64) (*Collaboration, error) {
 | 
					func (repo *Repository) getCollaboration(e Engine, uid int64) (*Collaboration, error) {
 | 
				
			||||||
	collaboration := &Collaboration{
 | 
						collaboration := &Collaboration{
 | 
				
			||||||
		RepoID: repo.ID,
 | 
							RepoID: repo.ID,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,7 +111,7 @@ func GenerateGitHooks(ctx DBContext, templateRepo, generateRepo *Repository) err
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GenerateWebhooks generates webhooks from a template repository
 | 
					// GenerateWebhooks generates webhooks from a template repository
 | 
				
			||||||
func GenerateWebhooks(ctx DBContext, templateRepo, generateRepo *Repository) error {
 | 
					func GenerateWebhooks(ctx DBContext, templateRepo, generateRepo *Repository) error {
 | 
				
			||||||
	templateWebhooks, err := GetWebhooksByRepoID(templateRepo.ID, ListOptions{})
 | 
						templateWebhooks, err := ListWebhooksByOpts(&ListWebhookOptions{RepoID: templateRepo.ID})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -291,8 +291,8 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if newOwner.IsOrganization() {
 | 
						if newOwner.IsOrganization() {
 | 
				
			||||||
		if err := newOwner.getTeams(sess); err != nil {
 | 
							if err := newOwner.loadTeams(sess); err != nil {
 | 
				
			||||||
			return fmt.Errorf("GetTeams: %v", err)
 | 
								return fmt.Errorf("LoadTeams: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for _, t := range newOwner.Teams {
 | 
							for _, t := range newOwner.Teams {
 | 
				
			||||||
			if t.IncludesAllRepositories {
 | 
								if t.IncludesAllRepositories {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -208,6 +208,11 @@ func FindReviews(opts FindReviewOptions) ([]*Review, error) {
 | 
				
			|||||||
	return findReviews(x, opts)
 | 
						return findReviews(x, opts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountReviews returns count of reviews passing FindReviewOptions
 | 
				
			||||||
 | 
					func CountReviews(opts FindReviewOptions) (int64, error) {
 | 
				
			||||||
 | 
						return x.Where(opts.toCond()).Count(&Review{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CreateReviewOptions represent the options to create a review. Type, Issue and Reviewer are required.
 | 
					// CreateReviewOptions represent the options to create a review. Type, Issue and Reviewer are required.
 | 
				
			||||||
type CreateReviewOptions struct {
 | 
					type CreateReviewOptions struct {
 | 
				
			||||||
	Content      string
 | 
						Content      string
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -205,6 +205,12 @@ func ListPublicKeys(uid int64, listOptions ListOptions) ([]*PublicKey, error) {
 | 
				
			|||||||
	return keys, sess.Find(&keys)
 | 
						return keys, sess.Find(&keys)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountPublicKeys count public keys a user has
 | 
				
			||||||
 | 
					func CountPublicKeys(userID int64) (int64, error) {
 | 
				
			||||||
 | 
						sess := x.Where("owner_id = ? AND type != ?", userID, KeyTypePrincipal)
 | 
				
			||||||
 | 
						return sess.Count(&PublicKey{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListPublicKeysBySource returns a list of synchronized public keys for a given user and login source.
 | 
					// ListPublicKeysBySource returns a list of synchronized public keys for a given user and login source.
 | 
				
			||||||
func ListPublicKeysBySource(uid, loginSourceID int64) ([]*PublicKey, error) {
 | 
					func ListPublicKeysBySource(uid, loginSourceID int64) ([]*PublicKey, error) {
 | 
				
			||||||
	keys := make([]*PublicKey, 0, 5)
 | 
						keys := make([]*PublicKey, 0, 5)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -264,36 +264,48 @@ func deleteDeployKey(sess Engine, doer *User, id int64) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListDeployKeys returns all deploy keys by given repository ID.
 | 
					// ListDeployKeysOptions are options for ListDeployKeys
 | 
				
			||||||
func ListDeployKeys(repoID int64, listOptions ListOptions) ([]*DeployKey, error) {
 | 
					type ListDeployKeysOptions struct {
 | 
				
			||||||
	return listDeployKeys(x, repoID, listOptions)
 | 
						ListOptions
 | 
				
			||||||
 | 
						RepoID      int64
 | 
				
			||||||
 | 
						KeyID       int64
 | 
				
			||||||
 | 
						Fingerprint string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func listDeployKeys(e Engine, repoID int64, listOptions ListOptions) ([]*DeployKey, error) {
 | 
					func (opt ListDeployKeysOptions) toCond() builder.Cond {
 | 
				
			||||||
	sess := e.Where("repo_id = ?", repoID)
 | 
					 | 
				
			||||||
	if listOptions.Page != 0 {
 | 
					 | 
				
			||||||
		sess = listOptions.setSessionPagination(sess)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		keys := make([]*DeployKey, 0, listOptions.PageSize)
 | 
					 | 
				
			||||||
		return keys, sess.Find(&keys)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	keys := make([]*DeployKey, 0, 5)
 | 
					 | 
				
			||||||
	return keys, sess.Find(&keys)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SearchDeployKeys returns a list of deploy keys matching the provided arguments.
 | 
					 | 
				
			||||||
func SearchDeployKeys(repoID, keyID int64, fingerprint string) ([]*DeployKey, error) {
 | 
					 | 
				
			||||||
	keys := make([]*DeployKey, 0, 5)
 | 
					 | 
				
			||||||
	cond := builder.NewCond()
 | 
						cond := builder.NewCond()
 | 
				
			||||||
	if repoID != 0 {
 | 
						if opt.RepoID != 0 {
 | 
				
			||||||
		cond = cond.And(builder.Eq{"repo_id": repoID})
 | 
							cond = cond.And(builder.Eq{"repo_id": opt.RepoID})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if keyID != 0 {
 | 
						if opt.KeyID != 0 {
 | 
				
			||||||
		cond = cond.And(builder.Eq{"key_id": keyID})
 | 
							cond = cond.And(builder.Eq{"key_id": opt.KeyID})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if fingerprint != "" {
 | 
						if opt.Fingerprint != "" {
 | 
				
			||||||
		cond = cond.And(builder.Eq{"fingerprint": fingerprint})
 | 
							cond = cond.And(builder.Eq{"fingerprint": opt.Fingerprint})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return keys, x.Where(cond).Find(&keys)
 | 
						return cond
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListDeployKeys returns a list of deploy keys matching the provided arguments.
 | 
				
			||||||
 | 
					func ListDeployKeys(opts *ListDeployKeysOptions) ([]*DeployKey, error) {
 | 
				
			||||||
 | 
						return listDeployKeys(x, opts)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func listDeployKeys(e Engine, opts *ListDeployKeysOptions) ([]*DeployKey, error) {
 | 
				
			||||||
 | 
						sess := e.Where(opts.toCond())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if opts.Page != 0 {
 | 
				
			||||||
 | 
							sess = opts.setSessionPagination(sess)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							keys := make([]*DeployKey, 0, opts.PageSize)
 | 
				
			||||||
 | 
							return keys, sess.Find(&keys)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						keys := make([]*DeployKey, 0, 5)
 | 
				
			||||||
 | 
						return keys, sess.Find(&keys)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountDeployKeys returns count deploy keys matching the provided arguments.
 | 
				
			||||||
 | 
					func CountDeployKeys(opts *ListDeployKeysOptions) (int64, error) {
 | 
				
			||||||
 | 
						return x.Where(opts.toCond()).Count(&DeployKey{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,6 +122,15 @@ func UpdateAccessToken(t *AccessToken) error {
 | 
				
			|||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountAccessTokens count access tokens belongs to given user by options
 | 
				
			||||||
 | 
					func CountAccessTokens(opts ListAccessTokensOptions) (int64, error) {
 | 
				
			||||||
 | 
						sess := x.Where("uid=?", opts.UserID)
 | 
				
			||||||
 | 
						if len(opts.Name) != 0 {
 | 
				
			||||||
 | 
							sess = sess.Where("name=?", opts.Name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sess.Count(&AccessToken{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteAccessTokenByID deletes access token by given ID.
 | 
					// DeleteAccessTokenByID deletes access token by given ID.
 | 
				
			||||||
func DeleteAccessTokenByID(id, userID int64) error {
 | 
					func DeleteAccessTokenByID(id, userID int64) error {
 | 
				
			||||||
	cnt, err := x.ID(id).Delete(&AccessToken{
 | 
						cnt, err := x.ID(id).Delete(&AccessToken{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -184,7 +184,7 @@ func (opts *FindTopicOptions) toConds() builder.Cond {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindTopics retrieves the topics via FindTopicOptions
 | 
					// FindTopics retrieves the topics via FindTopicOptions
 | 
				
			||||||
func FindTopics(opts *FindTopicOptions) (topics []*Topic, err error) {
 | 
					func FindTopics(opts *FindTopicOptions) ([]*Topic, int64, error) {
 | 
				
			||||||
	sess := x.Select("topic.*").Where(opts.toConds())
 | 
						sess := x.Select("topic.*").Where(opts.toConds())
 | 
				
			||||||
	if opts.RepoID > 0 {
 | 
						if opts.RepoID > 0 {
 | 
				
			||||||
		sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
 | 
							sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
 | 
				
			||||||
@@ -192,7 +192,18 @@ func FindTopics(opts *FindTopicOptions) (topics []*Topic, err error) {
 | 
				
			|||||||
	if opts.PageSize != 0 && opts.Page != 0 {
 | 
						if opts.PageSize != 0 && opts.Page != 0 {
 | 
				
			||||||
		sess = opts.setSessionPagination(sess)
 | 
							sess = opts.setSessionPagination(sess)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return topics, sess.Desc("topic.repo_count").Find(&topics)
 | 
						topics := make([]*Topic, 0, 10)
 | 
				
			||||||
 | 
						total, err := sess.Desc("topic.repo_count").FindAndCount(&topics)
 | 
				
			||||||
 | 
						return topics, total, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CountTopics counts the number of topics matching the FindTopicOptions
 | 
				
			||||||
 | 
					func CountTopics(opts *FindTopicOptions) (int64, error) {
 | 
				
			||||||
 | 
						sess := x.Where(opts.toConds())
 | 
				
			||||||
 | 
						if opts.RepoID > 0 {
 | 
				
			||||||
 | 
							sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sess.Count(new(Topic))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRepoTopicByName retrieves topic from name for a repo if it exist
 | 
					// GetRepoTopicByName retrieves topic from name for a repo if it exist
 | 
				
			||||||
@@ -269,7 +280,7 @@ func DeleteTopic(repoID int64, topicName string) (*Topic, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// SaveTopics save topics to a repository
 | 
					// SaveTopics save topics to a repository
 | 
				
			||||||
func SaveTopics(repoID int64, topicNames ...string) error {
 | 
					func SaveTopics(repoID int64, topicNames ...string) error {
 | 
				
			||||||
	topics, err := FindTopics(&FindTopicOptions{
 | 
						topics, _, err := FindTopics(&FindTopicOptions{
 | 
				
			||||||
		RepoID: repoID,
 | 
							RepoID: repoID,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,17 +17,18 @@ func TestAddTopic(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	topics, err := FindTopics(&FindTopicOptions{})
 | 
						topics, _, err := FindTopics(&FindTopicOptions{})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, topics, totalNrOfTopics)
 | 
						assert.Len(t, topics, totalNrOfTopics)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	topics, err = FindTopics(&FindTopicOptions{
 | 
						topics, total, err := FindTopics(&FindTopicOptions{
 | 
				
			||||||
		ListOptions: ListOptions{Page: 1, PageSize: 2},
 | 
							ListOptions: ListOptions{Page: 1, PageSize: 2},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, topics, 2)
 | 
						assert.Len(t, topics, 2)
 | 
				
			||||||
 | 
						assert.EqualValues(t, 6, total)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	topics, err = FindTopics(&FindTopicOptions{
 | 
						topics, _, err = FindTopics(&FindTopicOptions{
 | 
				
			||||||
		RepoID: 1,
 | 
							RepoID: 1,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
@@ -35,11 +36,11 @@ func TestAddTopic(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	assert.NoError(t, SaveTopics(2, "golang"))
 | 
						assert.NoError(t, SaveTopics(2, "golang"))
 | 
				
			||||||
	repo2NrOfTopics = 1
 | 
						repo2NrOfTopics = 1
 | 
				
			||||||
	topics, err = FindTopics(&FindTopicOptions{})
 | 
						topics, _, err = FindTopics(&FindTopicOptions{})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, topics, totalNrOfTopics)
 | 
						assert.Len(t, topics, totalNrOfTopics)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	topics, err = FindTopics(&FindTopicOptions{
 | 
						topics, _, err = FindTopics(&FindTopicOptions{
 | 
				
			||||||
		RepoID: 2,
 | 
							RepoID: 2,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
@@ -52,11 +53,11 @@ func TestAddTopic(t *testing.T) {
 | 
				
			|||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.EqualValues(t, 1, topic.RepoCount)
 | 
						assert.EqualValues(t, 1, topic.RepoCount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	topics, err = FindTopics(&FindTopicOptions{})
 | 
						topics, _, err = FindTopics(&FindTopicOptions{})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, topics, totalNrOfTopics)
 | 
						assert.Len(t, topics, totalNrOfTopics)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	topics, err = FindTopics(&FindTopicOptions{
 | 
						topics, _, err = FindTopics(&FindTopicOptions{
 | 
				
			||||||
		RepoID: 2,
 | 
							RepoID: 2,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1704,7 +1704,7 @@ func GetStarredRepos(userID int64, private bool, listOptions ListOptions) ([]*Re
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetWatchedRepos returns the repos watched by a particular user
 | 
					// GetWatchedRepos returns the repos watched by a particular user
 | 
				
			||||||
func GetWatchedRepos(userID int64, private bool, listOptions ListOptions) ([]*Repository, error) {
 | 
					func GetWatchedRepos(userID int64, private bool, listOptions ListOptions) ([]*Repository, int64, error) {
 | 
				
			||||||
	sess := x.Where("watch.user_id=?", userID).
 | 
						sess := x.Where("watch.user_id=?", userID).
 | 
				
			||||||
		And("`watch`.mode<>?", RepoWatchModeDont).
 | 
							And("`watch`.mode<>?", RepoWatchModeDont).
 | 
				
			||||||
		Join("LEFT", "watch", "`repository`.id=`watch`.repo_id")
 | 
							Join("LEFT", "watch", "`repository`.id=`watch`.repo_id")
 | 
				
			||||||
@@ -1716,11 +1716,13 @@ func GetWatchedRepos(userID int64, private bool, listOptions ListOptions) ([]*Re
 | 
				
			|||||||
		sess = listOptions.setSessionPagination(sess)
 | 
							sess = listOptions.setSessionPagination(sess)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		repos := make([]*Repository, 0, listOptions.PageSize)
 | 
							repos := make([]*Repository, 0, listOptions.PageSize)
 | 
				
			||||||
		return repos, sess.Find(&repos)
 | 
							total, err := sess.FindAndCount(&repos)
 | 
				
			||||||
 | 
							return repos, total, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repos := make([]*Repository, 0, 10)
 | 
						repos := make([]*Repository, 0, 10)
 | 
				
			||||||
	return repos, sess.Find(&repos)
 | 
						total, err := sess.FindAndCount(&repos)
 | 
				
			||||||
 | 
						return repos, total, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IterateUser iterate users
 | 
					// IterateUser iterate users
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,8 +16,10 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
						"code.gitea.io/gitea/modules/timeutil"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gouuid "github.com/google/uuid"
 | 
						gouuid "github.com/google/uuid"
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HookContentType is the content type of a web hook
 | 
					// HookContentType is the content type of a web hook
 | 
				
			||||||
@@ -387,53 +389,51 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
 | 
					// ListWebhookOptions are options to filter webhooks on ListWebhooksByOpts
 | 
				
			||||||
func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
 | 
					type ListWebhookOptions struct {
 | 
				
			||||||
	return getActiveWebhooksByRepoID(x, repoID)
 | 
						ListOptions
 | 
				
			||||||
 | 
						RepoID   int64
 | 
				
			||||||
 | 
						OrgID    int64
 | 
				
			||||||
 | 
						IsActive util.OptionalBool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) {
 | 
					func (opts *ListWebhookOptions) toCond() builder.Cond {
 | 
				
			||||||
	webhooks := make([]*Webhook, 0, 5)
 | 
						cond := builder.NewCond()
 | 
				
			||||||
	return webhooks, e.Where("is_active=?", true).
 | 
						if opts.RepoID != 0 {
 | 
				
			||||||
		Find(&webhooks, &Webhook{RepoID: repoID})
 | 
							cond = cond.And(builder.Eq{"webhook.repo_id": opts.RepoID})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if opts.OrgID != 0 {
 | 
				
			||||||
 | 
							cond = cond.And(builder.Eq{"webhook.org_id": opts.OrgID})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !opts.IsActive.IsNone() {
 | 
				
			||||||
 | 
							cond = cond.And(builder.Eq{"webhook.is_active": opts.IsActive.IsTrue()})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cond
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetWebhooksByRepoID returns all webhooks of a repository.
 | 
					func listWebhooksByOpts(e Engine, opts *ListWebhookOptions) ([]*Webhook, error) {
 | 
				
			||||||
func GetWebhooksByRepoID(repoID int64, listOptions ListOptions) ([]*Webhook, error) {
 | 
						sess := e.Where(opts.toCond())
 | 
				
			||||||
	if listOptions.Page == 0 {
 | 
					
 | 
				
			||||||
		webhooks := make([]*Webhook, 0, 5)
 | 
						if opts.Page != 0 {
 | 
				
			||||||
		return webhooks, x.Find(&webhooks, &Webhook{RepoID: repoID})
 | 
							sess = opts.setSessionPagination(sess)
 | 
				
			||||||
 | 
							webhooks := make([]*Webhook, 0, opts.PageSize)
 | 
				
			||||||
 | 
							err := sess.Find(&webhooks)
 | 
				
			||||||
 | 
							return webhooks, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sess := listOptions.getPaginatedSession()
 | 
						webhooks := make([]*Webhook, 0, 10)
 | 
				
			||||||
	webhooks := make([]*Webhook, 0, listOptions.PageSize)
 | 
						err := sess.Find(&webhooks)
 | 
				
			||||||
 | 
						return webhooks, err
 | 
				
			||||||
	return webhooks, sess.Find(&webhooks, &Webhook{RepoID: repoID})
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetActiveWebhooksByOrgID returns all active webhooks for an organization.
 | 
					// ListWebhooksByOpts return webhooks based on options
 | 
				
			||||||
func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
 | 
					func ListWebhooksByOpts(opts *ListWebhookOptions) ([]*Webhook, error) {
 | 
				
			||||||
	return getActiveWebhooksByOrgID(x, orgID)
 | 
						return listWebhooksByOpts(x, opts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getActiveWebhooksByOrgID(e Engine, orgID int64) (ws []*Webhook, err error) {
 | 
					// CountWebhooksByOpts count webhooks based on options and ignore pagination
 | 
				
			||||||
	err = e.
 | 
					func CountWebhooksByOpts(opts *ListWebhookOptions) (int64, error) {
 | 
				
			||||||
		Where("org_id=?", orgID).
 | 
						return x.Where(opts.toCond()).Count(&Webhook{})
 | 
				
			||||||
		And("is_active=?", true).
 | 
					 | 
				
			||||||
		Find(&ws)
 | 
					 | 
				
			||||||
	return ws, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetWebhooksByOrgID returns paginated webhooks for an organization.
 | 
					 | 
				
			||||||
func GetWebhooksByOrgID(orgID int64, listOptions ListOptions) ([]*Webhook, error) {
 | 
					 | 
				
			||||||
	if listOptions.Page == 0 {
 | 
					 | 
				
			||||||
		ws := make([]*Webhook, 0, 5)
 | 
					 | 
				
			||||||
		return ws, x.Find(&ws, &Webhook{OrgID: orgID})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sess := listOptions.getPaginatedSession()
 | 
					 | 
				
			||||||
	ws := make([]*Webhook, 0, listOptions.PageSize)
 | 
					 | 
				
			||||||
	return ws, sess.Find(&ws, &Webhook{OrgID: orgID})
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDefaultWebhooks returns all admin-default webhooks.
 | 
					// GetDefaultWebhooks returns all admin-default webhooks.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/modules/json"
 | 
						"code.gitea.io/gitea/modules/json"
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -118,7 +119,7 @@ func TestGetWebhookByOrgID(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestGetActiveWebhooksByRepoID(t *testing.T) {
 | 
					func TestGetActiveWebhooksByRepoID(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	hooks, err := GetActiveWebhooksByRepoID(1)
 | 
						hooks, err := ListWebhooksByOpts(&ListWebhookOptions{RepoID: 1, IsActive: util.OptionalBoolTrue})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	if assert.Len(t, hooks, 1) {
 | 
						if assert.Len(t, hooks, 1) {
 | 
				
			||||||
		assert.Equal(t, int64(1), hooks[0].ID)
 | 
							assert.Equal(t, int64(1), hooks[0].ID)
 | 
				
			||||||
@@ -128,7 +129,7 @@ func TestGetActiveWebhooksByRepoID(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestGetWebhooksByRepoID(t *testing.T) {
 | 
					func TestGetWebhooksByRepoID(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	hooks, err := GetWebhooksByRepoID(1, ListOptions{})
 | 
						hooks, err := ListWebhooksByOpts(&ListWebhookOptions{RepoID: 1})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	if assert.Len(t, hooks, 2) {
 | 
						if assert.Len(t, hooks, 2) {
 | 
				
			||||||
		assert.Equal(t, int64(1), hooks[0].ID)
 | 
							assert.Equal(t, int64(1), hooks[0].ID)
 | 
				
			||||||
@@ -138,7 +139,7 @@ func TestGetWebhooksByRepoID(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestGetActiveWebhooksByOrgID(t *testing.T) {
 | 
					func TestGetActiveWebhooksByOrgID(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	hooks, err := GetActiveWebhooksByOrgID(3)
 | 
						hooks, err := ListWebhooksByOpts(&ListWebhookOptions{OrgID: 3, IsActive: util.OptionalBoolTrue})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	if assert.Len(t, hooks, 1) {
 | 
						if assert.Len(t, hooks, 1) {
 | 
				
			||||||
		assert.Equal(t, int64(3), hooks[0].ID)
 | 
							assert.Equal(t, int64(3), hooks[0].ID)
 | 
				
			||||||
@@ -148,7 +149,7 @@ func TestGetActiveWebhooksByOrgID(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestGetWebhooksByOrgID(t *testing.T) {
 | 
					func TestGetWebhooksByOrgID(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	hooks, err := GetWebhooksByOrgID(3, ListOptions{})
 | 
						hooks, err := ListWebhooksByOpts(&ListWebhookOptions{OrgID: 3})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	if assert.Len(t, hooks, 1) {
 | 
						if assert.Len(t, hooks, 1) {
 | 
				
			||||||
		assert.Equal(t, int64(3), hooks[0].ID)
 | 
							assert.Equal(t, int64(3), hooks[0].ID)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -181,6 +181,23 @@ func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if len(links) > 0 {
 | 
						if len(links) > 0 {
 | 
				
			||||||
		ctx.Header().Set("Link", strings.Join(links, ","))
 | 
							ctx.Header().Set("Link", strings.Join(links, ","))
 | 
				
			||||||
 | 
							ctx.AppendAccessControlExposeHeaders("Link")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetTotalCountHeader set "X-Total-Count" header
 | 
				
			||||||
 | 
					func (ctx *APIContext) SetTotalCountHeader(total int64) {
 | 
				
			||||||
 | 
						ctx.Header().Set("X-Total-Count", fmt.Sprint(total))
 | 
				
			||||||
 | 
						ctx.AppendAccessControlExposeHeaders("X-Total-Count")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AppendAccessControlExposeHeaders append headers by name to "Access-Control-Expose-Headers" header
 | 
				
			||||||
 | 
					func (ctx *APIContext) AppendAccessControlExposeHeaders(names ...string) {
 | 
				
			||||||
 | 
						val := ctx.Header().Get("Access-Control-Expose-Headers")
 | 
				
			||||||
 | 
						if len(val) != 0 {
 | 
				
			||||||
 | 
							ctx.Header().Set("Access-Control-Expose-Headers", fmt.Sprintf("%s, %s", val, strings.Join(names, ", ")))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ctx.Header().Set("Access-Control-Expose-Headers", strings.Join(names, ", "))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -123,8 +123,8 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
 | 
				
			|||||||
	// Team.
 | 
						// Team.
 | 
				
			||||||
	if ctx.Org.IsMember {
 | 
						if ctx.Org.IsMember {
 | 
				
			||||||
		if ctx.Org.IsOwner {
 | 
							if ctx.Org.IsOwner {
 | 
				
			||||||
			if err := org.GetTeams(&models.SearchTeamOptions{}); err != nil {
 | 
								if err := org.LoadTeams(); err != nil {
 | 
				
			||||||
				ctx.ServerError("GetTeams", err)
 | 
									ctx.ServerError("LoadTeams", err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TagPrefix tags prefix path on the repository
 | 
					// TagPrefix tags prefix path on the repository
 | 
				
			||||||
@@ -160,24 +161,18 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetTagInfos returns all tag infos of the repository.
 | 
					// GetTagInfos returns all tag infos of the repository.
 | 
				
			||||||
func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, error) {
 | 
					func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
 | 
				
			||||||
	// TODO this a slow implementation, makes one git command per tag
 | 
						// TODO this a slow implementation, makes one git command per tag
 | 
				
			||||||
	stdout, err := NewCommand("tag").RunInDir(repo.Path)
 | 
						stdout, err := NewCommand("tag").RunInDir(repo.Path)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, 0, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tagNames := strings.Split(strings.TrimRight(stdout, "\n"), "\n")
 | 
						tagNames := strings.Split(strings.TrimRight(stdout, "\n"), "\n")
 | 
				
			||||||
 | 
						tagsTotal := len(tagNames)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if page != 0 {
 | 
						if page != 0 {
 | 
				
			||||||
		skip := (page - 1) * pageSize
 | 
							tagNames = util.PaginateSlice(tagNames, page, pageSize).([]string)
 | 
				
			||||||
		if skip >= len(tagNames) {
 | 
					 | 
				
			||||||
			return nil, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (len(tagNames) - skip) < pageSize {
 | 
					 | 
				
			||||||
			pageSize = len(tagNames) - skip
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		tagNames = tagNames[skip : skip+pageSize]
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var tags = make([]*Tag, 0, len(tagNames))
 | 
						var tags = make([]*Tag, 0, len(tagNames))
 | 
				
			||||||
@@ -189,13 +184,13 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		tag, err := repo.GetTag(tagName)
 | 
							tag, err := repo.GetTag(tagName)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, tagsTotal, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		tag.Name = tagName
 | 
							tag.Name = tagName
 | 
				
			||||||
		tags = append(tags, tag)
 | 
							tags = append(tags, tag)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sortTagsByTime(tags)
 | 
						sortTagsByTime(tags)
 | 
				
			||||||
	return tags, nil
 | 
						return tags, tagsTotal, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
 | 
					// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,9 +18,10 @@ func TestRepository_GetTags(t *testing.T) {
 | 
				
			|||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	defer bareRepo1.Close()
 | 
						defer bareRepo1.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tags, err := bareRepo1.GetTagInfos(0, 0)
 | 
						tags, total, err := bareRepo1.GetTagInfos(0, 0)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, tags, 1)
 | 
						assert.Len(t, tags, 1)
 | 
				
			||||||
 | 
						assert.Equal(t, len(tags), total)
 | 
				
			||||||
	assert.EqualValues(t, "test", tags[0].Name)
 | 
						assert.EqualValues(t, "test", tags[0].Name)
 | 
				
			||||||
	assert.EqualValues(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", tags[0].ID.String())
 | 
						assert.EqualValues(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", tags[0].ID.String())
 | 
				
			||||||
	assert.EqualValues(t, "tag", tags[0].Type)
 | 
						assert.EqualValues(t, "tag", tags[0].Type)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,14 +54,14 @@ func TestGiteaUploadRepo(t *testing.T) {
 | 
				
			|||||||
	assert.True(t, repo.HasWiki())
 | 
						assert.True(t, repo.HasWiki())
 | 
				
			||||||
	assert.EqualValues(t, models.RepositoryReady, repo.Status)
 | 
						assert.EqualValues(t, models.RepositoryReady, repo.Status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	milestones, err := models.GetMilestones(models.GetMilestonesOption{
 | 
						milestones, _, err := models.GetMilestones(models.GetMilestonesOption{
 | 
				
			||||||
		RepoID: repo.ID,
 | 
							RepoID: repo.ID,
 | 
				
			||||||
		State:  structs.StateOpen,
 | 
							State:  structs.StateOpen,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, milestones, 1)
 | 
						assert.Len(t, milestones, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	milestones, err = models.GetMilestones(models.GetMilestonesOption{
 | 
						milestones, _, err = models.GetMilestones(models.GetMilestonesOption{
 | 
				
			||||||
		RepoID: repo.ID,
 | 
							RepoID: repo.ID,
 | 
				
			||||||
		State:  structs.StateClosed,
 | 
							State:  structs.StateClosed,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@
 | 
				
			|||||||
package admin
 | 
					package admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -47,8 +46,7 @@ func ListUnadoptedRepositories(ctx *context.APIContext) {
 | 
				
			|||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", count))
 | 
						ctx.SetTotalCountHeader(int64(count))
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(http.StatusOK, repoNames)
 | 
						ctx.JSON(http.StatusOK, repoNames)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/cron"
 | 
						"code.gitea.io/gitea/modules/cron"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/structs"
 | 
						"code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
						"code.gitea.io/gitea/routers/api/v1/utils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,12 +37,10 @@ func ListCronTasks(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "403":
 | 
						//   "403":
 | 
				
			||||||
	//     "$ref": "#/responses/forbidden"
 | 
						//     "$ref": "#/responses/forbidden"
 | 
				
			||||||
	tasks := cron.ListTasks()
 | 
						tasks := cron.ListTasks()
 | 
				
			||||||
	listOpts := utils.GetListOptions(ctx)
 | 
						count := len(tasks)
 | 
				
			||||||
	start, end := listOpts.GetStartEnd()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(tasks) > listOpts.PageSize {
 | 
						listOpts := utils.GetListOptions(ctx)
 | 
				
			||||||
		tasks = tasks[start:end]
 | 
						tasks = util.PaginateSlice(tasks, listOpts.Page, listOpts.PageSize).(cron.TaskTable)
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res := make([]structs.Cron, len(tasks))
 | 
						res := make([]structs.Cron, len(tasks))
 | 
				
			||||||
	for i, task := range tasks {
 | 
						for i, task := range tasks {
 | 
				
			||||||
@@ -53,6 +52,8 @@ func ListCronTasks(ctx *context.APIContext) {
 | 
				
			|||||||
			ExecTimes: task.ExecTimes,
 | 
								ExecTimes: task.ExecTimes,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(count))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, res)
 | 
						ctx.JSON(http.StatusOK, res)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@
 | 
				
			|||||||
package admin
 | 
					package admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -121,7 +120,6 @@ func GetAllOrgs(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(maxResults)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &orgs)
 | 
						ctx.JSON(http.StatusOK, &orgs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -423,7 +423,6 @@ func GetAllUsers(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(maxResults)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &results)
 | 
						ctx.JSON(http.StatusOK, &results)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -108,6 +108,12 @@ func ListRepoNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	opts.RepoID = ctx.Repo.Repository.ID
 | 
						opts.RepoID = ctx.Repo.Repository.ID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						totalCount, err := models.CountNotifications(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nl, err := models.GetNotifications(opts)
 | 
						nl, err := models.GetNotifications(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
@@ -119,6 +125,8 @@ func ListRepoNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(totalCount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToNotifications(nl))
 | 
						ctx.JSON(http.StatusOK, convert.ToNotifications(nl))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,12 @@ func ListNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						totalCount, err := models.CountNotifications(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nl, err := models.GetNotifications(opts)
 | 
						nl, err := models.GetNotifications(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
@@ -79,6 +85,7 @@ func ListNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(totalCount)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToNotifications(nl))
 | 
						ctx.JSON(http.StatusOK, convert.ToNotifications(nl))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,16 +40,29 @@ func ListHooks(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/HookList"
 | 
						//     "$ref": "#/responses/HookList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	org := ctx.Org.Organization
 | 
						opts := &models.ListWebhookOptions{
 | 
				
			||||||
	orgHooks, err := models.GetWebhooksByOrgID(org.ID, utils.GetListOptions(ctx))
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
 | 
							OrgID:       ctx.Org.Organization.ID,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountWebhooksByOpts(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetWebhooksByOrgID", err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						orgHooks, err := models.ListWebhooksByOpts(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hooks := make([]*api.Hook, len(orgHooks))
 | 
						hooks := make([]*api.Hook, len(orgHooks))
 | 
				
			||||||
	for i, hook := range orgHooks {
 | 
						for i, hook := range orgHooks {
 | 
				
			||||||
		hooks[i] = convert.ToHook(org.HomeLink(), hook)
 | 
							hooks[i] = convert.ToHook(ctx.Org.Organization.HomeLink(), hook)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, hooks)
 | 
						ctx.JSON(http.StatusOK, hooks)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,6 +49,13 @@ func ListLabels(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountLabelsByOrgID(ctx.Org.Organization.ID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToLabelList(labels))
 | 
						ctx.JSON(http.StatusOK, convert.ToLabelList(labels))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,15 +18,21 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// listMembers list an organization's members
 | 
					// listMembers list an organization's members
 | 
				
			||||||
func listMembers(ctx *context.APIContext, publicOnly bool) {
 | 
					func listMembers(ctx *context.APIContext, publicOnly bool) {
 | 
				
			||||||
	var members []*models.User
 | 
						opts := &models.FindOrgMembersOpts{
 | 
				
			||||||
 | 
					 | 
				
			||||||
	members, _, err := models.FindOrgMembers(&models.FindOrgMembersOpts{
 | 
					 | 
				
			||||||
		OrgID:       ctx.Org.Organization.ID,
 | 
							OrgID:       ctx.Org.Organization.ID,
 | 
				
			||||||
		PublicOnly:  publicOnly,
 | 
							PublicOnly:  publicOnly,
 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountOrgMembers(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetUsersByIDs", err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						members, _, err := models.FindOrgMembers(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,6 +41,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) {
 | 
				
			|||||||
		apiMembers[i] = convert.ToUser(member, ctx.User)
 | 
							apiMembers[i] = convert.ToUser(member, ctx.User)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, apiMembers)
 | 
						ctx.JSON(http.StatusOK, apiMembers)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@
 | 
				
			|||||||
package org
 | 
					package org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -38,9 +37,8 @@ func listUserOrgs(ctx *context.APIContext, u *models.User) {
 | 
				
			|||||||
		apiOrgs[i] = convert.ToOrganization(orgs[i])
 | 
							apiOrgs[i] = convert.ToOrganization(orgs[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(maxResults, listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(int64(maxResults))
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiOrgs)
 | 
						ctx.JSON(http.StatusOK, &apiOrgs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -145,8 +143,7 @@ func GetAll(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(maxResults)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &orgs)
 | 
						ctx.JSON(http.StatusOK, &orgs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@
 | 
				
			|||||||
package org
 | 
					package org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -44,23 +43,27 @@ func ListTeams(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/TeamList"
 | 
						//     "$ref": "#/responses/TeamList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	org := ctx.Org.Organization
 | 
						teams, count, err := models.SearchTeam(&models.SearchTeamOptions{
 | 
				
			||||||
	if err := org.GetTeams(&models.SearchTeamOptions{
 | 
					 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
	}); err != nil {
 | 
							OrgID:       ctx.Org.Organization.ID,
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetTeams", err)
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusInternalServerError, "LoadTeams", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiTeams := make([]*api.Team, len(org.Teams))
 | 
						apiTeams := make([]*api.Team, len(teams))
 | 
				
			||||||
	for i := range org.Teams {
 | 
						for i := range teams {
 | 
				
			||||||
		if err := org.Teams[i].GetUnits(); err != nil {
 | 
							if err := teams[i].GetUnits(); err != nil {
 | 
				
			||||||
			ctx.Error(http.StatusInternalServerError, "GetUnits", err)
 | 
								ctx.Error(http.StatusInternalServerError, "GetUnits", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		apiTeams[i] = convert.ToTeam(org.Teams[i])
 | 
							apiTeams[i] = convert.ToTeam(teams[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, apiTeams)
 | 
						ctx.JSON(http.StatusOK, apiTeams)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,7 +87,10 @@ func ListUserTeams(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/TeamList"
 | 
						//     "$ref": "#/responses/TeamList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	teams, err := models.GetUserTeams(ctx.User.ID, utils.GetListOptions(ctx))
 | 
						teams, count, err := models.SearchTeam(&models.SearchTeamOptions{
 | 
				
			||||||
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
 | 
							UserID:      ctx.User.ID,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetUserTeams", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetUserTeams", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -106,6 +112,8 @@ func ListUserTeams(ctx *context.APIContext) {
 | 
				
			|||||||
		apiTeams[i] = convert.ToTeam(teams[i])
 | 
							apiTeams[i] = convert.ToTeam(teams[i])
 | 
				
			||||||
		apiTeams[i].Organization = apiOrg
 | 
							apiTeams[i].Organization = apiOrg
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, apiTeams)
 | 
						ctx.JSON(http.StatusOK, apiTeams)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -327,17 +335,19 @@ func GetTeamMembers(ctx *context.APIContext) {
 | 
				
			|||||||
		ctx.NotFound()
 | 
							ctx.NotFound()
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	team := ctx.Org.Team
 | 
					
 | 
				
			||||||
	if err := team.GetMembers(&models.SearchMembersOptions{
 | 
						if err := ctx.Org.Team.GetMembers(&models.SearchMembersOptions{
 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	members := make([]*api.User, len(team.Members))
 | 
						members := make([]*api.User, len(ctx.Org.Team.Members))
 | 
				
			||||||
	for i, member := range team.Members {
 | 
						for i, member := range ctx.Org.Team.Members {
 | 
				
			||||||
		members[i] = convert.ToUser(member, ctx.User)
 | 
							members[i] = convert.ToUser(member, ctx.User)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(ctx.Org.Team.NumMembers))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, members)
 | 
						ctx.JSON(http.StatusOK, members)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -687,8 +697,7 @@ func SearchTeam(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(maxResults)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
						ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
				
			||||||
		"ok":   true,
 | 
							"ok":   true,
 | 
				
			||||||
		"data": apiTeams,
 | 
							"data": apiTeams,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,9 +282,8 @@ func ListBranches(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(totalNumOfBranches), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(totalNumOfBranches, listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", totalNumOfBranches))
 | 
						ctx.SetTotalCountHeader(int64(totalNumOfBranches))
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiBranches)
 | 
						ctx.JSON(http.StatusOK, &apiBranches)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,15 +47,24 @@ func ListCollaborators(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/UserList"
 | 
						//     "$ref": "#/responses/UserList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := ctx.Repo.Repository.CountCollaborators()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	collaborators, err := ctx.Repo.Repository.GetCollaborators(utils.GetListOptions(ctx))
 | 
						collaborators, err := ctx.Repo.Repository.GetCollaborators(utils.GetListOptions(ctx))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "ListCollaborators", err)
 | 
							ctx.Error(http.StatusInternalServerError, "ListCollaborators", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	users := make([]*api.User, len(collaborators))
 | 
						users := make([]*api.User, len(collaborators))
 | 
				
			||||||
	for i, collaborator := range collaborators {
 | 
						for i, collaborator := range collaborators {
 | 
				
			||||||
		users[i] = convert.ToUser(collaborator.User, ctx.User)
 | 
							users[i] = convert.ToUser(collaborator.User, ctx.User)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, users)
 | 
						ctx.JSON(http.StatusOK, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -200,16 +200,16 @@ func GetAllCommits(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize)
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(commitsCountTotal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// kept for backwards compatibility
 | 
						// kept for backwards compatibility
 | 
				
			||||||
	ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page))
 | 
						ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page))
 | 
				
			||||||
	ctx.Header().Set("X-PerPage", strconv.Itoa(listOptions.PageSize))
 | 
						ctx.Header().Set("X-PerPage", strconv.Itoa(listOptions.PageSize))
 | 
				
			||||||
	ctx.Header().Set("X-Total", strconv.FormatInt(commitsCountTotal, 10))
 | 
						ctx.Header().Set("X-Total", strconv.FormatInt(commitsCountTotal, 10))
 | 
				
			||||||
	ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount))
 | 
						ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount))
 | 
				
			||||||
	ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < pageCount))
 | 
						ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < pageCount))
 | 
				
			||||||
 | 
						ctx.AppendAccessControlExposeHeaders("X-Page", "X-PerPage", "X-Total", "X-PageCount", "X-HasMore")
 | 
				
			||||||
	ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize)
 | 
					 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", commitsCountTotal))
 | 
					 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, X-PerPage, X-Total, X-PageCount, X-HasMore, Link")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiCommits)
 | 
						ctx.JSON(http.StatusOK, &apiCommits)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,6 +62,8 @@ func ListForks(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		apiForks[i] = convert.ToRepo(fork, access)
 | 
							apiForks[i] = convert.ToRepo(fork, access)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumForks))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, apiForks)
 | 
						ctx.JSON(http.StatusOK, apiForks)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,9 +48,20 @@ func ListHooks(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/HookList"
 | 
						//     "$ref": "#/responses/HookList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hooks, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID, utils.GetListOptions(ctx))
 | 
						opts := &models.ListWebhookOptions{
 | 
				
			||||||
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
 | 
							RepoID:      ctx.Repo.Repository.ID,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountWebhooksByOpts(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetWebhooksByRepoID", err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hooks, err := models.ListWebhooksByOpts(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,6 +69,8 @@ func ListHooks(ctx *context.APIContext) {
 | 
				
			|||||||
	for i := range hooks {
 | 
						for i := range hooks {
 | 
				
			||||||
		apiHooks[i] = convert.ToHook(ctx.Repo.RepoLink, hooks[i])
 | 
							apiHooks[i] = convert.ToHook(ctx.Repo.RepoLink, hooks[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiHooks)
 | 
						ctx.JSON(http.StatusOK, &apiHooks)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,8 +232,7 @@ func SearchIssues(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(filteredCount), setting.UI.IssuePagingNum)
 | 
						ctx.SetLinkHeader(int(filteredCount), setting.UI.IssuePagingNum)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", filteredCount))
 | 
						ctx.SetTotalCountHeader(filteredCount)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
 | 
						ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -442,8 +441,7 @@ func ListIssues(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", filteredCount))
 | 
						ctx.SetTotalCountHeader(filteredCount)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
 | 
						ctx.JSON(http.StatusOK, convert.ToAPIIssueList(issues))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,17 +68,25 @@ func ListIssueComments(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	issue.Repo = ctx.Repo.Repository
 | 
						issue.Repo = ctx.Repo.Repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	comments, err := models.FindComments(models.FindCommentsOptions{
 | 
						opts := &models.FindCommentsOptions{
 | 
				
			||||||
		IssueID: issue.ID,
 | 
							IssueID: issue.ID,
 | 
				
			||||||
		Since:   since,
 | 
							Since:   since,
 | 
				
			||||||
		Before:  before,
 | 
							Before:  before,
 | 
				
			||||||
		Type:    models.CommentTypeComment,
 | 
							Type:    models.CommentTypeComment,
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						comments, err := models.FindComments(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "FindComments", err)
 | 
							ctx.Error(http.StatusInternalServerError, "FindComments", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						totalCount, err := models.CountComments(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := models.CommentList(comments).LoadPosters(); err != nil {
 | 
						if err := models.CommentList(comments).LoadPosters(); err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "LoadPosters", err)
 | 
							ctx.Error(http.StatusInternalServerError, "LoadPosters", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -89,6 +97,8 @@ func ListIssueComments(ctx *context.APIContext) {
 | 
				
			|||||||
		comment.Issue = issue
 | 
							comment.Issue = issue
 | 
				
			||||||
		apiComments[i] = convert.ToComment(comments[i])
 | 
							apiComments[i] = convert.ToComment(comments[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(totalCount)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiComments)
 | 
						ctx.JSON(http.StatusOK, &apiComments)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -138,18 +148,26 @@ func ListRepoIssueComments(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	comments, err := models.FindComments(models.FindCommentsOptions{
 | 
						opts := &models.FindCommentsOptions{
 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
		RepoID:      ctx.Repo.Repository.ID,
 | 
							RepoID:      ctx.Repo.Repository.ID,
 | 
				
			||||||
		Type:        models.CommentTypeComment,
 | 
							Type:        models.CommentTypeComment,
 | 
				
			||||||
		Since:       since,
 | 
							Since:       since,
 | 
				
			||||||
		Before:      before,
 | 
							Before:      before,
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						comments, err := models.FindComments(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "FindComments", err)
 | 
							ctx.Error(http.StatusInternalServerError, "FindComments", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						totalCount, err := models.CountComments(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = models.CommentList(comments).LoadPosters(); err != nil {
 | 
						if err = models.CommentList(comments).LoadPosters(); err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "LoadPosters", err)
 | 
							ctx.Error(http.StatusInternalServerError, "LoadPosters", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -171,6 +189,8 @@ func ListRepoIssueComments(ctx *context.APIContext) {
 | 
				
			|||||||
	for i := range comments {
 | 
						for i := range comments {
 | 
				
			||||||
		apiComments[i] = convert.ToComment(comments[i])
 | 
							apiComments[i] = convert.ToComment(comments[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(totalCount)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiComments)
 | 
						ctx.JSON(http.StatusOK, &apiComments)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -225,11 +225,18 @@ func GetStopwatches(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountUserStopwatches(ctx.User.ID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiSWs, err := convert.ToStopWatches(sws)
 | 
						apiSWs, err := convert.ToStopWatches(sws)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "APIFormat", err)
 | 
							ctx.Error(http.StatusInternalServerError, "APIFormat", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, apiSWs)
 | 
						ctx.JSON(http.StatusOK, apiSWs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,7 +83,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts := models.FindTrackedTimesOptions{
 | 
						opts := &models.FindTrackedTimesOptions{
 | 
				
			||||||
		ListOptions:  utils.GetListOptions(ctx),
 | 
							ListOptions:  utils.GetListOptions(ctx),
 | 
				
			||||||
		RepositoryID: ctx.Repo.Repository.ID,
 | 
							RepositoryID: ctx.Repo.Repository.ID,
 | 
				
			||||||
		IssueID:      issue.ID,
 | 
							IssueID:      issue.ID,
 | 
				
			||||||
@@ -119,6 +119,12 @@ func ListTrackedTimes(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountTrackedTimes(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trackedTimes, err := models.GetTrackedTimes(opts)
 | 
						trackedTimes, err := models.GetTrackedTimes(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
 | 
				
			||||||
@@ -128,6 +134,8 @@ func ListTrackedTimes(ctx *context.APIContext) {
 | 
				
			|||||||
		ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
 | 
							ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes))
 | 
						ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -423,7 +431,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts := models.FindTrackedTimesOptions{
 | 
						opts := &models.FindTrackedTimesOptions{
 | 
				
			||||||
		UserID:       user.ID,
 | 
							UserID:       user.ID,
 | 
				
			||||||
		RepositoryID: ctx.Repo.Repository.ID,
 | 
							RepositoryID: ctx.Repo.Repository.ID,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -493,7 +501,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts := models.FindTrackedTimesOptions{
 | 
						opts := &models.FindTrackedTimesOptions{
 | 
				
			||||||
		ListOptions:  utils.GetListOptions(ctx),
 | 
							ListOptions:  utils.GetListOptions(ctx),
 | 
				
			||||||
		RepositoryID: ctx.Repo.Repository.ID,
 | 
							RepositoryID: ctx.Repo.Repository.ID,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -530,6 +538,12 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountTrackedTimes(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trackedTimes, err := models.GetTrackedTimes(opts)
 | 
						trackedTimes, err := models.GetTrackedTimes(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
 | 
				
			||||||
@@ -539,6 +553,8 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
 | 
				
			|||||||
		ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
 | 
							ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes))
 | 
						ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -573,7 +589,7 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/TrackedTimeList"
 | 
						//     "$ref": "#/responses/TrackedTimeList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts := models.FindTrackedTimesOptions{
 | 
						opts := &models.FindTrackedTimesOptions{
 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
		UserID:      ctx.User.ID,
 | 
							UserID:      ctx.User.ID,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -584,6 +600,12 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountTrackedTimes(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trackedTimes, err := models.GetTrackedTimes(opts)
 | 
						trackedTimes, err := models.GetTrackedTimes(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err)
 | 
				
			||||||
@@ -595,5 +617,6 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes))
 | 
						ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(trackedTimes))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,26 +75,29 @@ func ListDeployKeys(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/DeployKeyList"
 | 
						//     "$ref": "#/responses/DeployKeyList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var keys []*models.DeployKey
 | 
						opts := &models.ListDeployKeysOptions{
 | 
				
			||||||
	var err error
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
 | 
							RepoID:      ctx.Repo.Repository.ID,
 | 
				
			||||||
	fingerprint := ctx.FormString("fingerprint")
 | 
							KeyID:       ctx.FormInt64("key_id"),
 | 
				
			||||||
	keyID := ctx.FormInt64("key_id")
 | 
							Fingerprint: ctx.FormString("fingerprint"),
 | 
				
			||||||
	if fingerprint != "" || keyID != 0 {
 | 
					 | 
				
			||||||
		keys, err = models.SearchDeployKeys(ctx.Repo.Repository.ID, keyID, fingerprint)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		keys, err = models.ListDeployKeys(ctx.Repo.Repository.ID, utils.GetListOptions(ctx))
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						keys, err := models.ListDeployKeys(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "ListDeployKeys", err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountDeployKeys(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
 | 
						apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
 | 
				
			||||||
	apiKeys := make([]*api.DeployKey, len(keys))
 | 
						apiKeys := make([]*api.DeployKey, len(keys))
 | 
				
			||||||
	for i := range keys {
 | 
						for i := range keys {
 | 
				
			||||||
		if err = keys[i].GetContent(); err != nil {
 | 
							if err := keys[i].GetContent(); err != nil {
 | 
				
			||||||
			ctx.Error(http.StatusInternalServerError, "GetContent", err)
 | 
								ctx.Error(http.StatusInternalServerError, "GetContent", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -104,6 +107,7 @@ func ListDeployKeys(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiKeys)
 | 
						ctx.JSON(http.StatusOK, &apiKeys)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,13 @@ func ListLabels(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountLabelsByRepoID(ctx.Repo.Repository.ID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, convert.ToLabelList(labels))
 | 
						ctx.JSON(http.StatusOK, convert.ToLabelList(labels))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,7 @@ func ListMilestones(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/MilestoneList"
 | 
						//     "$ref": "#/responses/MilestoneList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	milestones, err := models.GetMilestones(models.GetMilestonesOption{
 | 
						milestones, total, err := models.GetMilestones(models.GetMilestonesOption{
 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
		RepoID:      ctx.Repo.Repository.ID,
 | 
							RepoID:      ctx.Repo.Repository.ID,
 | 
				
			||||||
		State:       api.StateType(ctx.FormString("state")),
 | 
							State:       api.StateType(ctx.FormString("state")),
 | 
				
			||||||
@@ -72,6 +72,8 @@ func ListMilestones(ctx *context.APIContext) {
 | 
				
			|||||||
	for i := range milestones {
 | 
						for i := range milestones {
 | 
				
			||||||
		apiMilestones[i] = convert.ToAPIMilestone(milestones[i])
 | 
							apiMilestones[i] = convert.ToAPIMilestone(milestones[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(total)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiMilestones)
 | 
						ctx.JSON(http.StatusOK, &apiMilestones)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,8 +119,7 @@ func ListPullRequests(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(maxResults)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiPrs)
 | 
						ctx.JSON(http.StatusOK, &apiPrs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1232,13 +1231,14 @@ func GetPullRequestCommits(ctx *context.APIContext) {
 | 
				
			|||||||
		apiCommits = append(apiCommits, apiCommit)
 | 
							apiCommits = append(apiCommits, apiCommit)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(totalNumberOfCommits), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(totalNumberOfCommits, listOptions.PageSize)
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(totalNumberOfCommits))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page))
 | 
						ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page))
 | 
				
			||||||
	ctx.Header().Set("X-PerPage", strconv.Itoa(listOptions.PageSize))
 | 
						ctx.Header().Set("X-PerPage", strconv.Itoa(listOptions.PageSize))
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", totalNumberOfCommits))
 | 
					 | 
				
			||||||
	ctx.Header().Set("X-PageCount", strconv.Itoa(totalNumberOfPages))
 | 
						ctx.Header().Set("X-PageCount", strconv.Itoa(totalNumberOfPages))
 | 
				
			||||||
	ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < totalNumberOfPages))
 | 
						ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < totalNumberOfPages))
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, X-PerPage, X-Total, X-PageCount, X-HasMore, Link")
 | 
						ctx.AppendAccessControlExposeHeaders("X-Page", "X-PerPage", "X-PageCount", "X-HasMore")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiCommits)
 | 
						ctx.JSON(http.StatusOK, &apiCommits)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,14 +78,21 @@ func ListPullReviews(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	allReviews, err := models.FindReviews(models.FindReviewOptions{
 | 
						opts := models.FindReviewOptions{
 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
		Type:        models.ReviewTypeUnknown,
 | 
							Type:        models.ReviewTypeUnknown,
 | 
				
			||||||
		IssueID:     pr.IssueID,
 | 
							IssueID:     pr.IssueID,
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allReviews, err := models.FindReviews(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "FindReviews", err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountReviews(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,6 +102,7 @@ func ListPullReviews(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiReviews)
 | 
						ctx.JSON(http.StatusOK, &apiReviews)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@
 | 
				
			|||||||
package repo
 | 
					package repo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -142,8 +141,7 @@ func ListReleases(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprint(filteredCount))
 | 
						ctx.SetTotalCountHeader(filteredCount)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, rels)
 | 
						ctx.JSON(http.StatusOK, rels)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -230,8 +230,7 @@ func Search(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(count), opts.PageSize)
 | 
						ctx.SetLinkHeader(int(count), opts.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", count))
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, api.SearchResults{
 | 
						ctx.JSON(http.StatusOK, api.SearchResults{
 | 
				
			||||||
		OK:   true,
 | 
							OK:   true,
 | 
				
			||||||
		Data: results,
 | 
							Data: results,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,5 +52,7 @@ func ListStargazers(ctx *context.APIContext) {
 | 
				
			|||||||
	for i, stargazer := range stargazers {
 | 
						for i, stargazer := range stargazers {
 | 
				
			||||||
		users[i] = convert.ToUser(stargazer, ctx.User)
 | 
							users[i] = convert.ToUser(stargazer, ctx.User)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumStars))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, users)
 | 
						ctx.JSON(http.StatusOK, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,8 +204,7 @@ func getCommitStatuses(ctx *context.APIContext, sha string) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(maxResults)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(http.StatusOK, apiStatuses)
 | 
						ctx.JSON(http.StatusOK, apiStatuses)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -267,5 +266,6 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	combiStatus := convert.ToCombinedStatus(statuses, convert.ToRepo(repo, ctx.Repo.AccessMode))
 | 
						combiStatus := convert.ToCombinedStatus(statuses, convert.ToRepo(repo, ctx.Repo.AccessMode))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, combiStatus)
 | 
						ctx.JSON(http.StatusOK, combiStatus)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,5 +52,7 @@ func ListSubscribers(ctx *context.APIContext) {
 | 
				
			|||||||
	for i, subscriber := range subscribers {
 | 
						for i, subscriber := range subscribers {
 | 
				
			||||||
		users[i] = convert.ToUser(subscriber, ctx.User)
 | 
							users[i] = convert.ToUser(subscriber, ctx.User)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumWatches))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, users)
 | 
						ctx.JSON(http.StatusOK, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,7 @@ func ListTags(ctx *context.APIContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	listOpts := utils.GetListOptions(ctx)
 | 
						listOpts := utils.GetListOptions(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tags, err := ctx.Repo.GitRepo.GetTagInfos(listOpts.Page, listOpts.PageSize)
 | 
						tags, total, err := ctx.Repo.GitRepo.GetTagInfos(listOpts.Page, listOpts.PageSize)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "GetTags", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetTags", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -61,6 +61,7 @@ func ListTags(ctx *context.APIContext) {
 | 
				
			|||||||
		apiTags[i] = convert.ToTag(ctx.Repo.Repository, tags[i])
 | 
							apiTags[i] = convert.ToTag(ctx.Repo.Repository, tags[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(total))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiTags)
 | 
						ctx.JSON(http.StatusOK, &apiTags)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,12 +47,13 @@ func ListTopics(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/TopicNames"
 | 
						//     "$ref": "#/responses/TopicNames"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	topics, err := models.FindTopics(&models.FindTopicOptions{
 | 
						opts := &models.FindTopicOptions{
 | 
				
			||||||
		ListOptions: utils.GetListOptions(ctx),
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
		RepoID:      ctx.Repo.Repository.ID,
 | 
							RepoID:      ctx.Repo.Repository.ID,
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						topics, total, err := models.FindTopics(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error("ListTopics failed: %v", err)
 | 
					 | 
				
			||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -61,6 +62,8 @@ func ListTopics(ctx *context.APIContext) {
 | 
				
			|||||||
	for i, topic := range topics {
 | 
						for i, topic := range topics {
 | 
				
			||||||
		topicNames[i] = topic.Name
 | 
							topicNames[i] = topic.Name
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(total)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
						ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
				
			||||||
		"topics": topicNames,
 | 
							"topics": topicNames,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -164,15 +167,15 @@ func AddTopic(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Prevent adding more topics than allowed to repo
 | 
						// Prevent adding more topics than allowed to repo
 | 
				
			||||||
	topics, err := models.FindTopics(&models.FindTopicOptions{
 | 
						count, err := models.CountTopics(&models.FindTopicOptions{
 | 
				
			||||||
		RepoID: ctx.Repo.Repository.ID,
 | 
							RepoID: ctx.Repo.Repository.ID,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error("AddTopic failed: %v", err)
 | 
							log.Error("CountTopics failed: %v", err)
 | 
				
			||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(topics) >= 25 {
 | 
						if count >= 25 {
 | 
				
			||||||
		ctx.JSON(http.StatusUnprocessableEntity, map[string]interface{}{
 | 
							ctx.JSON(http.StatusUnprocessableEntity, map[string]interface{}{
 | 
				
			||||||
			"message": "Exceeding maximum allowed topics per repo.",
 | 
								"message": "Exceeding maximum allowed topics per repo.",
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
@@ -269,21 +272,13 @@ func TopicSearch(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "403":
 | 
						//   "403":
 | 
				
			||||||
	//     "$ref": "#/responses/forbidden"
 | 
						//     "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.User == nil {
 | 
						opts := &models.FindTopicOptions{
 | 
				
			||||||
		ctx.Error(http.StatusForbidden, "UserIsNil", "Only owners could change the topics.")
 | 
							Keyword:     ctx.FormString("q"),
 | 
				
			||||||
		return
 | 
							ListOptions: utils.GetListOptions(ctx),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kw := ctx.FormString("q")
 | 
						topics, total, err := models.FindTopics(opts)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	listOptions := utils.GetListOptions(ctx)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	topics, err := models.FindTopics(&models.FindTopicOptions{
 | 
					 | 
				
			||||||
		Keyword:     kw,
 | 
					 | 
				
			||||||
		ListOptions: listOptions,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error("SearchTopics failed: %v", err)
 | 
					 | 
				
			||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -292,6 +287,8 @@ func TopicSearch(ctx *context.APIContext) {
 | 
				
			|||||||
	for i, topic := range topics {
 | 
						for i, topic := range topics {
 | 
				
			||||||
		topicResponses[i] = convert.ToTopicResponse(topic)
 | 
							topicResponses[i] = convert.ToTopicResponse(topic)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(total)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
						ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
				
			||||||
		"topics": topicResponses,
 | 
							"topics": topicResponses,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,9 +44,16 @@ func ListAccessTokens(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/AccessTokenList"
 | 
						//     "$ref": "#/responses/AccessTokenList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.User.ID, ListOptions: utils.GetListOptions(ctx)})
 | 
						opts := models.ListAccessTokensOptions{UserID: ctx.User.ID, ListOptions: utils.GetListOptions(ctx)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count, err := models.CountAccessTokens(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tokens, err := models.ListAccessTokens(opts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,6 +65,8 @@ func ListAccessTokens(ctx *context.APIContext) {
 | 
				
			|||||||
			TokenLastEight: tokens[i].TokenLastEight,
 | 
								TokenLastEight: tokens[i].TokenLastEight,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiTokens)
 | 
						ctx.JSON(http.StatusOK, &apiTokens)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -242,7 +251,7 @@ func ListOauth2Applications(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/OAuth2ApplicationList"
 | 
						//     "$ref": "#/responses/OAuth2ApplicationList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apps, err := models.ListOAuth2Applications(ctx.User.ID, utils.GetListOptions(ctx))
 | 
						apps, total, err := models.ListOAuth2Applications(ctx.User.ID, utils.GetListOptions(ctx))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "ListOAuth2Applications", err)
 | 
							ctx.Error(http.StatusInternalServerError, "ListOAuth2Applications", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -253,6 +262,8 @@ func ListOauth2Applications(ctx *context.APIContext) {
 | 
				
			|||||||
		apiApps[i] = convert.ToOAuth2Application(apps[i])
 | 
							apiApps[i] = convert.ToOAuth2Application(apps[i])
 | 
				
			||||||
		apiApps[i].ClientSecret = "" // Hide secret on application list
 | 
							apiApps[i].ClientSecret = "" // Hide secret on application list
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(total)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiApps)
 | 
						ctx.JSON(http.StatusOK, &apiApps)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,8 @@ func listUserFollowers(ctx *context.APIContext, u *models.User) {
 | 
				
			|||||||
		ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(u.NumFollowers))
 | 
				
			||||||
	responseAPIUsers(ctx, users)
 | 
						responseAPIUsers(ctx, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -93,6 +95,8 @@ func listUserFollowing(ctx *context.APIContext, u *models.User) {
 | 
				
			|||||||
		ctx.Error(http.StatusInternalServerError, "GetFollowing", err)
 | 
							ctx.Error(http.StatusInternalServerError, "GetFollowing", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(u.NumFollowing))
 | 
				
			||||||
	responseAPIUsers(ctx, users)
 | 
						responseAPIUsers(ctx, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,13 @@ func listGPGKeys(ctx *context.APIContext, uid int64, listOptions models.ListOpti
 | 
				
			|||||||
		apiKeys[i] = convert.ToGPGKey(keys[i])
 | 
							apiKeys[i] = convert.ToGPGKey(keys[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						total, err := models.CountUserGPGKeys(uid)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(total)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiKeys)
 | 
						ctx.JSON(http.StatusOK, &apiKeys)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,7 @@ func composePublicKeysAPILink() string {
 | 
				
			|||||||
func listPublicKeys(ctx *context.APIContext, user *models.User) {
 | 
					func listPublicKeys(ctx *context.APIContext, user *models.User) {
 | 
				
			||||||
	var keys []*models.PublicKey
 | 
						var keys []*models.PublicKey
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
						var count int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fingerprint := ctx.FormString("fingerprint")
 | 
						fingerprint := ctx.FormString("fingerprint")
 | 
				
			||||||
	username := ctx.Params("username")
 | 
						username := ctx.Params("username")
 | 
				
			||||||
@@ -60,7 +61,15 @@ func listPublicKeys(ctx *context.APIContext, user *models.User) {
 | 
				
			|||||||
			// Unrestricted
 | 
								// Unrestricted
 | 
				
			||||||
			keys, err = models.SearchPublicKey(0, fingerprint)
 | 
								keys, err = models.SearchPublicKey(0, fingerprint)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							count = len(keys)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							total, err2 := models.CountPublicKeys(user.ID)
 | 
				
			||||||
 | 
							if err2 != nil {
 | 
				
			||||||
 | 
								ctx.InternalServerError(err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							count = int(total)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Use ListPublicKeys
 | 
							// Use ListPublicKeys
 | 
				
			||||||
		keys, err = models.ListPublicKeys(user.ID, utils.GetListOptions(ctx))
 | 
							keys, err = models.ListPublicKeys(user.ID, utils.GetListOptions(ctx))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -79,6 +88,7 @@ func listPublicKeys(ctx *context.APIContext, user *models.User) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(count))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiKeys)
 | 
						ctx.JSON(http.StatusOK, &apiKeys)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@ package user
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
@@ -43,8 +42,7 @@ func listUserRepos(ctx *context.APIContext, u *models.User, private bool) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(count), opts.PageSize)
 | 
						ctx.SetLinkHeader(int(count), opts.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", strconv.FormatInt(count, 10))
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiRepos)
 | 
						ctx.JSON(http.StatusOK, &apiRepos)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -130,8 +128,7 @@ func ListMyRepos(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(count), opts.ListOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(count), opts.ListOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", strconv.FormatInt(count, 10))
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
	ctx.JSON(http.StatusOK, &results)
 | 
						ctx.JSON(http.StatusOK, &results)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,6 +92,8 @@ func GetMyStarredRepos(ctx *context.APIContext) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "getStarredRepos", err)
 | 
							ctx.Error(http.StatusInternalServerError, "getStarredRepos", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(int64(ctx.User.NumStars))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &repos)
 | 
						ctx.JSON(http.StatusOK, &repos)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@
 | 
				
			|||||||
package user
 | 
					package user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -73,8 +72,7 @@ func Search(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
 | 
						ctx.SetTotalCountHeader(maxResults)
 | 
				
			||||||
	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
						ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
				
			||||||
		"ok":   true,
 | 
							"ok":   true,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,23 +14,22 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
						"code.gitea.io/gitea/routers/api/v1/utils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getWatchedRepos returns the repos that the user with the specified userID is
 | 
					// getWatchedRepos returns the repos that the user with the specified userID is watching
 | 
				
			||||||
// watching
 | 
					func getWatchedRepos(user *models.User, private bool, listOptions models.ListOptions) ([]*api.Repository, int64, error) {
 | 
				
			||||||
func getWatchedRepos(user *models.User, private bool, listOptions models.ListOptions) ([]*api.Repository, error) {
 | 
						watchedRepos, total, err := models.GetWatchedRepos(user.ID, private, listOptions)
 | 
				
			||||||
	watchedRepos, err := models.GetWatchedRepos(user.ID, private, listOptions)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, 0, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repos := make([]*api.Repository, len(watchedRepos))
 | 
						repos := make([]*api.Repository, len(watchedRepos))
 | 
				
			||||||
	for i, watched := range watchedRepos {
 | 
						for i, watched := range watchedRepos {
 | 
				
			||||||
		access, err := models.AccessLevel(user, watched)
 | 
							access, err := models.AccessLevel(user, watched)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, 0, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		repos[i] = convert.ToRepo(watched, access)
 | 
							repos[i] = convert.ToRepo(watched, access)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return repos, nil
 | 
						return repos, total, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetWatchedRepos returns the repos that the user specified in ctx is watching
 | 
					// GetWatchedRepos returns the repos that the user specified in ctx is watching
 | 
				
			||||||
@@ -60,10 +59,12 @@ func GetWatchedRepos(ctx *context.APIContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	user := GetUserByParams(ctx)
 | 
						user := GetUserByParams(ctx)
 | 
				
			||||||
	private := user.ID == ctx.User.ID
 | 
						private := user.ID == ctx.User.ID
 | 
				
			||||||
	repos, err := getWatchedRepos(user, private, utils.GetListOptions(ctx))
 | 
						repos, total, err := getWatchedRepos(user, private, utils.GetListOptions(ctx))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
 | 
							ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(total)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &repos)
 | 
						ctx.JSON(http.StatusOK, &repos)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,10 +88,12 @@ func GetMyWatchedRepos(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/RepositoryList"
 | 
						//     "$ref": "#/responses/RepositoryList"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repos, err := getWatchedRepos(ctx.User, true, utils.GetListOptions(ctx))
 | 
						repos, total, err := getWatchedRepos(ctx.User, true, utils.GetListOptions(ctx))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
 | 
							ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(total)
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &repos)
 | 
						ctx.JSON(http.StatusOK, &repos)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,7 +107,7 @@ func Home(ctx *context.Context) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var opts = models.FindOrgMembersOpts{
 | 
						var opts = &models.FindOrgMembersOpts{
 | 
				
			||||||
		OrgID:       org.ID,
 | 
							OrgID:       org.ID,
 | 
				
			||||||
		PublicOnly:  true,
 | 
							PublicOnly:  true,
 | 
				
			||||||
		ListOptions: models.ListOptions{Page: 1, PageSize: 25},
 | 
							ListOptions: models.ListOptions{Page: 1, PageSize: 25},
 | 
				
			||||||
@@ -122,7 +122,7 @@ func Home(ctx *context.Context) {
 | 
				
			|||||||
		opts.PublicOnly = !isMember && !ctx.User.IsAdmin
 | 
							opts.PublicOnly = !isMember && !ctx.User.IsAdmin
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	members, _, err := models.FindOrgMembers(&opts)
 | 
						members, _, err := models.FindOrgMembers(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("FindOrgMembers", err)
 | 
							ctx.ServerError("FindOrgMembers", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,7 @@ func Members(ctx *context.Context) {
 | 
				
			|||||||
		page = 1
 | 
							page = 1
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var opts = models.FindOrgMembersOpts{
 | 
						var opts = &models.FindOrgMembersOpts{
 | 
				
			||||||
		OrgID:      org.ID,
 | 
							OrgID:      org.ID,
 | 
				
			||||||
		PublicOnly: true,
 | 
							PublicOnly: true,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -54,7 +54,7 @@ func Members(ctx *context.Context) {
 | 
				
			|||||||
	pager := context.NewPagination(int(total), setting.UI.MembersPagingNum, page, 5)
 | 
						pager := context.NewPagination(int(total), setting.UI.MembersPagingNum, page, 5)
 | 
				
			||||||
	opts.ListOptions.Page = page
 | 
						opts.ListOptions.Page = page
 | 
				
			||||||
	opts.ListOptions.PageSize = setting.UI.MembersPagingNum
 | 
						opts.ListOptions.PageSize = setting.UI.MembersPagingNum
 | 
				
			||||||
	members, membersIsPublic, err := models.FindOrgMembers(&opts)
 | 
						members, membersIsPublic, err := models.FindOrgMembers(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("GetMembers", err)
 | 
							ctx.ServerError("GetMembers", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -186,7 +186,7 @@ func Webhooks(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks"
 | 
						ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks"
 | 
				
			||||||
	ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc")
 | 
						ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ws, err := models.GetWebhooksByOrgID(ctx.Org.Organization.ID, models.ListOptions{})
 | 
						ws, err := models.ListWebhooksByOpts(&models.ListWebhookOptions{OrgID: ctx.Org.Organization.ID})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("GetWebhooksByOrgId", err)
 | 
							ctx.ServerError("GetWebhooksByOrgId", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -378,7 +378,7 @@ func Issues(ctx *context.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	// Get milestones
 | 
						// Get milestones
 | 
				
			||||||
	ctx.Data["Milestones"], err = models.GetMilestones(models.GetMilestonesOption{
 | 
						ctx.Data["Milestones"], _, err = models.GetMilestones(models.GetMilestonesOption{
 | 
				
			||||||
		RepoID: ctx.Repo.Repository.ID,
 | 
							RepoID: ctx.Repo.Repository.ID,
 | 
				
			||||||
		State:  api.StateType(ctx.FormString("state")),
 | 
							State:  api.StateType(ctx.FormString("state")),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -395,7 +395,7 @@ func Issues(ctx *context.Context) {
 | 
				
			|||||||
// RetrieveRepoMilestonesAndAssignees find all the milestones and assignees of a repository
 | 
					// RetrieveRepoMilestonesAndAssignees find all the milestones and assignees of a repository
 | 
				
			||||||
func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repository) {
 | 
					func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repository) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	ctx.Data["OpenMilestones"], err = models.GetMilestones(models.GetMilestonesOption{
 | 
						ctx.Data["OpenMilestones"], _, err = models.GetMilestones(models.GetMilestonesOption{
 | 
				
			||||||
		RepoID: repo.ID,
 | 
							RepoID: repo.ID,
 | 
				
			||||||
		State:  api.StateOpen,
 | 
							State:  api.StateOpen,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -403,7 +403,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repos
 | 
				
			|||||||
		ctx.ServerError("GetMilestones", err)
 | 
							ctx.ServerError("GetMilestones", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["ClosedMilestones"], err = models.GetMilestones(models.GetMilestonesOption{
 | 
						ctx.Data["ClosedMilestones"], _, err = models.GetMilestones(models.GetMilestonesOption{
 | 
				
			||||||
		RepoID: repo.ID,
 | 
							RepoID: repo.ID,
 | 
				
			||||||
		State:  api.StateClosed,
 | 
							State:  api.StateClosed,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -1265,7 +1265,7 @@ func ViewIssue(ctx *context.Context) {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.Data["CanUseTimetracker"] = false
 | 
								ctx.Data["CanUseTimetracker"] = false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if ctx.Data["WorkingUsers"], err = models.TotalTimes(models.FindTrackedTimesOptions{IssueID: issue.ID}); err != nil {
 | 
							if ctx.Data["WorkingUsers"], err = models.TotalTimes(&models.FindTrackedTimesOptions{IssueID: issue.ID}); err != nil {
 | 
				
			||||||
			ctx.ServerError("TotalTimes", err)
 | 
								ctx.ServerError("TotalTimes", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -2584,8 +2584,8 @@ func handleTeamMentions(ctx *context.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if isAdmin {
 | 
						if isAdmin {
 | 
				
			||||||
		if err := ctx.Repo.Owner.GetTeams(&models.SearchTeamOptions{}); err != nil {
 | 
							if err := ctx.Repo.Owner.LoadTeams(); err != nil {
 | 
				
			||||||
			ctx.ServerError("GetTeams", err)
 | 
								ctx.ServerError("LoadTeams", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,17 +53,12 @@ func Milestones(ctx *context.Context) {
 | 
				
			|||||||
		page = 1
 | 
							page = 1
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var total int
 | 
						state := structs.StateOpen
 | 
				
			||||||
	var state structs.StateType
 | 
						if isShowClosed {
 | 
				
			||||||
	if !isShowClosed {
 | 
					 | 
				
			||||||
		total = int(stats.OpenCount)
 | 
					 | 
				
			||||||
		state = structs.StateOpen
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		total = int(stats.ClosedCount)
 | 
					 | 
				
			||||||
		state = structs.StateClosed
 | 
							state = structs.StateClosed
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	miles, err := models.GetMilestones(models.GetMilestonesOption{
 | 
						miles, total, err := models.GetMilestones(models.GetMilestonesOption{
 | 
				
			||||||
		ListOptions: models.ListOptions{
 | 
							ListOptions: models.ListOptions{
 | 
				
			||||||
			Page:     page,
 | 
								Page:     page,
 | 
				
			||||||
			PageSize: setting.UI.IssuePagingNum,
 | 
								PageSize: setting.UI.IssuePagingNum,
 | 
				
			||||||
@@ -106,7 +101,7 @@ func Milestones(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["Keyword"] = keyword
 | 
						ctx.Data["Keyword"] = keyword
 | 
				
			||||||
	ctx.Data["IsShowClosed"] = isShowClosed
 | 
						ctx.Data["IsShowClosed"] = isShowClosed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
 | 
						pager := context.NewPagination(int(total), setting.UI.IssuePagingNum, page, 5)
 | 
				
			||||||
	pager.AddParam(ctx, "state", "State")
 | 
						pager.AddParam(ctx, "state", "State")
 | 
				
			||||||
	pager.AddParam(ctx, "q", "Keyword")
 | 
						pager.AddParam(ctx, "q", "Keyword")
 | 
				
			||||||
	ctx.Data["Page"] = pager
 | 
						ctx.Data["Page"] = pager
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1002,7 +1002,7 @@ func DeployKeys(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["PageIsSettingsKeys"] = true
 | 
						ctx.Data["PageIsSettingsKeys"] = true
 | 
				
			||||||
	ctx.Data["DisableSSH"] = setting.SSH.Disabled
 | 
						ctx.Data["DisableSSH"] = setting.SSH.Disabled
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keys, err := models.ListDeployKeys(ctx.Repo.Repository.ID, models.ListOptions{})
 | 
						keys, err := models.ListDeployKeys(&models.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("ListDeployKeys", err)
 | 
							ctx.ServerError("ListDeployKeys", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -1018,7 +1018,7 @@ func DeployKeysPost(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
 | 
						ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
 | 
				
			||||||
	ctx.Data["PageIsSettingsKeys"] = true
 | 
						ctx.Data["PageIsSettingsKeys"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keys, err := models.ListDeployKeys(ctx.Repo.Repository.ID, models.ListOptions{})
 | 
						keys, err := models.ListDeployKeys(&models.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("ListDeployKeys", err)
 | 
							ctx.ServerError("ListDeployKeys", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -674,7 +674,7 @@ func renderLanguageStats(ctx *context.Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func renderRepoTopics(ctx *context.Context) {
 | 
					func renderRepoTopics(ctx *context.Context) {
 | 
				
			||||||
	topics, err := models.FindTopics(&models.FindTopicOptions{
 | 
						topics, _, err := models.FindTopics(&models.FindTopicOptions{
 | 
				
			||||||
		RepoID: ctx.Repo.Repository.ID,
 | 
							RepoID: ctx.Repo.Repository.ID,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@ func Webhooks(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks"
 | 
						ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks"
 | 
				
			||||||
	ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://docs.gitea.io/en-us/webhooks/")
 | 
						ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://docs.gitea.io/en-us/webhooks/")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ws, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID, models.ListOptions{})
 | 
						ws, err := models.ListWebhooksByOpts(&models.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("GetWebhooksByRepoID", err)
 | 
							ctx.ServerError("GetWebhooksByRepoID", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -132,7 +132,7 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models
 | 
				
			|||||||
	head := pr.GetGitRefName()
 | 
						head := pr.GetGitRefName()
 | 
				
			||||||
	if line > 0 {
 | 
						if line > 0 {
 | 
				
			||||||
		if reviewID != 0 {
 | 
							if reviewID != 0 {
 | 
				
			||||||
			first, err := models.FindComments(models.FindCommentsOptions{
 | 
								first, err := models.FindComments(&models.FindCommentsOptions{
 | 
				
			||||||
				ReviewID: reviewID,
 | 
									ReviewID: reviewID,
 | 
				
			||||||
				Line:     line,
 | 
									Line:     line,
 | 
				
			||||||
				TreePath: treePath,
 | 
									TreePath: treePath,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,8 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/sync"
 | 
						"code.gitea.io/gitea/modules/sync"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gobwas/glob"
 | 
						"github.com/gobwas/glob"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -187,7 +189,10 @@ func PrepareWebhooks(repo *models.Repository, event models.HookEventType, p api.
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func prepareWebhooks(repo *models.Repository, event models.HookEventType, p api.Payloader) error {
 | 
					func prepareWebhooks(repo *models.Repository, event models.HookEventType, p api.Payloader) error {
 | 
				
			||||||
	ws, err := models.GetActiveWebhooksByRepoID(repo.ID)
 | 
						ws, err := models.ListWebhooksByOpts(&models.ListWebhookOptions{
 | 
				
			||||||
 | 
							RepoID:   repo.ID,
 | 
				
			||||||
 | 
							IsActive: util.OptionalBoolTrue,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
 | 
							return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -195,7 +200,10 @@ func prepareWebhooks(repo *models.Repository, event models.HookEventType, p api.
 | 
				
			|||||||
	// check if repo belongs to org and append additional webhooks
 | 
						// check if repo belongs to org and append additional webhooks
 | 
				
			||||||
	if repo.MustOwner().IsOrganization() {
 | 
						if repo.MustOwner().IsOrganization() {
 | 
				
			||||||
		// get hooks for org
 | 
							// get hooks for org
 | 
				
			||||||
		orgHooks, err := models.GetActiveWebhooksByOrgID(repo.OwnerID)
 | 
							orgHooks, err := models.ListWebhooksByOpts(&models.ListWebhookOptions{
 | 
				
			||||||
 | 
								OrgID:    repo.OwnerID,
 | 
				
			||||||
 | 
								IsActive: util.OptionalBoolTrue,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
 | 
								return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user