From 5f6b118007fb8e474883d22cc230b26016b6c987 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 24 Apr 2019 20:41:02 +0800 Subject: [PATCH] Fix team members API (#6714) (#6729) --- integrations/api_team_test.go | 13 ++++++++++++ routers/api/v1/api.go | 39 ++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/integrations/api_team_test.go b/integrations/api_team_test.go index f59d95c7122..da29dea9f79 100644 --- a/integrations/api_team_test.go +++ b/integrations/api_team_test.go @@ -16,6 +16,7 @@ import ( func TestAPITeam(t *testing.T) { prepareTestEnv(t) + teamUser := models.AssertExistsAndLoadBean(t, &models.TeamUser{}).(*models.TeamUser) team := models.AssertExistsAndLoadBean(t, &models.Team{ID: teamUser.TeamID}).(*models.Team) user := models.AssertExistsAndLoadBean(t, &models.User{ID: teamUser.UID}).(*models.User) @@ -29,4 +30,16 @@ func TestAPITeam(t *testing.T) { DecodeJSON(t, resp, &apiTeam) assert.EqualValues(t, team.ID, apiTeam.ID) assert.Equal(t, team.Name, apiTeam.Name) + + // non team member user will not access the teams details + teamUser2 := models.AssertExistsAndLoadBean(t, &models.TeamUser{ID: 3}).(*models.TeamUser) + user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: teamUser2.UID}).(*models.User) + + session = loginUser(t, user2.Name) + token = getTokenForLoggedInUser(t, session) + req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID) + resp = session.MakeRequest(t, req, http.StatusForbidden) + + req = NewRequestf(t, "GET", "/api/v1/teams/%d", teamUser.TeamID) + resp = session.MakeRequest(t, req, http.StatusUnauthorized) } diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index f377e309034..30fcdb31592 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -280,6 +280,43 @@ func reqOrgMembership() macaron.Handler { } } +// reqTeamMembership user should be an team member, or a site admin +func reqTeamMembership() macaron.Handler { + return func(ctx *context.APIContext) { + if ctx.User.IsAdmin { + return + } + if ctx.Org.Team == nil { + ctx.Error(500, "", "reqTeamMembership: unprepared context") + return + } + + var orgID = ctx.Org.Team.OrgID + isOwner, err := models.IsOrganizationOwner(orgID, ctx.User.ID) + if err != nil { + ctx.Error(500, "IsOrganizationOwner", err) + return + } else if isOwner { + return + } + + if isTeamMember, err := models.IsTeamMember(orgID, ctx.Org.Team.ID, ctx.User.ID); err != nil { + ctx.Error(500, "IsTeamMember", err) + return + } else if !isTeamMember { + isOrgMember, err := models.IsOrganizationMember(orgID, ctx.User.ID) + if err != nil { + ctx.Error(500, "IsOrganizationMember", err) + } else if isOrgMember { + ctx.Error(403, "", "Must be a team member") + } else { + ctx.Status(404) + } + return + } + } +} + func reqOrgOwnership() macaron.Handler { return func(ctx *context.APIContext) { var orgID int64 @@ -686,7 +723,7 @@ func RegisterRoutes(m *macaron.Macaron) { Put(org.AddTeamRepository). Delete(org.RemoveTeamRepository) }) - }, orgAssignment(false, true), reqToken(), reqOrgMembership()) + }, orgAssignment(false, true), reqToken(), reqTeamMembership()) m.Any("/*", func(ctx *context.Context) { ctx.Error(404)