From 59be704efb3ae9c2c5b41720e5cd1fc86c550608 Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Wed, 24 Apr 2019 13:32:35 +0800
Subject: [PATCH] Fix team members API (#6714)

---
 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 f59d95c712..da29dea9f7 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 d201dff917..4d8364afb0 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -286,6 +286,43 @@ func reqOrgOwnership() macaron.Handler {
 	}
 }
 
+// reqTeamMembership user should be an team member, or a site admin
+func reqTeamMembership() macaron.Handler {
+	return func(ctx *context.APIContext) {
+		if ctx.Context.IsUserSiteAdmin() {
+			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.NotFound()
+			}
+			return
+		}
+	}
+}
+
 // reqOrgMembership user should be an organization member, or a site admin
 func reqOrgMembership() macaron.Handler {
 	return func(ctx *context.APIContext) {
@@ -775,7 +812,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.APIContext) {
 			ctx.NotFound()