* introduce `GET /orgs` * add TEST * show also other VisibleType's * update description * refactor a lot * SearchUserOptions by default return only publictags/v1.21.12.1
| @@ -136,3 +136,17 @@ func TestAPIOrgDeny(t *testing.T) { | |||||
| MakeRequest(t, req, http.StatusNotFound) | 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) | |||||
| } | |||||
| @@ -1469,7 +1469,7 @@ type SearchUserOptions struct { | |||||
| UID int64 | UID int64 | ||||
| OrderBy SearchOrderBy | OrderBy SearchOrderBy | ||||
| Page int | Page int | ||||
| Private bool // Include private orgs in search | |||||
| Visible []structs.VisibleType | |||||
| OwnerID int64 // id of user for visibility calculation | OwnerID int64 // id of user for visibility calculation | ||||
| PageSize int // Can be smaller than or equal to setting.UI.ExplorePagingNum | PageSize int // Can be smaller than or equal to setting.UI.ExplorePagingNum | ||||
| IsActive util.OptionalBool | IsActive util.OptionalBool | ||||
| @@ -1492,8 +1492,9 @@ func (opts *SearchUserOptions) toConds() builder.Cond { | |||||
| cond = cond.And(keywordCond) | 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)) | cond = cond.And(builder.In("visibility", structs.VisibleTypePublic)) | ||||
| } | } | ||||
| @@ -9,6 +9,7 @@ import ( | |||||
| "code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
| "code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/structs" | |||||
| "code.gitea.io/gitea/routers" | "code.gitea.io/gitea/routers" | ||||
| ) | ) | ||||
| @@ -25,6 +26,6 @@ func Organizations(ctx *context.Context) { | |||||
| routers.RenderUserSearch(ctx, &models.SearchUserOptions{ | routers.RenderUserSearch(ctx, &models.SearchUserOptions{ | ||||
| Type: models.UserTypeOrganization, | Type: models.UserTypeOrganization, | ||||
| PageSize: setting.UI.Admin.OrgPagingNum, | PageSize: setting.UI.Admin.OrgPagingNum, | ||||
| Private: true, | |||||
| Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, | |||||
| }, tplOrgs) | }, tplOrgs) | ||||
| } | } | ||||
| @@ -104,7 +104,7 @@ func GetAllOrgs(ctx *context.APIContext) { | |||||
| OrderBy: models.SearchOrderByAlphabetically, | OrderBy: models.SearchOrderByAlphabetically, | ||||
| Page: ctx.QueryInt("page"), | Page: ctx.QueryInt("page"), | ||||
| PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), | PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), | ||||
| Private: true, | |||||
| 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) | ||||
| @@ -821,6 +821,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/user/orgs", reqToken(), org.ListMyOrgs) | m.Get("/user/orgs", reqToken(), org.ListMyOrgs) | ||||
| m.Get("/users/:username/orgs", org.ListUserOrgs) | m.Get("/users/:username/orgs", org.ListUserOrgs) | ||||
| m.Post("/orgs", reqToken(), bind(api.CreateOrgOption{}), org.Create) | m.Post("/orgs", reqToken(), bind(api.CreateOrgOption{}), org.Create) | ||||
| m.Get("/orgs", org.GetAll) | |||||
| m.Group("/orgs/:orgname", func() { | m.Group("/orgs/:orgname", func() { | ||||
| m.Combo("").Get(org.Get). | m.Combo("").Get(org.Get). | ||||
| Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit). | Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit). | ||||
| @@ -66,6 +66,53 @@ func ListUserOrgs(ctx *context.APIContext) { | |||||
| listUserOrgs(ctx, u, ctx.User.IsAdmin) | 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 | // Create api for create organization | ||||
| func Create(ctx *context.APIContext, form api.CreateOrgOption) { | func Create(ctx *context.APIContext, form api.CreateOrgOption) { | ||||
| // swagger:operation POST /orgs organization orgCreate | // swagger:operation POST /orgs organization orgCreate | ||||
| @@ -15,6 +15,7 @@ import ( | |||||
| code_indexer "code.gitea.io/gitea/modules/indexer/code" | code_indexer "code.gitea.io/gitea/modules/indexer/code" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/structs" | |||||
| "code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
| "code.gitea.io/gitea/routers/user" | "code.gitea.io/gitea/routers/user" | ||||
| ) | ) | ||||
| @@ -249,7 +250,7 @@ func ExploreUsers(ctx *context.Context) { | |||||
| Type: models.UserTypeIndividual, | Type: models.UserTypeIndividual, | ||||
| PageSize: setting.UI.ExplorePagingNum, | PageSize: setting.UI.ExplorePagingNum, | ||||
| IsActive: util.OptionalBoolTrue, | IsActive: util.OptionalBoolTrue, | ||||
| Private: true, | |||||
| Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, | |||||
| }, tplExploreUsers) | }, tplExploreUsers) | ||||
| } | } | ||||
| @@ -265,12 +266,17 @@ func ExploreOrganizations(ctx *context.Context) { | |||||
| ownerID = ctx.User.ID | ownerID = ctx.User.ID | ||||
| } | } | ||||
| RenderUserSearch(ctx, &models.SearchUserOptions{ | |||||
| opts := models.SearchUserOptions{ | |||||
| Type: models.UserTypeOrganization, | Type: models.UserTypeOrganization, | ||||
| PageSize: setting.UI.ExplorePagingNum, | PageSize: setting.UI.ExplorePagingNum, | ||||
| Private: ctx.User != nil, | |||||
| OwnerID: ownerID, | 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 | // ExploreCode render explore code page | ||||
| @@ -606,6 +606,35 @@ | |||||
| } | } | ||||
| }, | }, | ||||
| "/orgs": { | "/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": { | "post": { | ||||
| "consumes": [ | "consumes": [ | ||||
| "application/json" | "application/json" | ||||