diff --git a/integrations/org_count_test.go b/integrations/org_count_test.go index a394dba01..a45d1e81b 100644 --- a/integrations/org_count_test.go +++ b/integrations/org_count_test.go @@ -116,7 +116,10 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca Name: username, }).(*models.User) - orgs, err := models.GetOrgsByUserID(user.ID, true) + orgs, err := models.FindOrgs(models.FindOrgOptions{ + UserID: user.ID, + IncludePrivate: true, + }) assert.NoError(t, err) calcOrgCounts := map[string]int{} diff --git a/models/org.go b/models/org.go index 8e60422ef..b3e67fb52 100644 --- a/models/org.go +++ b/models/org.go @@ -440,24 +440,6 @@ func getUsersWhoCanCreateOrgRepo(e db.Engine, orgID int64) ([]*User, error) { And("team_user.org_id = ?", orgID).Asc("`user`.name").Find(&users) } -func getOrgsByUserID(e db.Engine, userID int64, showAll bool) ([]*Organization, error) { - orgs := make([]*Organization, 0, 10) - sess := e.Where("`org_user`.uid=?", userID) - if !showAll { - sess = sess.And("`org_user`.is_public=?", true) - } - return orgs, sess. - Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id"). - Asc("`user`.name"). - Find(&orgs) -} - -// GetOrgsByUserID returns a list of organizations that the given user ID -// has joined. -func GetOrgsByUserID(userID int64, showAll bool) ([]*Organization, error) { - return getOrgsByUserID(db.GetEngine(db.DefaultContext), userID, showAll) -} - // MinimalOrg represents a simple orgnization with only needed columns type MinimalOrg = Organization @@ -519,6 +501,51 @@ func GetUserOrgsList(user *User) ([]*MinimalOrg, error) { return orgs, nil } +// FindOrgOptions finds orgs options +type FindOrgOptions struct { + db.ListOptions + UserID int64 + IncludePrivate bool +} + +func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder { + var cond = builder.Eq{"uid": userID} + if !includePrivate { + cond["is_public"] = true + } + return builder.Select("org_id").From("org_user").Where(cond) +} + +func (opts FindOrgOptions) toConds() builder.Cond { + var cond = builder.NewCond() + if opts.UserID > 0 { + cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate))) + } + if !opts.IncludePrivate { + cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic}) + } + return cond +} + +// FindOrgs returns a list of organizations according given conditions +func FindOrgs(opts FindOrgOptions) ([]*Organization, error) { + orgs := make([]*Organization, 0, 10) + sess := db.GetEngine(db.DefaultContext). + Where(opts.toConds()). + Asc("`user`.name") + if opts.Page > 0 && opts.PageSize > 0 { + sess.Limit(opts.PageSize, opts.PageSize*(opts.Page-1)) + } + return orgs, sess.Find(&orgs) +} + +// CountOrgs returns total count organizations according options +func CountOrgs(opts FindOrgOptions) (int64, error) { + return db.GetEngine(db.DefaultContext). + Where(opts.toConds()). + Count(new(User)) +} + func getOwnedOrgsByUserID(sess db.Engine, userID int64) ([]*User, error) { orgs := make([]*User, 0, 10) return orgs, sess. diff --git a/models/org_test.go b/models/org_test.go index 10ae87745..805c63300 100644 --- a/models/org_test.go +++ b/models/org_test.go @@ -307,18 +307,31 @@ func TestIsPublicMembership(t *testing.T) { test(unittest.NonexistentID, unittest.NonexistentID, false) } -func TestGetOrgsByUserID(t *testing.T) { +func TestFindOrgs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - orgs, err := GetOrgsByUserID(4, true) + orgs, err := FindOrgs(FindOrgOptions{ + UserID: 4, + IncludePrivate: true, + }) assert.NoError(t, err) if assert.Len(t, orgs, 1) { assert.EqualValues(t, 3, orgs[0].ID) } - orgs, err = GetOrgsByUserID(4, false) + orgs, err = FindOrgs(FindOrgOptions{ + UserID: 4, + IncludePrivate: false, + }) assert.NoError(t, err) assert.Len(t, orgs, 0) + + total, err := CountOrgs(FindOrgOptions{ + UserID: 4, + IncludePrivate: true, + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, total) } func TestGetOwnedOrgsByUserID(t *testing.T) { diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index bbf127f89..f539662d6 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -12,7 +12,6 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" "code.gitea.io/gitea/routers/api/v1/utils" @@ -20,25 +19,31 @@ import ( ) func listUserOrgs(ctx *context.APIContext, u *models.User) { - listOptions := utils.GetListOptions(ctx) showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == u.ID) - orgs, err := models.GetOrgsByUserID(u.ID, showPrivate) + var opts = models.FindOrgOptions{ + ListOptions: listOptions, + UserID: u.ID, + IncludePrivate: showPrivate, + } + orgs, err := models.FindOrgs(opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "GetOrgsByUserID", err) + ctx.Error(http.StatusInternalServerError, "FindOrgs", err) + return + } + maxResults, err := models.CountOrgs(opts) + if err != nil { + ctx.Error(http.StatusInternalServerError, "CountOrgs", err) return } - - maxResults := len(orgs) - orgs, _ = util.PaginateSlice(orgs, listOptions.Page, listOptions.PageSize).([]*models.Organization) apiOrgs := make([]*api.Organization, len(orgs)) for i := range orgs { apiOrgs[i] = convert.ToOrganization(orgs[i]) } - ctx.SetLinkHeader(maxResults, listOptions.PageSize) + ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) ctx.SetTotalCountHeader(int64(maxResults)) ctx.JSON(http.StatusOK, &apiOrgs) } diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 72d36761d..9d0b4e3c1 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -167,9 +167,12 @@ func Profile(ctx *context.Context) { showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID) - orgs, err := models.GetOrgsByUserID(ctxUser.ID, showPrivate) + orgs, err := models.FindOrgs(models.FindOrgOptions{ + UserID: ctxUser.ID, + IncludePrivate: showPrivate, + }) if err != nil { - ctx.ServerError("GetOrgsByUserIDDesc", err) + ctx.ServerError("FindOrgs", err) return } diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index d7aa3264c..36fe45df0 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -214,12 +214,34 @@ func DeleteAvatar(ctx *context.Context) { func Organization(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsOrganization"] = true - orgs, err := models.GetOrgsByUserID(ctx.User.ID, ctx.IsSigned) + + opts := models.FindOrgOptions{ + ListOptions: db.ListOptions{ + PageSize: setting.UI.Admin.UserPagingNum, + Page: ctx.FormInt("page"), + }, + UserID: ctx.User.ID, + IncludePrivate: ctx.IsSigned, + } + + if opts.Page <= 0 { + opts.Page = 1 + } + + orgs, err := models.FindOrgs(opts) + if err != nil { + ctx.ServerError("FindOrgs", err) + return + } + total, err := models.CountOrgs(opts) if err != nil { - ctx.ServerError("GetOrgsByUserID", err) + ctx.ServerError("CountOrgs", err) return } ctx.Data["Orgs"] = orgs + pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5) + pager.SetDefaultParams(ctx) + ctx.Data["Page"] = pager ctx.HTML(http.StatusOK, tplSettingsOrganization) } diff --git a/templates/user/settings/organization.tmpl b/templates/user/settings/organization.tmpl index 3bab1c895..1689c1b9e 100644 --- a/templates/user/settings/organization.tmpl +++ b/templates/user/settings/organization.tmpl @@ -29,6 +29,7 @@ {{end}} + {{template "base/paginate" .}} {{else}} {{.i18n.Tr "settings.orgs_none"}} {{end}}