api: Add missing GET teams endpoints (#5382)
* api: Add an endpoint to list a particular member of team. * models: Rename `GetUserTeams()` to `GetUserOrgTeams()` in `org_team` model. `GetUserTeams()` sounds a bit misnomer since it actually returns the teams that user belongs to in a given organization rather than all the teams across all the organization that the user has joined. * models: Add `GetUserTeams()`. Returns all the teams that a user belongs to. * api: Add an endpoint for GET '/user/teams'. A GET request to this endpoint lists all the teams that a user belongs to.
This commit is contained in:
parent
734834a676
commit
5ac6da3c41
10 changed files with 160 additions and 12 deletions
4
Gopkg.lock
generated
4
Gopkg.lock
generated
|
@ -11,11 +11,11 @@
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:aed2bc1c4026233af8ad43cab9d9464a0e3b906d3d058d2d6e814f3e1ddfa528"
|
digest = "1:8a559f110defa54f847a3efa2734297571d960b476699579f2008e4a37b62a1a"
|
||||||
name = "code.gitea.io/sdk"
|
name = "code.gitea.io/sdk"
|
||||||
packages = ["gitea"]
|
packages = ["gitea"]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "d95a6e0392218961d1bdd18020290a20bd61b063"
|
revision = "140e9fcba7583e1c6f22eb57676bb00794ef14a8"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:3fcef06a1a6561955c94af6c7757a6fa37605eb653f0d06ab960e5bb80092195"
|
digest = "1:3fcef06a1a6561955c94af6c7757a6fa37605eb653f0d06ab960e5bb80092195"
|
||||||
|
|
|
@ -522,7 +522,7 @@ func removeOrgUser(sess *xorm.Session, orgID, userID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete member in his/her teams.
|
// Delete member in his/her teams.
|
||||||
teams, err := getUserTeams(sess, org.ID, userID)
|
teams, err := getUserOrgTeams(sess, org.ID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -543,7 +543,14 @@ func GetTeamMembers(teamID int64) ([]*User, error) {
|
||||||
return getTeamMembers(x, teamID)
|
return getTeamMembers(x, teamID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserTeams(e Engine, orgID, userID int64) (teams []*Team, err error) {
|
func getUserTeams(e Engine, userID int64) (teams []*Team, err error) {
|
||||||
|
return teams, e.
|
||||||
|
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||||
|
Where("team_user.uid=?", userID).
|
||||||
|
Find(&teams)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserOrgTeams(e Engine, orgID, userID int64) (teams []*Team, err error) {
|
||||||
return teams, e.
|
return teams, e.
|
||||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||||
Where("team.org_id = ?", orgID).
|
Where("team.org_id = ?", orgID).
|
||||||
|
@ -561,9 +568,14 @@ func getUserRepoTeams(e Engine, orgID, userID, repoID int64) (teams []*Team, err
|
||||||
Find(&teams)
|
Find(&teams)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserTeams returns all teams that user belongs to in given organization.
|
// GetUserOrgTeams returns all teams that user belongs to in given organization.
|
||||||
func GetUserTeams(orgID, userID int64) ([]*Team, error) {
|
func GetUserOrgTeams(orgID, userID int64) ([]*Team, error) {
|
||||||
return getUserTeams(x, orgID, userID)
|
return getUserOrgTeams(x, orgID, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserTeams returns all teams that user belongs across all organizations.
|
||||||
|
func GetUserTeams(userID int64) ([]*Team, error) {
|
||||||
|
return getUserTeams(x, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTeamMember adds new membership of given team to given organization,
|
// AddTeamMember adds new membership of given team to given organization,
|
||||||
|
|
|
@ -284,9 +284,23 @@ func TestGetTeamMembers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetUserTeams(t *testing.T) {
|
func TestGetUserTeams(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
test := func(userID int64) {
|
||||||
|
teams, err := GetUserTeams(userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
for _, team := range teams {
|
||||||
|
AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(2)
|
||||||
|
test(5)
|
||||||
|
test(NonexistentID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUserOrgTeams(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
test := func(orgID, userID int64) {
|
test := func(orgID, userID int64) {
|
||||||
teams, err := GetUserTeams(orgID, userID)
|
teams, err := GetUserOrgTeams(orgID, userID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
for _, team := range teams {
|
for _, team := range teams {
|
||||||
assert.EqualValues(t, orgID, team.OrgID)
|
assert.EqualValues(t, orgID, team.OrgID)
|
||||||
|
|
|
@ -463,6 +463,8 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Get("/times", repo.ListMyTrackedTimes)
|
m.Get("/times", repo.ListMyTrackedTimes)
|
||||||
|
|
||||||
m.Get("/subscriptions", user.GetMyWatchedRepos)
|
m.Get("/subscriptions", user.GetMyWatchedRepos)
|
||||||
|
|
||||||
|
m.Get("/teams", org.ListUserTeams)
|
||||||
}, reqToken())
|
}, reqToken())
|
||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
|
@ -652,6 +654,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Group("/members", func() {
|
m.Group("/members", func() {
|
||||||
m.Get("", org.GetTeamMembers)
|
m.Get("", org.GetTeamMembers)
|
||||||
m.Combo("/:username").
|
m.Combo("/:username").
|
||||||
|
Get(org.GetTeamMember).
|
||||||
Put(reqOrgOwnership(), org.AddTeamMember).
|
Put(reqOrgOwnership(), org.AddTeamMember).
|
||||||
Delete(reqOrgOwnership(), org.RemoveTeamMember)
|
Delete(reqOrgOwnership(), org.RemoveTeamMember)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -42,6 +43,41 @@ func ListTeams(ctx *context.APIContext) {
|
||||||
ctx.JSON(200, apiTeams)
|
ctx.JSON(200, apiTeams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListUserTeams list all the teams a user belongs to
|
||||||
|
func ListUserTeams(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /user/teams user userListTeams
|
||||||
|
// ---
|
||||||
|
// summary: List all the teams a user belongs to
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/TeamList"
|
||||||
|
teams, err := models.GetUserTeams(ctx.User.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(500, "GetUserTeams", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cache := make(map[int64]*api.Organization)
|
||||||
|
apiTeams := make([]*api.Team, len(teams))
|
||||||
|
for i := range teams {
|
||||||
|
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, apiTeams)
|
||||||
|
}
|
||||||
|
|
||||||
// GetTeam api for get a team
|
// GetTeam api for get a team
|
||||||
func GetTeam(ctx *context.APIContext) {
|
func GetTeam(ctx *context.APIContext) {
|
||||||
// swagger:operation GET /teams/{id} organization orgGetTeam
|
// swagger:operation GET /teams/{id} organization orgGetTeam
|
||||||
|
@ -221,6 +257,35 @@ func GetTeamMembers(ctx *context.APIContext) {
|
||||||
ctx.JSON(200, members)
|
ctx.JSON(200, members)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTeamMember api for get a particular member of team
|
||||||
|
func GetTeamMember(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /teams/{id}/members/{username} organization orgListTeamMember
|
||||||
|
// ---
|
||||||
|
// summary: List a particular member of team
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: id
|
||||||
|
// in: path
|
||||||
|
// description: id of the team
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// - name: username
|
||||||
|
// in: path
|
||||||
|
// description: username of the member to list
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/User"
|
||||||
|
u := user.GetUserByParams(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(200, u.APIFormat())
|
||||||
|
}
|
||||||
|
|
||||||
// AddTeamMember api for add a member to a team
|
// AddTeamMember api for add a member to a team
|
||||||
func AddTeamMember(ctx *context.APIContext) {
|
func AddTeamMember(ctx *context.APIContext) {
|
||||||
// swagger:operation PUT /teams/{id}/members/{username} organization orgAddTeamMember
|
// swagger:operation PUT /teams/{id}/members/{username} organization orgAddTeamMember
|
||||||
|
|
|
@ -4629,6 +4629,38 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/teams/{id}/members/{username}": {
|
"/teams/{id}/members/{username}": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"organization"
|
||||||
|
],
|
||||||
|
"summary": "List a particular member of team",
|
||||||
|
"operationId": "orgListTeamMember",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "id of the team",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "username of the member to list",
|
||||||
|
"name": "username",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/User"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"put": {
|
"put": {
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
|
@ -5418,6 +5450,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/teams": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "List all the teams a user belongs to",
|
||||||
|
"operationId": "userListTeams",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/TeamList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/times": {
|
"/user/times": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
@ -7942,6 +7991,9 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "Name"
|
"x-go-name": "Name"
|
||||||
},
|
},
|
||||||
|
"organization": {
|
||||||
|
"$ref": "#/definitions/Organization"
|
||||||
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
|
1
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
1
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
|
@ -371,6 +371,7 @@ type PushPayload struct {
|
||||||
After string `json:"after"`
|
After string `json:"after"`
|
||||||
CompareURL string `json:"compare_url"`
|
CompareURL string `json:"compare_url"`
|
||||||
Commits []*PayloadCommit `json:"commits"`
|
Commits []*PayloadCommit `json:"commits"`
|
||||||
|
HeadCommit *PayloadCommit `json:"head_commit"`
|
||||||
Repo *Repository `json:"repository"`
|
Repo *Repository `json:"repository"`
|
||||||
Pusher *User `json:"pusher"`
|
Pusher *User `json:"pusher"`
|
||||||
Sender *User `json:"sender"`
|
Sender *User `json:"sender"`
|
||||||
|
|
7
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
7
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
|
@ -7,9 +7,10 @@ package gitea
|
||||||
|
|
||||||
// Team represents a team in an organization
|
// Team represents a team in an organization
|
||||||
type Team struct {
|
type Team struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
|
Organization *Organization `json:"organization"`
|
||||||
// enum: none,read,write,admin,owner
|
// enum: none,read,write,admin,owner
|
||||||
Permission string `json:"permission"`
|
Permission string `json:"permission"`
|
||||||
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
|
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
|
||||||
|
|
2
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
2
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
|
@ -53,7 +53,7 @@ func (c *Client) GetRelease(user, repo string, id int64) (*Release, error) {
|
||||||
type CreateReleaseOption struct {
|
type CreateReleaseOption struct {
|
||||||
// required: true
|
// required: true
|
||||||
TagName string `json:"tag_name" binding:"Required"`
|
TagName string `json:"tag_name" binding:"Required"`
|
||||||
Target string `json:"target_commitish"`
|
Target string `json:"target_commitish" binding:"Required"`
|
||||||
Title string `json:"name"`
|
Title string `json:"name"`
|
||||||
Note string `json:"body"`
|
Note string `json:"body"`
|
||||||
IsDraft bool `json:"draft"`
|
IsDraft bool `json:"draft"`
|
||||||
|
|
Reference in a new issue