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.

509 lines
14 KiB

  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "fmt"
  7. "strings"
  8. "testing"
  9. "code.gitea.io/gitea/modules/structs"
  10. "github.com/stretchr/testify/assert"
  11. )
  12. func TestTeam_IsOwnerTeam(t *testing.T) {
  13. assert.NoError(t, PrepareTestDatabase())
  14. team := AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
  15. assert.True(t, team.IsOwnerTeam())
  16. team = AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
  17. assert.False(t, team.IsOwnerTeam())
  18. }
  19. func TestTeam_IsMember(t *testing.T) {
  20. assert.NoError(t, PrepareTestDatabase())
  21. team := AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
  22. assert.True(t, team.IsMember(2))
  23. assert.False(t, team.IsMember(4))
  24. assert.False(t, team.IsMember(NonexistentID))
  25. team = AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
  26. assert.True(t, team.IsMember(2))
  27. assert.True(t, team.IsMember(4))
  28. assert.False(t, team.IsMember(NonexistentID))
  29. }
  30. func TestTeam_GetRepositories(t *testing.T) {
  31. assert.NoError(t, PrepareTestDatabase())
  32. test := func(teamID int64) {
  33. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  34. assert.NoError(t, team.GetRepositories())
  35. assert.Len(t, team.Repos, team.NumRepos)
  36. for _, repo := range team.Repos {
  37. AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID})
  38. }
  39. }
  40. test(1)
  41. test(3)
  42. }
  43. func TestTeam_GetMembers(t *testing.T) {
  44. assert.NoError(t, PrepareTestDatabase())
  45. test := func(teamID int64) {
  46. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  47. assert.NoError(t, team.GetMembers())
  48. assert.Len(t, team.Members, team.NumMembers)
  49. for _, member := range team.Members {
  50. AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID})
  51. }
  52. }
  53. test(1)
  54. test(3)
  55. }
  56. func TestTeam_AddMember(t *testing.T) {
  57. assert.NoError(t, PrepareTestDatabase())
  58. test := func(teamID, userID int64) {
  59. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  60. assert.NoError(t, team.AddMember(userID))
  61. AssertExistsAndLoadBean(t, &TeamUser{UID: userID, TeamID: teamID})
  62. CheckConsistencyFor(t, &Team{ID: teamID}, &User{ID: team.OrgID})
  63. }
  64. test(1, 2)
  65. test(1, 4)
  66. test(3, 2)
  67. }
  68. func TestTeam_RemoveMember(t *testing.T) {
  69. assert.NoError(t, PrepareTestDatabase())
  70. testSuccess := func(teamID, userID int64) {
  71. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  72. assert.NoError(t, team.RemoveMember(userID))
  73. AssertNotExistsBean(t, &TeamUser{UID: userID, TeamID: teamID})
  74. CheckConsistencyFor(t, &Team{ID: teamID})
  75. }
  76. testSuccess(1, 4)
  77. testSuccess(2, 2)
  78. testSuccess(3, 2)
  79. testSuccess(3, NonexistentID)
  80. team := AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
  81. err := team.RemoveMember(2)
  82. assert.True(t, IsErrLastOrgOwner(err))
  83. }
  84. func TestTeam_HasRepository(t *testing.T) {
  85. assert.NoError(t, PrepareTestDatabase())
  86. test := func(teamID, repoID int64, expected bool) {
  87. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  88. assert.Equal(t, expected, team.HasRepository(repoID))
  89. }
  90. test(1, 1, false)
  91. test(1, 3, true)
  92. test(1, 5, true)
  93. test(1, NonexistentID, false)
  94. test(2, 3, true)
  95. test(2, 5, false)
  96. }
  97. func TestTeam_AddRepository(t *testing.T) {
  98. assert.NoError(t, PrepareTestDatabase())
  99. testSuccess := func(teamID, repoID int64) {
  100. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  101. repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
  102. assert.NoError(t, team.AddRepository(repo))
  103. AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repoID})
  104. CheckConsistencyFor(t, &Team{ID: teamID}, &Repository{ID: repoID})
  105. }
  106. testSuccess(2, 3)
  107. testSuccess(2, 5)
  108. team := AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
  109. repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
  110. assert.Error(t, team.AddRepository(repo))
  111. CheckConsistencyFor(t, &Team{ID: 1}, &Repository{ID: 1})
  112. }
  113. func TestTeam_RemoveRepository(t *testing.T) {
  114. assert.NoError(t, PrepareTestDatabase())
  115. testSuccess := func(teamID, repoID int64) {
  116. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  117. assert.NoError(t, team.RemoveRepository(repoID))
  118. AssertNotExistsBean(t, &TeamRepo{TeamID: teamID, RepoID: repoID})
  119. CheckConsistencyFor(t, &Team{ID: teamID}, &Repository{ID: repoID})
  120. }
  121. testSuccess(2, 3)
  122. testSuccess(2, 5)
  123. testSuccess(1, NonexistentID)
  124. }
  125. func TestIsUsableTeamName(t *testing.T) {
  126. assert.NoError(t, IsUsableTeamName("usable"))
  127. assert.True(t, IsErrNameReserved(IsUsableTeamName("new")))
  128. }
  129. func TestNewTeam(t *testing.T) {
  130. assert.NoError(t, PrepareTestDatabase())
  131. const teamName = "newTeamName"
  132. team := &Team{Name: teamName, OrgID: 3}
  133. assert.NoError(t, NewTeam(team))
  134. AssertExistsAndLoadBean(t, &Team{Name: teamName})
  135. CheckConsistencyFor(t, &Team{}, &User{ID: team.OrgID})
  136. }
  137. func TestGetTeam(t *testing.T) {
  138. assert.NoError(t, PrepareTestDatabase())
  139. testSuccess := func(orgID int64, name string) {
  140. team, err := GetTeam(orgID, name)
  141. assert.NoError(t, err)
  142. assert.EqualValues(t, orgID, team.OrgID)
  143. assert.Equal(t, name, team.Name)
  144. }
  145. testSuccess(3, "Owners")
  146. testSuccess(3, "team1")
  147. _, err := GetTeam(3, "nonexistent")
  148. assert.Error(t, err)
  149. _, err = GetTeam(NonexistentID, "Owners")
  150. assert.Error(t, err)
  151. }
  152. func TestGetTeamByID(t *testing.T) {
  153. assert.NoError(t, PrepareTestDatabase())
  154. testSuccess := func(teamID int64) {
  155. team, err := GetTeamByID(teamID)
  156. assert.NoError(t, err)
  157. assert.EqualValues(t, teamID, team.ID)
  158. }
  159. testSuccess(1)
  160. testSuccess(2)
  161. testSuccess(3)
  162. testSuccess(4)
  163. _, err := GetTeamByID(NonexistentID)
  164. assert.Error(t, err)
  165. }
  166. func TestUpdateTeam(t *testing.T) {
  167. // successful update
  168. assert.NoError(t, PrepareTestDatabase())
  169. team := AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
  170. team.LowerName = "newname"
  171. team.Name = "newName"
  172. team.Description = strings.Repeat("A long description!", 100)
  173. team.Authorize = AccessModeAdmin
  174. assert.NoError(t, UpdateTeam(team, true, false))
  175. team = AssertExistsAndLoadBean(t, &Team{Name: "newName"}).(*Team)
  176. assert.True(t, strings.HasPrefix(team.Description, "A long description!"))
  177. access := AssertExistsAndLoadBean(t, &Access{UserID: 4, RepoID: 3}).(*Access)
  178. assert.EqualValues(t, AccessModeAdmin, access.Mode)
  179. CheckConsistencyFor(t, &Team{ID: team.ID})
  180. }
  181. func TestUpdateTeam2(t *testing.T) {
  182. // update to already-existing team
  183. assert.NoError(t, PrepareTestDatabase())
  184. team := AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
  185. team.LowerName = "owners"
  186. team.Name = "Owners"
  187. team.Description = strings.Repeat("A long description!", 100)
  188. err := UpdateTeam(team, true, false)
  189. assert.True(t, IsErrTeamAlreadyExist(err))
  190. CheckConsistencyFor(t, &Team{ID: team.ID})
  191. }
  192. func TestDeleteTeam(t *testing.T) {
  193. assert.NoError(t, PrepareTestDatabase())
  194. team := AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
  195. assert.NoError(t, DeleteTeam(team))
  196. AssertNotExistsBean(t, &Team{ID: team.ID})
  197. AssertNotExistsBean(t, &TeamRepo{TeamID: team.ID})
  198. AssertNotExistsBean(t, &TeamUser{TeamID: team.ID})
  199. // check that team members don't have "leftover" access to repos
  200. user := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
  201. repo := AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository)
  202. accessMode, err := AccessLevel(user, repo)
  203. assert.NoError(t, err)
  204. assert.True(t, accessMode < AccessModeWrite)
  205. }
  206. func TestIsTeamMember(t *testing.T) {
  207. assert.NoError(t, PrepareTestDatabase())
  208. test := func(orgID, teamID, userID int64, expected bool) {
  209. isMember, err := IsTeamMember(orgID, teamID, userID)
  210. assert.NoError(t, err)
  211. assert.Equal(t, expected, isMember)
  212. }
  213. test(3, 1, 2, true)
  214. test(3, 1, 4, false)
  215. test(3, 1, NonexistentID, false)
  216. test(3, 2, 2, true)
  217. test(3, 2, 4, true)
  218. test(3, NonexistentID, NonexistentID, false)
  219. test(NonexistentID, NonexistentID, NonexistentID, false)
  220. }
  221. func TestGetTeamMembers(t *testing.T) {
  222. assert.NoError(t, PrepareTestDatabase())
  223. test := func(teamID int64) {
  224. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  225. members, err := GetTeamMembers(teamID)
  226. assert.NoError(t, err)
  227. assert.Len(t, members, team.NumMembers)
  228. for _, member := range members {
  229. AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID})
  230. }
  231. }
  232. test(1)
  233. test(3)
  234. }
  235. func TestGetUserTeams(t *testing.T) {
  236. assert.NoError(t, PrepareTestDatabase())
  237. test := func(userID int64) {
  238. teams, err := GetUserTeams(userID)
  239. assert.NoError(t, err)
  240. for _, team := range teams {
  241. AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
  242. }
  243. }
  244. test(2)
  245. test(5)
  246. test(NonexistentID)
  247. }
  248. func TestGetUserOrgTeams(t *testing.T) {
  249. assert.NoError(t, PrepareTestDatabase())
  250. test := func(orgID, userID int64) {
  251. teams, err := GetUserOrgTeams(orgID, userID)
  252. assert.NoError(t, err)
  253. for _, team := range teams {
  254. assert.EqualValues(t, orgID, team.OrgID)
  255. AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
  256. }
  257. }
  258. test(3, 2)
  259. test(3, 4)
  260. test(3, NonexistentID)
  261. }
  262. func TestAddTeamMember(t *testing.T) {
  263. assert.NoError(t, PrepareTestDatabase())
  264. test := func(teamID, userID int64) {
  265. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  266. assert.NoError(t, AddTeamMember(team, userID))
  267. AssertExistsAndLoadBean(t, &TeamUser{UID: userID, TeamID: teamID})
  268. CheckConsistencyFor(t, &Team{ID: teamID}, &User{ID: team.OrgID})
  269. }
  270. test(1, 2)
  271. test(1, 4)
  272. test(3, 2)
  273. }
  274. func TestRemoveTeamMember(t *testing.T) {
  275. assert.NoError(t, PrepareTestDatabase())
  276. testSuccess := func(teamID, userID int64) {
  277. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  278. assert.NoError(t, RemoveTeamMember(team, userID))
  279. AssertNotExistsBean(t, &TeamUser{UID: userID, TeamID: teamID})
  280. CheckConsistencyFor(t, &Team{ID: teamID})
  281. }
  282. testSuccess(1, 4)
  283. testSuccess(2, 2)
  284. testSuccess(3, 2)
  285. testSuccess(3, NonexistentID)
  286. team := AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
  287. err := RemoveTeamMember(team, 2)
  288. assert.True(t, IsErrLastOrgOwner(err))
  289. }
  290. func TestHasTeamRepo(t *testing.T) {
  291. assert.NoError(t, PrepareTestDatabase())
  292. test := func(teamID, repoID int64, expected bool) {
  293. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  294. assert.Equal(t, expected, HasTeamRepo(team.OrgID, teamID, repoID))
  295. }
  296. test(1, 1, false)
  297. test(1, 3, true)
  298. test(1, 5, true)
  299. test(1, NonexistentID, false)
  300. test(2, 3, true)
  301. test(2, 5, false)
  302. }
  303. func TestUsersInTeamsCount(t *testing.T) {
  304. assert.NoError(t, PrepareTestDatabase())
  305. test := func(teamIDs []int64, userIDs []int64, expected int64) {
  306. count, err := UsersInTeamsCount(teamIDs, userIDs)
  307. assert.NoError(t, err)
  308. assert.Equal(t, expected, count)
  309. }
  310. test([]int64{2}, []int64{1, 2, 3, 4}, 1) // only userid 2
  311. test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4
  312. test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5
  313. }
  314. func TestIncludesAllRepositoriesTeams(t *testing.T) {
  315. assert.NoError(t, PrepareTestDatabase())
  316. testTeamRepositories := func(teamID int64, repoIds []int64) {
  317. team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
  318. assert.NoError(t, team.GetRepositories(), "%s: GetRepositories", team.Name)
  319. assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name)
  320. assert.Equal(t, len(repoIds), len(team.Repos), "%s: repo count", team.Name)
  321. for i, rid := range repoIds {
  322. if rid > 0 {
  323. assert.True(t, team.HasRepository(rid), "%s: HasRepository(%d) %d", rid, i)
  324. }
  325. }
  326. }
  327. // Get an admin user.
  328. user, err := GetUserByID(1)
  329. assert.NoError(t, err, "GetUserByID")
  330. // Create org.
  331. org := &User{
  332. Name: "All repo",
  333. IsActive: true,
  334. Type: UserTypeOrganization,
  335. Visibility: structs.VisibleTypePublic,
  336. }
  337. assert.NoError(t, CreateOrganization(org, user), "CreateOrganization")
  338. // Check Owner team.
  339. ownerTeam, err := org.GetOwnerTeam()
  340. assert.NoError(t, err, "GetOwnerTeam")
  341. assert.True(t, ownerTeam.IncludesAllRepositories, "Owner team includes all repositories")
  342. // Create repos.
  343. repoIds := make([]int64, 0)
  344. for i := 0; i < 3; i++ {
  345. r, err := CreateRepository(user, org, CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)})
  346. assert.NoError(t, err, "CreateRepository %d", i)
  347. if r != nil {
  348. repoIds = append(repoIds, r.ID)
  349. }
  350. }
  351. // Get fresh copy of Owner team after creating repos.
  352. ownerTeam, err = org.GetOwnerTeam()
  353. assert.NoError(t, err, "GetOwnerTeam")
  354. // Create teams and check repositories.
  355. teams := []*Team{
  356. ownerTeam,
  357. {
  358. OrgID: org.ID,
  359. Name: "team one",
  360. Authorize: AccessModeRead,
  361. IncludesAllRepositories: true,
  362. },
  363. {
  364. OrgID: org.ID,
  365. Name: "team 2",
  366. Authorize: AccessModeRead,
  367. IncludesAllRepositories: false,
  368. },
  369. {
  370. OrgID: org.ID,
  371. Name: "team three",
  372. Authorize: AccessModeWrite,
  373. IncludesAllRepositories: true,
  374. },
  375. {
  376. OrgID: org.ID,
  377. Name: "team 4",
  378. Authorize: AccessModeWrite,
  379. IncludesAllRepositories: false,
  380. },
  381. }
  382. teamRepos := [][]int64{
  383. repoIds,
  384. repoIds,
  385. {},
  386. repoIds,
  387. {},
  388. }
  389. for i, team := range teams {
  390. if i > 0 { // first team is Owner.
  391. assert.NoError(t, NewTeam(team), "%s: NewTeam", team.Name)
  392. }
  393. testTeamRepositories(team.ID, teamRepos[i])
  394. }
  395. // Update teams and check repositories.
  396. teams[3].IncludesAllRepositories = false
  397. teams[4].IncludesAllRepositories = true
  398. teamRepos[4] = repoIds
  399. for i, team := range teams {
  400. assert.NoError(t, UpdateTeam(team, false, true), "%s: UpdateTeam", team.Name)
  401. testTeamRepositories(team.ID, teamRepos[i])
  402. }
  403. // Create repo and check teams repositories.
  404. org.Teams = nil // Reset teams to allow their reloading.
  405. r, err := CreateRepository(user, org, CreateRepoOptions{Name: "repo-last"})
  406. assert.NoError(t, err, "CreateRepository last")
  407. if r != nil {
  408. repoIds = append(repoIds, r.ID)
  409. }
  410. teamRepos[0] = repoIds
  411. teamRepos[1] = repoIds
  412. teamRepos[4] = repoIds
  413. for i, team := range teams {
  414. testTeamRepositories(team.ID, teamRepos[i])
  415. }
  416. // Remove repo and check teams repositories.
  417. assert.NoError(t, DeleteRepository(user, org.ID, repoIds[0]), "DeleteRepository")
  418. teamRepos[0] = repoIds[1:]
  419. teamRepos[1] = repoIds[1:]
  420. teamRepos[3] = repoIds[1:3]
  421. teamRepos[4] = repoIds[1:]
  422. for i, team := range teams {
  423. testTeamRepositories(team.ID, teamRepos[i])
  424. }
  425. // Wipe created items.
  426. for i, rid := range repoIds {
  427. if i > 0 { // first repo already deleted.
  428. assert.NoError(t, DeleteRepository(user, org.ID, rid), "DeleteRepository %d", i)
  429. }
  430. }
  431. assert.NoError(t, DeleteOrganization(org), "DeleteOrganization")
  432. }