Include group parents into read access for project and group
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
This commit is contained in:
		
							parent
							
								
									645412b57f
								
							
						
					
					
						commit
						7b4b3d5f26
					
				| 
						 | 
				
			
			@ -155,15 +155,17 @@ class Group < Namespace
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def has_owner?(user)
 | 
			
		||||
    owners.include?(user)
 | 
			
		||||
    members_with_parents.owners.where(user_id: user).any?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def has_master?(user)
 | 
			
		||||
    members.masters.where(user_id: user).any?
 | 
			
		||||
    members_with_parents.masters.where(user_id: user).any?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Check if user is a last owner of the group.
 | 
			
		||||
  # Parent owners are ignored for nested groups.
 | 
			
		||||
  def last_owner?(user)
 | 
			
		||||
    has_owner?(user) && owners.size == 1
 | 
			
		||||
    owners.include?(user) && owners.size == 1
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def avatar_type
 | 
			
		||||
| 
						 | 
				
			
			@ -189,6 +191,14 @@ class Group < Namespace
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def refresh_members_authorized_projects
 | 
			
		||||
    UserProjectAccessChangedService.new(users.pluck(:id)).execute
 | 
			
		||||
    UserProjectAccessChangedService.new(users_with_parents.pluck(:id)).execute
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def members_with_parents
 | 
			
		||||
    GroupMember.where(requested_at: nil, source_id: parents.map(&:id).push(id))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def users_with_parents
 | 
			
		||||
    User.where(id: members_with_parents.pluck(:user_id))
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ class GroupPolicy < BasePolicy
 | 
			
		|||
    return unless @user
 | 
			
		||||
 | 
			
		||||
    globally_viewable = @subject.public? || (@subject.internal? && !@user.external?)
 | 
			
		||||
    member = @subject.users.include?(@user)
 | 
			
		||||
    member = @subject.users_with_parents.include?(@user)
 | 
			
		||||
    owner = @user.admin? || @subject.has_owner?(@user)
 | 
			
		||||
    master = owner || @subject.has_master?(@user)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -245,7 +245,7 @@ class ProjectPolicy < BasePolicy
 | 
			
		|||
  def project_group_member?(user)
 | 
			
		||||
    project.group &&
 | 
			
		||||
      (
 | 
			
		||||
        project.group.members.exists?(user_id: user.id) ||
 | 
			
		||||
        project.group.members_with_parents.exists?(user_id: user.id) ||
 | 
			
		||||
        project.group.requesters.exists?(user_id: user.id)
 | 
			
		||||
      )
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -277,4 +277,15 @@ describe Group, models: true do
 | 
			
		|||
    it { is_expected.to be_valid }
 | 
			
		||||
    it { expect(subject.parent).to be_kind_of(Group) }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#members_with_parents' do
 | 
			
		||||
    let!(:group) { create(:group, :nested) }
 | 
			
		||||
    let!(:master) { group.parent.add_user(create(:user), GroupMember::MASTER) }
 | 
			
		||||
    let!(:developer) { group.add_user(create(:user), GroupMember::DEVELOPER) }
 | 
			
		||||
 | 
			
		||||
    it 'returns parents members' do
 | 
			
		||||
      expect(group.members_with_parents).to include(developer)
 | 
			
		||||
      expect(group.members_with_parents).to include(master)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,4 +105,70 @@ describe GroupPolicy, models: true do
 | 
			
		|||
      is_expected.to include(*owner_permissions)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'private nested group inherit permissions' do
 | 
			
		||||
    let(:nested_group) { create(:group, :private, parent: group) }
 | 
			
		||||
 | 
			
		||||
    subject { described_class.abilities(current_user, nested_group).to_set }
 | 
			
		||||
 | 
			
		||||
    context 'with no user' do
 | 
			
		||||
      let(:current_user) { nil }
 | 
			
		||||
 | 
			
		||||
      it do
 | 
			
		||||
        is_expected.not_to include(:read_group)
 | 
			
		||||
        is_expected.not_to include(*master_permissions)
 | 
			
		||||
        is_expected.not_to include(*owner_permissions)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'guests' do
 | 
			
		||||
      let(:current_user) { guest }
 | 
			
		||||
 | 
			
		||||
      it do
 | 
			
		||||
        is_expected.to include(:read_group)
 | 
			
		||||
        is_expected.not_to include(*master_permissions)
 | 
			
		||||
        is_expected.not_to include(*owner_permissions)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'reporter' do
 | 
			
		||||
      let(:current_user) { reporter }
 | 
			
		||||
 | 
			
		||||
      it do
 | 
			
		||||
        is_expected.to include(:read_group)
 | 
			
		||||
        is_expected.not_to include(*master_permissions)
 | 
			
		||||
        is_expected.not_to include(*owner_permissions)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'developer' do
 | 
			
		||||
      let(:current_user) { developer }
 | 
			
		||||
 | 
			
		||||
      it do
 | 
			
		||||
        is_expected.to include(:read_group)
 | 
			
		||||
        is_expected.not_to include(*master_permissions)
 | 
			
		||||
        is_expected.not_to include(*owner_permissions)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'master' do
 | 
			
		||||
      let(:current_user) { master }
 | 
			
		||||
 | 
			
		||||
      it do
 | 
			
		||||
        is_expected.to include(:read_group)
 | 
			
		||||
        is_expected.to include(*master_permissions)
 | 
			
		||||
        is_expected.not_to include(*owner_permissions)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'owner' do
 | 
			
		||||
      let(:current_user) { owner }
 | 
			
		||||
 | 
			
		||||
      it do
 | 
			
		||||
        is_expected.to include(:read_group)
 | 
			
		||||
        is_expected.to include(*master_permissions)
 | 
			
		||||
        is_expected.to include(*owner_permissions)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue