diff --git a/integrations/api_org_test.go b/integrations/api_org_test.go index 34579aa1e..551da3032 100644 --- a/integrations/api_org_test.go +++ b/integrations/api_org_test.go @@ -136,3 +136,17 @@ func TestAPIOrgDeny(t *testing.T) { MakeRequest(t, req, http.StatusNotFound) }) } + +func TestAPIGetAll(t *testing.T) { + defer prepareTestEnv(t)() + + req := NewRequestf(t, "GET", "/api/v1/orgs") + resp := MakeRequest(t, req, http.StatusOK) + + var apiOrgList []*api.Organization + DecodeJSON(t, resp, &apiOrgList) + + assert.Len(t, apiOrgList, 7) + assert.Equal(t, "org25", apiOrgList[0].FullName) + assert.Equal(t, "public", apiOrgList[0].Visibility) +} diff --git a/models/user.go b/models/user.go index 9ddd262ae..dc8ae7e0f 100644 --- a/models/user.go +++ b/models/user.go @@ -1469,7 +1469,7 @@ type SearchUserOptions struct { UID int64 OrderBy SearchOrderBy Page int - Private bool // Include private orgs in search + Visible []structs.VisibleType OwnerID int64 // id of user for visibility calculation PageSize int // Can be smaller than or equal to setting.UI.ExplorePagingNum IsActive util.OptionalBool @@ -1492,8 +1492,9 @@ func (opts *SearchUserOptions) toConds() builder.Cond { cond = cond.And(keywordCond) } - if !opts.Private { - // user not logged in and so they won't be allowed to see non-public orgs + if len(opts.Visible) > 0 { + cond = cond.And(builder.In("visibility", opts.Visible)) + } else { cond = cond.And(builder.In("visibility", structs.VisibleTypePublic)) } diff --git a/routers/admin/orgs.go b/routers/admin/orgs.go index e0be99872..02068d618 100644 --- a/routers/admin/orgs.go +++ b/routers/admin/orgs.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers" ) @@ -25,6 +26,6 @@ func Organizations(ctx *context.Context) { routers.RenderUserSearch(ctx, &models.SearchUserOptions{ Type: models.UserTypeOrganization, PageSize: setting.UI.Admin.OrgPagingNum, - Private: true, + Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, }, tplOrgs) } diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go index 1db4e592f..ca2ef574f 100644 --- a/routers/api/v1/admin/org.go +++ b/routers/api/v1/admin/org.go @@ -104,7 +104,7 @@ func GetAllOrgs(ctx *context.APIContext) { OrderBy: models.SearchOrderByAlphabetically, Page: ctx.QueryInt("page"), PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), - Private: true, + Visible: []api.VisibleType{api.VisibleTypePublic, api.VisibleTypeLimited, api.VisibleTypePrivate}, }) if err != nil { ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index fd7f7c05c..86c745017 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -821,6 +821,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/user/orgs", reqToken(), org.ListMyOrgs) m.Get("/users/:username/orgs", org.ListUserOrgs) m.Post("/orgs", reqToken(), bind(api.CreateOrgOption{}), org.Create) + m.Get("/orgs", org.GetAll) m.Group("/orgs/:orgname", func() { m.Combo("").Get(org.Get). Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit). diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 67770e70a..4bcd60a67 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -66,6 +66,53 @@ func ListUserOrgs(ctx *context.APIContext) { listUserOrgs(ctx, u, ctx.User.IsAdmin) } +// GetAll return list of all public organizations +func GetAll(ctx *context.APIContext) { + // swagger:operation Get /orgs organization orgGetAll + // --- + // summary: Get list of organizations + // produces: + // - 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: + // "200": + // "$ref": "#/responses/OrganizationList" + + vMode := []api.VisibleType{api.VisibleTypePublic} + if ctx.IsSigned { + vMode = append(vMode, api.VisibleTypeLimited) + if ctx.User.IsAdmin { + vMode = append(vMode, api.VisibleTypePrivate) + } + } + + publicOrgs, _, err := models.SearchUsers(&models.SearchUserOptions{ + Type: models.UserTypeOrganization, + OrderBy: models.SearchOrderByAlphabetically, + Page: ctx.QueryInt("page"), + PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), + Visible: vMode, + }) + if err != nil { + ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err) + return + } + orgs := make([]*api.Organization, len(publicOrgs)) + for i := range publicOrgs { + orgs[i] = convert.ToOrganization(publicOrgs[i]) + } + + ctx.JSON(http.StatusOK, &orgs) +} + // Create api for create organization func Create(ctx *context.APIContext, form api.CreateOrgOption) { // swagger:operation POST /orgs organization orgCreate diff --git a/routers/home.go b/routers/home.go index 773e0f3d6..0f59c9570 100644 --- a/routers/home.go +++ b/routers/home.go @@ -15,6 +15,7 @@ import ( code_indexer "code.gitea.io/gitea/modules/indexer/code" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/routers/user" ) @@ -249,7 +250,7 @@ func ExploreUsers(ctx *context.Context) { Type: models.UserTypeIndividual, PageSize: setting.UI.ExplorePagingNum, IsActive: util.OptionalBoolTrue, - Private: true, + Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, }, tplExploreUsers) } @@ -265,12 +266,17 @@ func ExploreOrganizations(ctx *context.Context) { ownerID = ctx.User.ID } - RenderUserSearch(ctx, &models.SearchUserOptions{ + opts := models.SearchUserOptions{ Type: models.UserTypeOrganization, PageSize: setting.UI.ExplorePagingNum, - Private: ctx.User != nil, OwnerID: ownerID, - }, tplExploreOrganizations) + } + if ctx.User != nil { + opts.Visible = []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate} + } else { + opts.Visible = []structs.VisibleType{structs.VisibleTypePublic} + } + RenderUserSearch(ctx, &opts, tplExploreOrganizations) } // ExploreCode render explore code page diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index ddf144066..de774de9f 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -606,6 +606,35 @@ } }, "/orgs": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization" + ], + "summary": "Get list of organizations", + "operationId": "orgGetAll", + "parameters": [ + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results, maximum page size is 50", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/OrganizationList" + } + } + }, "post": { "consumes": [ "application/json"