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:
Harshit Bansal 2019-01-17 06:09:50 +05:30 committed by techknowlogick
parent 734834a676
commit 5ac6da3c41
10 changed files with 160 additions and 12 deletions

4
Gopkg.lock generated
View file

@ -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"

View file

@ -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
} }

View file

@ -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,

View file

@ -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)

View file

@ -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)
}) })

View file

@ -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

View file

@ -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": [

View file

@ -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"`

View file

@ -10,6 +10,7 @@ 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

View file

@ -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"`