* COrrect use `UserID` in `SearchTeams` - Use `UserID` in the `SearchTeams` function, currently it was useless to pass such information. Now it does a INNER statement to `team_user` which obtains UserID -> TeamID data. - Make OrgID optional. - Resolves #18484 * Seperate searching specific user * Add condition back * Use correct struct type Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>tags/v1.18.0-dev
db.RegisterModel(new(TeamUnit)) | db.RegisterModel(new(TeamUnit)) | ||||
} | } | ||||
// SearchTeamOptions holds the search options | |||||
type SearchTeamOptions struct { | |||||
// SearchOrgTeamOptions holds the search options | |||||
type SearchOrgTeamOptions struct { | |||||
db.ListOptions | db.ListOptions | ||||
UserID int64 | |||||
Keyword string | Keyword string | ||||
OrgID int64 | OrgID int64 | ||||
IncludeDesc bool | IncludeDesc bool | ||||
} | } | ||||
// GetUserTeamOptions holds the search options. | |||||
type GetUserTeamOptions struct { | |||||
db.ListOptions | |||||
UserID int64 | |||||
} | |||||
// SearchMembersOptions holds the search options | // SearchMembersOptions holds the search options | ||||
type SearchMembersOptions struct { | type SearchMembersOptions struct { | ||||
db.ListOptions | db.ListOptions | ||||
} | } | ||||
// SearchTeam search for teams. Caller is responsible to check permissions. | |||||
func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) { | |||||
// GetUserTeams search for org teams. Caller is responsible to check permissions. | |||||
func GetUserTeams(opts *GetUserTeamOptions) ([]*Team, int64, error) { | |||||
if opts.Page <= 0 { | |||||
opts.Page = 1 | |||||
} | |||||
if opts.PageSize == 0 { | |||||
// Default limit | |||||
opts.PageSize = 10 | |||||
} | |||||
sess := db.GetEngine(db.DefaultContext) | |||||
sess = sess.Join("INNER", "team_user", "team_user.team_id = team.id"). | |||||
And("team_user.uid=?", opts.UserID) | |||||
count, err := sess. | |||||
Count(new(Team)) | |||||
if err != nil { | |||||
return nil, 0, err | |||||
} | |||||
if opts.PageSize == -1 { | |||||
opts.PageSize = int(count) | |||||
} else { | |||||
sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) | |||||
} | |||||
sess = sess.Join("INNER", "team_user", "team_user.team_id = team.id"). | |||||
And("team_user.uid=?", opts.UserID) | |||||
teams := make([]*Team, 0, opts.PageSize) | |||||
if err = sess. | |||||
OrderBy("lower_name"). | |||||
Find(&teams); err != nil { | |||||
return nil, 0, err | |||||
} | |||||
return teams, count, nil | |||||
} | |||||
// SearchOrgTeams search for org teams. Caller is responsible to check permissions. | |||||
func SearchOrgTeams(opts *SearchOrgTeamOptions) ([]*Team, int64, error) { | |||||
if opts.Page <= 0 { | if opts.Page <= 0 { | ||||
opts.Page = 1 | opts.Page = 1 | ||||
} | } | ||||
} | } | ||||
// GetRepositories returns paginated repositories in team of organization. | // GetRepositories returns paginated repositories in team of organization. | ||||
func (t *Team) GetRepositories(opts *SearchTeamOptions) error { | |||||
func (t *Team) GetRepositories(opts *SearchOrgTeamOptions) error { | |||||
if opts.Page == 0 { | if opts.Page == 0 { | ||||
return t.getRepositories(db.GetEngine(db.DefaultContext)) | return t.getRepositories(db.GetEngine(db.DefaultContext)) | ||||
} | } | ||||
// 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(&SearchTeamOptions{}); err != nil { | |||||
if err := t.GetRepositories(&SearchOrgTeamOptions{}); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// Get team and its repositories. | // Get team and its repositories. | ||||
if err := team.GetRepositories(&SearchTeamOptions{}); err != nil { | |||||
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil { | |||||
return err | return err | ||||
} | } | ||||
test := func(teamID int64) { | test := func(teamID int64) { | ||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team) | team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team) | ||||
assert.NoError(t, team.GetRepositories(&SearchTeamOptions{})) | |||||
assert.NoError(t, team.GetRepositories(&SearchOrgTeamOptions{})) | |||||
assert.Len(t, team.Repos, team.NumRepos) | assert.Len(t, team.Repos, team.NumRepos) | ||||
for _, repo := range team.Repos { | for _, repo := range team.Repos { | ||||
unittest.AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID}) | unittest.AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID}) | ||||
func TestGetUserTeams(t *testing.T) { | func TestGetUserTeams(t *testing.T) { | ||||
assert.NoError(t, unittest.PrepareTestDatabase()) | assert.NoError(t, unittest.PrepareTestDatabase()) | ||||
test := func(userID int64) { | test := func(userID int64) { | ||||
teams, _, err := SearchTeam(&SearchTeamOptions{UserID: userID}) | |||||
teams, _, err := GetUserTeams(&GetUserTeamOptions{UserID: userID}) | |||||
assert.NoError(t, err) | assert.NoError(t, err) | ||||
for _, team := range teams { | for _, team := range teams { | ||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID}) | unittest.AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID}) |
testTeamRepositories := func(teamID int64, repoIds []int64) { | testTeamRepositories := func(teamID int64, repoIds []int64) { | ||||
team := unittest.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team) | team := unittest.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team) | ||||
assert.NoError(t, team.GetRepositories(&models.SearchTeamOptions{}), "%s: GetRepositories", team.Name) | |||||
assert.NoError(t, team.GetRepositories(&models.SearchOrgTeamOptions{}), "%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.Len(t, team.Repos, len(repoIds), "%s: repo count", team.Name) | assert.Len(t, team.Repos, len(repoIds), "%s: repo count", team.Name) | ||||
for i, rid := range repoIds { | for i, rid := range repoIds { |
// "200": | // "200": | ||||
// "$ref": "#/responses/TeamList" | // "$ref": "#/responses/TeamList" | ||||
teams, count, err := models.SearchTeam(&models.SearchTeamOptions{ | |||||
teams, count, err := models.SearchOrgTeams(&models.SearchOrgTeamOptions{ | |||||
ListOptions: utils.GetListOptions(ctx), | ListOptions: utils.GetListOptions(ctx), | ||||
OrgID: ctx.Org.Organization.ID, | OrgID: ctx.Org.Organization.ID, | ||||
}) | }) | ||||
// "200": | // "200": | ||||
// "$ref": "#/responses/TeamList" | // "$ref": "#/responses/TeamList" | ||||
teams, count, err := models.SearchTeam(&models.SearchTeamOptions{ | |||||
teams, count, err := models.GetUserTeams(&models.GetUserTeamOptions{ | |||||
ListOptions: utils.GetListOptions(ctx), | ListOptions: utils.GetListOptions(ctx), | ||||
UserID: ctx.User.ID, | UserID: ctx.User.ID, | ||||
}) | }) | ||||
// "$ref": "#/responses/RepositoryList" | // "$ref": "#/responses/RepositoryList" | ||||
team := ctx.Org.Team | team := ctx.Org.Team | ||||
if err := team.GetRepositories(&models.SearchTeamOptions{ | |||||
if err := team.GetRepositories(&models.SearchOrgTeamOptions{ | |||||
ListOptions: utils.GetListOptions(ctx), | ListOptions: utils.GetListOptions(ctx), | ||||
}); err != nil { | }); err != nil { | ||||
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) | ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) | ||||
listOptions := utils.GetListOptions(ctx) | listOptions := utils.GetListOptions(ctx) | ||||
opts := &models.SearchTeamOptions{ | |||||
UserID: ctx.User.ID, | |||||
opts := &models.SearchOrgTeamOptions{ | |||||
Keyword: ctx.FormTrim("q"), | Keyword: ctx.FormTrim("q"), | ||||
OrgID: ctx.Org.Organization.ID, | OrgID: ctx.Org.Organization.ID, | ||||
IncludeDesc: ctx.FormString("include_desc") == "" || ctx.FormBool("include_desc"), | IncludeDesc: ctx.FormString("include_desc") == "" || ctx.FormBool("include_desc"), | ||||
ListOptions: listOptions, | ListOptions: listOptions, | ||||
} | } | ||||
teams, maxResults, err := models.SearchTeam(opts) | |||||
teams, maxResults, err := models.SearchOrgTeams(opts) | |||||
if err != nil { | if err != nil { | ||||
log.Error("SearchTeam failed: %v", err) | log.Error("SearchTeam failed: %v", err) | ||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ | ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ |
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(&models.SearchTeamOptions{}); err != nil { | |||||
if err := ctx.Org.Team.GetRepositories(&models.SearchOrgTeamOptions{}); err != nil { | |||||
ctx.ServerError("GetRepositories", err) | ctx.ServerError("GetRepositories", err) | ||||
return | return | ||||
} | } |