gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package access
  4. import (
  5. "testing"
  6. "code.gitea.io/gitea/models/db"
  7. "code.gitea.io/gitea/models/organization"
  8. perm_model "code.gitea.io/gitea/models/perm"
  9. repo_model "code.gitea.io/gitea/models/repo"
  10. "code.gitea.io/gitea/models/unit"
  11. "code.gitea.io/gitea/models/unittest"
  12. user_model "code.gitea.io/gitea/models/user"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. )
  16. func TestHasAnyUnitAccess(t *testing.T) {
  17. perm := Permission{}
  18. assert.False(t, perm.HasAnyUnitAccess())
  19. perm = Permission{
  20. units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}},
  21. }
  22. assert.False(t, perm.HasAnyUnitAccess())
  23. assert.False(t, perm.HasAnyUnitAccessOrPublicAccess())
  24. perm = Permission{
  25. units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}},
  26. everyoneAccessMode: map[unit.Type]perm_model.AccessMode{unit.TypeIssues: perm_model.AccessModeRead},
  27. }
  28. assert.False(t, perm.HasAnyUnitAccess())
  29. assert.True(t, perm.HasAnyUnitAccessOrPublicAccess())
  30. perm = Permission{
  31. units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}},
  32. anonymousAccessMode: map[unit.Type]perm_model.AccessMode{unit.TypeIssues: perm_model.AccessModeRead},
  33. }
  34. assert.False(t, perm.HasAnyUnitAccess())
  35. assert.True(t, perm.HasAnyUnitAccessOrPublicAccess())
  36. perm = Permission{
  37. AccessMode: perm_model.AccessModeRead,
  38. units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}},
  39. }
  40. assert.True(t, perm.HasAnyUnitAccess())
  41. perm = Permission{
  42. unitsMode: map[unit.Type]perm_model.AccessMode{unit.TypeWiki: perm_model.AccessModeRead},
  43. }
  44. assert.True(t, perm.HasAnyUnitAccess())
  45. }
  46. func TestApplyPublicAccessRepoPermission(t *testing.T) {
  47. perm := Permission{
  48. AccessMode: perm_model.AccessModeNone,
  49. units: []*repo_model.RepoUnit{
  50. {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
  51. },
  52. }
  53. finalProcessRepoUnitPermission(nil, &perm)
  54. assert.False(t, perm.CanRead(unit.TypeWiki))
  55. perm = Permission{
  56. AccessMode: perm_model.AccessModeNone,
  57. units: []*repo_model.RepoUnit{
  58. {Type: unit.TypeWiki, AnonymousAccessMode: perm_model.AccessModeRead},
  59. },
  60. }
  61. finalProcessRepoUnitPermission(nil, &perm)
  62. assert.True(t, perm.CanRead(unit.TypeWiki))
  63. perm = Permission{
  64. AccessMode: perm_model.AccessModeNone,
  65. units: []*repo_model.RepoUnit{
  66. {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
  67. },
  68. }
  69. finalProcessRepoUnitPermission(&user_model.User{ID: 0}, &perm)
  70. assert.False(t, perm.CanRead(unit.TypeWiki))
  71. perm = Permission{
  72. AccessMode: perm_model.AccessModeNone,
  73. units: []*repo_model.RepoUnit{
  74. {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
  75. },
  76. }
  77. finalProcessRepoUnitPermission(&user_model.User{ID: 1}, &perm)
  78. assert.True(t, perm.CanRead(unit.TypeWiki))
  79. perm = Permission{
  80. AccessMode: perm_model.AccessModeWrite,
  81. units: []*repo_model.RepoUnit{
  82. {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
  83. },
  84. }
  85. finalProcessRepoUnitPermission(&user_model.User{ID: 1}, &perm)
  86. // it should work the same as "EveryoneAccessMode: none" because the default AccessMode should be applied to units
  87. assert.True(t, perm.CanWrite(unit.TypeWiki))
  88. perm = Permission{
  89. units: []*repo_model.RepoUnit{
  90. {Type: unit.TypeCode}, // will be removed
  91. {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
  92. },
  93. unitsMode: map[unit.Type]perm_model.AccessMode{
  94. unit.TypeWiki: perm_model.AccessModeWrite,
  95. },
  96. }
  97. finalProcessRepoUnitPermission(&user_model.User{ID: 1}, &perm)
  98. assert.True(t, perm.CanWrite(unit.TypeWiki))
  99. assert.Len(t, perm.units, 1)
  100. }
  101. func TestUnitAccessMode(t *testing.T) {
  102. perm := Permission{
  103. AccessMode: perm_model.AccessModeNone,
  104. }
  105. assert.Equal(t, perm_model.AccessModeNone, perm.UnitAccessMode(unit.TypeWiki), "no unit, no map, use AccessMode")
  106. perm = Permission{
  107. AccessMode: perm_model.AccessModeRead,
  108. units: []*repo_model.RepoUnit{
  109. {Type: unit.TypeWiki},
  110. },
  111. }
  112. assert.Equal(t, perm_model.AccessModeRead, perm.UnitAccessMode(unit.TypeWiki), "only unit, no map, use AccessMode")
  113. perm = Permission{
  114. AccessMode: perm_model.AccessModeAdmin,
  115. unitsMode: map[unit.Type]perm_model.AccessMode{
  116. unit.TypeWiki: perm_model.AccessModeRead,
  117. },
  118. }
  119. assert.Equal(t, perm_model.AccessModeAdmin, perm.UnitAccessMode(unit.TypeWiki), "no unit, only map, admin overrides map")
  120. perm = Permission{
  121. AccessMode: perm_model.AccessModeNone,
  122. unitsMode: map[unit.Type]perm_model.AccessMode{
  123. unit.TypeWiki: perm_model.AccessModeRead,
  124. },
  125. }
  126. assert.Equal(t, perm_model.AccessModeRead, perm.UnitAccessMode(unit.TypeWiki), "no unit, only map, use map")
  127. perm = Permission{
  128. AccessMode: perm_model.AccessModeNone,
  129. units: []*repo_model.RepoUnit{
  130. {Type: unit.TypeWiki},
  131. },
  132. unitsMode: map[unit.Type]perm_model.AccessMode{
  133. unit.TypeWiki: perm_model.AccessModeRead,
  134. },
  135. }
  136. assert.Equal(t, perm_model.AccessModeRead, perm.UnitAccessMode(unit.TypeWiki), "has unit, and map, use map")
  137. }
  138. func TestGetUserRepoPermission(t *testing.T) {
  139. assert.NoError(t, unittest.PrepareTestDatabase())
  140. ctx := t.Context()
  141. repo32 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 32}) // org public repo
  142. require.NoError(t, repo32.LoadOwner(ctx))
  143. require.True(t, repo32.Owner.IsOrganization())
  144. require.NoError(t, db.TruncateBeans(ctx, &organization.Team{}, &organization.TeamUser{}, &organization.TeamRepo{}, &organization.TeamUnit{}))
  145. org := repo32.Owner
  146. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
  147. team := &organization.Team{OrgID: org.ID, LowerName: "test_team"}
  148. require.NoError(t, db.Insert(ctx, team))
  149. t.Run("DoerInTeamWithNoRepo", func(t *testing.T) {
  150. require.NoError(t, db.Insert(ctx, &organization.TeamUser{OrgID: org.ID, TeamID: team.ID, UID: user.ID}))
  151. perm, err := GetUserRepoPermission(ctx, repo32, user)
  152. require.NoError(t, err)
  153. assert.Equal(t, perm_model.AccessModeRead, perm.AccessMode)
  154. assert.Nil(t, perm.unitsMode) // doer in the team, but has no access to the repo
  155. })
  156. require.NoError(t, db.Insert(ctx, &organization.TeamRepo{OrgID: org.ID, TeamID: team.ID, RepoID: repo32.ID}))
  157. require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeCode, AccessMode: perm_model.AccessModeNone}))
  158. t.Run("DoerWithTeamUnitAccessNone", func(t *testing.T) {
  159. perm, err := GetUserRepoPermission(ctx, repo32, user)
  160. require.NoError(t, err)
  161. assert.Equal(t, perm_model.AccessModeRead, perm.AccessMode)
  162. assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeCode])
  163. assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues])
  164. })
  165. require.NoError(t, db.TruncateBeans(ctx, &organization.TeamUnit{}))
  166. require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeCode, AccessMode: perm_model.AccessModeWrite}))
  167. t.Run("DoerWithTeamUnitAccessWrite", func(t *testing.T) {
  168. perm, err := GetUserRepoPermission(ctx, repo32, user)
  169. require.NoError(t, err)
  170. assert.Equal(t, perm_model.AccessModeRead, perm.AccessMode)
  171. assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeCode])
  172. assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues])
  173. })
  174. repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // org private repo, same org as repo 32
  175. require.NoError(t, repo3.LoadOwner(ctx))
  176. require.True(t, repo3.Owner.IsOrganization())
  177. require.NoError(t, db.TruncateBeans(ctx, &organization.TeamUnit{}, &Access{})) // The user has access set of that repo, remove it, it is useless for our test
  178. require.NoError(t, db.Insert(ctx, &organization.TeamRepo{OrgID: org.ID, TeamID: team.ID, RepoID: repo3.ID}))
  179. t.Run("DoerWithNoopTeamOnPrivateRepo", func(t *testing.T) {
  180. perm, err := GetUserRepoPermission(ctx, repo3, user)
  181. require.NoError(t, err)
  182. assert.Equal(t, perm_model.AccessModeNone, perm.AccessMode)
  183. assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeCode])
  184. assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeIssues])
  185. })
  186. require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeCode, AccessMode: perm_model.AccessModeNone}))
  187. require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeIssues, AccessMode: perm_model.AccessModeRead}))
  188. t.Run("DoerWithReadIssueTeamOnPrivateRepo", func(t *testing.T) {
  189. perm, err := GetUserRepoPermission(ctx, repo3, user)
  190. require.NoError(t, err)
  191. assert.Equal(t, perm_model.AccessModeNone, perm.AccessMode)
  192. assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeCode])
  193. assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues])
  194. })
  195. require.NoError(t, db.Insert(ctx, repo_model.Collaboration{RepoID: repo3.ID, UserID: user.ID, Mode: perm_model.AccessModeWrite}))
  196. require.NoError(t, db.Insert(ctx, Access{RepoID: repo3.ID, UserID: user.ID, Mode: perm_model.AccessModeWrite}))
  197. t.Run("DoerWithReadIssueTeamAndWriteCollaboratorOnPrivateRepo", func(t *testing.T) {
  198. perm, err := GetUserRepoPermission(ctx, repo3, user)
  199. require.NoError(t, err)
  200. assert.Equal(t, perm_model.AccessModeWrite, perm.AccessMode)
  201. assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeCode])
  202. assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeIssues])
  203. })
  204. }