You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

api_team_test.go 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "fmt"
  6. "net/http"
  7. "sort"
  8. "testing"
  9. "code.gitea.io/gitea/models/organization"
  10. "code.gitea.io/gitea/models/repo"
  11. "code.gitea.io/gitea/models/unit"
  12. "code.gitea.io/gitea/models/unittest"
  13. user_model "code.gitea.io/gitea/models/user"
  14. "code.gitea.io/gitea/modules/convert"
  15. api "code.gitea.io/gitea/modules/structs"
  16. "code.gitea.io/gitea/tests"
  17. "github.com/stretchr/testify/assert"
  18. )
  19. func TestAPITeam(t *testing.T) {
  20. defer tests.PrepareTestEnv(t)()
  21. teamUser := unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{})
  22. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamUser.TeamID})
  23. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser.UID})
  24. session := loginUser(t, user.Name)
  25. token := getTokenForLoggedInUser(t, session)
  26. req := NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
  27. resp := session.MakeRequest(t, req, http.StatusOK)
  28. var apiTeam api.Team
  29. DecodeJSON(t, resp, &apiTeam)
  30. assert.EqualValues(t, team.ID, apiTeam.ID)
  31. assert.Equal(t, team.Name, apiTeam.Name)
  32. // non team member user will not access the teams details
  33. teamUser2 := unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{ID: 3})
  34. user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser2.UID})
  35. session = loginUser(t, user2.Name)
  36. token = getTokenForLoggedInUser(t, session)
  37. req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
  38. _ = session.MakeRequest(t, req, http.StatusForbidden)
  39. req = NewRequestf(t, "GET", "/api/v1/teams/%d", teamUser.TeamID)
  40. _ = session.MakeRequest(t, req, http.StatusUnauthorized)
  41. // Get an admin user able to create, update and delete teams.
  42. user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
  43. session = loginUser(t, user.Name)
  44. token = getTokenForLoggedInUser(t, session)
  45. org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 6})
  46. // Create team.
  47. teamToCreate := &api.CreateTeamOption{
  48. Name: "team1",
  49. Description: "team one",
  50. IncludesAllRepositories: true,
  51. Permission: "write",
  52. Units: []string{"repo.code", "repo.issues"},
  53. }
  54. req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams?token=%s", org.Name, token), teamToCreate)
  55. resp = session.MakeRequest(t, req, http.StatusCreated)
  56. apiTeam = api.Team{}
  57. DecodeJSON(t, resp, &apiTeam)
  58. checkTeamResponse(t, "CreateTeam1", &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
  59. teamToCreate.Permission, teamToCreate.Units, nil)
  60. checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
  61. teamToCreate.Permission, teamToCreate.Units, nil)
  62. teamID := apiTeam.ID
  63. // Edit team.
  64. editDescription := "team 1"
  65. editFalse := false
  66. teamToEdit := &api.EditTeamOption{
  67. Name: "teamone",
  68. Description: &editDescription,
  69. Permission: "admin",
  70. IncludesAllRepositories: &editFalse,
  71. Units: []string{"repo.code", "repo.pulls", "repo.releases"},
  72. }
  73. req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/teams/%d?token=%s", teamID, token), teamToEdit)
  74. resp = session.MakeRequest(t, req, http.StatusOK)
  75. apiTeam = api.Team{}
  76. DecodeJSON(t, resp, &apiTeam)
  77. checkTeamResponse(t, "EditTeam1", &apiTeam, teamToEdit.Name, *teamToEdit.Description, *teamToEdit.IncludesAllRepositories,
  78. teamToEdit.Permission, unit.AllUnitKeyNames(), nil)
  79. checkTeamBean(t, apiTeam.ID, teamToEdit.Name, *teamToEdit.Description, *teamToEdit.IncludesAllRepositories,
  80. teamToEdit.Permission, unit.AllUnitKeyNames(), nil)
  81. // Edit team Description only
  82. editDescription = "first team"
  83. teamToEditDesc := api.EditTeamOption{Description: &editDescription}
  84. req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/teams/%d?token=%s", teamID, token), teamToEditDesc)
  85. resp = session.MakeRequest(t, req, http.StatusOK)
  86. apiTeam = api.Team{}
  87. DecodeJSON(t, resp, &apiTeam)
  88. checkTeamResponse(t, "EditTeam1_DescOnly", &apiTeam, teamToEdit.Name, *teamToEditDesc.Description, *teamToEdit.IncludesAllRepositories,
  89. teamToEdit.Permission, unit.AllUnitKeyNames(), nil)
  90. checkTeamBean(t, apiTeam.ID, teamToEdit.Name, *teamToEditDesc.Description, *teamToEdit.IncludesAllRepositories,
  91. teamToEdit.Permission, unit.AllUnitKeyNames(), nil)
  92. // Read team.
  93. teamRead := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
  94. assert.NoError(t, teamRead.GetUnits())
  95. req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
  96. resp = session.MakeRequest(t, req, http.StatusOK)
  97. apiTeam = api.Team{}
  98. DecodeJSON(t, resp, &apiTeam)
  99. checkTeamResponse(t, "ReadTeam1", &apiTeam, teamRead.Name, *teamToEditDesc.Description, teamRead.IncludesAllRepositories,
  100. teamRead.AccessMode.String(), teamRead.GetUnitNames(), teamRead.GetUnitsMap())
  101. // Delete team.
  102. req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
  103. session.MakeRequest(t, req, http.StatusNoContent)
  104. unittest.AssertNotExistsBean(t, &organization.Team{ID: teamID})
  105. // create team again via UnitsMap
  106. // Create team.
  107. teamToCreate = &api.CreateTeamOption{
  108. Name: "team2",
  109. Description: "team two",
  110. IncludesAllRepositories: true,
  111. Permission: "write",
  112. UnitsMap: map[string]string{"repo.code": "read", "repo.issues": "write", "repo.wiki": "none"},
  113. }
  114. req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams?token=%s", org.Name, token), teamToCreate)
  115. resp = session.MakeRequest(t, req, http.StatusCreated)
  116. apiTeam = api.Team{}
  117. DecodeJSON(t, resp, &apiTeam)
  118. checkTeamResponse(t, "CreateTeam2", &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
  119. "read", nil, teamToCreate.UnitsMap)
  120. checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
  121. "read", nil, teamToCreate.UnitsMap)
  122. teamID = apiTeam.ID
  123. // Edit team.
  124. editDescription = "team 1"
  125. editFalse = false
  126. teamToEdit = &api.EditTeamOption{
  127. Name: "teamtwo",
  128. Description: &editDescription,
  129. Permission: "write",
  130. IncludesAllRepositories: &editFalse,
  131. UnitsMap: map[string]string{"repo.code": "read", "repo.pulls": "read", "repo.releases": "write"},
  132. }
  133. req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/teams/%d?token=%s", teamID, token), teamToEdit)
  134. resp = session.MakeRequest(t, req, http.StatusOK)
  135. apiTeam = api.Team{}
  136. DecodeJSON(t, resp, &apiTeam)
  137. checkTeamResponse(t, "EditTeam2", &apiTeam, teamToEdit.Name, *teamToEdit.Description, *teamToEdit.IncludesAllRepositories,
  138. "read", nil, teamToEdit.UnitsMap)
  139. checkTeamBean(t, apiTeam.ID, teamToEdit.Name, *teamToEdit.Description, *teamToEdit.IncludesAllRepositories,
  140. "read", nil, teamToEdit.UnitsMap)
  141. // Edit team Description only
  142. editDescription = "second team"
  143. teamToEditDesc = api.EditTeamOption{Description: &editDescription}
  144. req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/teams/%d?token=%s", teamID, token), teamToEditDesc)
  145. resp = session.MakeRequest(t, req, http.StatusOK)
  146. apiTeam = api.Team{}
  147. DecodeJSON(t, resp, &apiTeam)
  148. checkTeamResponse(t, "EditTeam2_DescOnly", &apiTeam, teamToEdit.Name, *teamToEditDesc.Description, *teamToEdit.IncludesAllRepositories,
  149. "read", nil, teamToEdit.UnitsMap)
  150. checkTeamBean(t, apiTeam.ID, teamToEdit.Name, *teamToEditDesc.Description, *teamToEdit.IncludesAllRepositories,
  151. "read", nil, teamToEdit.UnitsMap)
  152. // Read team.
  153. teamRead = unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
  154. req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
  155. resp = session.MakeRequest(t, req, http.StatusOK)
  156. apiTeam = api.Team{}
  157. DecodeJSON(t, resp, &apiTeam)
  158. assert.NoError(t, teamRead.GetUnits())
  159. checkTeamResponse(t, "ReadTeam2", &apiTeam, teamRead.Name, *teamToEditDesc.Description, teamRead.IncludesAllRepositories,
  160. teamRead.AccessMode.String(), teamRead.GetUnitNames(), teamRead.GetUnitsMap())
  161. // Delete team.
  162. req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
  163. session.MakeRequest(t, req, http.StatusNoContent)
  164. unittest.AssertNotExistsBean(t, &organization.Team{ID: teamID})
  165. }
  166. func checkTeamResponse(t *testing.T, testName string, apiTeam *api.Team, name, description string, includesAllRepositories bool, permission string, units []string, unitsMap map[string]string) {
  167. t.Run(testName, func(t *testing.T) {
  168. assert.Equal(t, name, apiTeam.Name, "name")
  169. assert.Equal(t, description, apiTeam.Description, "description")
  170. assert.Equal(t, includesAllRepositories, apiTeam.IncludesAllRepositories, "includesAllRepositories")
  171. assert.Equal(t, permission, apiTeam.Permission, "permission")
  172. if units != nil {
  173. sort.StringSlice(units).Sort()
  174. sort.StringSlice(apiTeam.Units).Sort()
  175. assert.EqualValues(t, units, apiTeam.Units, "units")
  176. }
  177. if unitsMap != nil {
  178. assert.EqualValues(t, unitsMap, apiTeam.UnitsMap, "unitsMap")
  179. }
  180. })
  181. }
  182. func checkTeamBean(t *testing.T, id int64, name, description string, includesAllRepositories bool, permission string, units []string, unitsMap map[string]string) {
  183. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: id})
  184. assert.NoError(t, team.GetUnits(), "GetUnits")
  185. apiTeam, err := convert.ToTeam(team)
  186. assert.NoError(t, err)
  187. checkTeamResponse(t, fmt.Sprintf("checkTeamBean/%s_%s", name, description), apiTeam, name, description, includesAllRepositories, permission, units, unitsMap)
  188. }
  189. type TeamSearchResults struct {
  190. OK bool `json:"ok"`
  191. Data []*api.Team `json:"data"`
  192. }
  193. func TestAPITeamSearch(t *testing.T) {
  194. defer tests.PrepareTestEnv(t)()
  195. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  196. org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 17})
  197. var results TeamSearchResults
  198. token := getUserToken(t, user.Name)
  199. req := NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "_team", token)
  200. resp := MakeRequest(t, req, http.StatusOK)
  201. DecodeJSON(t, resp, &results)
  202. assert.NotEmpty(t, results.Data)
  203. assert.Len(t, results.Data, 1)
  204. assert.Equal(t, "test_team", results.Data[0].Name)
  205. // no access if not organization member
  206. user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
  207. token5 := getUserToken(t, user5.Name)
  208. req = NewRequestf(t, "GET", "/api/v1/orgs/%s/teams/search?q=%s&token=%s", org.Name, "team", token5)
  209. MakeRequest(t, req, http.StatusForbidden)
  210. }
  211. func TestAPIGetTeamRepo(t *testing.T) {
  212. defer tests.PrepareTestEnv(t)()
  213. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
  214. teamRepo := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 24})
  215. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5})
  216. var results api.Repository
  217. token := getUserToken(t, user.Name)
  218. req := NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token)
  219. resp := MakeRequest(t, req, http.StatusOK)
  220. DecodeJSON(t, resp, &results)
  221. assert.Equal(t, "big_test_private_4", teamRepo.Name)
  222. // no access if not organization member
  223. user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
  224. token5 := getUserToken(t, user5.Name)
  225. req = NewRequestf(t, "GET", "/api/v1/teams/%d/repos/%s/?token=%s", team.ID, teamRepo.FullName(), token5)
  226. MakeRequest(t, req, http.StatusNotFound)
  227. }