API add/generalize pagination (#9452)
* paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
		
							parent
							
								
									333401e0fd
								
							
						
					
					
						commit
						1f01f53c53
					
				
					 113 changed files with 1885 additions and 564 deletions
				
			
		|  | @ -351,9 +351,11 @@ func runRepoSyncReleases(c *cli.Context) error { | ||||||
| 	log.Trace("Synchronizing repository releases (this may take a while)") | 	log.Trace("Synchronizing repository releases (this may take a while)") | ||||||
| 	for page := 1; ; page++ { | 	for page := 1; ; page++ { | ||||||
| 		repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{ | 		repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{ | ||||||
| 			Page:     page, | 			ListOptions: models.ListOptions{ | ||||||
| 			PageSize: models.RepositoryListDefaultPageSize, | 				PageSize: models.RepositoryListDefaultPageSize, | ||||||
| 			Private:  true, | 				Page:     page, | ||||||
|  | 			}, | ||||||
|  | 			Private: true, | ||||||
| 		}) | 		}) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return fmt.Errorf("SearchRepositoryByName: %v", err) | 			return fmt.Errorf("SearchRepositoryByName: %v", err) | ||||||
|  |  | ||||||
|  | @ -215,7 +215,7 @@ func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]*userAcces | ||||||
| 
 | 
 | ||||||
| // refreshCollaboratorAccesses retrieves repository collaborations with their access modes.
 | // refreshCollaboratorAccesses retrieves repository collaborations with their access modes.
 | ||||||
| func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]*userAccess) error { | func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]*userAccess) error { | ||||||
| 	collaborators, err := repo.getCollaborators(e) | 	collaborators, err := repo.getCollaborators(e, ListOptions{}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("getCollaborations: %v", err) | 		return fmt.Errorf("getCollaborations: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -104,7 +104,7 @@ func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus { | ||||||
| 
 | 
 | ||||||
| // CommitStatusOptions holds the options for query commit statuses
 | // CommitStatusOptions holds the options for query commit statuses
 | ||||||
| type CommitStatusOptions struct { | type CommitStatusOptions struct { | ||||||
| 	Page     int | 	ListOptions | ||||||
| 	State    string | 	State    string | ||||||
| 	SortType string | 	SortType string | ||||||
| } | } | ||||||
|  | @ -114,18 +114,22 @@ func GetCommitStatuses(repo *Repository, sha string, opts *CommitStatusOptions) | ||||||
| 	if opts.Page <= 0 { | 	if opts.Page <= 0 { | ||||||
| 		opts.Page = 1 | 		opts.Page = 1 | ||||||
| 	} | 	} | ||||||
|  | 	if opts.PageSize <= 0 { | ||||||
|  | 		opts.Page = ItemsPerPage | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	countSession := listCommitStatusesStatement(repo, sha, opts) | 	countSession := listCommitStatusesStatement(repo, sha, opts) | ||||||
|  | 	countSession = opts.setSessionPagination(countSession) | ||||||
| 	maxResults, err := countSession.Count(new(CommitStatus)) | 	maxResults, err := countSession.Count(new(CommitStatus)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("Count PRs: %v", err) | 		log.Error("Count PRs: %v", err) | ||||||
| 		return nil, maxResults, err | 		return nil, maxResults, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	statuses := make([]*CommitStatus, 0, ItemsPerPage) | 	statuses := make([]*CommitStatus, 0, opts.PageSize) | ||||||
| 	findSession := listCommitStatusesStatement(repo, sha, opts) | 	findSession := listCommitStatusesStatement(repo, sha, opts) | ||||||
|  | 	findSession = opts.setSessionPagination(findSession) | ||||||
| 	sortCommitStatusesSession(findSession, opts.SortType) | 	sortCommitStatusesSession(findSession, opts.SortType) | ||||||
| 	findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage) |  | ||||||
| 	return statuses, maxResults, findSession.Find(&statuses) | 	return statuses, maxResults, findSession.Find(&statuses) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -64,9 +64,14 @@ func (key *GPGKey) AfterLoad(session *xorm.Session) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ListGPGKeys returns a list of public keys belongs to given user.
 | // ListGPGKeys returns a list of public keys belongs to given user.
 | ||||||
| func ListGPGKeys(uid int64) ([]*GPGKey, error) { | func ListGPGKeys(uid int64, listOptions ListOptions) ([]*GPGKey, error) { | ||||||
| 	keys := make([]*GPGKey, 0, 5) | 	sess := x.Where("owner_id=? AND primary_key_id=''", uid) | ||||||
| 	return keys, x.Where("owner_id=? AND primary_key_id=''", uid).Find(&keys) | 	if listOptions.Page != 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	keys := make([]*GPGKey, 0, 2) | ||||||
|  | 	return keys, sess.Find(&keys) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetGPGKeyByID returns public key by given ID.
 | // GetGPGKeyByID returns public key by given ID.
 | ||||||
|  | @ -628,7 +633,7 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification { | ||||||
| 
 | 
 | ||||||
| 	// Now try to associate the signature with the committer, if present
 | 	// Now try to associate the signature with the committer, if present
 | ||||||
| 	if committer.ID != 0 { | 	if committer.ID != 0 { | ||||||
| 		keys, err := ListGPGKeys(committer.ID) | 		keys, err := ListGPGKeys(committer.ID, ListOptions{}) | ||||||
| 		if err != nil { //Skipping failed to get gpg keys of user
 | 		if err != nil { //Skipping failed to get gpg keys of user
 | ||||||
| 			log.Error("ListGPGKeys: %v", err) | 			log.Error("ListGPGKeys: %v", err) | ||||||
| 			return &CommitVerification{ | 			return &CommitVerification{ | ||||||
|  |  | ||||||
|  | @ -1103,13 +1103,12 @@ func GetIssuesByIDs(issueIDs []int64) ([]*Issue, error) { | ||||||
| 
 | 
 | ||||||
| // IssuesOptions represents options of an issue.
 | // IssuesOptions represents options of an issue.
 | ||||||
| type IssuesOptions struct { | type IssuesOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	RepoIDs     []int64 // include all repos if empty
 | 	RepoIDs     []int64 // include all repos if empty
 | ||||||
| 	AssigneeID  int64 | 	AssigneeID  int64 | ||||||
| 	PosterID    int64 | 	PosterID    int64 | ||||||
| 	MentionedID int64 | 	MentionedID int64 | ||||||
| 	MilestoneID int64 | 	MilestoneID int64 | ||||||
| 	Page        int |  | ||||||
| 	PageSize    int |  | ||||||
| 	IsClosed    util.OptionalBool | 	IsClosed    util.OptionalBool | ||||||
| 	IsPull      util.OptionalBool | 	IsPull      util.OptionalBool | ||||||
| 	LabelIDs    []int64 | 	LabelIDs    []int64 | ||||||
|  |  | ||||||
|  | @ -777,6 +777,7 @@ func GetCommentByID(id int64) (*Comment, error) { | ||||||
| 
 | 
 | ||||||
| // FindCommentsOptions describes the conditions to Find comments
 | // FindCommentsOptions describes the conditions to Find comments
 | ||||||
| type FindCommentsOptions struct { | type FindCommentsOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	RepoID   int64 | 	RepoID   int64 | ||||||
| 	IssueID  int64 | 	IssueID  int64 | ||||||
| 	ReviewID int64 | 	ReviewID int64 | ||||||
|  | @ -814,6 +815,11 @@ func findComments(e Engine, opts FindCommentsOptions) ([]*Comment, error) { | ||||||
| 	if opts.RepoID > 0 { | 	if opts.RepoID > 0 { | ||||||
| 		sess.Join("INNER", "issue", "issue.id = comment.issue_id") | 		sess.Join("INNER", "issue", "issue.id = comment.issue_id") | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if opts.Page != 0 { | ||||||
|  | 		sess = opts.setSessionPagination(sess) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return comments, sess. | 	return comments, sess. | ||||||
| 		Asc("comment.created_unix"). | 		Asc("comment.created_unix"). | ||||||
| 		Asc("comment.id"). | 		Asc("comment.id"). | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2016 The Gogs Authors. All rights reserved.
 | // Copyright 2016 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -298,7 +299,7 @@ func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) { | ||||||
| 		Find(&labels) | 		Find(&labels) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getLabelsByRepoID(e Engine, repoID int64, sortType string) ([]*Label, error) { | func getLabelsByRepoID(e Engine, repoID int64, sortType string, listOptions ListOptions) ([]*Label, error) { | ||||||
| 	labels := make([]*Label, 0, 10) | 	labels := make([]*Label, 0, 10) | ||||||
| 	sess := e.Where("repo_id = ?", repoID) | 	sess := e.Where("repo_id = ?", repoID) | ||||||
| 
 | 
 | ||||||
|  | @ -313,12 +314,16 @@ func getLabelsByRepoID(e Engine, repoID int64, sortType string) ([]*Label, error | ||||||
| 		sess.Asc("name") | 		sess.Asc("name") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if listOptions.Page != 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return labels, sess.Find(&labels) | 	return labels, sess.Find(&labels) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetLabelsByRepoID returns all labels that belong to given repository by ID.
 | // GetLabelsByRepoID returns all labels that belong to given repository by ID.
 | ||||||
| func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) { | func GetLabelsByRepoID(repoID int64, sortType string, listOptions ListOptions) ([]*Label, error) { | ||||||
| 	return getLabelsByRepoID(x, repoID, sortType) | 	return getLabelsByRepoID(x, repoID, sortType, listOptions) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) { | func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) { | ||||||
|  |  | ||||||
|  | @ -131,7 +131,7 @@ func TestGetLabelsInRepoByIDs(t *testing.T) { | ||||||
| func TestGetLabelsByRepoID(t *testing.T) { | func TestGetLabelsByRepoID(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 	testSuccess := func(repoID int64, sortType string, expectedIssueIDs []int64) { | 	testSuccess := func(repoID int64, sortType string, expectedIssueIDs []int64) { | ||||||
| 		labels, err := GetLabelsByRepoID(repoID, sortType) | 		labels, err := GetLabelsByRepoID(repoID, sortType, ListOptions{}) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		assert.Len(t, labels, len(expectedIssueIDs)) | 		assert.Len(t, labels, len(expectedIssueIDs)) | ||||||
| 		for i, label := range labels { | 		for i, label := range labels { | ||||||
|  |  | ||||||
|  | @ -221,7 +221,7 @@ func (milestones MilestoneList) getMilestoneIDs() []int64 { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetMilestonesByRepoID returns all opened milestones of a repository.
 | // GetMilestonesByRepoID returns all opened milestones of a repository.
 | ||||||
| func GetMilestonesByRepoID(repoID int64, state api.StateType) (MilestoneList, error) { | func GetMilestonesByRepoID(repoID int64, state api.StateType, listOptions ListOptions) (MilestoneList, error) { | ||||||
| 	sess := x.Where("repo_id = ?", repoID) | 	sess := x.Where("repo_id = ?", repoID) | ||||||
| 
 | 
 | ||||||
| 	switch state { | 	switch state { | ||||||
|  | @ -238,7 +238,11 @@ func GetMilestonesByRepoID(repoID int64, state api.StateType) (MilestoneList, er | ||||||
| 		sess = sess.And("is_closed = ?", false) | 		sess = sess.And("is_closed = ?", false) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	miles := make([]*Milestone, 0, 10) | 	if listOptions.Page != 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	miles := make([]*Milestone, 0, listOptions.PageSize) | ||||||
| 	return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles) | 	return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -71,7 +71,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 := GetMilestonesByRepoID(repo.ID, state) | 		milestones, err := GetMilestonesByRepoID(repo.ID, state, ListOptions{}) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 
 | 
 | ||||||
| 		var n int | 		var n int | ||||||
|  | @ -105,7 +105,7 @@ func TestGetMilestonesByRepoID(t *testing.T) { | ||||||
| 	test(3, api.StateClosed) | 	test(3, api.StateClosed) | ||||||
| 	test(3, api.StateAll) | 	test(3, api.StateAll) | ||||||
| 
 | 
 | ||||||
| 	milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen) | 	milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, milestones, 0) | 	assert.Len(t, milestones, 0) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ type Reaction struct { | ||||||
| 
 | 
 | ||||||
| // FindReactionsOptions describes the conditions to Find reactions
 | // FindReactionsOptions describes the conditions to Find reactions
 | ||||||
| type FindReactionsOptions struct { | type FindReactionsOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	IssueID   int64 | 	IssueID   int64 | ||||||
| 	CommentID int64 | 	CommentID int64 | ||||||
| 	UserID    int64 | 	UserID    int64 | ||||||
|  | @ -71,20 +72,28 @@ func FindCommentReactions(comment *Comment) (ReactionList, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FindIssueReactions returns a ReactionList of all reactions from an issue
 | // FindIssueReactions returns a ReactionList of all reactions from an issue
 | ||||||
| func FindIssueReactions(issue *Issue) (ReactionList, error) { | func FindIssueReactions(issue *Issue, listOptions ListOptions) (ReactionList, error) { | ||||||
| 	return findReactions(x, FindReactionsOptions{ | 	return findReactions(x, FindReactionsOptions{ | ||||||
| 		IssueID:   issue.ID, | 		ListOptions: listOptions, | ||||||
| 		CommentID: -1, | 		IssueID:     issue.ID, | ||||||
|  | 		CommentID:   -1, | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func findReactions(e Engine, opts FindReactionsOptions) ([]*Reaction, error) { | func findReactions(e Engine, opts FindReactionsOptions) ([]*Reaction, error) { | ||||||
| 	reactions := make([]*Reaction, 0, 10) | 	e = e. | ||||||
| 	sess := e.Where(opts.toConds()) | 		Where(opts.toConds()). | ||||||
| 	return reactions, sess. |  | ||||||
| 		In("reaction.`type`", setting.UI.Reactions). | 		In("reaction.`type`", setting.UI.Reactions). | ||||||
| 		Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id"). | 		Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id") | ||||||
| 		Find(&reactions) | 	if opts.Page != 0 { | ||||||
|  | 		e = opts.setEnginePagination(e) | ||||||
|  | 
 | ||||||
|  | 		reactions := make([]*Reaction, 0, opts.PageSize) | ||||||
|  | 		return reactions, e.Find(&reactions) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	reactions := make([]*Reaction, 0, 10) | ||||||
|  | 	return reactions, e.Find(&reactions) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func createReaction(e *xorm.Session, opts *ReactionOptions) (*Reaction, error) { | func createReaction(e *xorm.Session, opts *ReactionOptions) (*Reaction, error) { | ||||||
|  |  | ||||||
|  | @ -33,9 +33,14 @@ func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetUserStopwatches return list of all stopwatches of a user
 | // GetUserStopwatches return list of all stopwatches of a user
 | ||||||
| func GetUserStopwatches(userID int64) (sws *Stopwatches, err error) { | func GetUserStopwatches(userID int64, listOptions ListOptions) (*Stopwatches, error) { | ||||||
| 	sws = new(Stopwatches) | 	sws := new(Stopwatches) | ||||||
| 	err = x.Where("stopwatch.user_id = ?", userID).Find(sws) | 	sess := x.Where("stopwatch.user_id = ?", userID) | ||||||
|  | 	if listOptions.Page != 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err := sess.Find(sws) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -139,24 +139,30 @@ func TestIssues(t *testing.T) { | ||||||
| 			IssuesOptions{ | 			IssuesOptions{ | ||||||
| 				RepoIDs:  []int64{1, 3}, | 				RepoIDs:  []int64{1, 3}, | ||||||
| 				SortType: "oldest", | 				SortType: "oldest", | ||||||
| 				Page:     1, | 				ListOptions: ListOptions{ | ||||||
| 				PageSize: 4, | 					Page:     1, | ||||||
|  | 					PageSize: 4, | ||||||
|  | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			[]int64{1, 2, 3, 5}, | 			[]int64{1, 2, 3, 5}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			IssuesOptions{ | 			IssuesOptions{ | ||||||
| 				LabelIDs: []int64{1}, | 				LabelIDs: []int64{1}, | ||||||
| 				Page:     1, | 				ListOptions: ListOptions{ | ||||||
| 				PageSize: 4, | 					Page:     1, | ||||||
|  | 					PageSize: 4, | ||||||
|  | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			[]int64{2, 1}, | 			[]int64{2, 1}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			IssuesOptions{ | 			IssuesOptions{ | ||||||
| 				LabelIDs: []int64{1, 2}, | 				LabelIDs: []int64{1, 2}, | ||||||
| 				Page:     1, | 				ListOptions: ListOptions{ | ||||||
| 				PageSize: 4, | 					Page:     1, | ||||||
|  | 					PageSize: 4, | ||||||
|  | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			[]int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests
 | 			[]int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests
 | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 
 | 
 | ||||||
| 	"xorm.io/builder" | 	"xorm.io/builder" | ||||||
| 	"xorm.io/xorm" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // TrackedTime represents a time that was spent for a specific issue.
 | // TrackedTime represents a time that was spent for a specific issue.
 | ||||||
|  | @ -71,6 +70,7 @@ func (tl TrackedTimeList) LoadAttributes() (err error) { | ||||||
| 
 | 
 | ||||||
| // FindTrackedTimesOptions represent the filters for tracked times. If an ID is 0 it will be ignored.
 | // FindTrackedTimesOptions represent the filters for tracked times. If an ID is 0 it will be ignored.
 | ||||||
| type FindTrackedTimesOptions struct { | type FindTrackedTimesOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	IssueID           int64 | 	IssueID           int64 | ||||||
| 	UserID            int64 | 	UserID            int64 | ||||||
| 	RepositoryID      int64 | 	RepositoryID      int64 | ||||||
|  | @ -104,11 +104,19 @@ func (opts *FindTrackedTimesOptions) ToCond() builder.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) *xorm.Session { | func (opts *FindTrackedTimesOptions) ToSession(e Engine) Engine { | ||||||
|  | 	sess := e | ||||||
| 	if opts.RepositoryID > 0 || opts.MilestoneID > 0 { | 	if opts.RepositoryID > 0 || opts.MilestoneID > 0 { | ||||||
| 		return e.Join("INNER", "issue", "issue.id = tracked_time.issue_id").Where(opts.ToCond()) | 		sess = e.Join("INNER", "issue", "issue.id = tracked_time.issue_id") | ||||||
| 	} | 	} | ||||||
| 	return e.Where(opts.ToCond()) | 
 | ||||||
|  | 	sess = sess.Where(opts.ToCond()) | ||||||
|  | 
 | ||||||
|  | 	if opts.Page != 0 { | ||||||
|  | 		sess = opts.setEnginePagination(sess) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sess | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getTrackedTimes(e Engine, options FindTrackedTimesOptions) (trackedTimes TrackedTimeList, err error) { | func getTrackedTimes(e Engine, options FindTrackedTimesOptions) (trackedTimes TrackedTimeList, err error) { | ||||||
|  |  | ||||||
|  | @ -77,18 +77,22 @@ func GetIssueWatchersIDs(issueID int64) ([]int64, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetIssueWatchers returns watchers/unwatchers of a given issue
 | // GetIssueWatchers returns watchers/unwatchers of a given issue
 | ||||||
| func GetIssueWatchers(issueID int64) (IssueWatchList, error) { | func GetIssueWatchers(issueID int64, listOptions ListOptions) (IssueWatchList, error) { | ||||||
| 	return getIssueWatchers(x, issueID) | 	return getIssueWatchers(x, issueID, listOptions) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getIssueWatchers(e Engine, issueID int64) (watches IssueWatchList, err error) { | func getIssueWatchers(e Engine, issueID int64, listOptions ListOptions) (watches IssueWatchList, err error) { | ||||||
| 	err = e. | 	sess := e. | ||||||
| 		Where("`issue_watch`.issue_id = ?", issueID). | 		Where("`issue_watch`.issue_id = ?", issueID). | ||||||
| 		And("`issue_watch`.is_watching = ?", true). | 		And("`issue_watch`.is_watching = ?", true). | ||||||
| 		And("`user`.is_active = ?", true). | 		And("`user`.is_active = ?", true). | ||||||
| 		And("`user`.prohibit_login = ?", false). | 		And("`user`.prohibit_login = ?", false). | ||||||
| 		Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id"). | 		Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id") | ||||||
| 		Find(&watches) | 
 | ||||||
|  | 	if listOptions.Page == 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 	} | ||||||
|  | 	err = sess.Find(&watches) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,22 +42,22 @@ func TestGetIssueWatch(t *testing.T) { | ||||||
| func TestGetIssueWatchers(t *testing.T) { | func TestGetIssueWatchers(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 
 | 
 | ||||||
| 	iws, err := GetIssueWatchers(1) | 	iws, err := GetIssueWatchers(1, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	// Watcher is inactive, thus 0
 | 	// Watcher is inactive, thus 0
 | ||||||
| 	assert.Len(t, iws, 0) | 	assert.Len(t, iws, 0) | ||||||
| 
 | 
 | ||||||
| 	iws, err = GetIssueWatchers(2) | 	iws, err = GetIssueWatchers(2, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	// Watcher is explicit not watching
 | 	// Watcher is explicit not watching
 | ||||||
| 	assert.Len(t, iws, 0) | 	assert.Len(t, iws, 0) | ||||||
| 
 | 
 | ||||||
| 	iws, err = GetIssueWatchers(5) | 	iws, err = GetIssueWatchers(5, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	// Issue has no Watchers
 | 	// Issue has no Watchers
 | ||||||
| 	assert.Len(t, iws, 0) | 	assert.Len(t, iws, 0) | ||||||
| 
 | 
 | ||||||
| 	iws, err = GetIssueWatchers(7) | 	iws, err = GetIssueWatchers(7, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	// Issue has one watcher
 | 	// Issue has one watcher
 | ||||||
| 	assert.Len(t, iws, 1) | 	assert.Len(t, iws, 1) | ||||||
|  |  | ||||||
							
								
								
									
										44
									
								
								models/list_options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								models/list_options.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | // Copyright 2020 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package models | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
|  | 
 | ||||||
|  | 	"xorm.io/xorm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // ListOptions options to paginate results
 | ||||||
|  | type ListOptions struct { | ||||||
|  | 	PageSize int | ||||||
|  | 	Page     int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (opts ListOptions) getPaginatedSession() *xorm.Session { | ||||||
|  | 	opts.setDefaultValues() | ||||||
|  | 
 | ||||||
|  | 	return x.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (opts ListOptions) setSessionPagination(sess *xorm.Session) *xorm.Session { | ||||||
|  | 	opts.setDefaultValues() | ||||||
|  | 
 | ||||||
|  | 	return sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (opts ListOptions) setEnginePagination(e Engine) Engine { | ||||||
|  | 	opts.setDefaultValues() | ||||||
|  | 
 | ||||||
|  | 	return e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (opts ListOptions) setDefaultValues() { | ||||||
|  | 	if opts.PageSize <= 0 || opts.PageSize > setting.API.MaxResponseItems { | ||||||
|  | 		opts.PageSize = setting.API.MaxResponseItems | ||||||
|  | 	} | ||||||
|  | 	if opts.Page <= 0 { | ||||||
|  | 		opts.Page = 1 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -44,6 +44,8 @@ type Engine interface { | ||||||
| 	SQL(interface{}, ...interface{}) *xorm.Session | 	SQL(interface{}, ...interface{}) *xorm.Session | ||||||
| 	Where(interface{}, ...interface{}) *xorm.Session | 	Where(interface{}, ...interface{}) *xorm.Session | ||||||
| 	Asc(colNames ...string) *xorm.Session | 	Asc(colNames ...string) *xorm.Session | ||||||
|  | 	Limit(limit int, start ...int) *xorm.Session | ||||||
|  | 	SumInt(bean interface{}, columnName string) (res int64, err error) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
|  |  | ||||||
|  | @ -68,6 +68,7 @@ type Notification struct { | ||||||
| 
 | 
 | ||||||
| // FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored.
 | // FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored.
 | ||||||
| type FindNotificationOptions struct { | type FindNotificationOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	UserID            int64 | 	UserID            int64 | ||||||
| 	RepoID            int64 | 	RepoID            int64 | ||||||
| 	IssueID           int64 | 	IssueID           int64 | ||||||
|  | @ -102,7 +103,7 @@ func (opts *FindNotificationOptions) ToCond() builder.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 *FindNotificationOptions) ToSession(e Engine) *xorm.Session { | func (opts *FindNotificationOptions) ToSession(e Engine) *xorm.Session { | ||||||
| 	return e.Where(opts.ToCond()) | 	return opts.setSessionPagination(e.Where(opts.ToCond())) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getNotifications(e Engine, options FindNotificationOptions) (nl NotificationList, err error) { | func getNotifications(e Engine, options FindNotificationOptions) (nl NotificationList, err error) { | ||||||
|  | @ -132,7 +133,7 @@ func CreateOrUpdateIssueNotifications(issueID, commentID int64, notificationAuth | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func createOrUpdateIssueNotifications(e Engine, issueID, commentID int64, notificationAuthorID int64) error { | func createOrUpdateIssueNotifications(e Engine, issueID, commentID int64, notificationAuthorID int64) error { | ||||||
| 	issueWatches, err := getIssueWatchers(e, issueID) | 	issueWatches, err := getIssueWatchers(e, issueID, ListOptions{}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -62,14 +62,18 @@ func (org *User) getTeams(e Engine) error { | ||||||
| 		Find(&org.Teams) | 		Find(&org.Teams) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetTeams returns all teams that belong to organization.
 | // GetTeams returns paginated teams that belong to organization.
 | ||||||
| func (org *User) GetTeams() error { | func (org *User) GetTeams(opts *SearchTeamOptions) error { | ||||||
|  | 	if opts.Page != 0 { | ||||||
|  | 		return org.getTeams(opts.getPaginatedSession()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return org.getTeams(x) | 	return org.getTeams(x) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetMembers returns all members of organization.
 | // GetMembers returns all members of organization.
 | ||||||
| func (org *User) GetMembers() (err error) { | func (org *User) GetMembers() (err error) { | ||||||
| 	org.Members, org.MembersIsPublic, err = FindOrgMembers(FindOrgMembersOpts{ | 	org.Members, org.MembersIsPublic, err = FindOrgMembers(&FindOrgMembersOpts{ | ||||||
| 		OrgID: org.ID, | 		OrgID: org.ID, | ||||||
| 	}) | 	}) | ||||||
| 	return | 	return | ||||||
|  | @ -77,10 +81,9 @@ func (org *User) GetMembers() (err error) { | ||||||
| 
 | 
 | ||||||
| // FindOrgMembersOpts represensts find org members condtions
 | // FindOrgMembersOpts represensts find org members condtions
 | ||||||
| type FindOrgMembersOpts struct { | type FindOrgMembersOpts struct { | ||||||
|  | 	ListOptions | ||||||
| 	OrgID      int64 | 	OrgID      int64 | ||||||
| 	PublicOnly bool | 	PublicOnly bool | ||||||
| 	Start      int |  | ||||||
| 	Limit      int |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CountOrgMembers counts the organization's members
 | // CountOrgMembers counts the organization's members
 | ||||||
|  | @ -93,8 +96,8 @@ func CountOrgMembers(opts FindOrgMembersOpts) (int64, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FindOrgMembers loads organization members according conditions
 | // FindOrgMembers loads organization members according conditions
 | ||||||
| func FindOrgMembers(opts FindOrgMembersOpts) (UserList, map[int64]bool, error) { | func FindOrgMembers(opts *FindOrgMembersOpts) (UserList, map[int64]bool, error) { | ||||||
| 	ous, err := GetOrgUsersByOrgID(opts.OrgID, opts.PublicOnly, opts.Start, opts.Limit) | 	ous, err := GetOrgUsersByOrgID(opts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, nil, err | 		return nil, nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -479,15 +482,20 @@ func GetOrgsCanCreateRepoByUserID(userID int64) ([]*User, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetOrgUsersByUserID returns all organization-user relations by user ID.
 | // GetOrgUsersByUserID returns all organization-user relations by user ID.
 | ||||||
| func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) { | func GetOrgUsersByUserID(uid int64, opts *SearchOrganizationsOptions) ([]*OrgUser, error) { | ||||||
| 	ous := make([]*OrgUser, 0, 10) | 	ous := make([]*OrgUser, 0, 10) | ||||||
| 	sess := x. | 	sess := x. | ||||||
| 		Join("LEFT", "`user`", "`org_user`.org_id=`user`.id"). | 		Join("LEFT", "`user`", "`org_user`.org_id=`user`.id"). | ||||||
| 		Where("`org_user`.uid=?", uid) | 		Where("`org_user`.uid=?", uid) | ||||||
| 	if !all { | 	if !opts.All { | ||||||
| 		// Only show public organizations
 | 		// Only show public organizations
 | ||||||
| 		sess.And("is_public=?", true) | 		sess.And("is_public=?", true) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if opts.PageSize != 0 { | ||||||
|  | 		sess = opts.setSessionPagination(sess) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	err := sess. | 	err := sess. | ||||||
| 		Asc("`user`.name"). | 		Asc("`user`.name"). | ||||||
| 		Find(&ous) | 		Find(&ous) | ||||||
|  | @ -495,21 +503,24 @@ func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetOrgUsersByOrgID returns all organization-user relations by organization ID.
 | // GetOrgUsersByOrgID returns all organization-user relations by organization ID.
 | ||||||
| func GetOrgUsersByOrgID(orgID int64, publicOnly bool, start, limit int) ([]*OrgUser, error) { | func GetOrgUsersByOrgID(opts *FindOrgMembersOpts) ([]*OrgUser, error) { | ||||||
| 	return getOrgUsersByOrgID(x, orgID, publicOnly, start, limit) | 	return getOrgUsersByOrgID(x, opts) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getOrgUsersByOrgID(e Engine, orgID int64, publicOnly bool, start, limit int) ([]*OrgUser, error) { | func getOrgUsersByOrgID(e Engine, opts *FindOrgMembersOpts) ([]*OrgUser, error) { | ||||||
| 	ous := make([]*OrgUser, 0, 10) | 	sess := e.Where("org_id=?", opts.OrgID) | ||||||
| 	sess := e.Where("org_id=?", orgID) | 	if opts.PublicOnly { | ||||||
| 	if publicOnly { |  | ||||||
| 		sess.And("is_public = ?", true) | 		sess.And("is_public = ?", true) | ||||||
| 	} | 	} | ||||||
| 	if limit > 0 { | 	if opts.ListOptions.PageSize > 0 { | ||||||
| 		sess.Limit(limit, start) | 		sess = opts.setSessionPagination(sess) | ||||||
|  | 
 | ||||||
|  | 		ous := make([]*OrgUser, 0, opts.PageSize) | ||||||
|  | 		return ous, sess.Find(&ous) | ||||||
| 	} | 	} | ||||||
| 	err := sess.Find(&ous) | 
 | ||||||
| 	return ous, err | 	var ous []*OrgUser | ||||||
|  | 	return ous, sess.Find(&ous) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ChangeOrgUserStatus changes public or private membership status.
 | // ChangeOrgUserStatus changes public or private membership status.
 | ||||||
|  |  | ||||||
|  | @ -39,12 +39,16 @@ type Team struct { | ||||||
| 
 | 
 | ||||||
| // SearchTeamOptions holds the search options
 | // SearchTeamOptions holds the search options
 | ||||||
| type SearchTeamOptions struct { | type SearchTeamOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	UserID      int64 | 	UserID      int64 | ||||||
| 	Keyword     string | 	Keyword     string | ||||||
| 	OrgID       int64 | 	OrgID       int64 | ||||||
| 	IncludeDesc bool | 	IncludeDesc bool | ||||||
| 	PageSize    int | } | ||||||
| 	Page        int | 
 | ||||||
|  | // SearchMembersOptions holds the search options
 | ||||||
|  | type SearchMembersOptions struct { | ||||||
|  | 	ListOptions | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SearchTeam search for teams. Caller is responsible to check permissions.
 | // SearchTeam search for teams. Caller is responsible to check permissions.
 | ||||||
|  | @ -160,9 +164,13 @@ func (t *Team) getRepositories(e Engine) error { | ||||||
| 		Find(&t.Repos) | 		Find(&t.Repos) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetRepositories returns all repositories in team of organization.
 | // GetRepositories returns paginated repositories in team of organization.
 | ||||||
| func (t *Team) GetRepositories() error { | func (t *Team) GetRepositories(opts *SearchTeamOptions) error { | ||||||
| 	return t.getRepositories(x) | 	if opts.Page == 0 { | ||||||
|  | 		return t.getRepositories(x) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return t.getRepositories(opts.getPaginatedSession()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (t *Team) getMembers(e Engine) (err error) { | func (t *Team) getMembers(e Engine) (err error) { | ||||||
|  | @ -170,9 +178,13 @@ func (t *Team) getMembers(e Engine) (err error) { | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetMembers returns all members in team of organization.
 | // GetMembers returns paginated members in team of organization.
 | ||||||
| func (t *Team) GetMembers() (err error) { | func (t *Team) GetMembers(opts *SearchMembersOptions) (err error) { | ||||||
| 	return t.getMembers(x) | 	if opts.Page == 0 { | ||||||
|  | 		return t.getMembers(x) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return t.getMembers(opts.getPaginatedSession()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // AddMember adds new membership of the team to the organization,
 | // AddMember adds new membership of the team to the organization,
 | ||||||
|  | @ -642,7 +654,7 @@ func UpdateTeam(t *Team, authChanged bool, includeAllChanged bool) (err error) { | ||||||
| // DeleteTeam deletes given team.
 | // DeleteTeam deletes given team.
 | ||||||
| // It's caller's responsibility to assign organization ID.
 | // It's caller's responsibility to assign organization ID.
 | ||||||
| func DeleteTeam(t *Team) error { | func DeleteTeam(t *Team) error { | ||||||
| 	if err := t.GetRepositories(); err != nil { | 	if err := t.GetRepositories(&SearchTeamOptions{}); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -747,11 +759,14 @@ func GetTeamMembers(teamID int64) ([]*User, error) { | ||||||
| 	return getTeamMembers(x, teamID) | 	return getTeamMembers(x, teamID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getUserTeams(e Engine, userID int64) (teams []*Team, err error) { | func getUserTeams(e Engine, userID int64, listOptions ListOptions) (teams []*Team, err error) { | ||||||
| 	return teams, e. | 	sess := e. | ||||||
| 		Join("INNER", "team_user", "team_user.team_id = team.id"). | 		Join("INNER", "team_user", "team_user.team_id = team.id"). | ||||||
| 		Where("team_user.uid=?", userID). | 		Where("team_user.uid=?", userID) | ||||||
| 		Find(&teams) | 	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) { | ||||||
|  | @ -778,8 +793,8 @@ func GetUserOrgTeams(orgID, userID int64) ([]*Team, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetUserTeams returns all teams that user belongs across all organizations.
 | // GetUserTeams returns all teams that user belongs across all organizations.
 | ||||||
| func GetUserTeams(userID int64) ([]*Team, error) { | func GetUserTeams(userID int64, listOptions ListOptions) ([]*Team, error) { | ||||||
| 	return getUserTeams(x, userID) | 	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,
 | ||||||
|  | @ -795,7 +810,7 @@ func AddTeamMember(team *Team, userID int64) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Get team and its repositories.
 | 	// Get team and its repositories.
 | ||||||
| 	if err := team.GetRepositories(); err != nil { | 	if err := team.GetRepositories(&SearchTeamOptions{}); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ func TestTeam_GetRepositories(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	test := func(teamID int64) { | 	test := func(teamID int64) { | ||||||
| 		team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team) | 		team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team) | ||||||
| 		assert.NoError(t, team.GetRepositories()) | 		assert.NoError(t, team.GetRepositories(&SearchTeamOptions{})) | ||||||
| 		assert.Len(t, team.Repos, team.NumRepos) | 		assert.Len(t, team.Repos, team.NumRepos) | ||||||
| 		for _, repo := range team.Repos { | 		for _, repo := range team.Repos { | ||||||
| 			AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID}) | 			AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID}) | ||||||
|  | @ -55,7 +55,7 @@ func TestTeam_GetMembers(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	test := func(teamID int64) { | 	test := func(teamID int64) { | ||||||
| 		team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team) | 		team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team) | ||||||
| 		assert.NoError(t, team.GetMembers()) | 		assert.NoError(t, team.GetMembers(&SearchMembersOptions{})) | ||||||
| 		assert.Len(t, team.Members, team.NumMembers) | 		assert.Len(t, team.Members, team.NumMembers) | ||||||
| 		for _, member := range team.Members { | 		for _, member := range team.Members { | ||||||
| 			AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID}) | 			AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID}) | ||||||
|  | @ -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) | 		teams, err := GetUserTeams(userID, ListOptions{}) | ||||||
| 		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()) | 	assert.NoError(t, org.GetTeams(&SearchTeamOptions{})) | ||||||
| 	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) | ||||||
|  | @ -367,7 +367,7 @@ func TestGetOwnedOrgsByUserIDDesc(t *testing.T) { | ||||||
| func TestGetOrgUsersByUserID(t *testing.T) { | func TestGetOrgUsersByUserID(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 
 | 
 | ||||||
| 	orgUsers, err := GetOrgUsersByUserID(5, true) | 	orgUsers, err := GetOrgUsersByUserID(5, &SearchOrganizationsOptions{All: true}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	if assert.Len(t, orgUsers, 2) { | 	if assert.Len(t, orgUsers, 2) { | ||||||
| 		assert.Equal(t, OrgUser{ | 		assert.Equal(t, OrgUser{ | ||||||
|  | @ -382,12 +382,12 @@ func TestGetOrgUsersByUserID(t *testing.T) { | ||||||
| 			IsPublic: false}, *orgUsers[1]) | 			IsPublic: false}, *orgUsers[1]) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	publicOrgUsers, err := GetOrgUsersByUserID(5, false) | 	publicOrgUsers, err := GetOrgUsersByUserID(5, &SearchOrganizationsOptions{All: false}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, publicOrgUsers, 1) | 	assert.Len(t, publicOrgUsers, 1) | ||||||
| 	assert.Equal(t, *orgUsers[0], *publicOrgUsers[0]) | 	assert.Equal(t, *orgUsers[0], *publicOrgUsers[0]) | ||||||
| 
 | 
 | ||||||
| 	orgUsers, err = GetOrgUsersByUserID(1, true) | 	orgUsers, err = GetOrgUsersByUserID(1, &SearchOrganizationsOptions{All: true}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, orgUsers, 0) | 	assert.Len(t, orgUsers, 0) | ||||||
| } | } | ||||||
|  | @ -395,7 +395,11 @@ func TestGetOrgUsersByUserID(t *testing.T) { | ||||||
| func TestGetOrgUsersByOrgID(t *testing.T) { | func TestGetOrgUsersByOrgID(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 
 | 
 | ||||||
| 	orgUsers, err := GetOrgUsersByOrgID(3, false, 0, 0) | 	orgUsers, err := GetOrgUsersByOrgID(&FindOrgMembersOpts{ | ||||||
|  | 		ListOptions: ListOptions{}, | ||||||
|  | 		OrgID:       3, | ||||||
|  | 		PublicOnly:  false, | ||||||
|  | 	}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	if assert.Len(t, orgUsers, 3) { | 	if assert.Len(t, orgUsers, 3) { | ||||||
| 		assert.Equal(t, OrgUser{ | 		assert.Equal(t, OrgUser{ | ||||||
|  | @ -410,7 +414,11 @@ func TestGetOrgUsersByOrgID(t *testing.T) { | ||||||
| 			IsPublic: false}, *orgUsers[1]) | 			IsPublic: false}, *orgUsers[1]) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	orgUsers, err = GetOrgUsersByOrgID(NonexistentID, false, 0, 0) | 	orgUsers, err = GetOrgUsersByOrgID(&FindOrgMembersOpts{ | ||||||
|  | 		ListOptions: ListOptions{}, | ||||||
|  | 		OrgID:       NonexistentID, | ||||||
|  | 		PublicOnly:  false, | ||||||
|  | 	}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, orgUsers, 0) | 	assert.Len(t, orgUsers, 0) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| // PullRequestsOptions holds the options for PRs
 | // PullRequestsOptions holds the options for PRs
 | ||||||
| type PullRequestsOptions struct { | type PullRequestsOptions struct { | ||||||
| 	Page        int | 	ListOptions | ||||||
| 	State       string | 	State       string | ||||||
| 	SortType    string | 	SortType    string | ||||||
| 	Labels      []string | 	Labels      []string | ||||||
|  | @ -94,14 +94,14 @@ func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, | ||||||
| 		return nil, maxResults, err | 		return nil, maxResults, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	prs := make([]*PullRequest, 0, ItemsPerPage) |  | ||||||
| 	findSession, err := listPullRequestStatement(baseRepoID, opts) | 	findSession, err := listPullRequestStatement(baseRepoID, opts) | ||||||
| 	sortIssuesSession(findSession, opts.SortType, 0) | 	sortIssuesSession(findSession, opts.SortType, 0) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("listPullRequestStatement: %v", err) | 		log.Error("listPullRequestStatement: %v", err) | ||||||
| 		return nil, maxResults, err | 		return nil, maxResults, err | ||||||
| 	} | 	} | ||||||
| 	findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage) | 	findSession = opts.setSessionPagination(findSession) | ||||||
|  | 	prs := make([]*PullRequest, 0, opts.PageSize) | ||||||
| 	return prs, maxResults, findSession.Find(&prs) | 	return prs, maxResults, findSession.Find(&prs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ func (pr *PullRequest) SignMerge(u *User, tmpBasePath, baseCommit, headCommit st | ||||||
| 		case always: | 		case always: | ||||||
| 			break | 			break | ||||||
| 		case pubkey: | 		case pubkey: | ||||||
| 			keys, err := ListGPGKeys(u.ID) | 			keys, err := ListGPGKeys(u.ID, ListOptions{}) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return false, "", err | 				return false, "", err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -55,7 +55,9 @@ func TestPullRequest_GetHeadRepo(t *testing.T) { | ||||||
| func TestPullRequestsNewest(t *testing.T) { | func TestPullRequestsNewest(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 	prs, count, err := PullRequests(1, &PullRequestsOptions{ | 	prs, count, err := PullRequests(1, &PullRequestsOptions{ | ||||||
| 		Page:     1, | 		ListOptions: ListOptions{ | ||||||
|  | 			Page: 1, | ||||||
|  | 		}, | ||||||
| 		State:    "open", | 		State:    "open", | ||||||
| 		SortType: "newest", | 		SortType: "newest", | ||||||
| 		Labels:   []string{}, | 		Labels:   []string{}, | ||||||
|  | @ -72,7 +74,9 @@ func TestPullRequestsNewest(t *testing.T) { | ||||||
| func TestPullRequestsOldest(t *testing.T) { | func TestPullRequestsOldest(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 	prs, count, err := PullRequests(1, &PullRequestsOptions{ | 	prs, count, err := PullRequests(1, &PullRequestsOptions{ | ||||||
| 		Page:     1, | 		ListOptions: ListOptions{ | ||||||
|  | 			Page: 1, | ||||||
|  | 		}, | ||||||
| 		State:    "open", | 		State:    "open", | ||||||
| 		SortType: "oldest", | 		SortType: "oldest", | ||||||
| 		Labels:   []string{}, | 		Labels:   []string{}, | ||||||
|  |  | ||||||
|  | @ -175,6 +175,7 @@ func GetReleaseByID(id int64) (*Release, error) { | ||||||
| 
 | 
 | ||||||
| // FindReleasesOptions describes the conditions to Find releases
 | // FindReleasesOptions describes the conditions to Find releases
 | ||||||
| type FindReleasesOptions struct { | type FindReleasesOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	IncludeDrafts bool | 	IncludeDrafts bool | ||||||
| 	IncludeTags   bool | 	IncludeTags   bool | ||||||
| 	TagNames      []string | 	TagNames      []string | ||||||
|  | @ -197,17 +198,17 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetReleasesByRepoID returns a list of releases of repository.
 | // GetReleasesByRepoID returns a list of releases of repository.
 | ||||||
| func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions, page, pageSize int) (rels []*Release, err error) { | func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, error) { | ||||||
| 	if page <= 0 { | 	sess := x. | ||||||
| 		page = 1 | 		Desc("created_unix", "id"). | ||||||
|  | 		Where(opts.toConds(repoID)) | ||||||
|  | 
 | ||||||
|  | 	if opts.PageSize != 0 { | ||||||
|  | 		sess = opts.setSessionPagination(sess) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = x. | 	rels := make([]*Release, 0, opts.PageSize) | ||||||
| 		Desc("created_unix", "id"). | 	return rels, sess.Find(&rels) | ||||||
| 		Limit(pageSize, (page-1)*pageSize). |  | ||||||
| 		Where(opts.toConds(repoID)). |  | ||||||
| 		Find(&rels) |  | ||||||
| 	return rels, err |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames.
 | // GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames.
 | ||||||
|  |  | ||||||
|  | @ -1024,7 +1024,7 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error | ||||||
| 
 | 
 | ||||||
| 	// 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(); err != nil { | 		if err := u.GetTeams(&SearchTeamOptions{}); err != nil { | ||||||
| 			return fmt.Errorf("GetTeams: %v", err) | 			return fmt.Errorf("GetTeams: %v", err) | ||||||
| 		} | 		} | ||||||
| 		for _, t := range u.Teams { | 		for _, t := range u.Teams { | ||||||
|  | @ -1141,7 +1141,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Remove redundant collaborators.
 | 	// Remove redundant collaborators.
 | ||||||
| 	collaborators, err := repo.getCollaborators(sess) | 	collaborators, err := repo.getCollaborators(sess, ListOptions{}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("getCollaborators: %v", err) | 		return fmt.Errorf("getCollaborators: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -1171,7 +1171,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if newOwner.IsOrganization() { | 	if newOwner.IsOrganization() { | ||||||
| 		if err := newOwner.GetTeams(); err != nil { | 		if err := newOwner.GetTeams(&SearchTeamOptions{}); err != nil { | ||||||
| 			return fmt.Errorf("GetTeams: %v", err) | 			return fmt.Errorf("GetTeams: %v", err) | ||||||
| 		} | 		} | ||||||
| 		for _, t := range newOwner.Teams { | 		for _, t := range newOwner.Teams { | ||||||
|  | @ -1422,7 +1422,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if org.IsOrganization() { | 	if org.IsOrganization() { | ||||||
| 		if err = org.GetTeams(); err != nil { | 		if err = org.GetTeams(&SearchTeamOptions{}); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1442,7 +1442,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Delete Deploy Keys
 | 	// Delete Deploy Keys
 | ||||||
| 	deployKeys, err := listDeployKeys(sess, repo.ID) | 	deployKeys, err := listDeployKeys(sess, repo.ID, ListOptions{}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("listDeployKeys: %v", err) | 		return fmt.Errorf("listDeployKeys: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -1701,25 +1701,22 @@ func GetRepositoriesMapByIDs(ids []int64) (map[int64]*Repository, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetUserRepositories returns a list of repositories of given user.
 | // GetUserRepositories returns a list of repositories of given user.
 | ||||||
| func GetUserRepositories(userID int64, private bool, page, pageSize int, orderBy string) ([]*Repository, error) { | func GetUserRepositories(opts *SearchRepoOptions) ([]*Repository, error) { | ||||||
| 	if len(orderBy) == 0 { | 	if len(opts.OrderBy) == 0 { | ||||||
| 		orderBy = "updated_unix DESC" | 		opts.OrderBy = "updated_unix DESC" | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sess := x. | 	sess := x. | ||||||
| 		Where("owner_id = ?", userID). | 		Where("owner_id = ?", opts.Actor.ID). | ||||||
| 		OrderBy(orderBy) | 		OrderBy(opts.OrderBy.String()) | ||||||
| 	if !private { | 	if !opts.Private { | ||||||
| 		sess.And("is_private=?", false) | 		sess.And("is_private=?", false) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if page <= 0 { | 	sess = opts.setSessionPagination(sess) | ||||||
| 		page = 1 |  | ||||||
| 	} |  | ||||||
| 	sess.Limit(pageSize, (page-1)*pageSize) |  | ||||||
| 
 | 
 | ||||||
| 	repos := make([]*Repository, 0, pageSize) | 	repos := make([]*Repository, 0, opts.PageSize) | ||||||
| 	return repos, sess.Find(&repos) | 	return repos, opts.setSessionPagination(sess).Find(&repos) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetUserMirrorRepositories returns a list of mirror repositories of given user.
 | // GetUserMirrorRepositories returns a list of mirror repositories of given user.
 | ||||||
|  | @ -2029,9 +2026,15 @@ func CopyLFS(ctx DBContext, newRepo, oldRepo *Repository) error { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetForks returns all the forks of the repository
 | // GetForks returns all the forks of the repository
 | ||||||
| func (repo *Repository) GetForks() ([]*Repository, error) { | func (repo *Repository) GetForks(listOptions ListOptions) ([]*Repository, error) { | ||||||
| 	forks := make([]*Repository, 0, repo.NumForks) | 	if listOptions.Page == 0 { | ||||||
| 	return forks, x.Find(&forks, &Repository{ForkID: repo.ID}) | 		forks := make([]*Repository, 0, repo.NumForks) | ||||||
|  | 		return forks, x.Find(&forks, &Repository{ForkID: repo.ID}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := listOptions.getPaginatedSession() | ||||||
|  | 	forks := make([]*Repository, 0, listOptions.PageSize) | ||||||
|  | 	return forks, sess.Find(&forks, &Repository{ForkID: repo.ID}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetUserFork return user forked repository from this repository, if not forked return nil
 | // GetUserFork return user forked repository from this repository, if not forked return nil
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2016 The Gogs Authors. All rights reserved.
 | // Copyright 2016 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -52,8 +53,15 @@ func (repo *Repository) AddCollaborator(u *User) error { | ||||||
| 	return sess.Commit() | 	return sess.Commit() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (repo *Repository) getCollaborations(e Engine) ([]*Collaboration, error) { | func (repo *Repository) getCollaborations(e Engine, listOptions ListOptions) ([]*Collaboration, error) { | ||||||
| 	var collaborations []*Collaboration | 	if listOptions.Page == 0 { | ||||||
|  | 		collaborations := make([]*Collaboration, 0, 8) | ||||||
|  | 		return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repo.ID}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	e = listOptions.setEnginePagination(e) | ||||||
|  | 
 | ||||||
|  | 	collaborations := make([]*Collaboration, 0, listOptions.PageSize) | ||||||
| 	return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repo.ID}) | 	return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repo.ID}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -63,8 +71,8 @@ type Collaborator struct { | ||||||
| 	Collaboration *Collaboration | 	Collaboration *Collaboration | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (repo *Repository) getCollaborators(e Engine) ([]*Collaborator, error) { | func (repo *Repository) getCollaborators(e Engine, listOptions ListOptions) ([]*Collaborator, error) { | ||||||
| 	collaborations, err := repo.getCollaborations(e) | 	collaborations, err := repo.getCollaborations(e, listOptions) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("getCollaborations: %v", err) | 		return nil, fmt.Errorf("getCollaborations: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -84,8 +92,8 @@ func (repo *Repository) getCollaborators(e Engine) ([]*Collaborator, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetCollaborators returns the collaborators for a repository
 | // GetCollaborators returns the collaborators for a repository
 | ||||||
| func (repo *Repository) GetCollaborators() ([]*Collaborator, error) { | func (repo *Repository) GetCollaborators(listOptions ListOptions) ([]*Collaborator, error) { | ||||||
| 	return repo.getCollaborators(x) | 	return repo.getCollaborators(x, listOptions) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (repo *Repository) getCollaboration(e Engine, uid int64) (*Collaboration, error) { | func (repo *Repository) getCollaboration(e Engine, uid int64) (*Collaboration, error) { | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ func TestRepository_GetCollaborators(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 	test := func(repoID int64) { | 	test := func(repoID int64) { | ||||||
| 		repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) | 		repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) | ||||||
| 		collaborators, err := repo.GetCollaborators() | 		collaborators, err := repo.GetCollaborators(ListOptions{}) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
| 		expectedLen, err := x.Count(&Collaboration{RepoID: repoID}) | 		expectedLen, err := x.Count(&Collaboration{RepoID: repoID}) | ||||||
| 		assert.NoError(t, err) | 		assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | @ -110,7 +110,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) | 	templateWebhooks, err := GetWebhooksByRepoID(templateRepo.ID, ListOptions{}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | @ -148,7 +148,7 @@ func GenerateAvatar(ctx DBContext, templateRepo, generateRepo *Repository) error | ||||||
| 
 | 
 | ||||||
| // GenerateIssueLabels generates issue labels from a template repository
 | // GenerateIssueLabels generates issue labels from a template repository
 | ||||||
| func GenerateIssueLabels(ctx DBContext, templateRepo, generateRepo *Repository) error { | func GenerateIssueLabels(ctx DBContext, templateRepo, generateRepo *Repository) error { | ||||||
| 	templateLabels, err := getLabelsByRepoID(ctx.e, templateRepo.ID, "") | 	templateLabels, err := getLabelsByRepoID(ctx.e, templateRepo.ID, "", ListOptions{}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -111,6 +111,7 @@ func (repos MirrorRepositoryList) LoadAttributes() error { | ||||||
| 
 | 
 | ||||||
| // SearchRepoOptions holds the search options
 | // SearchRepoOptions holds the search options
 | ||||||
| type SearchRepoOptions struct { | type SearchRepoOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	Actor           *User | 	Actor           *User | ||||||
| 	Keyword         string | 	Keyword         string | ||||||
| 	OwnerID         int64 | 	OwnerID         int64 | ||||||
|  | @ -118,11 +119,9 @@ type SearchRepoOptions struct { | ||||||
| 	OrderBy         SearchOrderBy | 	OrderBy         SearchOrderBy | ||||||
| 	Private         bool // Include private repositories in results
 | 	Private         bool // Include private repositories in results
 | ||||||
| 	StarredByID     int64 | 	StarredByID     int64 | ||||||
| 	Page            int |  | ||||||
| 	IsProfile       bool | 	IsProfile       bool | ||||||
| 	AllPublic       bool // Include also all public repositories of users and public organisations
 | 	AllPublic       bool // Include also all public repositories of users and public organisations
 | ||||||
| 	AllLimited      bool // Include also all public repositories of limited organisations
 | 	AllLimited      bool // Include also all public repositories of limited organisations
 | ||||||
| 	PageSize        int  // Can be smaller than or equal to setting.ExplorePagingNum
 |  | ||||||
| 	// None -> include collaborative AND non-collaborative
 | 	// None -> include collaborative AND non-collaborative
 | ||||||
| 	// True -> include just collaborative
 | 	// True -> include just collaborative
 | ||||||
| 	// False -> incude just non-collaborative
 | 	// False -> incude just non-collaborative
 | ||||||
|  |  | ||||||
|  | @ -17,9 +17,11 @@ func TestSearchRepository(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// test search public repository on explore page
 | 	// test search public repository on explore page
 | ||||||
| 	repos, count, err := SearchRepositoryByName(&SearchRepoOptions{ | 	repos, count, err := SearchRepositoryByName(&SearchRepoOptions{ | ||||||
|  | 		ListOptions: ListOptions{ | ||||||
|  | 			Page:     1, | ||||||
|  | 			PageSize: 10, | ||||||
|  | 		}, | ||||||
| 		Keyword:     "repo_12", | 		Keyword:     "repo_12", | ||||||
| 		Page:        1, |  | ||||||
| 		PageSize:    10, |  | ||||||
| 		Collaborate: util.OptionalBoolFalse, | 		Collaborate: util.OptionalBoolFalse, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
|  | @ -30,9 +32,11 @@ func TestSearchRepository(t *testing.T) { | ||||||
| 	assert.Equal(t, int64(1), count) | 	assert.Equal(t, int64(1), count) | ||||||
| 
 | 
 | ||||||
| 	repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ | 	repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ | ||||||
|  | 		ListOptions: ListOptions{ | ||||||
|  | 			Page:     1, | ||||||
|  | 			PageSize: 10, | ||||||
|  | 		}, | ||||||
| 		Keyword:     "test_repo", | 		Keyword:     "test_repo", | ||||||
| 		Page:        1, |  | ||||||
| 		PageSize:    10, |  | ||||||
| 		Collaborate: util.OptionalBoolFalse, | 		Collaborate: util.OptionalBoolFalse, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
|  | @ -42,9 +46,11 @@ func TestSearchRepository(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// test search private repository on explore page
 | 	// test search private repository on explore page
 | ||||||
| 	repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ | 	repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ | ||||||
|  | 		ListOptions: ListOptions{ | ||||||
|  | 			Page:     1, | ||||||
|  | 			PageSize: 10, | ||||||
|  | 		}, | ||||||
| 		Keyword:     "repo_13", | 		Keyword:     "repo_13", | ||||||
| 		Page:        1, |  | ||||||
| 		PageSize:    10, |  | ||||||
| 		Private:     true, | 		Private:     true, | ||||||
| 		Collaborate: util.OptionalBoolFalse, | 		Collaborate: util.OptionalBoolFalse, | ||||||
| 	}) | 	}) | ||||||
|  | @ -56,9 +62,11 @@ func TestSearchRepository(t *testing.T) { | ||||||
| 	assert.Equal(t, int64(1), count) | 	assert.Equal(t, int64(1), count) | ||||||
| 
 | 
 | ||||||
| 	repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ | 	repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ | ||||||
|  | 		ListOptions: ListOptions{ | ||||||
|  | 			Page:     1, | ||||||
|  | 			PageSize: 10, | ||||||
|  | 		}, | ||||||
| 		Keyword:     "test_repo", | 		Keyword:     "test_repo", | ||||||
| 		Page:        1, |  | ||||||
| 		PageSize:    10, |  | ||||||
| 		Private:     true, | 		Private:     true, | ||||||
| 		Collaborate: util.OptionalBoolFalse, | 		Collaborate: util.OptionalBoolFalse, | ||||||
| 	}) | 	}) | ||||||
|  | @ -76,9 +84,11 @@ func TestSearchRepository(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// Test search within description
 | 	// Test search within description
 | ||||||
| 	repos, count, err = SearchRepository(&SearchRepoOptions{ | 	repos, count, err = SearchRepository(&SearchRepoOptions{ | ||||||
|  | 		ListOptions: ListOptions{ | ||||||
|  | 			Page:     1, | ||||||
|  | 			PageSize: 10, | ||||||
|  | 		}, | ||||||
| 		Keyword:            "description_14", | 		Keyword:            "description_14", | ||||||
| 		Page:               1, |  | ||||||
| 		PageSize:           10, |  | ||||||
| 		Collaborate:        util.OptionalBoolFalse, | 		Collaborate:        util.OptionalBoolFalse, | ||||||
| 		IncludeDescription: true, | 		IncludeDescription: true, | ||||||
| 	}) | 	}) | ||||||
|  | @ -91,9 +101,11 @@ func TestSearchRepository(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// Test NOT search within description
 | 	// Test NOT search within description
 | ||||||
| 	repos, count, err = SearchRepository(&SearchRepoOptions{ | 	repos, count, err = SearchRepository(&SearchRepoOptions{ | ||||||
|  | 		ListOptions: ListOptions{ | ||||||
|  | 			Page:     1, | ||||||
|  | 			PageSize: 10, | ||||||
|  | 		}, | ||||||
| 		Keyword:            "description_14", | 		Keyword:            "description_14", | ||||||
| 		Page:               1, |  | ||||||
| 		PageSize:           10, |  | ||||||
| 		Collaborate:        util.OptionalBoolFalse, | 		Collaborate:        util.OptionalBoolFalse, | ||||||
| 		IncludeDescription: false, | 		IncludeDescription: false, | ||||||
| 	}) | 	}) | ||||||
|  | @ -108,88 +120,88 @@ func TestSearchRepository(t *testing.T) { | ||||||
| 		count int | 		count int | ||||||
| 	}{ | 	}{ | ||||||
| 		{name: "PublicRepositoriesByName", | 		{name: "PublicRepositoriesByName", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", PageSize: 10, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{PageSize: 10}, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 7}, | 			count: 7}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesByName", | 		{name: "PublicAndPrivateRepositoriesByName", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", Page: 1, PageSize: 10, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 14}, | 			count: 14}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFirstPage", | 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFirstPage", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", Page: 1, PageSize: 5, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 14}, | 			count: 14}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitSecondPage", | 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitSecondPage", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", Page: 2, PageSize: 5, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 14}, | 			count: 14}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitThirdPage", | 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitThirdPage", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", Page: 3, PageSize: 5, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 14}, | 			count: 14}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFourthPage", | 		{name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFourthPage", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", Page: 3, PageSize: 5, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 14}, | 			count: 14}, | ||||||
| 		{name: "PublicRepositoriesOfUser", | 		{name: "PublicRepositoriesOfUser", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 2}, | 			count: 2}, | ||||||
| 		{name: "PublicRepositoriesOfUser2", | 		{name: "PublicRepositoriesOfUser2", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 18, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 0}, | 			count: 0}, | ||||||
| 		{name: "PublicRepositoriesOfUser3", | 		{name: "PublicRepositoriesOfUser3", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 20, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 2}, | 			count: 2}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesOfUser", | 		{name: "PublicAndPrivateRepositoriesOfUser", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 4}, | 			count: 4}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesOfUser2", | 		{name: "PublicAndPrivateRepositoriesOfUser2", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 18, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 0}, | 			count: 0}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesOfUser3", | 		{name: "PublicAndPrivateRepositoriesOfUser3", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 20, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 4}, | 			count: 4}, | ||||||
| 		{name: "PublicRepositoriesOfUserIncludingCollaborative", | 		{name: "PublicRepositoriesOfUserIncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 15}, | ||||||
| 			count: 5}, | 			count: 5}, | ||||||
| 		{name: "PublicRepositoriesOfUser2IncludingCollaborative", | 		{name: "PublicRepositoriesOfUser2IncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 18}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 18}, | ||||||
| 			count: 1}, | 			count: 1}, | ||||||
| 		{name: "PublicRepositoriesOfUser3IncludingCollaborative", | 		{name: "PublicRepositoriesOfUser3IncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 20}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 20}, | ||||||
| 			count: 3}, | 			count: 3}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesOfUserIncludingCollaborative", | 		{name: "PublicAndPrivateRepositoriesOfUserIncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true}, | ||||||
| 			count: 9}, | 			count: 9}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesOfUser2IncludingCollaborative", | 		{name: "PublicAndPrivateRepositoriesOfUser2IncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 18, Private: true}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true}, | ||||||
| 			count: 4}, | 			count: 4}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesOfUser3IncludingCollaborative", | 		{name: "PublicAndPrivateRepositoriesOfUser3IncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 20, Private: true}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true}, | ||||||
| 			count: 7}, | 			count: 7}, | ||||||
| 		{name: "PublicRepositoriesOfOrganization", | 		{name: "PublicRepositoriesOfOrganization", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 1}, | 			count: 1}, | ||||||
| 		{name: "PublicAndPrivateRepositoriesOfOrganization", | 		{name: "PublicAndPrivateRepositoriesOfOrganization", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, Private: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 2}, | 			count: 2}, | ||||||
| 		{name: "AllPublic/PublicRepositoriesByName", | 		{name: "AllPublic/PublicRepositoriesByName", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", PageSize: 10, AllPublic: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{PageSize: 10}, AllPublic: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 7}, | 			count: 7}, | ||||||
| 		{name: "AllPublic/PublicAndPrivateRepositoriesByName", | 		{name: "AllPublic/PublicAndPrivateRepositoriesByName", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "big_test_", Page: 1, PageSize: 10, Private: true, AllPublic: true, Collaborate: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{Keyword: "big_test_", ListOptions: ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: util.OptionalBoolFalse}, | ||||||
| 			count: 14}, | 			count: 14}, | ||||||
| 		{name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative", | 		{name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse}, | ||||||
| 			count: 25}, | 			count: 25}, | ||||||
| 		{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative", | 		{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse}, | ||||||
| 			count: 30}, | 			count: 30}, | ||||||
| 		{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName", | 		{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true}, | 			opts:  &SearchRepoOptions{Keyword: "test", ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true}, | ||||||
| 			count: 15}, | 			count: 15}, | ||||||
| 		{name: "AllPublic/PublicAndPrivateRepositoriesOfUser2IncludingCollaborativeByName", | 		{name: "AllPublic/PublicAndPrivateRepositoriesOfUser2IncludingCollaborativeByName", | ||||||
| 			opts:  &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 18, Private: true, AllPublic: true}, | 			opts:  &SearchRepoOptions{Keyword: "test", ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, AllPublic: true}, | ||||||
| 			count: 13}, | 			count: 13}, | ||||||
| 		{name: "AllPublic/PublicRepositoriesOfOrganization", | 		{name: "AllPublic/PublicRepositoriesOfOrganization", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse}, | ||||||
| 			count: 25}, | 			count: 25}, | ||||||
| 		{name: "AllTemplates", | 		{name: "AllTemplates", | ||||||
| 			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, Template: util.OptionalBoolTrue}, | 			opts:  &SearchRepoOptions{ListOptions: ListOptions{Page: 1, PageSize: 10}, Template: util.OptionalBoolTrue}, | ||||||
| 			count: 2}, | 			count: 2}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -110,7 +110,7 @@ func SignInitialCommit(repoPath string, u *User) (bool, string, error) { | ||||||
| 		case always: | 		case always: | ||||||
| 			break | 			break | ||||||
| 		case pubkey: | 		case pubkey: | ||||||
| 			keys, err := ListGPGKeys(u.ID) | 			keys, err := ListGPGKeys(u.ID, ListOptions{}) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return false, "", err | 				return false, "", err | ||||||
| 			} | 			} | ||||||
|  | @ -145,7 +145,7 @@ func (repo *Repository) SignWikiCommit(u *User) (bool, string, error) { | ||||||
| 		case always: | 		case always: | ||||||
| 			break | 			break | ||||||
| 		case pubkey: | 		case pubkey: | ||||||
| 			keys, err := ListGPGKeys(u.ID) | 			keys, err := ListGPGKeys(u.ID, ListOptions{}) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return false, "", err | 				return false, "", err | ||||||
| 			} | 			} | ||||||
|  | @ -197,7 +197,7 @@ func (repo *Repository) SignCRUDAction(u *User, tmpBasePath, parentCommit string | ||||||
| 		case always: | 		case always: | ||||||
| 			break | 			break | ||||||
| 		case pubkey: | 		case pubkey: | ||||||
| 			keys, err := ListGPGKeys(u.ID) | 			keys, err := ListGPGKeys(u.ID, ListOptions{}) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return false, "", err | 				return false, "", err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -153,14 +153,18 @@ func GetRepoWatchersIDs(repoID int64) ([]int64, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetWatchers returns range of users watching given repository.
 | // GetWatchers returns range of users watching given repository.
 | ||||||
| func (repo *Repository) GetWatchers(page int) ([]*User, error) { | func (repo *Repository) GetWatchers(opts ListOptions) ([]*User, error) { | ||||||
| 	users := make([]*User, 0, ItemsPerPage) |  | ||||||
| 	sess := x.Where("watch.repo_id=?", repo.ID). | 	sess := x.Where("watch.repo_id=?", repo.ID). | ||||||
| 		Join("LEFT", "watch", "`user`.id=`watch`.user_id"). | 		Join("LEFT", "watch", "`user`.id=`watch`.user_id"). | ||||||
| 		And("`watch`.mode<>?", RepoWatchModeDont) | 		And("`watch`.mode<>?", RepoWatchModeDont) | ||||||
| 	if page > 0 { | 	if opts.Page > 0 { | ||||||
| 		sess = sess.Limit(ItemsPerPage, (page-1)*ItemsPerPage) | 		sess = opts.setSessionPagination(sess) | ||||||
|  | 		users := make([]*User, 0, opts.PageSize) | ||||||
|  | 
 | ||||||
|  | 		return users, sess.Find(&users) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	users := make([]*User, 0, 8) | ||||||
| 	return users, sess.Find(&users) | 	return users, sess.Find(&users) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ func TestRepository_GetWatchers(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 
 | 
 | ||||||
| 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) | 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) | ||||||
| 	watchers, err := repo.GetWatchers(1) | 	watchers, err := repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, repo.NumWatches) | 	assert.Len(t, watchers, repo.NumWatches) | ||||||
| 	for _, watcher := range watchers { | 	for _, watcher := range watchers { | ||||||
|  | @ -67,7 +67,7 @@ func TestRepository_GetWatchers(t *testing.T) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	repo = AssertExistsAndLoadBean(t, &Repository{ID: 9}).(*Repository) | 	repo = AssertExistsAndLoadBean(t, &Repository{ID: 9}).(*Repository) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, 0) | 	assert.Len(t, watchers, 0) | ||||||
| } | } | ||||||
|  | @ -113,7 +113,7 @@ func TestWatchIfAuto(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 
 | 
 | ||||||
| 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) | 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) | ||||||
| 	watchers, err := repo.GetWatchers(1) | 	watchers, err := repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, repo.NumWatches) | 	assert.Len(t, watchers, repo.NumWatches) | ||||||
| 
 | 
 | ||||||
|  | @ -123,13 +123,13 @@ func TestWatchIfAuto(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// Must not add watch
 | 	// Must not add watch
 | ||||||
| 	assert.NoError(t, WatchIfAuto(8, 1, true)) | 	assert.NoError(t, WatchIfAuto(8, 1, true)) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, prevCount) | 	assert.Len(t, watchers, prevCount) | ||||||
| 
 | 
 | ||||||
| 	// Should not add watch
 | 	// Should not add watch
 | ||||||
| 	assert.NoError(t, WatchIfAuto(10, 1, true)) | 	assert.NoError(t, WatchIfAuto(10, 1, true)) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, prevCount) | 	assert.Len(t, watchers, prevCount) | ||||||
| 
 | 
 | ||||||
|  | @ -137,31 +137,31 @@ func TestWatchIfAuto(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// Must not add watch
 | 	// Must not add watch
 | ||||||
| 	assert.NoError(t, WatchIfAuto(8, 1, true)) | 	assert.NoError(t, WatchIfAuto(8, 1, true)) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, prevCount) | 	assert.Len(t, watchers, prevCount) | ||||||
| 
 | 
 | ||||||
| 	// Should not add watch
 | 	// Should not add watch
 | ||||||
| 	assert.NoError(t, WatchIfAuto(12, 1, false)) | 	assert.NoError(t, WatchIfAuto(12, 1, false)) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, prevCount) | 	assert.Len(t, watchers, prevCount) | ||||||
| 
 | 
 | ||||||
| 	// Should add watch
 | 	// Should add watch
 | ||||||
| 	assert.NoError(t, WatchIfAuto(12, 1, true)) | 	assert.NoError(t, WatchIfAuto(12, 1, true)) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, prevCount+1) | 	assert.Len(t, watchers, prevCount+1) | ||||||
| 
 | 
 | ||||||
| 	// Should remove watch, inhibit from adding auto
 | 	// Should remove watch, inhibit from adding auto
 | ||||||
| 	assert.NoError(t, WatchRepo(12, 1, false)) | 	assert.NoError(t, WatchRepo(12, 1, false)) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, prevCount) | 	assert.Len(t, watchers, prevCount) | ||||||
| 
 | 
 | ||||||
| 	// Must not add watch
 | 	// Must not add watch
 | ||||||
| 	assert.NoError(t, WatchIfAuto(12, 1, true)) | 	assert.NoError(t, WatchIfAuto(12, 1, true)) | ||||||
| 	watchers, err = repo.GetWatchers(1) | 	watchers, err = repo.GetWatchers(ListOptions{Page: 1}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, watchers, prevCount) | 	assert.Len(t, watchers, prevCount) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -567,11 +567,17 @@ func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ListPublicKeys returns a list of public keys belongs to given user.
 | // ListPublicKeys returns a list of public keys belongs to given user.
 | ||||||
| func ListPublicKeys(uid int64) ([]*PublicKey, error) { | func ListPublicKeys(uid int64, listOptions ListOptions) ([]*PublicKey, error) { | ||||||
|  | 	sess := x.Where("owner_id = ?", uid) | ||||||
|  | 	if listOptions.Page != 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 
 | ||||||
|  | 		keys := make([]*PublicKey, 0, listOptions.PageSize) | ||||||
|  | 		return keys, sess.Find(&keys) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	keys := make([]*PublicKey, 0, 5) | 	keys := make([]*PublicKey, 0, 5) | ||||||
| 	return keys, x. | 	return keys, sess.Find(&keys) | ||||||
| 		Where("owner_id = ?", uid). |  | ||||||
| 		Find(&keys) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ListPublicLdapSSHKeys returns a list of synchronized public ldap ssh keys belongs to given user and login source.
 | // ListPublicLdapSSHKeys returns a list of synchronized public ldap ssh keys belongs to given user and login source.
 | ||||||
|  | @ -970,15 +976,21 @@ func deleteDeployKey(sess Engine, doer *User, id int64) error { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ListDeployKeys returns all deploy keys by given repository ID.
 | // ListDeployKeys returns all deploy keys by given repository ID.
 | ||||||
| func ListDeployKeys(repoID int64) ([]*DeployKey, error) { | func ListDeployKeys(repoID int64, listOptions ListOptions) ([]*DeployKey, error) { | ||||||
| 	return listDeployKeys(x, repoID) | 	return listDeployKeys(x, repoID, listOptions) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func listDeployKeys(e Engine, repoID int64) ([]*DeployKey, error) { | func listDeployKeys(e Engine, repoID int64, listOptions ListOptions) ([]*DeployKey, error) { | ||||||
|  | 	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) | 	keys := make([]*DeployKey, 0, 5) | ||||||
| 	return keys, e. | 	return keys, sess.Find(&keys) | ||||||
| 		Where("repo_id = ?", repoID). |  | ||||||
| 		Find(&keys) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SearchDeployKeys returns a list of deploy keys matching the provided arguments.
 | // SearchDeployKeys returns a list of deploy keys matching the provided arguments.
 | ||||||
|  |  | ||||||
|  | @ -64,13 +64,17 @@ func isStaring(e Engine, userID, repoID int64) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetStargazers returns the users that starred the repo.
 | // GetStargazers returns the users that starred the repo.
 | ||||||
| func (repo *Repository) GetStargazers(page int) ([]*User, error) { | func (repo *Repository) GetStargazers(opts ListOptions) ([]*User, error) { | ||||||
| 	users := make([]*User, 0, ItemsPerPage) |  | ||||||
| 	sess := x.Where("star.repo_id = ?", repo.ID). | 	sess := x.Where("star.repo_id = ?", repo.ID). | ||||||
| 		Join("LEFT", "star", "`user`.id = star.uid") | 		Join("LEFT", "star", "`user`.id = star.uid") | ||||||
| 	if page > 0 { | 	if opts.Page > 0 { | ||||||
| 		sess = sess.Limit(ItemsPerPage, (page-1)*ItemsPerPage) | 		sess = opts.setSessionPagination(sess) | ||||||
|  | 
 | ||||||
|  | 		users := make([]*User, 0, opts.PageSize) | ||||||
|  | 		return users, sess.Find(&users) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	users := make([]*User, 0, 8) | ||||||
| 	return users, sess.Find(&users) | 	return users, sess.Find(&users) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ func TestRepository_GetStargazers(t *testing.T) { | ||||||
| 	// repo with stargazers
 | 	// repo with stargazers
 | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 4}).(*Repository) | 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 4}).(*Repository) | ||||||
| 	gazers, err := repo.GetStargazers(0) | 	gazers, err := repo.GetStargazers(ListOptions{Page: 0}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	if assert.Len(t, gazers, 1) { | 	if assert.Len(t, gazers, 1) { | ||||||
| 		assert.Equal(t, int64(2), gazers[0].ID) | 		assert.Equal(t, int64(2), gazers[0].ID) | ||||||
|  | @ -44,7 +44,7 @@ func TestRepository_GetStargazers2(t *testing.T) { | ||||||
| 	// repo with stargazers
 | 	// repo with stargazers
 | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository) | 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository) | ||||||
| 	gazers, err := repo.GetStargazers(0) | 	gazers, err := repo.GetStargazers(ListOptions{Page: 0}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, gazers, 0) | 	assert.Len(t, gazers, 0) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -78,12 +78,20 @@ func GetAccessTokenBySHA(token string) (*AccessToken, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ListAccessTokens returns a list of access tokens belongs to given user.
 | // ListAccessTokens returns a list of access tokens belongs to given user.
 | ||||||
| func ListAccessTokens(uid int64) ([]*AccessToken, error) { | func ListAccessTokens(uid int64, listOptions ListOptions) ([]*AccessToken, error) { | ||||||
| 	tokens := make([]*AccessToken, 0, 5) | 	sess := x. | ||||||
| 	return tokens, x. |  | ||||||
| 		Where("uid=?", uid). | 		Where("uid=?", uid). | ||||||
| 		Desc("id"). | 		Desc("id") | ||||||
| 		Find(&tokens) | 
 | ||||||
|  | 	if listOptions.Page == 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 
 | ||||||
|  | 		tokens := make([]*AccessToken, 0, listOptions.PageSize) | ||||||
|  | 		return tokens, sess.Find(&tokens) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tokens := make([]*AccessToken, 0, 5) | ||||||
|  | 	return tokens, sess.Find(&tokens) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UpdateAccessToken updates information of access token.
 | // UpdateAccessToken updates information of access token.
 | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ func TestGetAccessTokenBySHA(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestListAccessTokens(t *testing.T) { | func TestListAccessTokens(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 	tokens, err := ListAccessTokens(1) | 	tokens, err := ListAccessTokens(1, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	if assert.Len(t, tokens, 2) { | 	if assert.Len(t, tokens, 2) { | ||||||
| 		assert.Equal(t, int64(1), tokens[0].UID) | 		assert.Equal(t, int64(1), tokens[0].UID) | ||||||
|  | @ -56,14 +56,14 @@ func TestListAccessTokens(t *testing.T) { | ||||||
| 		assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B") | 		assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tokens, err = ListAccessTokens(2) | 	tokens, err = ListAccessTokens(2, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	if assert.Len(t, tokens, 1) { | 	if assert.Len(t, tokens, 1) { | ||||||
| 		assert.Equal(t, int64(2), tokens[0].UID) | 		assert.Equal(t, int64(2), tokens[0].UID) | ||||||
| 		assert.Equal(t, "Token A", tokens[0].Name) | 		assert.Equal(t, "Token A", tokens[0].Name) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tokens, err = ListAccessTokens(100) | 	tokens, err = ListAccessTokens(100, ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Empty(t, tokens) | 	assert.Empty(t, tokens) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -147,10 +147,9 @@ func removeTopicFromRepo(repoID int64, topic *Topic, e Engine) error { | ||||||
| 
 | 
 | ||||||
| // FindTopicOptions represents the options when fdin topics
 | // FindTopicOptions represents the options when fdin topics
 | ||||||
| type FindTopicOptions struct { | type FindTopicOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	RepoID  int64 | 	RepoID  int64 | ||||||
| 	Keyword string | 	Keyword string | ||||||
| 	Limit   int |  | ||||||
| 	Page    int |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (opts *FindTopicOptions) toConds() builder.Cond { | func (opts *FindTopicOptions) toConds() builder.Cond { | ||||||
|  | @ -172,8 +171,8 @@ func FindTopics(opts *FindTopicOptions) (topics []*Topic, err error) { | ||||||
| 	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") | ||||||
| 	} | 	} | ||||||
| 	if opts.Limit > 0 { | 	if opts.PageSize != 0 && opts.Page != 0 { | ||||||
| 		sess.Limit(opts.Limit, opts.Page*opts.Limit) | 		sess = opts.setSessionPagination(sess) | ||||||
| 	} | 	} | ||||||
| 	return topics, sess.Desc("topic.repo_count").Find(&topics) | 	return topics, sess.Desc("topic.repo_count").Find(&topics) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ func TestAddTopic(t *testing.T) { | ||||||
| 	assert.EqualValues(t, totalNrOfTopics, len(topics)) | 	assert.EqualValues(t, totalNrOfTopics, len(topics)) | ||||||
| 
 | 
 | ||||||
| 	topics, err = FindTopics(&FindTopicOptions{ | 	topics, err = FindTopics(&FindTopicOptions{ | ||||||
| 		Limit: 2, | 		ListOptions: ListOptions{Page: 1, PageSize: 2}, | ||||||
| 	}) | 	}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.EqualValues(t, 2, len(topics)) | 	assert.EqualValues(t, 2, len(topics)) | ||||||
|  |  | ||||||
|  | @ -163,6 +163,12 @@ type User struct { | ||||||
| 	Theme         string `xorm:"NOT NULL DEFAULT ''"` | 	Theme         string `xorm:"NOT NULL DEFAULT ''"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // SearchOrganizationsOptions options to filter organizations
 | ||||||
|  | type SearchOrganizationsOptions struct { | ||||||
|  | 	ListOptions | ||||||
|  | 	All bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // ColorFormat writes a colored string to identify this struct
 | // ColorFormat writes a colored string to identify this struct
 | ||||||
| func (u *User) ColorFormat(s fmt.State) { | func (u *User) ColorFormat(s fmt.State) { | ||||||
| 	log.ColorFprintf(s, "%d:%s", | 	log.ColorFprintf(s, "%d:%s", | ||||||
|  | @ -430,12 +436,19 @@ func (u *User) AvatarLink() string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetFollowers returns range of user's followers.
 | // GetFollowers returns range of user's followers.
 | ||||||
| func (u *User) GetFollowers(page int) ([]*User, error) { | func (u *User) GetFollowers(listOptions ListOptions) ([]*User, error) { | ||||||
| 	users := make([]*User, 0, ItemsPerPage) |  | ||||||
| 	sess := x. | 	sess := x. | ||||||
| 		Limit(ItemsPerPage, (page-1)*ItemsPerPage). |  | ||||||
| 		Where("follow.follow_id=?", u.ID). | 		Where("follow.follow_id=?", u.ID). | ||||||
| 		Join("LEFT", "follow", "`user`.id=follow.user_id") | 		Join("LEFT", "follow", "`user`.id=follow.user_id") | ||||||
|  | 
 | ||||||
|  | 	if listOptions.Page != 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 
 | ||||||
|  | 		users := make([]*User, 0, listOptions.PageSize) | ||||||
|  | 		return users, sess.Find(&users) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	users := make([]*User, 0, 8) | ||||||
| 	return users, sess.Find(&users) | 	return users, sess.Find(&users) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -445,12 +458,19 @@ func (u *User) IsFollowing(followID int64) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetFollowing returns range of user's following.
 | // GetFollowing returns range of user's following.
 | ||||||
| func (u *User) GetFollowing(page int) ([]*User, error) { | func (u *User) GetFollowing(listOptions ListOptions) ([]*User, error) { | ||||||
| 	users := make([]*User, 0, ItemsPerPage) |  | ||||||
| 	sess := x. | 	sess := x. | ||||||
| 		Limit(ItemsPerPage, (page-1)*ItemsPerPage). |  | ||||||
| 		Where("follow.user_id=?", u.ID). | 		Where("follow.user_id=?", u.ID). | ||||||
| 		Join("LEFT", "follow", "`user`.id=follow.follow_id") | 		Join("LEFT", "follow", "`user`.id=follow.follow_id") | ||||||
|  | 
 | ||||||
|  | 	if listOptions.Page != 0 { | ||||||
|  | 		sess = listOptions.setSessionPagination(sess) | ||||||
|  | 
 | ||||||
|  | 		users := make([]*User, 0, listOptions.PageSize) | ||||||
|  | 		return users, sess.Find(&users) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	users := make([]*User, 0, 8) | ||||||
| 	return users, sess.Find(&users) | 	return users, sess.Find(&users) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -616,8 +636,8 @@ func (u *User) GetOrganizationCount() (int64, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetRepositories returns repositories that user owns, including private repositories.
 | // GetRepositories returns repositories that user owns, including private repositories.
 | ||||||
| func (u *User) GetRepositories(page, pageSize int) (err error) { | func (u *User) GetRepositories(listOpts ListOptions) (err error) { | ||||||
| 	u.Repos, err = GetUserRepositories(u.ID, true, page, pageSize, "") | 	u.Repos, err = GetUserRepositories(&SearchRepoOptions{Actor: u, Private: true, ListOptions: listOpts}) | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -682,9 +702,9 @@ func (u *User) GetOwnedOrganizations() (err error) { | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetOrganizations returns all organizations that user belongs to.
 | // GetOrganizations returns paginated organizations that user belongs to.
 | ||||||
| func (u *User) GetOrganizations(all bool) error { | func (u *User) GetOrganizations(opts *SearchOrganizationsOptions) error { | ||||||
| 	ous, err := GetOrgUsersByUserID(u.ID, all) | 	ous, err := GetOrgUsersByUserID(u.ID, opts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | @ -1477,14 +1497,13 @@ func GetUser(user *User) (bool, error) { | ||||||
| 
 | 
 | ||||||
| // SearchUserOptions contains the options for searching
 | // SearchUserOptions contains the options for searching
 | ||||||
| type SearchUserOptions struct { | type SearchUserOptions struct { | ||||||
|  | 	ListOptions | ||||||
| 	Keyword       string | 	Keyword       string | ||||||
| 	Type          UserType | 	Type          UserType | ||||||
| 	UID           int64 | 	UID           int64 | ||||||
| 	OrderBy       SearchOrderBy | 	OrderBy       SearchOrderBy | ||||||
| 	Page          int |  | ||||||
| 	Visible       []structs.VisibleType | 	Visible       []structs.VisibleType | ||||||
| 	Actor         *User // The user doing the search
 | 	Actor         *User // The user doing the search
 | ||||||
| 	PageSize      int   // Can be smaller than or equal to setting.UI.ExplorePagingNum
 |  | ||||||
| 	IsActive      util.OptionalBool | 	IsActive      util.OptionalBool | ||||||
| 	SearchByEmail bool // Search by email as well as username/full name
 | 	SearchByEmail bool // Search by email as well as username/full name
 | ||||||
| } | } | ||||||
|  | @ -1552,57 +1571,56 @@ func SearchUsers(opts *SearchUserOptions) (users []*User, _ int64, _ error) { | ||||||
| 		return nil, 0, fmt.Errorf("Count: %v", err) | 		return nil, 0, fmt.Errorf("Count: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if opts.PageSize == 0 || opts.PageSize > setting.UI.ExplorePagingNum { |  | ||||||
| 		opts.PageSize = setting.UI.ExplorePagingNum |  | ||||||
| 	} |  | ||||||
| 	if opts.Page <= 0 { |  | ||||||
| 		opts.Page = 1 |  | ||||||
| 	} |  | ||||||
| 	if len(opts.OrderBy) == 0 { | 	if len(opts.OrderBy) == 0 { | ||||||
| 		opts.OrderBy = SearchOrderByAlphabetically | 		opts.OrderBy = SearchOrderByAlphabetically | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sess := x.Where(cond) | 	sess := x.Where(cond).OrderBy(opts.OrderBy.String()) | ||||||
| 	if opts.PageSize > 0 { | 	if opts.Page != 0 { | ||||||
| 		sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) | 		sess = opts.setSessionPagination(sess) | ||||||
| 	} |  | ||||||
| 	if opts.PageSize == -1 { |  | ||||||
| 		opts.PageSize = int(count) |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	users = make([]*User, 0, opts.PageSize) | 	users = make([]*User, 0, opts.PageSize) | ||||||
| 	return users, count, sess.OrderBy(opts.OrderBy.String()).Find(&users) | 	return users, count, sess.Find(&users) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetStarredRepos returns the repos starred by a particular user
 | // GetStarredRepos returns the repos starred by a particular user
 | ||||||
| func GetStarredRepos(userID int64, private bool) ([]*Repository, error) { | func GetStarredRepos(userID int64, private bool, listOptions ListOptions) ([]*Repository, error) { | ||||||
| 	sess := x.Where("star.uid=?", userID). | 	sess := x.Where("star.uid=?", userID). | ||||||
| 		Join("LEFT", "star", "`repository`.id=`star`.repo_id") | 		Join("LEFT", "star", "`repository`.id=`star`.repo_id") | ||||||
| 	if !private { | 	if !private { | ||||||
| 		sess = sess.And("is_private=?", false) | 		sess = sess.And("is_private=?", false) | ||||||
| 	} | 	} | ||||||
| 	repos := make([]*Repository, 0, 10) | 
 | ||||||
| 	err := sess.Find(&repos) | 	if listOptions.Page != 0 { | ||||||
| 	if err != nil { | 		sess = listOptions.setSessionPagination(sess) | ||||||
| 		return nil, err | 
 | ||||||
|  | 		repos := make([]*Repository, 0, listOptions.PageSize) | ||||||
|  | 		return repos, sess.Find(&repos) | ||||||
| 	} | 	} | ||||||
| 	return repos, nil | 
 | ||||||
|  | 	repos := make([]*Repository, 0, 10) | ||||||
|  | 	return repos, sess.Find(&repos) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetWatchedRepos returns the repos watched by a particular user
 | // GetWatchedRepos returns the repos watched by a particular user
 | ||||||
| func GetWatchedRepos(userID int64, private bool) ([]*Repository, error) { | func GetWatchedRepos(userID int64, private bool, listOptions ListOptions) ([]*Repository, 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") | ||||||
| 	if !private { | 	if !private { | ||||||
| 		sess = sess.And("is_private=?", false) | 		sess = sess.And("is_private=?", false) | ||||||
| 	} | 	} | ||||||
| 	repos := make([]*Repository, 0, 10) | 
 | ||||||
| 	err := sess.Find(&repos) | 	if listOptions.Page != 0 { | ||||||
| 	if err != nil { | 		sess = listOptions.setSessionPagination(sess) | ||||||
| 		return nil, err | 
 | ||||||
|  | 		repos := make([]*Repository, 0, listOptions.PageSize) | ||||||
|  | 		return repos, sess.Find(&repos) | ||||||
| 	} | 	} | ||||||
| 	return repos, nil | 
 | ||||||
|  | 	repos := make([]*Repository, 0, 10) | ||||||
|  | 	return repos, sess.Find(&repos) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // deleteKeysMarkedForDeletion returns true if ssh keys needs update
 | // deleteKeysMarkedForDeletion returns true if ssh keys needs update
 | ||||||
|  |  | ||||||
|  | @ -131,19 +131,19 @@ func TestSearchUsers(t *testing.T) { | ||||||
| 		testSuccess(opts, expectedOrgIDs) | 		testSuccess(opts, expectedOrgIDs) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 1, PageSize: 2}, | 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: ListOptions{Page: 1, PageSize: 2}}, | ||||||
| 		[]int64{3, 6}) | 		[]int64{3, 6}) | ||||||
| 
 | 
 | ||||||
| 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 2, PageSize: 2}, | 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: ListOptions{Page: 2, PageSize: 2}}, | ||||||
| 		[]int64{7, 17}) | 		[]int64{7, 17}) | ||||||
| 
 | 
 | ||||||
| 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 3, PageSize: 2}, | 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: ListOptions{Page: 3, PageSize: 2}}, | ||||||
| 		[]int64{19, 25}) | 		[]int64{19, 25}) | ||||||
| 
 | 
 | ||||||
| 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 4, PageSize: 2}, | 	testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: ListOptions{Page: 4, PageSize: 2}}, | ||||||
| 		[]int64{26}) | 		[]int64{26}) | ||||||
| 
 | 
 | ||||||
| 	testOrgSuccess(&SearchUserOptions{Page: 5, PageSize: 2}, | 	testOrgSuccess(&SearchUserOptions{ListOptions: ListOptions{Page: 5, PageSize: 2}}, | ||||||
| 		[]int64{}) | 		[]int64{}) | ||||||
| 
 | 
 | ||||||
| 	// test users
 | 	// test users
 | ||||||
|  | @ -152,20 +152,20 @@ func TestSearchUsers(t *testing.T) { | ||||||
| 		testSuccess(opts, expectedUserIDs) | 		testSuccess(opts, expectedUserIDs) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 1}, | 	testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: ListOptions{Page: 1}}, | ||||||
| 		[]int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29}) | 		[]int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29}) | ||||||
| 
 | 
 | ||||||
| 	testUserSuccess(&SearchUserOptions{Page: 1, IsActive: util.OptionalBoolFalse}, | 	testUserSuccess(&SearchUserOptions{ListOptions: ListOptions{Page: 1}, IsActive: util.OptionalBoolFalse}, | ||||||
| 		[]int64{9}) | 		[]int64{9}) | ||||||
| 
 | 
 | ||||||
| 	testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 1, IsActive: util.OptionalBoolTrue}, | 	testUserSuccess(&SearchUserOptions{OrderBy: "id ASC", ListOptions: ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue}, | ||||||
| 		[]int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 28, 29}) | 		[]int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 28, 29}) | ||||||
| 
 | 
 | ||||||
| 	testUserSuccess(&SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", Page: 1, IsActive: util.OptionalBoolTrue}, | 	testUserSuccess(&SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", ListOptions: ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue}, | ||||||
| 		[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18}) | 		[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18}) | ||||||
| 
 | 
 | ||||||
| 	// order by name asc default
 | 	// order by name asc default
 | ||||||
| 	testUserSuccess(&SearchUserOptions{Keyword: "user1", Page: 1, IsActive: util.OptionalBoolTrue}, | 	testUserSuccess(&SearchUserOptions{Keyword: "user1", ListOptions: ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue}, | ||||||
| 		[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18}) | 		[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -97,7 +97,7 @@ func (users UserList) loadTwoFactorStatus(e Engine) (map[int64]*TwoFactor, error | ||||||
| 
 | 
 | ||||||
| //APIFormat return list of users in api format
 | //APIFormat return list of users in api format
 | ||||||
| func (users UserList) APIFormat() []*api.User { | func (users UserList) APIFormat() []*api.User { | ||||||
| 	var result []*api.User | 	result := make([]*api.User, 0, len(users)) | ||||||
| 	for _, u := range users { | 	for _, u := range users { | ||||||
| 		result = append(result, u.APIFormat()) | 		result = append(result, u.APIFormat()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -274,9 +274,16 @@ func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetWebhooksByRepoID returns all webhooks of a repository.
 | // GetWebhooksByRepoID returns all webhooks of a repository.
 | ||||||
| func GetWebhooksByRepoID(repoID int64) ([]*Webhook, error) { | func GetWebhooksByRepoID(repoID int64, listOptions ListOptions) ([]*Webhook, error) { | ||||||
| 	webhooks := make([]*Webhook, 0, 5) | 	if listOptions.Page == 0 { | ||||||
| 	return webhooks, x.Find(&webhooks, &Webhook{RepoID: repoID}) | 		webhooks := make([]*Webhook, 0, 5) | ||||||
|  | 		return webhooks, x.Find(&webhooks, &Webhook{RepoID: repoID}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := listOptions.getPaginatedSession() | ||||||
|  | 	webhooks := make([]*Webhook, 0, listOptions.PageSize) | ||||||
|  | 
 | ||||||
|  | 	return webhooks, sess.Find(&webhooks, &Webhook{RepoID: repoID}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetActiveWebhooksByOrgID returns all active webhooks for an organization.
 | // GetActiveWebhooksByOrgID returns all active webhooks for an organization.
 | ||||||
|  | @ -292,10 +299,16 @@ func getActiveWebhooksByOrgID(e Engine, orgID int64) (ws []*Webhook, err error) | ||||||
| 	return ws, err | 	return ws, err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetWebhooksByOrgID returns all webhooks for an organization.
 | // GetWebhooksByOrgID returns paginated webhooks for an organization.
 | ||||||
| func GetWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) { | func GetWebhooksByOrgID(orgID int64, listOptions ListOptions) ([]*Webhook, error) { | ||||||
| 	err = x.Find(&ws, &Webhook{OrgID: orgID}) | 	if listOptions.Page == 0 { | ||||||
| 	return ws, err | 		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}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetDefaultWebhook returns admin-default webhook by given ID.
 | // GetDefaultWebhook returns admin-default webhook by given ID.
 | ||||||
|  |  | ||||||
|  | @ -120,7 +120,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) | 	hooks, err := GetWebhooksByRepoID(1, ListOptions{}) | ||||||
| 	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) | ||||||
|  | @ -140,7 +140,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) | 	hooks, err := GetWebhooksByOrgID(3, ListOptions{}) | ||||||
| 	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) | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -118,7 +119,7 @@ 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(); err != nil { | 			if err := org.GetTeams(&models.SearchTeamOptions{}); err != nil { | ||||||
| 				ctx.ServerError("GetTeams", err) | 				ctx.ServerError("GetTeams", err) | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -297,8 +297,8 @@ func (c *Commit) CommitsCount() (int64, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CommitsByRange returns the specific page commits before current revision, every page's number default by CommitsRangeSize
 | // CommitsByRange returns the specific page commits before current revision, every page's number default by CommitsRangeSize
 | ||||||
| func (c *Commit) CommitsByRange(page int) (*list.List, error) { | func (c *Commit) CommitsByRange(page, pageSize int) (*list.List, error) { | ||||||
| 	return c.repo.commitsByRange(c.ID, page) | 	return c.repo.commitsByRange(c.ID, page, pageSize) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CommitsBefore returns all the commits before current revision
 | // CommitsBefore returns all the commits before current revision
 | ||||||
|  |  | ||||||
|  | @ -198,9 +198,10 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) { | ||||||
| // CommitsRangeSize the default commits range size
 | // CommitsRangeSize the default commits range size
 | ||||||
| var CommitsRangeSize = 50 | var CommitsRangeSize = 50 | ||||||
| 
 | 
 | ||||||
| func (repo *Repository) commitsByRange(id SHA1, page int) (*list.List, error) { | func (repo *Repository) commitsByRange(id SHA1, page, pageSize int) (*list.List, error) { | ||||||
| 	stdout, err := NewCommand("log", id.String(), "--skip="+strconv.Itoa((page-1)*CommitsRangeSize), | 	stdout, err := NewCommand("log", id.String(), "--skip="+strconv.Itoa((page-1)*pageSize), | ||||||
| 		"--max-count="+strconv.Itoa(CommitsRangeSize), prettyLogFormat).RunInDirBytes(repo.Path) | 		"--max-count="+strconv.Itoa(pageSize), prettyLogFormat).RunInDirBytes(repo.Path) | ||||||
|  | 
 | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -221,8 +221,7 @@ func populateIssueIndexer(ctx context.Context) { | ||||||
| 		default: | 		default: | ||||||
| 		} | 		} | ||||||
| 		repos, _, err := models.SearchRepositoryByName(&models.SearchRepoOptions{ | 		repos, _, err := models.SearchRepositoryByName(&models.SearchRepoOptions{ | ||||||
| 			Page:        page, | 			ListOptions: models.ListOptions{Page: page, PageSize: models.RepositoryListDefaultPageSize}, | ||||||
| 			PageSize:    models.RepositoryListDefaultPageSize, |  | ||||||
| 			OrderBy:     models.SearchOrderByID, | 			OrderBy:     models.SearchOrderByID, | ||||||
| 			Private:     true, | 			Private:     true, | ||||||
| 			Collaborate: util.OptionalBoolFalse, | 			Collaborate: util.OptionalBoolFalse, | ||||||
|  |  | ||||||
|  | @ -59,19 +59,27 @@ func TestGiteaUploadRepo(t *testing.T) { | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.EqualValues(t, 0, len(milestones)) | 	assert.EqualValues(t, 0, len(milestones)) | ||||||
| 
 | 
 | ||||||
| 	labels, err := models.GetLabelsByRepoID(repo.ID, "") | 	labels, err := models.GetLabelsByRepoID(repo.ID, "", models.ListOptions{}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.EqualValues(t, 11, len(labels)) | 	assert.EqualValues(t, 11, len(labels)) | ||||||
| 
 | 
 | ||||||
| 	releases, err := models.GetReleasesByRepoID(repo.ID, models.FindReleasesOptions{ | 	releases, err := models.GetReleasesByRepoID(repo.ID, models.FindReleasesOptions{ | ||||||
|  | 		ListOptions: models.ListOptions{ | ||||||
|  | 			PageSize: 10, | ||||||
|  | 			Page:     0, | ||||||
|  | 		}, | ||||||
| 		IncludeTags: true, | 		IncludeTags: true, | ||||||
| 	}, 0, 10) | 	}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.EqualValues(t, 8, len(releases)) | 	assert.EqualValues(t, 8, len(releases)) | ||||||
| 
 | 
 | ||||||
| 	releases, err = models.GetReleasesByRepoID(repo.ID, models.FindReleasesOptions{ | 	releases, err = models.GetReleasesByRepoID(repo.ID, models.FindReleasesOptions{ | ||||||
|  | 		ListOptions: models.ListOptions{ | ||||||
|  | 			PageSize: 10, | ||||||
|  | 			Page:     0, | ||||||
|  | 		}, | ||||||
| 		IncludeTags: false, | 		IncludeTags: false, | ||||||
| 	}, 0, 10) | 	}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.EqualValues(t, 1, len(releases)) | 	assert.EqualValues(t, 1, len(releases)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	testTeamRepositories := func(teamID int64, repoIds []int64) { | 	testTeamRepositories := func(teamID int64, repoIds []int64) { | ||||||
| 		team := models.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team) | 		team := models.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team) | ||||||
| 		assert.NoError(t, team.GetRepositories(), "%s: GetRepositories", team.Name) | 		assert.NoError(t, team.GetRepositories(&models.SearchTeamOptions{}), "%s: GetRepositories", team.Name) | ||||||
| 		assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name) | 		assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name) | ||||||
| 		assert.Equal(t, len(repoIds), len(team.Repos), "%s: repo count", team.Name) | 		assert.Equal(t, len(repoIds), len(team.Repos), "%s: repo count", team.Name) | ||||||
| 		for i, rid := range repoIds { | 		for i, rid := range repoIds { | ||||||
|  |  | ||||||
|  | @ -183,9 +183,10 @@ func CleanUpMigrateInfo(repo *models.Repository) (*models.Repository, error) { | ||||||
| // SyncReleasesWithTags synchronizes release table with repository tags
 | // SyncReleasesWithTags synchronizes release table with repository tags
 | ||||||
| func SyncReleasesWithTags(repo *models.Repository, gitRepo *git.Repository) error { | func SyncReleasesWithTags(repo *models.Repository, gitRepo *git.Repository) error { | ||||||
| 	existingRelTags := make(map[string]struct{}) | 	existingRelTags := make(map[string]struct{}) | ||||||
| 	opts := models.FindReleasesOptions{IncludeDrafts: true, IncludeTags: true} | 	opts := models.FindReleasesOptions{IncludeDrafts: true, IncludeTags: true, ListOptions: models.ListOptions{PageSize: 50}} | ||||||
| 	for page := 1; ; page++ { | 	for page := 1; ; page++ { | ||||||
| 		rels, err := models.GetReleasesByRepoID(repo.ID, opts, page, 100) | 		opts.Page = page | ||||||
|  | 		rels, err := models.GetReleasesByRepoID(repo.ID, opts) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return fmt.Errorf("GetReleasesByRepoID: %v", err) | 			return fmt.Errorf("GetReleasesByRepoID: %v", err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -24,8 +25,10 @@ func Organizations(ctx *context.Context) { | ||||||
| 	ctx.Data["PageIsAdminOrganizations"] = true | 	ctx.Data["PageIsAdminOrganizations"] = true | ||||||
| 
 | 
 | ||||||
| 	routers.RenderUserSearch(ctx, &models.SearchUserOptions{ | 	routers.RenderUserSearch(ctx, &models.SearchUserOptions{ | ||||||
| 		Type:     models.UserTypeOrganization, | 		Type: models.UserTypeOrganization, | ||||||
| 		PageSize: setting.UI.Admin.OrgPagingNum, | 		ListOptions: models.ListOptions{ | ||||||
| 		Visible:  []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, | 			PageSize: setting.UI.Admin.OrgPagingNum, | ||||||
|  | 		}, | ||||||
|  | 		Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, | ||||||
| 	}, tplOrgs) | 	}, tplOrgs) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -33,8 +34,10 @@ func Users(ctx *context.Context) { | ||||||
| 	ctx.Data["PageIsAdminUsers"] = true | 	ctx.Data["PageIsAdminUsers"] = true | ||||||
| 
 | 
 | ||||||
| 	routers.RenderUserSearch(ctx, &models.SearchUserOptions{ | 	routers.RenderUserSearch(ctx, &models.SearchUserOptions{ | ||||||
| 		Type:          models.UserTypeIndividual, | 		Type: models.UserTypeIndividual, | ||||||
| 		PageSize:      setting.UI.Admin.UserPagingNum, | 		ListOptions: models.ListOptions{ | ||||||
|  | 			PageSize: setting.UI.Admin.UserPagingNum, | ||||||
|  | 		}, | ||||||
| 		SearchByEmail: true, | 		SearchByEmail: true, | ||||||
| 	}, tplUsers) | 	}, tplUsers) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/routers/api/v1/user" | 	"code.gitea.io/gitea/routers/api/v1/user" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // CreateOrg api for create organization
 | // CreateOrg api for create organization
 | ||||||
|  | @ -100,11 +101,10 @@ func GetAllOrgs(ctx *context.APIContext) { | ||||||
| 	//     "$ref": "#/responses/forbidden"
 | 	//     "$ref": "#/responses/forbidden"
 | ||||||
| 
 | 
 | ||||||
| 	users, _, err := models.SearchUsers(&models.SearchUserOptions{ | 	users, _, err := models.SearchUsers(&models.SearchUserOptions{ | ||||||
| 		Type:     models.UserTypeOrganization, | 		Type:        models.UserTypeOrganization, | ||||||
| 		OrderBy:  models.SearchOrderByAlphabetically, | 		OrderBy:     models.SearchOrderByAlphabetically, | ||||||
| 		Page:     ctx.QueryInt("page"), | 		ListOptions: utils.GetListOptions(ctx), | ||||||
| 		PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), | 		Visible:     []api.VisibleType{api.VisibleTypePublic, api.VisibleTypeLimited, api.VisibleTypePrivate}, | ||||||
| 		Visible:  []api.VisibleType{api.VisibleTypePublic, api.VisibleTypeLimited, api.VisibleTypePrivate}, |  | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err) | 		ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err) | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/password" | 	"code.gitea.io/gitea/modules/password" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/routers/api/v1/user" | 	"code.gitea.io/gitea/routers/api/v1/user" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| 	"code.gitea.io/gitea/services/mailer" | 	"code.gitea.io/gitea/services/mailer" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -328,6 +329,15 @@ func GetAllUsers(ctx *context.APIContext) { | ||||||
| 	// summary: List all users
 | 	// summary: List all users
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
|  | @ -335,9 +345,9 @@ func GetAllUsers(ctx *context.APIContext) { | ||||||
| 	//     "$ref": "#/responses/forbidden"
 | 	//     "$ref": "#/responses/forbidden"
 | ||||||
| 
 | 
 | ||||||
| 	users, _, err := models.SearchUsers(&models.SearchUserOptions{ | 	users, _, err := models.SearchUsers(&models.SearchUserOptions{ | ||||||
| 		Type:     models.UserTypeIndividual, | 		Type:        models.UserTypeIndividual, | ||||||
| 		OrderBy:  models.SearchOrderByAlphabetically, | 		OrderBy:     models.SearchOrderByAlphabetically, | ||||||
| 		PageSize: -1, | 		ListOptions: utils.GetListOptions(ctx), | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetAllUsers", err) | 		ctx.Error(http.StatusInternalServerError, "GetAllUsers", err) | ||||||
|  |  | ||||||
|  | @ -51,6 +51,14 @@ func ListRepoNotifications(ctx *context.APIContext) { | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   format: date-time
 | 	//   format: date-time
 | ||||||
| 	//   required: false
 | 	//   required: false
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/NotificationThreadList"
 | 	//     "$ref": "#/responses/NotificationThreadList"
 | ||||||
|  | @ -61,6 +69,7 @@ func ListRepoNotifications(ctx *context.APIContext) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	opts := models.FindNotificationOptions{ | 	opts := models.FindNotificationOptions{ | ||||||
|  | 		ListOptions:       utils.GetListOptions(ctx), | ||||||
| 		UserID:            ctx.User.ID, | 		UserID:            ctx.User.ID, | ||||||
| 		RepoID:            ctx.Repo.Repository.ID, | 		RepoID:            ctx.Repo.Repository.ID, | ||||||
| 		UpdatedBeforeUnix: before, | 		UpdatedBeforeUnix: before, | ||||||
|  |  | ||||||
|  | @ -41,6 +41,14 @@ func ListNotifications(ctx *context.APIContext) { | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   format: date-time
 | 	//   format: date-time
 | ||||||
| 	//   required: false
 | 	//   required: false
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/NotificationThreadList"
 | 	//     "$ref": "#/responses/NotificationThreadList"
 | ||||||
|  | @ -51,6 +59,7 @@ func ListNotifications(ctx *context.APIContext) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	opts := models.FindNotificationOptions{ | 	opts := models.FindNotificationOptions{ | ||||||
|  | 		ListOptions:       utils.GetListOptions(ctx), | ||||||
| 		UserID:            ctx.User.ID, | 		UserID:            ctx.User.ID, | ||||||
| 		UpdatedBeforeUnix: before, | 		UpdatedBeforeUnix: before, | ||||||
| 		UpdatedAfterUnix:  since, | 		UpdatedAfterUnix:  since, | ||||||
|  |  | ||||||
|  | @ -27,12 +27,20 @@ func ListHooks(ctx *context.APIContext) { | ||||||
| 	//   description: name of the organization
 | 	//   description: name of the organization
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/HookList"
 | 	//     "$ref": "#/responses/HookList"
 | ||||||
| 
 | 
 | ||||||
| 	org := ctx.Org.Organization | 	org := ctx.Org.Organization | ||||||
| 	orgHooks, err := models.GetWebhooksByOrgID(org.ID) | 	orgHooks, err := models.GetWebhooksByOrgID(org.ID, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetWebhooksByOrgID", err) | 		ctx.Error(http.StatusInternalServerError, "GetWebhooksByOrgID", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -14,14 +14,16 @@ 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/routers/api/v1/user" | 	"code.gitea.io/gitea/routers/api/v1/user" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // 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 | 	var members []*models.User | ||||||
| 	members, _, err := models.FindOrgMembers(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), | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetUsersByIDs", err) | 		ctx.Error(http.StatusInternalServerError, "GetUsersByIDs", err) | ||||||
|  | @ -48,6 +50,14 @@ func ListMembers(ctx *context.APIContext) { | ||||||
| 	//   description: name of the organization
 | 	//   description: name of the organization
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
|  | @ -75,6 +85,14 @@ func ListPublicMembers(ctx *context.APIContext) { | ||||||
| 	//   description: name of the organization
 | 	//   description: name of the organization
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
|  |  | ||||||
|  | @ -13,10 +13,14 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/routers/api/v1/user" | 	"code.gitea.io/gitea/routers/api/v1/user" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func listUserOrgs(ctx *context.APIContext, u *models.User, all bool) { | func listUserOrgs(ctx *context.APIContext, u *models.User, all bool) { | ||||||
| 	if err := u.GetOrganizations(all); err != nil { | 	if err := u.GetOrganizations(&models.SearchOrganizationsOptions{ | ||||||
|  | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 		All:         all, | ||||||
|  | 	}); err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetOrganizations", err) | 		ctx.Error(http.StatusInternalServerError, "GetOrganizations", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -35,6 +39,15 @@ func ListMyOrgs(ctx *context.APIContext) { | ||||||
| 	// summary: List the current user's organizations
 | 	// summary: List the current user's organizations
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/OrganizationList"
 | 	//     "$ref": "#/responses/OrganizationList"
 | ||||||
|  | @ -55,6 +68,14 @@ func ListUserOrgs(ctx *context.APIContext) { | ||||||
| 	//   description: username of user
 | 	//   description: username of user
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/OrganizationList"
 | 	//     "$ref": "#/responses/OrganizationList"
 | ||||||
|  | @ -95,11 +116,10 @@ func GetAll(ctx *context.APIContext) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	publicOrgs, _, err := models.SearchUsers(&models.SearchUserOptions{ | 	publicOrgs, _, err := models.SearchUsers(&models.SearchUserOptions{ | ||||||
| 		Type:     models.UserTypeOrganization, | 		ListOptions: utils.GetListOptions(ctx), | ||||||
| 		OrderBy:  models.SearchOrderByAlphabetically, | 		Type:        models.UserTypeOrganization, | ||||||
| 		Page:     ctx.QueryInt("page"), | 		OrderBy:     models.SearchOrderByAlphabetically, | ||||||
| 		PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), | 		Visible:     vMode, | ||||||
| 		Visible:  vMode, |  | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err) | 		ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err) | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/routers/api/v1/user" | 	"code.gitea.io/gitea/routers/api/v1/user" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListTeams list all the teams of an organization
 | // ListTeams list all the teams of an organization
 | ||||||
|  | @ -30,12 +31,22 @@ func ListTeams(ctx *context.APIContext) { | ||||||
| 	//   description: name of the organization
 | 	//   description: name of the organization
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/TeamList"
 | 	//     "$ref": "#/responses/TeamList"
 | ||||||
| 
 | 
 | ||||||
| 	org := ctx.Org.Organization | 	org := ctx.Org.Organization | ||||||
| 	if err := org.GetTeams(); err != nil { | 	if err := org.GetTeams(&models.SearchTeamOptions{ | ||||||
|  | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 	}); err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetTeams", err) | 		ctx.Error(http.StatusInternalServerError, "GetTeams", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -59,11 +70,20 @@ func ListUserTeams(ctx *context.APIContext) { | ||||||
| 	// summary: List all the teams a user belongs to
 | 	// summary: List all the teams a user belongs to
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/TeamList"
 | 	//     "$ref": "#/responses/TeamList"
 | ||||||
| 
 | 
 | ||||||
| 	teams, err := models.GetUserTeams(ctx.User.ID) | 	teams, err := models.GetUserTeams(ctx.User.ID, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetUserTeams", err) | 		ctx.Error(http.StatusInternalServerError, "GetUserTeams", err) | ||||||
| 		return | 		return | ||||||
|  | @ -284,6 +304,14 @@ func GetTeamMembers(ctx *context.APIContext) { | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
| 	//   format: int64
 | 	//   format: int64
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
|  | @ -297,7 +325,9 @@ func GetTeamMembers(ctx *context.APIContext) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	team := ctx.Org.Team | 	team := ctx.Org.Team | ||||||
| 	if err := team.GetMembers(); err != nil { | 	if err := team.GetMembers(&models.SearchMembersOptions{ | ||||||
|  | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 	}); err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err) | 		ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -436,12 +466,22 @@ func GetTeamRepos(ctx *context.APIContext) { | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
| 	//   format: int64
 | 	//   format: int64
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
| 
 | 
 | ||||||
| 	team := ctx.Org.Team | 	team := ctx.Org.Team | ||||||
| 	if err := team.GetRepositories(); err != nil { | 	if err := team.GetRepositories(&models.SearchTeamOptions{ | ||||||
|  | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 	}); err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) | 		ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) | ||||||
| 	} | 	} | ||||||
| 	repos := make([]*api.Repository, len(team.Repos)) | 	repos := make([]*api.Repository, len(team.Repos)) | ||||||
|  | @ -589,14 +629,14 @@ func SearchTeam(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: include search within team description (defaults to true)
 | 	//   description: include search within team description (defaults to true)
 | ||||||
| 	//   type: boolean
 | 	//   type: boolean
 | ||||||
| 	// - name: limit
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: limit size of results
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	// - name: page
 | 	// - name: page
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: page number of results to return (1-based)
 | 	//   description: page number of results to return (1-based)
 | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     description: "SearchResults of a successful search"
 | 	//     description: "SearchResults of a successful search"
 | ||||||
|  | @ -615,8 +655,7 @@ func SearchTeam(ctx *context.APIContext) { | ||||||
| 		Keyword:     strings.TrimSpace(ctx.Query("q")), | 		Keyword:     strings.TrimSpace(ctx.Query("q")), | ||||||
| 		OrgID:       ctx.Org.Organization.ID, | 		OrgID:       ctx.Org.Organization.ID, | ||||||
| 		IncludeDesc: (ctx.Query("include_desc") == "" || ctx.QueryBool("include_desc")), | 		IncludeDesc: (ctx.Query("include_desc") == "" || ctx.QueryBool("include_desc")), | ||||||
| 		PageSize:    ctx.QueryInt("limit"), | 		ListOptions: utils.GetListOptions(ctx), | ||||||
| 		Page:        ctx.QueryInt("page"), |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	teams, _, err := models.SearchTeam(opts) | 	teams, _, err := models.SearchTeam(opts) | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListCollaborators list a repository's collaborators
 | // ListCollaborators list a repository's collaborators
 | ||||||
|  | @ -33,11 +34,19 @@ func ListCollaborators(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
| 
 | 
 | ||||||
| 	collaborators, err := ctx.Repo.Repository.GetCollaborators() | 	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 | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"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/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // GetSingleCommit get a commit via
 | // GetSingleCommit get a commit via
 | ||||||
|  | @ -92,7 +93,11 @@ func GetAllCommits(ctx *context.APIContext) { | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	// - name: page
 | 	// - name: page
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: page number of requested commits
 | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
|  | @ -117,9 +122,13 @@ func GetAllCommits(ctx *context.APIContext) { | ||||||
| 	} | 	} | ||||||
| 	defer gitRepo.Close() | 	defer gitRepo.Close() | ||||||
| 
 | 
 | ||||||
| 	page := ctx.QueryInt("page") | 	listOptions := utils.GetListOptions(ctx) | ||||||
| 	if page <= 0 { | 	if listOptions.Page <= 0 { | ||||||
| 		page = 1 | 		listOptions.Page = 1 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if listOptions.PageSize > git.CommitsRangeSize { | ||||||
|  | 		listOptions.PageSize = git.CommitsRangeSize | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sha := ctx.Query("sha") | 	sha := ctx.Query("sha") | ||||||
|  | @ -154,10 +163,10 @@ func GetAllCommits(ctx *context.APIContext) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	pageCount := int(math.Ceil(float64(commitsCountTotal) / float64(git.CommitsRangeSize))) | 	pageCount := int(math.Ceil(float64(commitsCountTotal) / float64(listOptions.PageSize))) | ||||||
| 
 | 
 | ||||||
| 	// Query commits
 | 	// Query commits
 | ||||||
| 	commits, err := baseCommit.CommitsByRange(page) | 	commits, err := baseCommit.CommitsByRange(listOptions.Page, listOptions.PageSize) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("CommitsByRange", err) | 		ctx.ServerError("CommitsByRange", err) | ||||||
| 		return | 		return | ||||||
|  | @ -181,13 +190,13 @@ func GetAllCommits(ctx *context.APIContext) { | ||||||
| 		i++ | 		i++ | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ctx.SetLinkHeader(int(commitsCountTotal), git.CommitsRangeSize) | 	ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize) | ||||||
| 
 | 
 | ||||||
| 	ctx.Header().Set("X-Page", strconv.Itoa(page)) | 	ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page)) | ||||||
| 	ctx.Header().Set("X-PerPage", strconv.Itoa(git.CommitsRangeSize)) | 	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(page < pageCount)) | 	ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < pageCount)) | ||||||
| 
 | 
 | ||||||
| 	ctx.JSON(http.StatusOK, &apiCommits) | 	ctx.JSON(http.StatusOK, &apiCommits) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2016 The Gogs Authors. All rights reserved.
 | // Copyright 2016 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -11,6 +12,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| 	repo_service "code.gitea.io/gitea/services/repository" | 	repo_service "code.gitea.io/gitea/services/repository" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -32,11 +34,19 @@ func ListForks(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
| 
 | 
 | ||||||
| 	forks, err := ctx.Repo.Repository.GetForks() | 	forks, err := ctx.Repo.Repository.GetForks(utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetForks", err) | 		ctx.Error(http.StatusInternalServerError, "GetForks", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -34,11 +35,19 @@ func ListHooks(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/HookList"
 | 	//     "$ref": "#/responses/HookList"
 | ||||||
| 
 | 
 | ||||||
| 	hooks, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID) | 	hooks, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetWebhooksByRepoID", err) | 		ctx.Error(http.StatusInternalServerError, "GetWebhooksByRepoID", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ import ( | ||||||
| 	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" | 	"code.gitea.io/gitea/modules/util" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| 	issue_service "code.gitea.io/gitea/services/issue" | 	issue_service "code.gitea.io/gitea/services/issue" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -38,10 +39,6 @@ func SearchIssues(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
 | 	//   description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	// - name: page
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: page number of requested issues
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	// - name: q
 | 	// - name: q
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: search string
 | 	//   description: search string
 | ||||||
|  | @ -55,6 +52,10 @@ func SearchIssues(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: filter by type (issues / pulls) if set
 | 	//   description: filter by type (issues / pulls) if set
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of requested issues
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/IssueList"
 | 	//     "$ref": "#/responses/IssueList"
 | ||||||
|  | @ -72,7 +73,9 @@ func SearchIssues(ctx *context.APIContext) { | ||||||
| 	// find repos user can access (for issue search)
 | 	// find repos user can access (for issue search)
 | ||||||
| 	repoIDs := make([]int64, 0) | 	repoIDs := make([]int64, 0) | ||||||
| 	opts := &models.SearchRepoOptions{ | 	opts := &models.SearchRepoOptions{ | ||||||
| 		PageSize:    15, | 		ListOptions: models.ListOptions{ | ||||||
|  | 			PageSize: 15, | ||||||
|  | 		}, | ||||||
| 		Private:     false, | 		Private:     false, | ||||||
| 		AllPublic:   true, | 		AllPublic:   true, | ||||||
| 		TopicOnly:   false, | 		TopicOnly:   false, | ||||||
|  | @ -146,9 +149,11 @@ func SearchIssues(ctx *context.APIContext) { | ||||||
| 	// This would otherwise return all issues if no issues were found by the search.
 | 	// This would otherwise return all issues if no issues were found by the search.
 | ||||||
| 	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 { | 	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 { | ||||||
| 		issues, err = models.Issues(&models.IssuesOptions{ | 		issues, err = models.Issues(&models.IssuesOptions{ | ||||||
|  | 			ListOptions: models.ListOptions{ | ||||||
|  | 				Page:     ctx.QueryInt("page"), | ||||||
|  | 				PageSize: setting.UI.IssuePagingNum, | ||||||
|  | 			}, | ||||||
| 			RepoIDs:        repoIDs, | 			RepoIDs:        repoIDs, | ||||||
| 			Page:           ctx.QueryInt("page"), |  | ||||||
| 			PageSize:       setting.UI.IssuePagingNum, |  | ||||||
| 			IsClosed:       isClosed, | 			IsClosed:       isClosed, | ||||||
| 			IssueIDs:       issueIDs, | 			IssueIDs:       issueIDs, | ||||||
| 			LabelIDs:       labelIDs, | 			LabelIDs:       labelIDs, | ||||||
|  | @ -198,10 +203,6 @@ func ListIssues(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
 | 	//   description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	// - name: page
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: page number of requested issues
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	// - name: q
 | 	// - name: q
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: search string
 | 	//   description: search string
 | ||||||
|  | @ -210,6 +211,14 @@ func ListIssues(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: filter by type (issues / pulls) if set
 | 	//   description: filter by type (issues / pulls) if set
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/IssueList"
 | 	//     "$ref": "#/responses/IssueList"
 | ||||||
|  | @ -245,6 +254,11 @@ func ListIssues(ctx *context.APIContext) { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	listOptions := utils.GetListOptions(ctx) | ||||||
|  | 	if ctx.QueryInt("limit") == 0 { | ||||||
|  | 		listOptions.PageSize = setting.UI.IssuePagingNum | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	var isPull util.OptionalBool | 	var isPull util.OptionalBool | ||||||
| 	switch ctx.Query("type") { | 	switch ctx.Query("type") { | ||||||
| 	case "pulls": | 	case "pulls": | ||||||
|  | @ -259,13 +273,12 @@ func ListIssues(ctx *context.APIContext) { | ||||||
| 	// This would otherwise return all issues if no issues were found by the search.
 | 	// This would otherwise return all issues if no issues were found by the search.
 | ||||||
| 	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 { | 	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 { | ||||||
| 		issues, err = models.Issues(&models.IssuesOptions{ | 		issues, err = models.Issues(&models.IssuesOptions{ | ||||||
| 			RepoIDs:  []int64{ctx.Repo.Repository.ID}, | 			ListOptions: listOptions, | ||||||
| 			Page:     ctx.QueryInt("page"), | 			RepoIDs:     []int64{ctx.Repo.Repository.ID}, | ||||||
| 			PageSize: setting.UI.IssuePagingNum, | 			IsClosed:    isClosed, | ||||||
| 			IsClosed: isClosed, | 			IssueIDs:    issueIDs, | ||||||
| 			IssueIDs: issueIDs, | 			LabelIDs:    labelIDs, | ||||||
| 			LabelIDs: labelIDs, | 			IsPull:      isPull, | ||||||
| 			IsPull:   isPull, |  | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -279,7 +292,7 @@ func ListIssues(ctx *context.APIContext) { | ||||||
| 		apiIssues[i] = issues[i].APIFormat() | 		apiIssues[i] = issues[i].APIFormat() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ctx.SetLinkHeader(ctx.Repo.Repository.NumIssues, setting.UI.IssuePagingNum) | 	ctx.SetLinkHeader(ctx.Repo.Repository.NumIssues, listOptions.PageSize) | ||||||
| 	ctx.JSON(http.StatusOK, &apiIssues) | 	ctx.JSON(http.StatusOK, &apiIssues) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2015 The Gogs Authors. All rights reserved.
 | // Copyright 2015 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -117,6 +118,14 @@ func ListRepoIssueComments(ctx *context.APIContext) { | ||||||
| 	//   description: if provided, only comments updated before the provided time are returned.
 | 	//   description: if provided, only comments updated before the provided time are returned.
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   format: date-time
 | 	//   format: date-time
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/CommentList"
 | 	//     "$ref": "#/responses/CommentList"
 | ||||||
|  | @ -128,10 +137,11 @@ func ListRepoIssueComments(ctx *context.APIContext) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	comments, err := models.FindComments(models.FindCommentsOptions{ | 	comments, err := models.FindComments(models.FindCommentsOptions{ | ||||||
| 		RepoID: ctx.Repo.Repository.ID, | 		ListOptions: utils.GetListOptions(ctx), | ||||||
| 		Since:  since, | 		RepoID:      ctx.Repo.Repository.ID, | ||||||
| 		Before: before, | 		Type:        models.CommentTypeComment, | ||||||
| 		Type:   models.CommentTypeComment, | 		Since:       since, | ||||||
|  | 		Before:      before, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "FindComments", err) | 		ctx.Error(http.StatusInternalServerError, "FindComments", err) | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // GetIssueCommentReactions list reactions of a comment from an issue
 | // GetIssueCommentReactions list reactions of a comment from an issue
 | ||||||
|  | @ -245,6 +246,14 @@ func GetIssueReactions(ctx *context.APIContext) { | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
| 	//   format: int64
 | 	//   format: int64
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/ReactionList"
 | 	//     "$ref": "#/responses/ReactionList"
 | ||||||
|  | @ -266,7 +275,7 @@ func GetIssueReactions(ctx *context.APIContext) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	reactions, err := models.FindIssueReactions(issue) | 	reactions, err := models.FindIssueReactions(issue, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err) | 		ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // StartIssueStopwatch creates a stopwatch for the given issue.
 | // StartIssueStopwatch creates a stopwatch for the given issue.
 | ||||||
|  | @ -197,6 +198,15 @@ func GetStopwatches(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /user/stopwatches user userGetStopWatches
 | 	// swagger:operation GET /user/stopwatches user userGetStopWatches
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: Get list of all existing stopwatches
 | 	// summary: Get list of all existing stopwatches
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// consumes:
 | 	// consumes:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
|  | @ -205,7 +215,7 @@ func GetStopwatches(ctx *context.APIContext) { | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/StopWatchList"
 | 	//     "$ref": "#/responses/StopWatchList"
 | ||||||
| 
 | 
 | ||||||
| 	sws, err := models.GetUserStopwatches(ctx.User.ID) | 	sws, err := models.GetUserStopwatches(ctx.User.ID, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetUserStopwatches", err) | 		ctx.Error(http.StatusInternalServerError, "GetUserStopwatches", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // AddIssueSubscription Subscribe user to issue
 | // AddIssueSubscription Subscribe user to issue
 | ||||||
|  | @ -158,6 +159,14 @@ func GetIssueSubscribers(ctx *context.APIContext) { | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
| 	//   format: int64
 | 	//   format: int64
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
|  | @ -175,7 +184,7 @@ func GetIssueSubscribers(ctx *context.APIContext) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	iwl, err := models.GetIssueWatchers(issue.ID) | 	iwl, err := models.GetIssueWatchers(issue.ID, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetIssueWatchers", err) | 		ctx.Error(http.StatusInternalServerError, "GetIssueWatchers", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -51,6 +51,14 @@ func ListTrackedTimes(ctx *context.APIContext) { | ||||||
| 	//   description: Only show times updated before the given time. This is a timestamp in RFC 3339 format
 | 	//   description: Only show times updated before the given time. This is a timestamp in RFC 3339 format
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   format: date-time
 | 	//   format: date-time
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/TrackedTimeList"
 | 	//     "$ref": "#/responses/TrackedTimeList"
 | ||||||
|  | @ -72,6 +80,7 @@ func ListTrackedTimes(ctx *context.APIContext) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	opts := models.FindTrackedTimesOptions{ | 	opts := models.FindTrackedTimesOptions{ | ||||||
|  | 		ListOptions:  utils.GetListOptions(ctx), | ||||||
| 		RepositoryID: ctx.Repo.Repository.ID, | 		RepositoryID: ctx.Repo.Repository.ID, | ||||||
| 		IssueID:      issue.ID, | 		IssueID:      issue.ID, | ||||||
| 	} | 	} | ||||||
|  | @ -435,6 +444,14 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { | ||||||
| 	//   description: Only show times updated before the given time. This is a timestamp in RFC 3339 format
 | 	//   description: Only show times updated before the given time. This is a timestamp in RFC 3339 format
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   format: date-time
 | 	//   format: date-time
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/TrackedTimeList"
 | 	//     "$ref": "#/responses/TrackedTimeList"
 | ||||||
|  | @ -449,6 +466,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	opts := models.FindTrackedTimesOptions{ | 	opts := models.FindTrackedTimesOptions{ | ||||||
|  | 		ListOptions:  utils.GetListOptions(ctx), | ||||||
| 		RepositoryID: ctx.Repo.Repository.ID, | 		RepositoryID: ctx.Repo.Repository.ID, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -495,6 +513,15 @@ func ListMyTrackedTimes(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /user/times user userCurrentTrackedTimes
 | 	// swagger:operation GET /user/times user userCurrentTrackedTimes
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: List the current user's tracked times
 | 	// summary: List the current user's tracked times
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// parameters:
 | 	// parameters:
 | ||||||
|  | @ -512,7 +539,10 @@ func ListMyTrackedTimes(ctx *context.APIContext) { | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/TrackedTimeList"
 | 	//     "$ref": "#/responses/TrackedTimeList"
 | ||||||
| 
 | 
 | ||||||
| 	opts := models.FindTrackedTimesOptions{UserID: ctx.User.ID} | 	opts := models.FindTrackedTimesOptions{ | ||||||
|  | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 		UserID:      ctx.User.ID, | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	var err error | 	var err error | ||||||
| 	if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil { | 	if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil { | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2015 The Gogs Authors. All rights reserved.
 | // Copyright 2015 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -13,6 +14,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	"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/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // appendPrivateInformation appends the owner and key type information to api.PublicKey
 | // appendPrivateInformation appends the owner and key type information to api.PublicKey
 | ||||||
|  | @ -60,6 +62,14 @@ func ListDeployKeys(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: fingerprint of the key
 | 	//   description: fingerprint of the key
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/DeployKeyList"
 | 	//     "$ref": "#/responses/DeployKeyList"
 | ||||||
|  | @ -72,7 +82,7 @@ func ListDeployKeys(ctx *context.APIContext) { | ||||||
| 	if fingerprint != "" || keyID != 0 { | 	if fingerprint != "" || keyID != 0 { | ||||||
| 		keys, err = models.SearchDeployKeys(ctx.Repo.Repository.ID, keyID, fingerprint) | 		keys, err = models.SearchDeployKeys(ctx.Repo.Repository.ID, keyID, fingerprint) | ||||||
| 	} else { | 	} else { | ||||||
| 		keys, err = models.ListDeployKeys(ctx.Repo.Repository.ID) | 		keys, err = models.ListDeployKeys(ctx.Repo.Repository.ID, utils.GetListOptions(ctx)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListLabels list all the labels of a repository
 | // ListLabels list all the labels of a repository
 | ||||||
|  | @ -32,11 +33,19 @@ func ListLabels(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/LabelList"
 | 	//     "$ref": "#/responses/LabelList"
 | ||||||
| 
 | 
 | ||||||
| 	labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort")) | 	labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID, ctx.Query("sort"), utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetLabelsByRepoID", err) | 		ctx.Error(http.StatusInternalServerError, "GetLabelsByRepoID", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2016 The Gogs Authors. All rights reserved.
 | // Copyright 2016 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -12,6 +13,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	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/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListMilestones list milestones for a repository
 | // ListMilestones list milestones for a repository
 | ||||||
|  | @ -36,11 +38,19 @@ func ListMilestones(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: Milestone state, Recognised values are open, closed and all. Defaults to "open"
 | 	//   description: Milestone state, Recognised values are open, closed and all. Defaults to "open"
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/MilestoneList"
 | 	//     "$ref": "#/responses/MilestoneList"
 | ||||||
| 
 | 
 | ||||||
| 	milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state"))) | 	milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state")), utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetMilestonesByRepoID", err) | 		ctx.Error(http.StatusInternalServerError, "GetMilestonesByRepoID", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/notification" | 	"code.gitea.io/gitea/modules/notification" | ||||||
| 	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/routers/api/v1/utils" | ||||||
| 	issue_service "code.gitea.io/gitea/services/issue" | 	issue_service "code.gitea.io/gitea/services/issue" | ||||||
| 	pull_service "code.gitea.io/gitea/services/pull" | 	pull_service "code.gitea.io/gitea/services/pull" | ||||||
| ) | ) | ||||||
|  | @ -41,10 +42,6 @@ func ListPullRequests(ctx *context.APIContext, form api.ListPullRequestsOptions) | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
| 	// - name: page
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: Page number
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	// - name: state
 | 	// - name: state
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: "State of pull request: open or closed (optional)"
 | 	//   description: "State of pull request: open or closed (optional)"
 | ||||||
|  | @ -68,12 +65,22 @@ func ListPullRequests(ctx *context.APIContext, form api.ListPullRequestsOptions) | ||||||
| 	//   items:
 | 	//   items:
 | ||||||
| 	//     type: integer
 | 	//     type: integer
 | ||||||
| 	//     format: int64
 | 	//     format: int64
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/PullRequestList"
 | 	//     "$ref": "#/responses/PullRequestList"
 | ||||||
| 
 | 
 | ||||||
|  | 	listOptions := utils.GetListOptions(ctx) | ||||||
|  | 
 | ||||||
| 	prs, maxResults, err := models.PullRequests(ctx.Repo.Repository.ID, &models.PullRequestsOptions{ | 	prs, maxResults, err := models.PullRequests(ctx.Repo.Repository.ID, &models.PullRequestsOptions{ | ||||||
| 		Page:        ctx.QueryInt("page"), | 		ListOptions: listOptions, | ||||||
| 		State:       ctx.QueryTrim("state"), | 		State:       ctx.QueryTrim("state"), | ||||||
| 		SortType:    ctx.QueryTrim("sort"), | 		SortType:    ctx.QueryTrim("sort"), | ||||||
| 		Labels:      ctx.QueryStrings("labels"), | 		Labels:      ctx.QueryStrings("labels"), | ||||||
|  | @ -106,7 +113,7 @@ func ListPullRequests(ctx *context.APIContext, form api.ListPullRequestsOptions) | ||||||
| 		apiPrs[i] = convert.ToAPIPullRequest(prs[i]) | 		apiPrs[i] = convert.ToAPIPullRequest(prs[i]) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ctx.SetLinkHeader(int(maxResults), models.ItemsPerPage) | 	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) | ||||||
| 	ctx.JSON(http.StatusOK, &apiPrs) | 	ctx.JSON(http.StatusOK, &apiPrs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/setting" |  | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| 	releaseservice "code.gitea.io/gitea/services/release" | 	releaseservice "code.gitea.io/gitea/services/release" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -59,20 +59,6 @@ func GetRelease(ctx *context.APIContext) { | ||||||
| 	ctx.JSON(http.StatusOK, release.APIFormat()) | 	ctx.JSON(http.StatusOK, release.APIFormat()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getPagesInfo(ctx *context.APIContext) (int, int) { |  | ||||||
| 	page := ctx.QueryInt("page") |  | ||||||
| 	if page == 0 { |  | ||||||
| 		page = 1 |  | ||||||
| 	} |  | ||||||
| 	perPage := ctx.QueryInt("per_page") |  | ||||||
| 	if perPage == 0 { |  | ||||||
| 		perPage = setting.API.DefaultPagingNum |  | ||||||
| 	} else if perPage > setting.API.MaxResponseItems { |  | ||||||
| 		perPage = setting.API.MaxResponseItems |  | ||||||
| 	} |  | ||||||
| 	return page, perPage |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ListReleases list a repository's releases
 | // ListReleases list a repository's releases
 | ||||||
| func ListReleases(ctx *context.APIContext) { | func ListReleases(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /repos/{owner}/{repo}/releases repository repoListReleases
 | 	// swagger:operation GET /repos/{owner}/{repo}/releases repository repoListReleases
 | ||||||
|  | @ -91,23 +77,32 @@ func ListReleases(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
| 	// - name: page
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: page wants to load
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	// - name: per_page
 | 	// - name: per_page
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: items count every page wants to load
 | 	//   description: items count every page wants to load
 | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
|  | 	//   deprecated: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/ReleaseList"
 | 	//     "$ref": "#/responses/ReleaseList"
 | ||||||
|  | 	listOptions := utils.GetListOptions(ctx) | ||||||
|  | 	if ctx.QueryInt("per_page") != 0 { | ||||||
|  | 		listOptions.PageSize = ctx.QueryInt("per_page") | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	page, limit := getPagesInfo(ctx) |  | ||||||
| 	releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ | 	releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ | ||||||
|  | 		ListOptions:   listOptions, | ||||||
| 		IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite, | 		IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite, | ||||||
| 		IncludeTags:   false, | 		IncludeTags:   false, | ||||||
| 	}, page, limit) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) | 		ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -16,7 +16,6 @@ import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/auth" | 	"code.gitea.io/gitea/modules/auth" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/convert" |  | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"code.gitea.io/gitea/modules/graceful" | 	"code.gitea.io/gitea/modules/graceful" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
|  | @ -27,6 +26,7 @@ import ( | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/modules/util" | 	"code.gitea.io/gitea/modules/util" | ||||||
| 	"code.gitea.io/gitea/modules/validation" | 	"code.gitea.io/gitea/modules/validation" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| 	mirror_service "code.gitea.io/gitea/services/mirror" | 	mirror_service "code.gitea.io/gitea/services/mirror" | ||||||
| 	repo_service "code.gitea.io/gitea/services/repository" | 	repo_service "code.gitea.io/gitea/services/repository" | ||||||
| ) | ) | ||||||
|  | @ -91,14 +91,6 @@ func Search(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: include template repositories this user has access to (defaults to true)
 | 	//   description: include template repositories this user has access to (defaults to true)
 | ||||||
| 	//   type: boolean
 | 	//   type: boolean
 | ||||||
| 	// - name: page
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: page number of results to return (1-based)
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	// - name: limit
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: page size of results, maximum page size is 50
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	// - name: mode
 | 	// - name: mode
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: type of repository to search for. Supported values are
 | 	//   description: type of repository to search for. Supported values are
 | ||||||
|  | @ -119,6 +111,14 @@ func Search(ctx *context.APIContext) { | ||||||
| 	//   description: sort order, either "asc" (ascending) or "desc" (descending).
 | 	//   description: sort order, either "asc" (ascending) or "desc" (descending).
 | ||||||
| 	//                Default is "asc", ignored if "sort" is not specified.
 | 	//                Default is "asc", ignored if "sort" is not specified.
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/SearchResults"
 | 	//     "$ref": "#/responses/SearchResults"
 | ||||||
|  | @ -126,12 +126,11 @@ func Search(ctx *context.APIContext) { | ||||||
| 	//     "$ref": "#/responses/validationError"
 | 	//     "$ref": "#/responses/validationError"
 | ||||||
| 
 | 
 | ||||||
| 	opts := &models.SearchRepoOptions{ | 	opts := &models.SearchRepoOptions{ | ||||||
|  | 		ListOptions:        utils.GetListOptions(ctx), | ||||||
| 		Actor:              ctx.User, | 		Actor:              ctx.User, | ||||||
| 		Keyword:            strings.Trim(ctx.Query("q"), " "), | 		Keyword:            strings.Trim(ctx.Query("q"), " "), | ||||||
| 		OwnerID:            ctx.QueryInt64("uid"), | 		OwnerID:            ctx.QueryInt64("uid"), | ||||||
| 		PriorityOwnerID:    ctx.QueryInt64("priority_owner_id"), | 		PriorityOwnerID:    ctx.QueryInt64("priority_owner_id"), | ||||||
| 		Page:               ctx.QueryInt("page"), |  | ||||||
| 		PageSize:           convert.ToCorrectPageSize(ctx.QueryInt("limit")), |  | ||||||
| 		TopicOnly:          ctx.QueryBool("topic"), | 		TopicOnly:          ctx.QueryBool("topic"), | ||||||
| 		Collaborate:        util.OptionalBoolNone, | 		Collaborate:        util.OptionalBoolNone, | ||||||
| 		Private:            ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")), | 		Private:            ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")), | ||||||
|  | @ -214,7 +213,7 @@ func Search(ctx *context.APIContext) { | ||||||
| 		results[i] = repo.APIFormat(accessMode) | 		results[i] = repo.APIFormat(accessMode) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ctx.SetLinkHeader(int(count), setting.API.MaxResponseItems) | 	ctx.SetLinkHeader(int(count), opts.PageSize) | ||||||
| 	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", count)) | 	ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", count)) | ||||||
| 	ctx.JSON(http.StatusOK, api.SearchResults{ | 	ctx.JSON(http.StatusOK, api.SearchResults{ | ||||||
| 		OK:   true, | 		OK:   true, | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListStargazers list a repository's stargazers
 | // ListStargazers list a repository's stargazers
 | ||||||
|  | @ -30,11 +31,19 @@ func ListStargazers(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
| 
 | 
 | ||||||
| 	stargazers, err := ctx.Repo.Repository.GetStargazers(-1) | 	stargazers, err := ctx.Repo.Repository.GetStargazers(utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetStargazers", err) | 		ctx.Error(http.StatusInternalServerError, "GetStargazers", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/repofiles" | 	"code.gitea.io/gitea/modules/repofiles" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // NewCommitStatus creates a new CommitStatus
 | // NewCommitStatus creates a new CommitStatus
 | ||||||
|  | @ -89,11 +90,6 @@ func GetCommitStatuses(ctx *context.APIContext) { | ||||||
| 	//   description: sha of the commit
 | 	//   description: sha of the commit
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
| 	// - name: page
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: page number of results
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	//   required: false
 |  | ||||||
| 	// - name: sort
 | 	// - name: sort
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: type of sort
 | 	//   description: type of sort
 | ||||||
|  | @ -106,6 +102,14 @@ func GetCommitStatuses(ctx *context.APIContext) { | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   enum: [pending, success, error, failure, warning]
 | 	//   enum: [pending, success, error, failure, warning]
 | ||||||
| 	//   required: false
 | 	//   required: false
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/StatusList"
 | 	//     "$ref": "#/responses/StatusList"
 | ||||||
|  | @ -138,11 +142,6 @@ func GetCommitStatusesByRef(ctx *context.APIContext) { | ||||||
| 	//   description: name of branch/tag/commit
 | 	//   description: name of branch/tag/commit
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
| 	// - name: page
 |  | ||||||
| 	//   in: query
 |  | ||||||
| 	//   description: page number of results
 |  | ||||||
| 	//   type: integer
 |  | ||||||
| 	//   required: false
 |  | ||||||
| 	// - name: sort
 | 	// - name: sort
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: type of sort
 | 	//   description: type of sort
 | ||||||
|  | @ -155,6 +154,14 @@ func GetCommitStatusesByRef(ctx *context.APIContext) { | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   enum: [pending, success, error, failure, warning]
 | 	//   enum: [pending, success, error, failure, warning]
 | ||||||
| 	//   required: false
 | 	//   required: false
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/StatusList"
 | 	//     "$ref": "#/responses/StatusList"
 | ||||||
|  | @ -202,9 +209,9 @@ func getCommitStatuses(ctx *context.APIContext, sha string) { | ||||||
| 	repo := ctx.Repo.Repository | 	repo := ctx.Repo.Repository | ||||||
| 
 | 
 | ||||||
| 	statuses, _, err := models.GetCommitStatuses(repo, sha, &models.CommitStatusOptions{ | 	statuses, _, err := models.GetCommitStatuses(repo, sha, &models.CommitStatusOptions{ | ||||||
| 		Page:     ctx.QueryInt("page"), | 		ListOptions: utils.GetListOptions(ctx), | ||||||
| 		SortType: ctx.QueryTrim("sort"), | 		SortType:    ctx.QueryTrim("sort"), | ||||||
| 		State:    ctx.QueryTrim("state"), | 		State:       ctx.QueryTrim("state"), | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetCommitStatuses", fmt.Errorf("GetCommitStatuses[%s, %s, %d]: %v", repo.FullName(), sha, ctx.QueryInt("page"), err)) | 		ctx.Error(http.StatusInternalServerError, "GetCommitStatuses", fmt.Errorf("GetCommitStatuses[%s, %s, %d]: %v", repo.FullName(), sha, ctx.QueryInt("page"), err)) | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListSubscribers list a repo's subscribers (i.e. watchers)
 | // ListSubscribers list a repo's subscribers (i.e. watchers)
 | ||||||
|  | @ -30,11 +31,19 @@ func ListSubscribers(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
| 
 | 
 | ||||||
| 	subscribers, err := ctx.Repo.Repository.GetWatchers(0) | 	subscribers, err := ctx.Repo.Repository.GetWatchers(utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetWatchers", err) | 		ctx.Error(http.StatusInternalServerError, "GetWatchers", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListTopics returns list of current topics for repo
 | // ListTopics returns list of current topics for repo
 | ||||||
|  | @ -33,12 +34,21 @@ func ListTopics(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/TopicNames"
 | 	//     "$ref": "#/responses/TopicNames"
 | ||||||
| 
 | 
 | ||||||
| 	topics, err := models.FindTopics(&models.FindTopicOptions{ | 	topics, err := models.FindTopics(&models.FindTopicOptions{ | ||||||
| 		RepoID: ctx.Repo.Repository.ID, | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 		RepoID:      ctx.Repo.Repository.ID, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("ListTopics failed: %v", err) | 		log.Error("ListTopics failed: %v", err) | ||||||
|  | @ -231,7 +241,7 @@ func DeleteTopic(ctx *context.APIContext) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // TopicSearch search for creating topic
 | // TopicSearch search for creating topic
 | ||||||
| func TopicSearch(ctx *context.Context) { | func TopicSearch(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /topics/search repository topicSearch
 | 	// swagger:operation GET /topics/search repository topicSearch
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: search topics via keyword
 | 	// summary: search topics via keyword
 | ||||||
|  | @ -243,6 +253,14 @@ func TopicSearch(ctx *context.Context) { | ||||||
| 	//     description: keywords to search
 | 	//     description: keywords to search
 | ||||||
| 	//     required: true
 | 	//     required: true
 | ||||||
| 	//     type: string
 | 	//     type: string
 | ||||||
|  | 	//   - name: page
 | ||||||
|  | 	//     in: query
 | ||||||
|  | 	//     description: page number of results to return (1-based)
 | ||||||
|  | 	//     type: integer
 | ||||||
|  | 	//   - name: limit
 | ||||||
|  | 	//     in: query
 | ||||||
|  | 	//     description: page size of results, maximum page size is 50
 | ||||||
|  | 	//     type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/TopicListResponse"
 | 	//     "$ref": "#/responses/TopicListResponse"
 | ||||||
|  | @ -256,9 +274,17 @@ func TopicSearch(ctx *context.Context) { | ||||||
| 
 | 
 | ||||||
| 	kw := ctx.Query("q") | 	kw := ctx.Query("q") | ||||||
| 
 | 
 | ||||||
|  | 	listOptions := utils.GetListOptions(ctx) | ||||||
|  | 	if listOptions.Page < 1 { | ||||||
|  | 		listOptions.Page = 1 | ||||||
|  | 	} | ||||||
|  | 	if listOptions.PageSize < 1 { | ||||||
|  | 		listOptions.PageSize = 10 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	topics, err := models.FindTopics(&models.FindTopicOptions{ | 	topics, err := models.FindTopics(&models.FindTopicOptions{ | ||||||
| 		Keyword: kw, | 		Keyword:     kw, | ||||||
| 		Limit:   10, | 		ListOptions: listOptions, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("SearchTopics failed: %v", err) | 		log.Error("SearchTopics failed: %v", err) | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // ListAccessTokens list all the access tokens
 | // ListAccessTokens list all the access tokens
 | ||||||
|  | @ -26,11 +27,19 @@ func ListAccessTokens(ctx *context.APIContext) { | ||||||
| 	//   description: username of user
 | 	//   description: username of user
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/AccessTokenList"
 | 	//     "$ref": "#/responses/AccessTokenList"
 | ||||||
| 
 | 
 | ||||||
| 	tokens, err := models.ListAccessTokens(ctx.User.ID) | 	tokens, err := models.ListAccessTokens(ctx.User.ID, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err) | 		ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2015 The Gogs Authors. All rights reserved.
 | // Copyright 2015 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -11,6 +12,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func responseAPIUsers(ctx *context.APIContext, users []*models.User) { | func responseAPIUsers(ctx *context.APIContext, users []*models.User) { | ||||||
|  | @ -22,7 +24,7 @@ func responseAPIUsers(ctx *context.APIContext, users []*models.User) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func listUserFollowers(ctx *context.APIContext, u *models.User) { | func listUserFollowers(ctx *context.APIContext, u *models.User) { | ||||||
| 	users, err := u.GetFollowers(ctx.QueryInt("page")) | 	users, err := u.GetFollowers(utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err) | 		ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err) | ||||||
| 		return | 		return | ||||||
|  | @ -35,6 +37,15 @@ func ListMyFollowers(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /user/followers user userCurrentListFollowers
 | 	// swagger:operation GET /user/followers user userCurrentListFollowers
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: List the authenticated user's followers
 | 	// summary: List the authenticated user's followers
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
|  | @ -57,6 +68,14 @@ func ListFollowers(ctx *context.APIContext) { | ||||||
| 	//   description: username of user
 | 	//   description: username of user
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
|  | @ -69,7 +88,7 @@ func ListFollowers(ctx *context.APIContext) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func listUserFollowing(ctx *context.APIContext, u *models.User) { | func listUserFollowing(ctx *context.APIContext, u *models.User) { | ||||||
| 	users, err := u.GetFollowing(ctx.QueryInt("page")) | 	users, err := u.GetFollowing(utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetFollowing", err) | 		ctx.Error(http.StatusInternalServerError, "GetFollowing", err) | ||||||
| 		return | 		return | ||||||
|  | @ -82,6 +101,15 @@ func ListMyFollowing(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /user/following user userCurrentListFollowing
 | 	// swagger:operation GET /user/following user userCurrentListFollowing
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: List the users that the authenticated user is following
 | 	// summary: List the users that the authenticated user is following
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
|  | @ -104,6 +132,14 @@ func ListFollowing(ctx *context.APIContext) { | ||||||
| 	//   description: username of user
 | 	//   description: username of user
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/UserList"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
|  |  | ||||||
|  | @ -11,10 +11,11 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func listGPGKeys(ctx *context.APIContext, uid int64) { | func listGPGKeys(ctx *context.APIContext, uid int64, listOptions models.ListOptions) { | ||||||
| 	keys, err := models.ListGPGKeys(uid) | 	keys, err := models.ListGPGKeys(uid, listOptions) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "ListGPGKeys", err) | 		ctx.Error(http.StatusInternalServerError, "ListGPGKeys", err) | ||||||
| 		return | 		return | ||||||
|  | @ -41,6 +42,14 @@ func ListGPGKeys(ctx *context.APIContext) { | ||||||
| 	//   description: username of user
 | 	//   description: username of user
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/GPGKeyList"
 | 	//     "$ref": "#/responses/GPGKeyList"
 | ||||||
|  | @ -49,7 +58,7 @@ func ListGPGKeys(ctx *context.APIContext) { | ||||||
| 	if ctx.Written() { | 	if ctx.Written() { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	listGPGKeys(ctx, user.ID) | 	listGPGKeys(ctx, user.ID, utils.GetListOptions(ctx)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //ListMyGPGKeys get the GPG key list of the authenticated user
 | //ListMyGPGKeys get the GPG key list of the authenticated user
 | ||||||
|  | @ -57,13 +66,22 @@ func ListMyGPGKeys(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /user/gpg_keys user userCurrentListGPGKeys
 | 	// swagger:operation GET /user/gpg_keys user userCurrentListGPGKeys
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: List the authenticated user's GPG keys
 | 	// summary: List the authenticated user's GPG keys
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/GPGKeyList"
 | 	//     "$ref": "#/responses/GPGKeyList"
 | ||||||
| 
 | 
 | ||||||
| 	listGPGKeys(ctx, ctx.User.ID) | 	listGPGKeys(ctx, ctx.User.ID, utils.GetListOptions(ctx)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //GetGPGKey get the GPG key based on a id
 | //GetGPGKey get the GPG key based on a id
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ 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/routers/api/v1/repo" | 	"code.gitea.io/gitea/routers/api/v1/repo" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // appendPrivateInformation appends the owner and key type information to api.PublicKey
 | // appendPrivateInformation appends the owner and key type information to api.PublicKey
 | ||||||
|  | @ -79,7 +80,7 @@ func listPublicKeys(ctx *context.APIContext, user *models.User) { | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		// Use ListPublicKeys
 | 		// Use ListPublicKeys
 | ||||||
| 		keys, err = models.ListPublicKeys(user.ID) | 		keys, err = models.ListPublicKeys(user.ID, utils.GetListOptions(ctx)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -109,6 +110,14 @@ func ListMyPublicKeys(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: fingerprint of the key
 | 	//   description: fingerprint of the key
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
|  | @ -135,6 +144,14 @@ func ListPublicKeys(ctx *context.APIContext) { | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: fingerprint of the key
 | 	//   description: fingerprint of the key
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/PublicKeyList"
 | 	//     "$ref": "#/responses/PublicKeyList"
 | ||||||
|  |  | ||||||
|  | @ -10,11 +10,16 @@ import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // listUserRepos - List the repositories owned by the given user.
 | // listUserRepos - List the repositories owned by the given user.
 | ||||||
| func listUserRepos(ctx *context.APIContext, u *models.User, private bool) { | func listUserRepos(ctx *context.APIContext, u *models.User, private bool) { | ||||||
| 	repos, err := models.GetUserRepositories(u.ID, private, 1, u.NumRepos, "") | 	repos, err := models.GetUserRepositories(&models.SearchRepoOptions{ | ||||||
|  | 		Actor:       u, | ||||||
|  | 		Private:     private, | ||||||
|  | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) | 		ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) | ||||||
| 		return | 		return | ||||||
|  | @ -47,6 +52,14 @@ func ListUserRepos(ctx *context.APIContext) { | ||||||
| 	//   description: username of user
 | 	//   description: username of user
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
|  | @ -66,11 +79,24 @@ func ListMyRepos(ctx *context.APIContext) { | ||||||
| 	// summary: List the repos that the authenticated user owns or has access to
 | 	// summary: List the repos that the authenticated user owns or has access to
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
| 
 | 
 | ||||||
| 	ownRepos, err := models.GetUserRepositories(ctx.User.ID, true, 1, ctx.User.NumRepos, "") | 	ownRepos, err := models.GetUserRepositories(&models.SearchRepoOptions{ | ||||||
|  | 		Actor:       ctx.User, | ||||||
|  | 		Private:     true, | ||||||
|  | 		ListOptions: utils.GetListOptions(ctx), | ||||||
|  | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) | 		ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) | ||||||
| 		return | 		return | ||||||
|  | @ -106,6 +132,14 @@ func ListOrgRepos(ctx *context.APIContext) { | ||||||
| 	//   description: name of the organization
 | 	//   description: name of the organization
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2016 The Gogs Authors. All rights reserved.
 | // Copyright 2016 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -10,12 +11,13 @@ import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // getStarredRepos returns the repos that the user with the specified userID has
 | // getStarredRepos returns the repos that the user with the specified userID has
 | ||||||
| // starred
 | // starred
 | ||||||
| func getStarredRepos(user *models.User, private bool) ([]*api.Repository, error) { | func getStarredRepos(user *models.User, private bool, listOptions models.ListOptions) ([]*api.Repository, error) { | ||||||
| 	starredRepos, err := models.GetStarredRepos(user.ID, private) | 	starredRepos, err := models.GetStarredRepos(user.ID, private, listOptions) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -44,13 +46,21 @@ func GetStarredRepos(ctx *context.APIContext) { | ||||||
| 	//   description: username of user
 | 	//   description: username of user
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
| 
 | 
 | ||||||
| 	user := GetUserByParams(ctx) | 	user := GetUserByParams(ctx) | ||||||
| 	private := user.ID == ctx.User.ID | 	private := user.ID == ctx.User.ID | ||||||
| 	repos, err := getStarredRepos(user, private) | 	repos, err := getStarredRepos(user, private, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) | 		ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) | ||||||
| 	} | 	} | ||||||
|  | @ -62,13 +72,22 @@ func GetMyStarredRepos(ctx *context.APIContext) { | ||||||
| 	// swagger:operation GET /user/starred user userCurrentListStarred
 | 	// swagger:operation GET /user/starred user userCurrentListStarred
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: The repos that the authenticated user has starred
 | 	// summary: The repos that the authenticated user has starred
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
| 
 | 
 | ||||||
| 	repos, err := getStarredRepos(ctx.User, true) | 	repos, err := getStarredRepos(ctx.User, true, utils.GetListOptions(ctx)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) | 		ctx.Error(http.StatusInternalServerError, "getStarredRepos", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -12,6 +13,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/convert" | 	"code.gitea.io/gitea/modules/convert" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/routers/api/v1/utils" | ||||||
| 
 | 
 | ||||||
| 	"github.com/unknwon/com" | 	"github.com/unknwon/com" | ||||||
| ) | ) | ||||||
|  | @ -33,9 +35,13 @@ func Search(ctx *context.APIContext) { | ||||||
| 	//   description: ID of the user to search for
 | 	//   description: ID of the user to search for
 | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
| 	//   format: int64
 | 	//   format: int64
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// - name: limit
 | 	// - name: limit
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: maximum number of users to return
 | 	//   description: page size of results, maximum page size is 50
 | ||||||
| 	//   type: integer
 | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
|  | @ -51,10 +57,10 @@ func Search(ctx *context.APIContext) { | ||||||
| 	//             "$ref": "#/definitions/User"
 | 	//             "$ref": "#/definitions/User"
 | ||||||
| 
 | 
 | ||||||
| 	opts := &models.SearchUserOptions{ | 	opts := &models.SearchUserOptions{ | ||||||
| 		Keyword:  strings.Trim(ctx.Query("q"), " "), | 		Keyword:     strings.Trim(ctx.Query("q"), " "), | ||||||
| 		UID:      com.StrTo(ctx.Query("uid")).MustInt64(), | 		UID:         com.StrTo(ctx.Query("uid")).MustInt64(), | ||||||
| 		Type:     models.UserTypeIndividual, | 		Type:        models.UserTypeIndividual, | ||||||
| 		PageSize: com.StrTo(ctx.Query("limit")).MustInt(), | 		ListOptions: utils.GetListOptions(ctx), | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	users, _, err := models.SearchUsers(opts) | 	users, _, err := models.SearchUsers(opts) | ||||||
|  |  | ||||||
|  | @ -11,12 +11,13 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"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/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) ([]*api.Repository, error) { | func getWatchedRepos(user *models.User, private bool, listOptions models.ListOptions) ([]*api.Repository, error) { | ||||||
| 	watchedRepos, err := models.GetWatchedRepos(user.ID, private) | 	watchedRepos, err := models.GetWatchedRepos(user.ID, private, listOptions) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -45,13 +46,21 @@ func GetWatchedRepos(ctx *context.APIContext) { | ||||||
| 	//   in: path
 | 	//   in: path
 | ||||||
| 	//   description: username of the user
 | 	//   description: username of the user
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
| 
 | 
 | ||||||
| 	user := GetUserByParams(ctx) | 	user := GetUserByParams(ctx) | ||||||
| 	private := user.ID == ctx.User.ID | 	private := user.ID == ctx.User.ID | ||||||
| 	repos, err := getWatchedRepos(user, private) | 	repos, 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) | ||||||
| 	} | 	} | ||||||
|  | @ -65,11 +74,20 @@ func GetMyWatchedRepos(ctx *context.APIContext) { | ||||||
| 	// summary: List repositories watched by the authenticated user
 | 	// summary: List repositories watched by the authenticated user
 | ||||||
| 	// produces:
 | 	// produces:
 | ||||||
| 	// - application/json
 | 	// - application/json
 | ||||||
|  | 	// parameters:
 | ||||||
|  | 	// - name: page
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page number of results to return (1-based)
 | ||||||
|  | 	//   type: integer
 | ||||||
|  | 	// - name: limit
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: page size of results, maximum page size is 50
 | ||||||
|  | 	//   type: integer
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/RepositoryList"
 | 	//     "$ref": "#/responses/RepositoryList"
 | ||||||
| 
 | 
 | ||||||
| 	repos, err := getWatchedRepos(ctx.User, true) | 	repos, 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) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -8,7 +8,9 @@ import ( | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
|  | 	"code.gitea.io/gitea/modules/convert" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // UserID user ID of authenticated user, or 0 if not authenticated
 | // UserID user ID of authenticated user, or 0 if not authenticated
 | ||||||
|  | @ -44,3 +46,11 @@ func GetQueryBeforeSince(ctx *context.APIContext) (before, since int64, err erro | ||||||
| 	} | 	} | ||||||
| 	return before, since, nil | 	return before, since, nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // GetListOptions returns list options using the page and limit parameters
 | ||||||
|  | func GetListOptions(ctx *context.APIContext) models.ListOptions { | ||||||
|  | 	return models.ListOptions{ | ||||||
|  | 		Page:     ctx.QueryInt("page"), | ||||||
|  | 		PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -137,9 +137,11 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | ||||||
| 	ctx.Data["TopicOnly"] = topicOnly | 	ctx.Data["TopicOnly"] = topicOnly | ||||||
| 
 | 
 | ||||||
| 	repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ | 	repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ | ||||||
|  | 		ListOptions: models.ListOptions{ | ||||||
|  | 			Page:     page, | ||||||
|  | 			PageSize: opts.PageSize, | ||||||
|  | 		}, | ||||||
| 		Actor:              ctx.User, | 		Actor:              ctx.User, | ||||||
| 		Page:               page, |  | ||||||
| 		PageSize:           opts.PageSize, |  | ||||||
| 		OrderBy:            orderBy, | 		OrderBy:            orderBy, | ||||||
| 		Private:            opts.Private, | 		Private:            opts.Private, | ||||||
| 		Keyword:            keyword, | 		Keyword:            keyword, | ||||||
|  | @ -250,10 +252,10 @@ func ExploreUsers(ctx *context.Context) { | ||||||
| 	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | 	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ||||||
| 
 | 
 | ||||||
| 	RenderUserSearch(ctx, &models.SearchUserOptions{ | 	RenderUserSearch(ctx, &models.SearchUserOptions{ | ||||||
| 		Type:     models.UserTypeIndividual, | 		Type:        models.UserTypeIndividual, | ||||||
| 		PageSize: setting.UI.ExplorePagingNum, | 		ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum}, | ||||||
| 		IsActive: util.OptionalBoolTrue, | 		IsActive:    util.OptionalBoolTrue, | ||||||
| 		Visible:  []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, | 		Visible:     []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, | ||||||
| 	}, tplExploreUsers) | 	}, tplExploreUsers) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -270,9 +272,9 @@ func ExploreOrganizations(ctx *context.Context) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	RenderUserSearch(ctx, &models.SearchUserOptions{ | 	RenderUserSearch(ctx, &models.SearchUserOptions{ | ||||||
| 		Type:     models.UserTypeOrganization, | 		Type:        models.UserTypeOrganization, | ||||||
| 		PageSize: setting.UI.ExplorePagingNum, | 		ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum}, | ||||||
| 		Visible:  visibleTypes, | 		Visible:     visibleTypes, | ||||||
| 	}, tplExploreOrganizations) | 	}, tplExploreOrganizations) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,14 +76,16 @@ func Home(ctx *context.Context) { | ||||||
| 		err   error | 		err   error | ||||||
| 	) | 	) | ||||||
| 	repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ | 	repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ | ||||||
|  | 		ListOptions: models.ListOptions{ | ||||||
|  | 			PageSize: setting.UI.User.RepoPagingNum, | ||||||
|  | 			Page:     page, | ||||||
|  | 		}, | ||||||
| 		Keyword:            keyword, | 		Keyword:            keyword, | ||||||
| 		OwnerID:            org.ID, | 		OwnerID:            org.ID, | ||||||
| 		OrderBy:            orderBy, | 		OrderBy:            orderBy, | ||||||
| 		Private:            ctx.IsSigned, | 		Private:            ctx.IsSigned, | ||||||
| 		Actor:              ctx.User, | 		Actor:              ctx.User, | ||||||
| 		Page:               page, |  | ||||||
| 		IsProfile:          true, | 		IsProfile:          true, | ||||||
| 		PageSize:           setting.UI.User.RepoPagingNum, |  | ||||||
| 		IncludeDescription: setting.UI.SearchRepoDescription, | 		IncludeDescription: setting.UI.SearchRepoDescription, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -92,9 +94,9 @@ func Home(ctx *context.Context) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var opts = models.FindOrgMembersOpts{ | 	var opts = models.FindOrgMembersOpts{ | ||||||
| 		OrgID:      org.ID, | 		OrgID:       org.ID, | ||||||
| 		PublicOnly: true, | 		PublicOnly:  true, | ||||||
| 		Limit:      25, | 		ListOptions: models.ListOptions{Page: 1, PageSize: 25}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if ctx.User != nil { | 	if ctx.User != nil { | ||||||
|  | @ -106,7 +108,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 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2020 The Gitea Authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -51,9 +52,9 @@ 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.Start = (page - 1) * setting.UI.MembersPagingNum | 	opts.ListOptions.Page = (page - 1) * setting.UI.MembersPagingNum | ||||||
| 	opts.Limit = 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 | ||||||
|  |  | ||||||
|  | @ -155,7 +155,7 @@ func Webhooks(ctx *context.Context) { | ||||||
| 	ctx.Data["BaseLink"] = ctx.Org.OrgLink + "/settings/hooks" | 	ctx.Data["BaseLink"] = 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) | 	ws, err := models.GetWebhooksByOrgID(ctx.Org.Organization.ID, models.ListOptions{}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("GetWebhooksByOrgId", err) | 		ctx.ServerError("GetWebhooksByOrgId", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ func Teams(ctx *context.Context) { | ||||||
| 	ctx.Data["PageIsOrgTeams"] = true | 	ctx.Data["PageIsOrgTeams"] = true | ||||||
| 
 | 
 | ||||||
| 	for _, t := range org.Teams { | 	for _, t := range org.Teams { | ||||||
| 		if err := t.GetMembers(); err != nil { | 		if err := t.GetMembers(&models.SearchMembersOptions{}); err != nil { | ||||||
| 			ctx.ServerError("GetMembers", err) | 			ctx.ServerError("GetMembers", err) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  | @ -246,7 +246,7 @@ func TeamMembers(ctx *context.Context) { | ||||||
| 	ctx.Data["Title"] = ctx.Org.Team.Name | 	ctx.Data["Title"] = ctx.Org.Team.Name | ||||||
| 	ctx.Data["PageIsOrgTeams"] = true | 	ctx.Data["PageIsOrgTeams"] = true | ||||||
| 	ctx.Data["PageIsOrgTeamMembers"] = true | 	ctx.Data["PageIsOrgTeamMembers"] = true | ||||||
| 	if err := ctx.Org.Team.GetMembers(); err != nil { | 	if err := ctx.Org.Team.GetMembers(&models.SearchMembersOptions{}); err != nil { | ||||||
| 		ctx.ServerError("GetMembers", err) | 		ctx.ServerError("GetMembers", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -258,7 +258,7 @@ func TeamRepositories(ctx *context.Context) { | ||||||
| 	ctx.Data["Title"] = ctx.Org.Team.Name | 	ctx.Data["Title"] = ctx.Org.Team.Name | ||||||
| 	ctx.Data["PageIsOrgTeams"] = true | 	ctx.Data["PageIsOrgTeams"] = true | ||||||
| 	ctx.Data["PageIsOrgTeamRepos"] = true | 	ctx.Data["PageIsOrgTeamRepos"] = true | ||||||
| 	if err := ctx.Org.Team.GetRepositories(); err != nil { | 	if err := ctx.Org.Team.GetRepositories(&models.SearchTeamOptions{}); err != nil { | ||||||
| 		ctx.ServerError("GetRepositories", err) | 		ctx.ServerError("GetRepositories", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -58,8 +58,13 @@ func Commits(ctx *context.Context) { | ||||||
| 		page = 1 | 		page = 1 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	pageSize := ctx.QueryInt("limit") | ||||||
|  | 	if pageSize <= 0 { | ||||||
|  | 		pageSize = git.CommitsRangeSize | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// Both `git log branchName` and `git log commitId` work.
 | 	// Both `git log branchName` and `git log commitId` work.
 | ||||||
| 	commits, err := ctx.Repo.Commit.CommitsByRange(page) | 	commits, err := ctx.Repo.Commit.CommitsByRange(page, pageSize) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("CommitsByRange", err) | 		ctx.ServerError("CommitsByRange", err) | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue