mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 01:34:27 +00:00 
			
		
		
		
	hide issues from org private repos w/o team assignment (#4034)
This commit is contained in:
		
				
					committed by
					
						
						techknowlogick
					
				
			
			
				
	
			
			
			
						parent
						
							46d19c4676
						
					
				
				
					commit
					0b3ea42847
				
			@@ -67,9 +67,9 @@ func TestAPISearchRepo(t *testing.T) {
 | 
				
			|||||||
		expectedResults
 | 
							expectedResults
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50", expectedResults: expectedResults{
 | 
							{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50", expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 15},
 | 
								nil:   {count: 16},
 | 
				
			||||||
			user:  {count: 15},
 | 
								user:  {count: 16},
 | 
				
			||||||
			user2: {count: 15}},
 | 
								user2: {count: 16}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10", expectedResults: expectedResults{
 | 
							{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10", expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 10},
 | 
								nil:   {count: 10},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,8 +22,12 @@ func TestAccessLevel(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
 | 
						user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
 | 
				
			||||||
	user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
 | 
						user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
 | 
				
			||||||
	repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository)
 | 
						// A public repository owned by User 2
 | 
				
			||||||
	repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository)
 | 
						repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
 | 
				
			||||||
 | 
						assert.False(t, repo1.IsPrivate)
 | 
				
			||||||
 | 
						// A private repository owned by Org 3
 | 
				
			||||||
 | 
						repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository)
 | 
				
			||||||
 | 
						assert.True(t, repo2.IsPrivate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	level, err := AccessLevel(user1.ID, repo1)
 | 
						level, err := AccessLevel(user1.ID, repo1)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
@@ -47,8 +51,12 @@ func TestHasAccess(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
 | 
						user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
 | 
				
			||||||
	user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
 | 
						user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
 | 
				
			||||||
	repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository)
 | 
						// A public repository owned by User 2
 | 
				
			||||||
	repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository)
 | 
						repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
 | 
				
			||||||
 | 
						assert.False(t, repo1.IsPrivate)
 | 
				
			||||||
 | 
						// A private repository owned by Org 3
 | 
				
			||||||
 | 
						repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository)
 | 
				
			||||||
 | 
						assert.True(t, repo2.IsPrivate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, accessMode := range accessModes {
 | 
						for _, accessMode := range accessModes {
 | 
				
			||||||
		has, err := HasAccess(user1.ID, repo1, accessMode)
 | 
							has, err := HasAccess(user1.ID, repo1, accessMode)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -389,3 +389,14 @@
 | 
				
			|||||||
  num_forks: 0
 | 
					  num_forks: 0
 | 
				
			||||||
  num_issues: 0
 | 
					  num_issues: 0
 | 
				
			||||||
  is_mirror: false
 | 
					  is_mirror: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 32
 | 
				
			||||||
 | 
					  owner_id: 3
 | 
				
			||||||
 | 
					  lower_name: repo21
 | 
				
			||||||
 | 
					  name: repo21
 | 
				
			||||||
 | 
					  is_private: false
 | 
				
			||||||
 | 
					  num_stars: 0
 | 
				
			||||||
 | 
					  num_forks: 0
 | 
				
			||||||
 | 
					  num_issues: 0
 | 
				
			||||||
 | 
					  is_mirror: false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,9 +4,8 @@
 | 
				
			|||||||
  lower_name: owners
 | 
					  lower_name: owners
 | 
				
			||||||
  name: Owners
 | 
					  name: Owners
 | 
				
			||||||
  authorize: 4 # owner
 | 
					  authorize: 4 # owner
 | 
				
			||||||
  num_repos: 2
 | 
					  num_repos: 3
 | 
				
			||||||
  num_members: 1
 | 
					  num_members: 1
 | 
				
			||||||
  unit_types: '[1,2,3,4,5,6,7]'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
-
 | 
					-
 | 
				
			||||||
  id: 2
 | 
					  id: 2
 | 
				
			||||||
@@ -16,7 +15,6 @@
 | 
				
			|||||||
  authorize: 2 # write
 | 
					  authorize: 2 # write
 | 
				
			||||||
  num_repos: 1
 | 
					  num_repos: 1
 | 
				
			||||||
  num_members: 2
 | 
					  num_members: 2
 | 
				
			||||||
  unit_types: '[1,2,3,4,5,6,7]'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
-
 | 
					-
 | 
				
			||||||
  id: 3
 | 
					  id: 3
 | 
				
			||||||
@@ -26,7 +24,6 @@
 | 
				
			|||||||
  authorize: 4 # owner
 | 
					  authorize: 4 # owner
 | 
				
			||||||
  num_repos: 0
 | 
					  num_repos: 0
 | 
				
			||||||
  num_members: 1
 | 
					  num_members: 1
 | 
				
			||||||
  unit_types: '[1,2,3,4,5,6,7]'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
-
 | 
					-
 | 
				
			||||||
  id: 4
 | 
					  id: 4
 | 
				
			||||||
@@ -36,7 +33,6 @@
 | 
				
			|||||||
  authorize: 4 # owner
 | 
					  authorize: 4 # owner
 | 
				
			||||||
  num_repos: 0
 | 
					  num_repos: 0
 | 
				
			||||||
  num_members: 1
 | 
					  num_members: 1
 | 
				
			||||||
  unit_types: '[1,2,3,4,5,6,7]'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
-
 | 
					-
 | 
				
			||||||
  id: 5
 | 
					  id: 5
 | 
				
			||||||
@@ -46,7 +42,6 @@
 | 
				
			|||||||
  authorize: 4 # owner
 | 
					  authorize: 4 # owner
 | 
				
			||||||
  num_repos: 2
 | 
					  num_repos: 2
 | 
				
			||||||
  num_members: 2
 | 
					  num_members: 2
 | 
				
			||||||
  unit_types: '[1,2,3,4,5,6,7]'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
-
 | 
					-
 | 
				
			||||||
  id: 6
 | 
					  id: 6
 | 
				
			||||||
@@ -56,4 +51,3 @@
 | 
				
			|||||||
  authorize: 4 # owner
 | 
					  authorize: 4 # owner
 | 
				
			||||||
  num_repos: 2
 | 
					  num_repos: 2
 | 
				
			||||||
  num_members: 1
 | 
					  num_members: 1
 | 
				
			||||||
  unit_types: '[1,2,3,4,5,6,7]'
 | 
					 | 
				
			||||||
@@ -39,3 +39,9 @@
 | 
				
			|||||||
  org_id: 19
 | 
					  org_id: 19
 | 
				
			||||||
  team_id: 6
 | 
					  team_id: 6
 | 
				
			||||||
  repo_id: 28
 | 
					  repo_id: 28
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 8
 | 
				
			||||||
 | 
					  org_id: 3
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  repo_id: 32
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										209
									
								
								models/fixtures/team_unit.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								models/fixtures/team_unit.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
				
			|||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 1
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  type: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 2
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  type: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 3
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  type: 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 4
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  type: 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 5
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  type: 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 6
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  type: 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 7
 | 
				
			||||||
 | 
					  team_id: 1
 | 
				
			||||||
 | 
					  type: 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 8
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 9
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 10
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 11
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 12
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 13
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 14
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 15
 | 
				
			||||||
 | 
					  team_id: 3
 | 
				
			||||||
 | 
					  type: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 16
 | 
				
			||||||
 | 
					  team_id: 3
 | 
				
			||||||
 | 
					  type: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 17
 | 
				
			||||||
 | 
					  team_id: 3
 | 
				
			||||||
 | 
					  type: 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 18
 | 
				
			||||||
 | 
					  team_id: 3
 | 
				
			||||||
 | 
					  type: 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 19
 | 
				
			||||||
 | 
					  team_id: 3
 | 
				
			||||||
 | 
					  type: 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 20
 | 
				
			||||||
 | 
					  team_id: 3
 | 
				
			||||||
 | 
					  type: 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 21
 | 
				
			||||||
 | 
					  team_id: 3
 | 
				
			||||||
 | 
					  type: 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 22
 | 
				
			||||||
 | 
					  team_id: 4
 | 
				
			||||||
 | 
					  type: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 23
 | 
				
			||||||
 | 
					  team_id: 4
 | 
				
			||||||
 | 
					  type: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 24
 | 
				
			||||||
 | 
					  team_id: 4
 | 
				
			||||||
 | 
					  type: 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 25
 | 
				
			||||||
 | 
					  team_id: 4
 | 
				
			||||||
 | 
					  type: 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 26
 | 
				
			||||||
 | 
					  team_id: 4
 | 
				
			||||||
 | 
					  type: 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 27
 | 
				
			||||||
 | 
					  team_id: 4
 | 
				
			||||||
 | 
					  type: 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 28
 | 
				
			||||||
 | 
					  team_id: 4
 | 
				
			||||||
 | 
					  type: 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 29
 | 
				
			||||||
 | 
					  team_id: 5
 | 
				
			||||||
 | 
					  type: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 30
 | 
				
			||||||
 | 
					  team_id: 5
 | 
				
			||||||
 | 
					  type: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 31
 | 
				
			||||||
 | 
					  team_id: 5
 | 
				
			||||||
 | 
					  type: 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 32
 | 
				
			||||||
 | 
					  team_id: 5
 | 
				
			||||||
 | 
					  type: 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 33
 | 
				
			||||||
 | 
					  team_id: 5
 | 
				
			||||||
 | 
					  type: 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 34
 | 
				
			||||||
 | 
					  team_id: 5
 | 
				
			||||||
 | 
					  type: 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 35
 | 
				
			||||||
 | 
					  team_id: 5
 | 
				
			||||||
 | 
					  type: 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 36
 | 
				
			||||||
 | 
					  team_id: 6
 | 
				
			||||||
 | 
					  type: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 37
 | 
				
			||||||
 | 
					  team_id: 6
 | 
				
			||||||
 | 
					  type: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 38
 | 
				
			||||||
 | 
					  team_id: 6
 | 
				
			||||||
 | 
					  type: 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 39
 | 
				
			||||||
 | 
					  team_id: 6
 | 
				
			||||||
 | 
					  type: 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 40
 | 
				
			||||||
 | 
					  team_id: 6
 | 
				
			||||||
 | 
					  type: 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 41
 | 
				
			||||||
 | 
					  team_id: 6
 | 
				
			||||||
 | 
					  type: 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 42
 | 
				
			||||||
 | 
					  team_id: 6
 | 
				
			||||||
 | 
					  type: 7
 | 
				
			||||||
@@ -45,7 +45,7 @@
 | 
				
			|||||||
  is_admin: false
 | 
					  is_admin: false
 | 
				
			||||||
  avatar: avatar3
 | 
					  avatar: avatar3
 | 
				
			||||||
  avatar_email: user3@example.com
 | 
					  avatar_email: user3@example.com
 | 
				
			||||||
  num_repos: 2
 | 
					  num_repos: 3
 | 
				
			||||||
  num_members: 2
 | 
					  num_members: 2
 | 
				
			||||||
  num_teams: 2
 | 
					  num_teams: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -190,6 +190,8 @@ var migrations = []Migration{
 | 
				
			|||||||
	NewMigration("remove stale watches", removeStaleWatches),
 | 
						NewMigration("remove stale watches", removeStaleWatches),
 | 
				
			||||||
	// v68 -> V69
 | 
						// v68 -> V69
 | 
				
			||||||
	NewMigration("Reformat and remove incorrect topics", reformatAndRemoveIncorrectTopics),
 | 
						NewMigration("Reformat and remove incorrect topics", reformatAndRemoveIncorrectTopics),
 | 
				
			||||||
 | 
						// v69 -> v70
 | 
				
			||||||
 | 
						NewMigration("move team units to team_unit table", moveTeamUnitsToTeamUnitTable),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Migrate database to current version
 | 
					// Migrate database to current version
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,10 +25,15 @@ func removeCommitsUnitType(x *xorm.Engine) (err error) {
 | 
				
			|||||||
		Created     time.Time       `xorm:"-"`
 | 
							Created     time.Time       `xorm:"-"`
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type Team struct {
 | 
				
			||||||
 | 
							ID        int64
 | 
				
			||||||
 | 
							UnitTypes []int `xorm:"json"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Update team unit types
 | 
						// Update team unit types
 | 
				
			||||||
	const batchSize = 100
 | 
						const batchSize = 100
 | 
				
			||||||
	for start := 0; ; start += batchSize {
 | 
						for start := 0; ; start += batchSize {
 | 
				
			||||||
		teams := make([]*models.Team, 0, batchSize)
 | 
							teams := make([]*Team, 0, batchSize)
 | 
				
			||||||
		if err := x.Limit(batchSize, start).Find(&teams); err != nil {
 | 
							if err := x.Limit(batchSize, start).Find(&teams); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -36,7 +41,7 @@ func removeCommitsUnitType(x *xorm.Engine) (err error) {
 | 
				
			|||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for _, team := range teams {
 | 
							for _, team := range teams {
 | 
				
			||||||
			ut := make([]models.UnitType, 0, len(team.UnitTypes))
 | 
								ut := make([]int, 0, len(team.UnitTypes))
 | 
				
			||||||
			for _, u := range team.UnitTypes {
 | 
								for _, u := range team.UnitTypes {
 | 
				
			||||||
				if u < V16UnitTypeCommits {
 | 
									if u < V16UnitTypeCommits {
 | 
				
			||||||
					ut = append(ut, u)
 | 
										ut = append(ut, u)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										80
									
								
								models/migrations/v69.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								models/migrations/v69.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					// Copyright 2018 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func moveTeamUnitsToTeamUnitTable(x *xorm.Engine) error {
 | 
				
			||||||
 | 
						// Team see models/team.go
 | 
				
			||||||
 | 
						type Team struct {
 | 
				
			||||||
 | 
							ID        int64
 | 
				
			||||||
 | 
							OrgID     int64
 | 
				
			||||||
 | 
							UnitTypes []int `xorm:"json"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TeamUnit see models/org_team.go
 | 
				
			||||||
 | 
						type TeamUnit struct {
 | 
				
			||||||
 | 
							ID     int64 `xorm:"pk autoincr"`
 | 
				
			||||||
 | 
							OrgID  int64 `xorm:"INDEX"`
 | 
				
			||||||
 | 
							TeamID int64 `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
							Type   int   `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := x.Sync2(new(TeamUnit)); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Sync2: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess := x.NewSession()
 | 
				
			||||||
 | 
						defer sess.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := sess.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update team unit types
 | 
				
			||||||
 | 
						const batchSize = 100
 | 
				
			||||||
 | 
						for start := 0; ; start += batchSize {
 | 
				
			||||||
 | 
							teams := make([]*Team, 0, batchSize)
 | 
				
			||||||
 | 
							if err := x.Limit(batchSize, start).Find(&teams); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(teams) == 0 {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, team := range teams {
 | 
				
			||||||
 | 
								var unitTypes []int
 | 
				
			||||||
 | 
								if len(team.UnitTypes) == 0 {
 | 
				
			||||||
 | 
									unitTypes = allUnitTypes
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									unitTypes = team.UnitTypes
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// insert units for team
 | 
				
			||||||
 | 
								var units = make([]TeamUnit, 0, len(unitTypes))
 | 
				
			||||||
 | 
								for _, tp := range unitTypes {
 | 
				
			||||||
 | 
									units = append(units, TeamUnit{
 | 
				
			||||||
 | 
										OrgID:  team.OrgID,
 | 
				
			||||||
 | 
										TeamID: team.ID,
 | 
				
			||||||
 | 
										Type:   tp,
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if _, err := sess.Insert(&units); err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("Insert team units: %v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := dropTableColumns(sess, "team", "unit_types"); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sess.Commit()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -122,6 +122,7 @@ func init() {
 | 
				
			|||||||
		new(Reaction),
 | 
							new(Reaction),
 | 
				
			||||||
		new(IssueAssignees),
 | 
							new(IssueAssignees),
 | 
				
			||||||
		new(U2FRegistration),
 | 
							new(U2FRegistration),
 | 
				
			||||||
 | 
							new(TeamUnit),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gonicNames := []string{"SSL", "UID"}
 | 
						gonicNames := []string{"SSL", "UID"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,7 +119,17 @@ func createOrUpdateIssueNotifications(e Engine, issue *Issue, notificationAuthor
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						issue.loadRepo(e)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, watch := range watches {
 | 
						for _, watch := range watches {
 | 
				
			||||||
 | 
							issue.Repo.Units = nil
 | 
				
			||||||
 | 
							if issue.IsPull && !issue.Repo.CheckUnitUser(watch.UserID, false, UnitTypePullRequests) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !issue.IsPull && !issue.Repo.CheckUnitUser(watch.UserID, false, UnitTypeIssues) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := notifyUser(watch.UserID); err != nil {
 | 
							if err := notifyUser(watch.UserID); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -154,12 +154,26 @@ func CreateOrganization(org, owner *User) (err error) {
 | 
				
			|||||||
		Name:       ownerTeamName,
 | 
							Name:       ownerTeamName,
 | 
				
			||||||
		Authorize:  AccessModeOwner,
 | 
							Authorize:  AccessModeOwner,
 | 
				
			||||||
		NumMembers: 1,
 | 
							NumMembers: 1,
 | 
				
			||||||
		UnitTypes:  allRepUnitTypes,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, err = sess.Insert(t); err != nil {
 | 
						if _, err = sess.Insert(t); err != nil {
 | 
				
			||||||
		return fmt.Errorf("insert owner team: %v", err)
 | 
							return fmt.Errorf("insert owner team: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// insert units for team
 | 
				
			||||||
 | 
						var units = make([]TeamUnit, 0, len(allRepUnitTypes))
 | 
				
			||||||
 | 
						for _, tp := range allRepUnitTypes {
 | 
				
			||||||
 | 
							units = append(units, TeamUnit{
 | 
				
			||||||
 | 
								OrgID:  org.ID,
 | 
				
			||||||
 | 
								TeamID: t.ID,
 | 
				
			||||||
 | 
								Type:   tp,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Insert(&units); err != nil {
 | 
				
			||||||
 | 
							sess.Rollback()
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err = sess.Insert(&TeamUser{
 | 
						if _, err = sess.Insert(&TeamUser{
 | 
				
			||||||
		UID:    owner.ID,
 | 
							UID:    owner.ID,
 | 
				
			||||||
		OrgID:  org.ID,
 | 
							OrgID:  org.ID,
 | 
				
			||||||
@@ -238,6 +252,7 @@ func deleteOrg(e *xorm.Session, u *User) error {
 | 
				
			|||||||
		&Team{OrgID: u.ID},
 | 
							&Team{OrgID: u.ID},
 | 
				
			||||||
		&OrgUser{OrgID: u.ID},
 | 
							&OrgUser{OrgID: u.ID},
 | 
				
			||||||
		&TeamUser{OrgID: u.ID},
 | 
							&TeamUser{OrgID: u.ID},
 | 
				
			||||||
 | 
							&TeamUnit{OrgID: u.ID},
 | 
				
			||||||
	); err != nil {
 | 
						); err != nil {
 | 
				
			||||||
		return fmt.Errorf("deleteBeans: %v", err)
 | 
							return fmt.Errorf("deleteBeans: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					// Copyright 2018 The Gitea Authors. All rights reserved.
 | 
				
			||||||
// Copyright 2016 The Gogs Authors. All rights reserved.
 | 
					// Copyright 2016 The Gogs Authors. All rights reserved.
 | 
				
			||||||
// Use of this source code is governed by a MIT-style
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
@@ -10,7 +11,6 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,15 +28,16 @@ type Team struct {
 | 
				
			|||||||
	Members     []*User       `xorm:"-"`
 | 
						Members     []*User       `xorm:"-"`
 | 
				
			||||||
	NumRepos    int
 | 
						NumRepos    int
 | 
				
			||||||
	NumMembers  int
 | 
						NumMembers  int
 | 
				
			||||||
	UnitTypes   []UnitType `xorm:"json"`
 | 
						Units       []*TeamUnit `xorm:"-"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetUnitTypes returns unit types the team owned, empty means all the unit types
 | 
					func (t *Team) getUnits(e Engine) (err error) {
 | 
				
			||||||
func (t *Team) GetUnitTypes() []UnitType {
 | 
						if t.Units != nil {
 | 
				
			||||||
	if len(t.UnitTypes) == 0 {
 | 
							return nil
 | 
				
			||||||
		return allRepUnitTypes
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return t.UnitTypes
 | 
					
 | 
				
			||||||
 | 
						t.Units, err = getUnitsByTeamID(e, t.ID)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HasWriteAccess returns true if team has at least write level access mode.
 | 
					// HasWriteAccess returns true if team has at least write level access mode.
 | 
				
			||||||
@@ -214,11 +215,12 @@ func (t *Team) RemoveRepository(repoID int64) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// UnitEnabled returns if the team has the given unit type enabled
 | 
					// UnitEnabled returns if the team has the given unit type enabled
 | 
				
			||||||
func (t *Team) UnitEnabled(tp UnitType) bool {
 | 
					func (t *Team) UnitEnabled(tp UnitType) bool {
 | 
				
			||||||
	if len(t.UnitTypes) == 0 {
 | 
						if err := t.getUnits(x); err != nil {
 | 
				
			||||||
		return true
 | 
							log.Warn("Error loading repository (ID: %d) units: %s", t.ID, err.Error())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, u := range t.UnitTypes {
 | 
					
 | 
				
			||||||
		if u == tp {
 | 
						for _, unit := range t.Units {
 | 
				
			||||||
 | 
							if unit.Type == tp {
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -275,6 +277,17 @@ func NewTeam(t *Team) (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// insert units for team
 | 
				
			||||||
 | 
						if len(t.Units) > 0 {
 | 
				
			||||||
 | 
							for _, unit := range t.Units {
 | 
				
			||||||
 | 
								unit.TeamID = t.ID
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if _, err = sess.Insert(&t.Units); err != nil {
 | 
				
			||||||
 | 
								sess.Rollback()
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Update organization number of teams.
 | 
						// Update organization number of teams.
 | 
				
			||||||
	if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil {
 | 
						if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil {
 | 
				
			||||||
		sess.Rollback()
 | 
							sess.Rollback()
 | 
				
			||||||
@@ -424,6 +437,13 @@ func DeleteTeam(t *Team) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delete team-unit.
 | 
				
			||||||
 | 
						if _, err := sess.
 | 
				
			||||||
 | 
							Where("team_id=?", t.ID).
 | 
				
			||||||
 | 
							Delete(new(TeamUnit)); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete team.
 | 
						// Delete team.
 | 
				
			||||||
	if _, err := sess.ID(t.ID).Delete(new(Team)); err != nil {
 | 
						if _, err := sess.ID(t.ID).Delete(new(Team)); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -695,3 +715,47 @@ func GetTeamsWithAccessToRepo(orgID, repoID int64, mode AccessMode) ([]*Team, er
 | 
				
			|||||||
		And("team_repo.repo_id = ?", repoID).
 | 
							And("team_repo.repo_id = ?", repoID).
 | 
				
			||||||
		Find(&teams)
 | 
							Find(&teams)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ___________                    ____ ___      .__  __
 | 
				
			||||||
 | 
					// \__    ___/___ _____    _____ |    |   \____ |__|/  |_
 | 
				
			||||||
 | 
					//   |    |_/ __ \\__  \  /     \|    |   /    \|  \   __\
 | 
				
			||||||
 | 
					//   |    |\  ___/ / __ \|  Y Y  \    |  /   |  \  ||  |
 | 
				
			||||||
 | 
					//   |____| \___  >____  /__|_|  /______/|___|  /__||__|
 | 
				
			||||||
 | 
					//              \/     \/      \/             \/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TeamUnit describes all units of a repository
 | 
				
			||||||
 | 
					type TeamUnit struct {
 | 
				
			||||||
 | 
						ID     int64    `xorm:"pk autoincr"`
 | 
				
			||||||
 | 
						OrgID  int64    `xorm:"INDEX"`
 | 
				
			||||||
 | 
						TeamID int64    `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
						Type   UnitType `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unit returns Unit
 | 
				
			||||||
 | 
					func (t *TeamUnit) Unit() Unit {
 | 
				
			||||||
 | 
						return Units[t.Type]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getUnitsByTeamID(e Engine, teamID int64) (units []*TeamUnit, err error) {
 | 
				
			||||||
 | 
						return units, e.Where("team_id = ?", teamID).Find(&units)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UpdateTeamUnits updates a teams's units
 | 
				
			||||||
 | 
					func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
 | 
				
			||||||
 | 
						sess := x.NewSession()
 | 
				
			||||||
 | 
						defer sess.Close()
 | 
				
			||||||
 | 
						if err = sess.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Where("team_id = ?", team.ID).Delete(new(TeamUnit)); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Insert(units); err != nil {
 | 
				
			||||||
 | 
							sess.Rollback()
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sess.Commit()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -489,8 +489,8 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) {
 | 
				
			|||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		assert.EqualValues(t, expectedCount, count)
 | 
							assert.EqualValues(t, expectedCount, count)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testSuccess(2, 2)
 | 
						testSuccess(2, 3)
 | 
				
			||||||
	testSuccess(4, 1)
 | 
						testSuccess(4, 2)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
 | 
					func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
 | 
				
			||||||
@@ -503,8 +503,8 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
 | 
				
			|||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		assert.Equal(t, expectedRepoIDs, repoIDs)
 | 
							assert.Equal(t, expectedRepoIDs, repoIDs)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testSuccess(2, 1, 100, []int64{3, 5})
 | 
						testSuccess(2, 1, 100, []int64{3, 5, 32})
 | 
				
			||||||
	testSuccess(4, 0, 100, []int64{3})
 | 
						testSuccess(4, 0, 100, []int64{3, 32})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAccessibleReposEnv_Repos(t *testing.T) {
 | 
					func TestAccessibleReposEnv_Repos(t *testing.T) {
 | 
				
			||||||
@@ -522,8 +522,8 @@ func TestAccessibleReposEnv_Repos(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		assert.Equal(t, expectedRepos, repos)
 | 
							assert.Equal(t, expectedRepos, repos)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testSuccess(2, []int64{3, 5})
 | 
						testSuccess(2, []int64{3, 5, 32})
 | 
				
			||||||
	testSuccess(4, []int64{3})
 | 
						testSuccess(4, []int64{3, 32})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
 | 
					func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -365,22 +365,14 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) (
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var allTypes = make(map[UnitType]struct{}, len(allRepUnitTypes))
 | 
					 | 
				
			||||||
	for _, team := range teams {
 | 
					 | 
				
			||||||
		// Administrators can not be limited
 | 
					 | 
				
			||||||
		if team.Authorize >= AccessModeAdmin {
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, unitType := range team.UnitTypes {
 | 
					 | 
				
			||||||
			allTypes[unitType] = struct{}{}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// unique
 | 
						// unique
 | 
				
			||||||
	var newRepoUnits = make([]*RepoUnit, 0, len(repo.Units))
 | 
						var newRepoUnits = make([]*RepoUnit, 0, len(repo.Units))
 | 
				
			||||||
	for _, u := range repo.Units {
 | 
						for _, u := range repo.Units {
 | 
				
			||||||
		if _, ok := allTypes[u.Type]; ok {
 | 
							for _, team := range teams {
 | 
				
			||||||
 | 
								if team.UnitEnabled(u.Type) {
 | 
				
			||||||
				newRepoUnits = append(newRepoUnits, u)
 | 
									newRepoUnits = append(newRepoUnits, u)
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -147,10 +147,10 @@ func TestSearchRepositoryByName(t *testing.T) {
 | 
				
			|||||||
			count: 14},
 | 
								count: 14},
 | 
				
			||||||
		{name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
 | 
							{name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
 | 
				
			||||||
			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, AllPublic: true},
 | 
								opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, AllPublic: true},
 | 
				
			||||||
			count: 15},
 | 
								count: 16},
 | 
				
			||||||
		{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
 | 
							{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
 | 
				
			||||||
			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
 | 
								opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
 | 
				
			||||||
			count: 19},
 | 
								count: 20},
 | 
				
			||||||
		{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
 | 
							{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
 | 
				
			||||||
			opts:  &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
 | 
								opts:  &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
 | 
				
			||||||
			count: 13},
 | 
								count: 13},
 | 
				
			||||||
@@ -159,7 +159,7 @@ func TestSearchRepositoryByName(t *testing.T) {
 | 
				
			|||||||
			count: 11},
 | 
								count: 11},
 | 
				
			||||||
		{name: "AllPublic/PublicRepositoriesOfOrganization",
 | 
							{name: "AllPublic/PublicRepositoriesOfOrganization",
 | 
				
			||||||
			opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse},
 | 
								opts:  &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse},
 | 
				
			||||||
			count: 15},
 | 
								count: 16},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, testCase := range testCases {
 | 
						for _, testCase := range testCases {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,6 +109,23 @@ func notifyWatchers(e Engine, act *Action) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		act.ID = 0
 | 
							act.ID = 0
 | 
				
			||||||
		act.UserID = watches[i].UserID
 | 
							act.UserID = watches[i].UserID
 | 
				
			||||||
 | 
							act.Repo.Units = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch act.OpType {
 | 
				
			||||||
 | 
							case ActionCommitRepo, ActionPushTag, ActionDeleteTag, ActionDeleteBranch:
 | 
				
			||||||
 | 
								if !act.Repo.CheckUnitUser(act.UserID, false, UnitTypeCode) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case ActionCreateIssue, ActionCommentIssue, ActionCloseIssue, ActionReopenIssue:
 | 
				
			||||||
 | 
								if !act.Repo.CheckUnitUser(act.UserID, false, UnitTypeIssues) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case ActionCreatePullRequest, ActionMergePullRequest, ActionClosePullRequest, ActionReopenPullRequest:
 | 
				
			||||||
 | 
								if !act.Repo.CheckUnitUser(act.UserID, false, UnitTypePullRequests) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if _, err = e.InsertOne(act); err != nil {
 | 
							if _, err = e.InsertOne(act); err != nil {
 | 
				
			||||||
			return fmt.Errorf("insert new action: %v", err)
 | 
								return fmt.Errorf("insert new action: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -546,28 +546,46 @@ func (u *User) GetRepositories(page, pageSize int) (err error) {
 | 
				
			|||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRepositoryIDs returns repositories IDs where user owned
 | 
					// GetRepositoryIDs returns repositories IDs where user owned and has unittypes
 | 
				
			||||||
func (u *User) GetRepositoryIDs() ([]int64, error) {
 | 
					func (u *User) GetRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
				
			||||||
	var ids []int64
 | 
						var ids []int64
 | 
				
			||||||
	return ids, x.Table("repository").Cols("id").Where("owner_id = ?", u.ID).Find(&ids)
 | 
					
 | 
				
			||||||
 | 
						sess := x.Table("repository").Cols("repository.id")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(units) > 0 {
 | 
				
			||||||
 | 
							sess = sess.Join("INNER", "repo_unit", "repository.id = repo_unit.repo_id")
 | 
				
			||||||
 | 
							sess = sess.In("repo_unit.type", units)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ids, sess.Where("owner_id = ?", u.ID).Find(&ids)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetOrgRepositoryIDs returns repositories IDs where user's team owned
 | 
					// GetOrgRepositoryIDs returns repositories IDs where user's team owned and has unittypes
 | 
				
			||||||
func (u *User) GetOrgRepositoryIDs() ([]int64, error) {
 | 
					func (u *User) GetOrgRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
				
			||||||
	var ids []int64
 | 
						var ids []int64
 | 
				
			||||||
	return ids, x.Table("repository").
 | 
					
 | 
				
			||||||
 | 
						sess := x.Table("repository").
 | 
				
			||||||
		Cols("repository.id").
 | 
							Cols("repository.id").
 | 
				
			||||||
		Join("INNER", "team_user", "repository.owner_id = team_user.org_id AND team_user.uid = ?", u.ID).
 | 
							Join("INNER", "team_user", "repository.owner_id = team_user.org_id").
 | 
				
			||||||
 | 
							Join("INNER", "team_repo", "repository.is_private != ? OR (team_user.team_id = team_repo.team_id AND repository.id = team_repo.repo_id)", true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(units) > 0 {
 | 
				
			||||||
 | 
							sess = sess.Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id")
 | 
				
			||||||
 | 
							sess = sess.In("team_unit.type", units)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ids, sess.
 | 
				
			||||||
 | 
							Where("team_user.uid = ?", u.ID).
 | 
				
			||||||
		GroupBy("repository.id").Find(&ids)
 | 
							GroupBy("repository.id").Find(&ids)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetAccessRepoIDs returns all repositories IDs where user's or user is a team member organizations
 | 
					// GetAccessRepoIDs returns all repositories IDs where user's or user is a team member organizations
 | 
				
			||||||
func (u *User) GetAccessRepoIDs() ([]int64, error) {
 | 
					func (u *User) GetAccessRepoIDs(units ...UnitType) ([]int64, error) {
 | 
				
			||||||
	ids, err := u.GetRepositoryIDs()
 | 
						ids, err := u.GetRepositoryIDs(units...)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ids2, err := u.GetOrgRepositoryIDs()
 | 
						ids2, err := u.GetOrgRepositoryIDs(units...)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -159,3 +159,25 @@ func BenchmarkHashPassword(b *testing.B) {
 | 
				
			|||||||
		u.HashPassword(pass)
 | 
							u.HashPassword(pass)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGetOrgRepositoryIDs(t *testing.T) {
 | 
				
			||||||
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
 | 
						user2 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
 | 
				
			||||||
 | 
						user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
 | 
				
			||||||
 | 
						user5 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accessibleRepos, err := user2.GetOrgRepositoryIDs()
 | 
				
			||||||
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
						// User 2's team has access to private repos 3, 5, repo 32 is a public repo of the organization
 | 
				
			||||||
 | 
						assert.Equal(t, []int64{3, 5, 32}, accessibleRepos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accessibleRepos, err = user4.GetOrgRepositoryIDs()
 | 
				
			||||||
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
						// User 4's team has access to private repo 3, repo 32 is a public repo of the organization
 | 
				
			||||||
 | 
						assert.Equal(t, []int64{3, 32}, accessibleRepos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accessibleRepos, err = user5.GetOrgRepositoryIDs()
 | 
				
			||||||
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
						// User 5's team has no access to any repo
 | 
				
			||||||
 | 
						assert.Len(t, accessibleRepos, 0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -182,7 +182,14 @@ func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
 | 
				
			|||||||
		Authorize:   models.ParseAccessMode(form.Permission),
 | 
							Authorize:   models.ParseAccessMode(form.Permission),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if t.Authorize < models.AccessModeAdmin {
 | 
						if t.Authorize < models.AccessModeAdmin {
 | 
				
			||||||
		t.UnitTypes = form.Units
 | 
							var units = make([]*models.TeamUnit, 0, len(form.Units))
 | 
				
			||||||
 | 
							for _, tp := range form.Units {
 | 
				
			||||||
 | 
								units = append(units, &models.TeamUnit{
 | 
				
			||||||
 | 
									OrgID: ctx.Org.Organization.ID,
 | 
				
			||||||
 | 
									Type:  tp,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t.Units = units
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Data["Team"] = t
 | 
						ctx.Data["Team"] = t
 | 
				
			||||||
@@ -264,9 +271,17 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	t.Description = form.Description
 | 
						t.Description = form.Description
 | 
				
			||||||
	if t.Authorize < models.AccessModeAdmin {
 | 
						if t.Authorize < models.AccessModeAdmin {
 | 
				
			||||||
		t.UnitTypes = form.Units
 | 
							var units = make([]models.TeamUnit, 0, len(form.Units))
 | 
				
			||||||
 | 
							for _, tp := range form.Units {
 | 
				
			||||||
 | 
								units = append(units, models.TeamUnit{
 | 
				
			||||||
 | 
									OrgID:  t.OrgID,
 | 
				
			||||||
 | 
									TeamID: t.ID,
 | 
				
			||||||
 | 
									Type:   tp,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							models.UpdateTeamUnits(t, units)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		t.UnitTypes = nil
 | 
							models.UpdateTeamUnits(t, nil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.HasError() {
 | 
						if ctx.HasError() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -203,7 +203,11 @@ func Issues(ctx *context.Context) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		userRepoIDs, err = ctxUser.GetAccessRepoIDs()
 | 
							unitType := models.UnitTypeIssues
 | 
				
			||||||
 | 
							if isPullList {
 | 
				
			||||||
 | 
								unitType = models.UnitTypePullRequests
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							userRepoIDs, err = ctxUser.GetAccessRepoIDs(unitType)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.ServerError("ctxUser.GetAccessRepoIDs", err)
 | 
								ctx.ServerError("ctxUser.GetAccessRepoIDs", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,8 @@ func TestIssues(t *testing.T) {
 | 
				
			|||||||
	Issues(ctx)
 | 
						Issues(ctx)
 | 
				
			||||||
	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
						assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	assert.EqualValues(t, map[int64]int64{1: 1, 2: 1}, ctx.Data["Counts"])
 | 
						assert.EqualValues(t, map[int64]int64{1: 1}, ctx.Data["Counts"])
 | 
				
			||||||
	assert.EqualValues(t, true, ctx.Data["IsShowClosed"])
 | 
						assert.EqualValues(t, true, ctx.Data["IsShowClosed"])
 | 
				
			||||||
	assert.Len(t, ctx.Data["Issues"], 1)
 | 
						assert.Len(t, ctx.Data["Issues"], 1)
 | 
				
			||||||
	assert.Len(t, ctx.Data["Repos"], 2)
 | 
						assert.Len(t, ctx.Data["Repos"], 1)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,7 @@
 | 
				
			|||||||
							{{range $t, $unit := $.Units}}
 | 
												{{range $t, $unit := $.Units}}
 | 
				
			||||||
							<div class="field">
 | 
												<div class="field">
 | 
				
			||||||
								<div class="ui toggle checkbox">
 | 
													<div class="ui toggle checkbox">
 | 
				
			||||||
									<input type="checkbox" class="hidden" name="units" value="{{$unit.Type}}"{{if $.Team.UnitEnabled $unit.Type}} checked{{end}}>
 | 
														<input type="checkbox" class="hidden" name="units" value="{{$unit.Type}}"{{if or (eq $.Team.ID 0) ($.Team.UnitEnabled $unit.Type)}} checked{{end}}>
 | 
				
			||||||
									<label>{{$.i18n.Tr $unit.NameKey}}</label>
 | 
														<label>{{$.i18n.Tr $unit.NameKey}}</label>
 | 
				
			||||||
									<span class="help">{{$.i18n.Tr $unit.DescKey}}</span>
 | 
														<span class="help">{{$.i18n.Tr $unit.DescKey}}</span>
 | 
				
			||||||
								</div>
 | 
													</div>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user