From 7cfa3d5c66c0ff52aea1c0184055ba6bc99ffb26 Mon Sep 17 00:00:00 2001 From: dasv Date: Thu, 5 Sep 2019 22:40:33 +0200 Subject: [PATCH 01/15] Api endpoint for searching teams. Signed-off-by: dasv --- models/org_team.go | 68 ++++++++++++++++++++++ routers/api/v1/api.go | 4 ++ routers/api/v1/org/team.go | 102 +++++++++++++++++++++++++++++++++ templates/swagger/v1_json.tmpl | 59 +++++++++++++++++++ 4 files changed, 233 insertions(+) diff --git a/models/org_team.go b/models/org_team.go index 799716679c4a..1388bb1a5f75 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/setting" "github.com/go-xorm/xorm" + "xorm.io/builder" ) const ownerTeamName = "Owners" @@ -34,6 +35,73 @@ type Team struct { Units []*TeamUnit `xorm:"-"` } +// SearchTeamOptions holds the search options +type SearchTeamOptions struct { + UserID int64 + UserIsAdmin bool + Keyword string + OrgID int64 + IncludeDesc bool + Limit int +} + +// SearchTeam search for teams +func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) { + if opts.Limit <= 0 { + opts.Limit = 10 + } + var cond = builder.NewCond() + + if len(opts.Keyword) > 0 { + lowerKeyword := strings.ToLower(opts.Keyword) + var keywordCond = builder.NewCond() + if opts.IncludeDesc { + keywordCond = builder.Or( + builder.Like{"lower_name", lowerKeyword}, + builder.Like{"LOWER(description)", lowerKeyword}, + ) + } else { + keywordCond = builder.Or( + builder.Like{"lower_name", lowerKeyword}, + ) + } + cond = cond.And(keywordCond) + } + + if opts.OrgID > 0 { + cond = cond.And(builder.Eq{"org_id": opts.OrgID}) + } else if !opts.UserIsAdmin { + // Limit search to organizations where user is member + cond = cond.And( + builder.In("org_id", builder.Select("`org_user`.org_id"). + From("org_user"). + Where(builder.Eq{"`org_user`.uid": opts.UserID}). + Join("INNER", "org_user", "`org_user`.org_id = `team`.org_id"))) + } + + sess := x.NewSession() + defer sess.Close() + + count, err := sess. + Where(cond). + Count(new(Team)) + + if err != nil { + return nil, 0, fmt.Errorf("Count: %v", err) + } + + teams := make([]*Team, 0, opts.Limit) + if err = sess. + Where(cond). + OrderBy("lower_name"). + Limit(opts.Limit). + Find(&teams); err != nil { + return nil, 0, fmt.Errorf("Team: %v", err) + } + + return teams, count, nil +} + // ColorFormat provides a basic color format for a Team func (t *Team) ColorFormat(s fmt.State) { log.ColorFprintf(s, "%d:%s (OrgID: %d) %-v", diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index c57edf6a9928..f119a4ccd923 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -831,6 +831,10 @@ func RegisterRoutes(m *macaron.Macaron) { }) }, orgAssignment(false, true), reqToken(), reqTeamMembership()) + m.Group("/teams", func() { + m.Get("/search", org.SearchTeam) + }) + m.Any("/*", func(ctx *context.APIContext) { ctx.NotFound() }) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 3357c072517d..5575833bbe2b 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -6,6 +6,8 @@ package org import ( + "strings" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" @@ -495,3 +497,103 @@ func RemoveTeamRepository(ctx *context.APIContext) { } ctx.Status(204) } + +// SearchTeam api for searching teams +func SearchTeam(ctx *context.APIContext) { + // swagger:operation GET /teams/search organization teamSearch + // --- + // summary: Search for teams + // produces: + // - application/json + // parameters: + // - name: q + // in: query + // description: keywords to search + // required: true + // type: string + // - name: org_id + // in: query + // description: search only teams within organization + // type: integer + // format: int64 + // required: false + // - name: inclDesc + // in: query + // description: include search within team description (defaults to true) + // type: boolean + // - name: limit + // in: query + // description: limit size of results + // type: integer + // responses: + // "200": + // description: "SearchResults of a successful search" + // schema: + // type: object + // properties: + // ok: + // type: boolean + // data: + // type: array + // items: + // "$ref": "#/definitions/Team" + opts := &models.SearchTeamOptions{ + UserID: ctx.Data["SignedUserID"].(int64), + UserIsAdmin: ctx.IsUserSiteAdmin(), + Keyword: strings.Trim(ctx.Query("q"), " "), + OrgID: ctx.QueryInt64("org_id"), + IncludeDesc: (ctx.Query("inclDesc") == "" || ctx.QueryBool("inclDesc")), + Limit: ctx.QueryInt("limit"), + } + + // If searching in a specific organization, require organization membership + if opts.OrgID > 0 { + if isMember, err := models.IsOrganizationMember(opts.OrgID, opts.UserID); err != nil { + ctx.Error(500, "IsOrganizationMember", err) + return + } else if !isMember && !ctx.IsUserSiteAdmin() { + ctx.Error(403, "", "Must be an organization member") + return + } + } + + teams, _, err := models.SearchTeam(opts) + if err != nil { + ctx.JSON(500, map[string]interface{}{ + "ok": false, + "error": err.Error(), + }) + return + } + + apiTeams := make([]*api.Team, len(teams)) + cache := make(map[int64]*api.Organization) + for i := range teams { + if err := teams[i].GetUnits(); err != nil { + ctx.Error(500, "GetUnits", err) + return + } + apiTeams[i] = convert.ToTeam(teams[i]) + + if opts.OrgID <= 0 { + apiOrg, ok := cache[teams[i].OrgID] + if !ok { + org, err := models.GetUserByID(teams[i].OrgID) + if err != nil { + ctx.Error(500, "GetUserByID", err) + return + } + apiOrg = convert.ToOrganization(org) + cache[teams[i].OrgID] = apiOrg + } + apiTeams[i] = convert.ToTeam(teams[i]) + apiTeams[i].Organization = apiOrg + } + } + + ctx.JSON(200, map[string]interface{}{ + "ok": true, + "data": apiTeams, + }) + +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 8cf22251a6eb..47e6a4347561 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -5627,6 +5627,65 @@ } } }, + "/teams/search": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization" + ], + "summary": "Search for teams", + "operationId": "teamSearch", + "parameters": [ + { + "type": "string", + "description": "keywords to search", + "name": "q", + "in": "query", + "required": true + }, + { + "type": "integer", + "format": "int64", + "description": "search only teams within organization", + "name": "org_id", + "in": "query" + }, + { + "type": "boolean", + "description": "include search within team description (defaults to true)", + "name": "inclDesc", + "in": "query" + }, + { + "type": "integer", + "description": "limit size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "SearchResults of a successful search", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/Team" + } + }, + "ok": { + "type": "boolean" + } + } + } + } + } + } + }, "/teams/{id}": { "get": { "produces": [ From ebecd5a6a5257b0304624e7793ea1b060ac34980 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Fri, 6 Sep 2019 17:12:44 +0200 Subject: [PATCH 02/15] Move API to /orgs/:org/teams/search Signed-off-by: David Svantesson --- models/org_team.go | 13 ++--------- routers/api/v1/api.go | 11 +++++----- routers/api/v1/org/team.go | 44 +++++++------------------------------- 3 files changed, 15 insertions(+), 53 deletions(-) diff --git a/models/org_team.go b/models/org_team.go index 1388bb1a5f75..6257153a22e2 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -45,7 +45,7 @@ type SearchTeamOptions struct { Limit int } -// SearchTeam search for teams +// SearchTeam search for teams. Caller is responsible to check permissions. func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) { if opts.Limit <= 0 { opts.Limit = 10 @@ -68,16 +68,7 @@ func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) { cond = cond.And(keywordCond) } - if opts.OrgID > 0 { - cond = cond.And(builder.Eq{"org_id": opts.OrgID}) - } else if !opts.UserIsAdmin { - // Limit search to organizations where user is member - cond = cond.And( - builder.In("org_id", builder.Select("`org_user`.org_id"). - From("org_user"). - Where(builder.Eq{"`org_user`.uid": opts.UserID}). - Join("INNER", "org_user", "`org_user`.org_id = `team`.org_id"))) - } + cond = cond.And(builder.Eq{"org_id": opts.OrgID}) sess := x.NewSession() defer sess.Close() diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index f119a4ccd923..800bb1424aff 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -802,8 +802,11 @@ func RegisterRoutes(m *macaron.Macaron) { Put(reqToken(), reqOrgMembership(), org.PublicizeMember). Delete(reqToken(), reqOrgMembership(), org.ConcealMember) }) - m.Combo("/teams", reqToken(), reqOrgMembership()).Get(org.ListTeams). - Post(reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam) + m.Group("/teams", func() { + m.Combo("", reqToken()).Get(org.ListTeams). + Post(reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam) + m.Post("/search", org.SearchTeam) + }, reqOrgMembership()) m.Group("/hooks", func() { m.Combo("").Get(org.ListHooks). Post(bind(api.CreateHookOption{}), org.CreateHook) @@ -831,10 +834,6 @@ func RegisterRoutes(m *macaron.Macaron) { }) }, orgAssignment(false, true), reqToken(), reqTeamMembership()) - m.Group("/teams", func() { - m.Get("/search", org.SearchTeam) - }) - m.Any("/*", func(ctx *context.APIContext) { ctx.NotFound() }) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 5575833bbe2b..518299362b70 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -500,23 +500,22 @@ func RemoveTeamRepository(ctx *context.APIContext) { // SearchTeam api for searching teams func SearchTeam(ctx *context.APIContext) { - // swagger:operation GET /teams/search organization teamSearch + // swagger:operation GET /orgs/{org}/teams/search organization teamSearch // --- - // summary: Search for teams + // summary: Search for teams within organization // produces: // - application/json // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true // - name: q // in: query // description: keywords to search // required: true // type: string - // - name: org_id - // in: query - // description: search only teams within organization - // type: integer - // format: int64 - // required: false // - name: inclDesc // in: query // description: include search within team description (defaults to true) @@ -541,22 +540,11 @@ func SearchTeam(ctx *context.APIContext) { UserID: ctx.Data["SignedUserID"].(int64), UserIsAdmin: ctx.IsUserSiteAdmin(), Keyword: strings.Trim(ctx.Query("q"), " "), - OrgID: ctx.QueryInt64("org_id"), + OrgID: ctx.Org.Organization.ID, IncludeDesc: (ctx.Query("inclDesc") == "" || ctx.QueryBool("inclDesc")), Limit: ctx.QueryInt("limit"), } - // If searching in a specific organization, require organization membership - if opts.OrgID > 0 { - if isMember, err := models.IsOrganizationMember(opts.OrgID, opts.UserID); err != nil { - ctx.Error(500, "IsOrganizationMember", err) - return - } else if !isMember && !ctx.IsUserSiteAdmin() { - ctx.Error(403, "", "Must be an organization member") - return - } - } - teams, _, err := models.SearchTeam(opts) if err != nil { ctx.JSON(500, map[string]interface{}{ @@ -567,28 +555,12 @@ func SearchTeam(ctx *context.APIContext) { } apiTeams := make([]*api.Team, len(teams)) - cache := make(map[int64]*api.Organization) for i := range teams { if err := teams[i].GetUnits(); err != nil { ctx.Error(500, "GetUnits", err) return } apiTeams[i] = convert.ToTeam(teams[i]) - - if opts.OrgID <= 0 { - apiOrg, ok := cache[teams[i].OrgID] - if !ok { - org, err := models.GetUserByID(teams[i].OrgID) - if err != nil { - ctx.Error(500, "GetUserByID", err) - return - } - apiOrg = convert.ToOrganization(org) - cache[teams[i].OrgID] = apiOrg - } - apiTeams[i] = convert.ToTeam(teams[i]) - apiTeams[i].Organization = apiOrg - } } ctx.JSON(200, map[string]interface{}{ From 2476663ad86d93d22655388821836c13987353fe Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Fri, 6 Sep 2019 15:31:56 +0000 Subject: [PATCH 03/15] Regenerate swagger Signed-off-by: David Svantesson --- templates/swagger/v1_json.tmpl | 118 ++++++++++++++++----------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 47e6a4347561..2736a8bb9239 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1047,6 +1047,65 @@ } } }, + "/orgs/{org}/teams/search": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization" + ], + "summary": "Search for teams within organization", + "operationId": "teamSearch", + "parameters": [ + { + "type": "string", + "description": "name of the organization", + "name": "org", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "keywords to search", + "name": "q", + "in": "query", + "required": true + }, + { + "type": "boolean", + "description": "include search within team description (defaults to true)", + "name": "inclDesc", + "in": "query" + }, + { + "type": "integer", + "description": "limit size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "SearchResults of a successful search", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/Team" + } + }, + "ok": { + "type": "boolean" + } + } + } + } + } + } + }, "/repos/migrate": { "post": { "consumes": [ @@ -5627,65 +5686,6 @@ } } }, - "/teams/search": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "organization" - ], - "summary": "Search for teams", - "operationId": "teamSearch", - "parameters": [ - { - "type": "string", - "description": "keywords to search", - "name": "q", - "in": "query", - "required": true - }, - { - "type": "integer", - "format": "int64", - "description": "search only teams within organization", - "name": "org_id", - "in": "query" - }, - { - "type": "boolean", - "description": "include search within team description (defaults to true)", - "name": "inclDesc", - "in": "query" - }, - { - "type": "integer", - "description": "limit size of results", - "name": "limit", - "in": "query" - } - ], - "responses": { - "200": { - "description": "SearchResults of a successful search", - "schema": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/Team" - } - }, - "ok": { - "type": "boolean" - } - } - } - } - } - } - }, "/teams/{id}": { "get": { "produces": [ From 0f075c191750ecb4cabe1be718afcdeee0d815f6 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Fri, 6 Sep 2019 16:00:45 +0000 Subject: [PATCH 04/15] Fix search is Get Signed-off-by: David Svantesson --- routers/api/v1/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 800bb1424aff..04ff91fbbf93 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -805,7 +805,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/teams", func() { m.Combo("", reqToken()).Get(org.ListTeams). Post(reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam) - m.Post("/search", org.SearchTeam) + m.Get("/search", org.SearchTeam) }, reqOrgMembership()) m.Group("/hooks", func() { m.Combo("").Get(org.ListHooks). From bfbc4ab6d9c78ca3606eb9b6ab96ab954e0d8d89 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Fri, 6 Sep 2019 20:50:35 +0200 Subject: [PATCH 05/15] Add test for search team API. Signed-off-by: David Svantesson --- integrations/api_team_test.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/integrations/api_team_test.go b/integrations/api_team_test.go index a7c22d6ba1ca..dbf7ef5e5152 100644 --- a/integrations/api_team_test.go +++ b/integrations/api_team_test.go @@ -107,3 +107,33 @@ func checkTeamBean(t *testing.T, id int64, name, description string, permission assert.NoError(t, team.GetUnits(), "GetUnits") checkTeamResponse(t, convert.ToTeam(team), name, description, permission, units) } + +type TeamSearchResults struct { + OK bool `json:"ok"` + Data []*api.Team `json:"data"` +} + +func TestAPITeamSearch(t *testing.T) { + prepareTestEnv(t) + + teamUser := models.AssertExistsAndLoadBean(t, &models.TeamUser{}).(*models.TeamUser) + user := models.AssertExistsAndLoadBean(t, &models.User{ID: teamUser.UID}).(*models.User) + org := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User) + + var results TeamSearchResults + + session := loginUser(t, user.Name) + req := NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s", org.Name, "_team") + resp := session.MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &results) + assert.NotEmpty(t, results.Data) + assert.Equal(t, 1, len(results.Data)) + assert.Equal(t, "test_team", results.Data[0].Name) + + // no access if not organization member + user5 := models.AssertExistsAndLoadBean(t, &models.User{ID: 5}).(*models.User) + session = loginUser(t, user5.Name) + req = NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s", org.Name, "team") + resp = session.MakeRequest(t, req, http.StatusForbidden) + +} From ff4520b2368cb70de380205e1015ae1439b5bada Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Fri, 6 Sep 2019 22:20:34 +0200 Subject: [PATCH 06/15] Update routers/api/v1/org/team.go grammar Co-Authored-By: Richard Mahn --- routers/api/v1/org/team.go | 2 +- templates/swagger/v1_json.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 518299362b70..e926f1c7e7b6 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -502,7 +502,7 @@ func RemoveTeamRepository(ctx *context.APIContext) { func SearchTeam(ctx *context.APIContext) { // swagger:operation GET /orgs/{org}/teams/search organization teamSearch // --- - // summary: Search for teams within organization + // summary: Search for teams within an organization // produces: // - application/json // parameters: diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 2736a8bb9239..02e462663724 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1055,7 +1055,7 @@ "tags": [ "organization" ], - "summary": "Search for teams within organization", + "summary": "Search for teams within an organization", "operationId": "teamSearch", "parameters": [ { From a1e1a9ad6a51efb2ff9110d0c028866b7af7e70f Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Fri, 13 Sep 2019 06:14:31 +0000 Subject: [PATCH 07/15] Fix review comments Signed-off-by: David Svantesson --- models/org_team.go | 4 ++-- routers/api/v1/org/team.go | 11 ++++++++--- templates/swagger/v1_json.tmpl | 3 +-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/models/org_team.go b/models/org_team.go index 6257153a22e2..af031f9b41c5 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -78,7 +78,7 @@ func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) { Count(new(Team)) if err != nil { - return nil, 0, fmt.Errorf("Count: %v", err) + return nil, 0, err } teams := make([]*Team, 0, opts.Limit) @@ -87,7 +87,7 @@ func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) { OrderBy("lower_name"). Limit(opts.Limit). Find(&teams); err != nil { - return nil, 0, fmt.Errorf("Team: %v", err) + return nil, 0, err } return teams, count, nil diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index e926f1c7e7b6..dbc23056edf5 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/convert" "code.gitea.io/gitea/routers/api/v1/user" @@ -514,7 +515,6 @@ func SearchTeam(ctx *context.APIContext) { // - name: q // in: query // description: keywords to search - // required: true // type: string // - name: inclDesc // in: query @@ -547,9 +547,10 @@ func SearchTeam(ctx *context.APIContext) { teams, _, err := models.SearchTeam(opts) if err != nil { + log.Error("SearchTeam failed: %v", err) ctx.JSON(500, map[string]interface{}{ "ok": false, - "error": err.Error(), + "error": "SearchTeam internal failure", }) return } @@ -557,7 +558,11 @@ func SearchTeam(ctx *context.APIContext) { apiTeams := make([]*api.Team, len(teams)) for i := range teams { if err := teams[i].GetUnits(); err != nil { - ctx.Error(500, "GetUnits", err) + log.Error("Team GetUnits failed: %v", err) + ctx.JSON(500, map[string]interface{}{ + "ok": false, + "error": "SearchTeam failed to get units", + }) return } apiTeams[i] = convert.ToTeam(teams[i]) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 02e462663724..a12448296881 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1069,8 +1069,7 @@ "type": "string", "description": "keywords to search", "name": "q", - "in": "query", - "required": true + "in": "query" }, { "type": "boolean", From 57bf39265e2d607121b7817356f818c6443f746b Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Mon, 23 Sep 2019 23:45:35 +0200 Subject: [PATCH 08/15] Fix some issues in repo collaboration team search, after changes in this PR. Signed-off-by: David Svantesson --- public/js/index.js | 4 ++-- templates/repo/settings/collaboration.tmpl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/js/index.js b/public/js/index.js index ad5e3912de15..8a85ad91579e 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1766,11 +1766,11 @@ function searchTeams() { $searchTeamBox.search({ minCharacters: 2, apiSettings: { - url: suburl + '/api/v1/orgs/' + $searchTeamBox.data('org') + '/teams', + url: suburl + '/api/v1/orgs/' + $searchTeamBox.data('org') + '/teams/search?q={query}', headers: {"X-Csrf-Token": csrf}, onResponse: function(response) { const items = []; - $.each(response, function (_i, item) { + $.each(response.data, function (_i, item) { const title = item.name + ' (' + item.permission + ' access)'; items.push({ title: title, diff --git a/templates/repo/settings/collaboration.tmpl b/templates/repo/settings/collaboration.tmpl index b65fd4e1679c..5e9606216316 100644 --- a/templates/repo/settings/collaboration.tmpl +++ b/templates/repo/settings/collaboration.tmpl @@ -94,7 +94,7 @@
{{.CsrfTokenHtml}}
-