323 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			323 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Ruby
		
	
	
	
RSpec.shared_examples 'snippet visibility' do
 | 
						|
  let!(:author) { create(:user) }
 | 
						|
  let!(:member) { create(:user) }
 | 
						|
  let!(:external) { create(:user, :external) }
 | 
						|
 | 
						|
  let!(:snippet_type_visibilities) do
 | 
						|
    {
 | 
						|
      public: Snippet::PUBLIC,
 | 
						|
      internal: Snippet::INTERNAL,
 | 
						|
      private: Snippet::PRIVATE
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  context "For project snippets" do
 | 
						|
    let!(:users) do
 | 
						|
      {
 | 
						|
        unauthenticated: nil,
 | 
						|
        external: external,
 | 
						|
        non_member: create(:user),
 | 
						|
        member: member,
 | 
						|
        author: author
 | 
						|
      }
 | 
						|
    end
 | 
						|
 | 
						|
    let!(:project_type_visibilities) do
 | 
						|
      {
 | 
						|
        public: Gitlab::VisibilityLevel::PUBLIC,
 | 
						|
        internal: Gitlab::VisibilityLevel::INTERNAL,
 | 
						|
        private: Gitlab::VisibilityLevel::PRIVATE
 | 
						|
      }
 | 
						|
    end
 | 
						|
 | 
						|
    let(:project_feature_visibilities) do
 | 
						|
      {
 | 
						|
        enabled: ProjectFeature::ENABLED,
 | 
						|
        private: ProjectFeature::PRIVATE,
 | 
						|
        disabled: ProjectFeature::DISABLED
 | 
						|
      }
 | 
						|
    end
 | 
						|
 | 
						|
    where(:project_type, :feature_visibility, :user_type, :snippet_type, :outcome) do
 | 
						|
      [
 | 
						|
        # Public projects
 | 
						|
        [:public, :enabled, :unauthenticated,    :public,   true],
 | 
						|
        [:public, :enabled, :unauthenticated,    :internal, false],
 | 
						|
        [:public, :enabled, :unauthenticated,    :private,  false],
 | 
						|
 | 
						|
        [:public, :enabled, :external,           :public,   true],
 | 
						|
        [:public, :enabled, :external,           :internal, false],
 | 
						|
        [:public, :enabled, :external,           :private,  false],
 | 
						|
 | 
						|
        [:public, :enabled, :non_member,         :public,   true],
 | 
						|
        [:public, :enabled, :non_member,         :internal, true],
 | 
						|
        [:public, :enabled, :non_member,         :private,  false],
 | 
						|
 | 
						|
        [:public, :enabled, :member,             :public,   true],
 | 
						|
        [:public, :enabled, :member,             :internal, true],
 | 
						|
        [:public, :enabled, :member,             :private,  true],
 | 
						|
 | 
						|
        [:public, :enabled, :author,             :public,   true],
 | 
						|
        [:public, :enabled, :author,             :internal, true],
 | 
						|
        [:public, :enabled, :author,             :private,  true],
 | 
						|
 | 
						|
        [:public, :private, :unauthenticated,    :public,   false],
 | 
						|
        [:public, :private, :unauthenticated,    :internal, false],
 | 
						|
        [:public, :private, :unauthenticated,    :private,  false],
 | 
						|
 | 
						|
        [:public, :private, :external,           :public,   false],
 | 
						|
        [:public, :private, :external,           :internal, false],
 | 
						|
        [:public, :private, :external,           :private,  false],
 | 
						|
 | 
						|
        [:public, :private, :non_member,         :public,   false],
 | 
						|
        [:public, :private, :non_member,         :internal, false],
 | 
						|
        [:public, :private, :non_member,         :private,  false],
 | 
						|
 | 
						|
        [:public, :private, :member,             :public,   true],
 | 
						|
        [:public, :private, :member,             :internal, true],
 | 
						|
        [:public, :private, :member,             :private,  true],
 | 
						|
 | 
						|
        [:public, :private, :author,             :public,   true],
 | 
						|
        [:public, :private, :author,             :internal, true],
 | 
						|
        [:public, :private, :author,             :private,  true],
 | 
						|
 | 
						|
        [:public, :disabled, :unauthenticated,   :public,   false],
 | 
						|
        [:public, :disabled, :unauthenticated,   :internal, false],
 | 
						|
        [:public, :disabled, :unauthenticated,   :private,  false],
 | 
						|
 | 
						|
        [:public, :disabled, :external,          :public,   false],
 | 
						|
        [:public, :disabled, :external,          :internal, false],
 | 
						|
        [:public, :disabled, :external,          :private,  false],
 | 
						|
 | 
						|
        [:public, :disabled, :non_member,        :public,   false],
 | 
						|
        [:public, :disabled, :non_member,        :internal, false],
 | 
						|
        [:public, :disabled, :non_member,        :private,  false],
 | 
						|
 | 
						|
        [:public, :disabled, :member,            :public,   false],
 | 
						|
        [:public, :disabled, :member,            :internal, false],
 | 
						|
        [:public, :disabled, :member,            :private,  false],
 | 
						|
 | 
						|
        [:public, :disabled, :author,            :public,   false],
 | 
						|
        [:public, :disabled, :author,            :internal, false],
 | 
						|
        [:public, :disabled, :author,            :private,  false],
 | 
						|
 | 
						|
        # Internal projects
 | 
						|
        [:internal, :enabled, :unauthenticated,  :public,   false],
 | 
						|
        [:internal, :enabled, :unauthenticated,  :internal, false],
 | 
						|
        [:internal, :enabled, :unauthenticated,  :private,  false],
 | 
						|
 | 
						|
        [:internal, :enabled, :external,         :public,   false],
 | 
						|
        [:internal, :enabled, :external,         :internal, false],
 | 
						|
        [:internal, :enabled, :external,         :private,  false],
 | 
						|
 | 
						|
        [:internal, :enabled, :non_member,       :public,   true],
 | 
						|
        [:internal, :enabled, :non_member,       :internal, true],
 | 
						|
        [:internal, :enabled, :non_member,       :private,  false],
 | 
						|
 | 
						|
        [:internal, :enabled, :member,           :public,   true],
 | 
						|
        [:internal, :enabled, :member,           :internal, true],
 | 
						|
        [:internal, :enabled, :member,           :private,  true],
 | 
						|
 | 
						|
        [:internal, :enabled, :author,           :public,   true],
 | 
						|
        [:internal, :enabled, :author,           :internal, true],
 | 
						|
        [:internal, :enabled, :author,           :private,  true],
 | 
						|
 | 
						|
        [:internal, :private, :unauthenticated,  :public,   false],
 | 
						|
        [:internal, :private, :unauthenticated,  :internal, false],
 | 
						|
        [:internal, :private, :unauthenticated,  :private,  false],
 | 
						|
 | 
						|
        [:internal, :private, :external,         :public,   false],
 | 
						|
        [:internal, :private, :external,         :internal, false],
 | 
						|
        [:internal, :private, :external,         :private,  false],
 | 
						|
 | 
						|
        [:internal, :private, :non_member,       :public,   false],
 | 
						|
        [:internal, :private, :non_member,       :internal, false],
 | 
						|
        [:internal, :private, :non_member,       :private,  false],
 | 
						|
 | 
						|
        [:internal, :private, :member,           :public,   true],
 | 
						|
        [:internal, :private, :member,           :internal, true],
 | 
						|
        [:internal, :private, :member,           :private,  true],
 | 
						|
 | 
						|
        [:internal, :private, :author,           :public,   true],
 | 
						|
        [:internal, :private, :author,           :internal, true],
 | 
						|
        [:internal, :private, :author,           :private,  true],
 | 
						|
 | 
						|
        [:internal, :disabled, :unauthenticated, :public,   false],
 | 
						|
        [:internal, :disabled, :unauthenticated, :internal, false],
 | 
						|
        [:internal, :disabled, :unauthenticated, :private,  false],
 | 
						|
 | 
						|
        [:internal, :disabled, :external,        :public,   false],
 | 
						|
        [:internal, :disabled, :external,        :internal, false],
 | 
						|
        [:internal, :disabled, :external,        :private,  false],
 | 
						|
 | 
						|
        [:internal, :disabled, :non_member,      :public,   false],
 | 
						|
        [:internal, :disabled, :non_member,      :internal, false],
 | 
						|
        [:internal, :disabled, :non_member,      :private,  false],
 | 
						|
 | 
						|
        [:internal, :disabled, :member,          :public,   false],
 | 
						|
        [:internal, :disabled, :member,          :internal, false],
 | 
						|
        [:internal, :disabled, :member,          :private,  false],
 | 
						|
 | 
						|
        [:internal, :disabled, :author,          :public,   false],
 | 
						|
        [:internal, :disabled, :author,          :internal, false],
 | 
						|
        [:internal, :disabled, :author,          :private,  false],
 | 
						|
 | 
						|
        # Private projects
 | 
						|
        [:private, :enabled, :unauthenticated,   :public,   false],
 | 
						|
        [:private, :enabled, :unauthenticated,   :internal, false],
 | 
						|
        [:private, :enabled, :unauthenticated,   :private,  false],
 | 
						|
 | 
						|
        [:private, :enabled, :external,          :public,   true],
 | 
						|
        [:private, :enabled, :external,          :internal, true],
 | 
						|
        [:private, :enabled, :external,          :private,  true],
 | 
						|
 | 
						|
        [:private, :enabled, :non_member,        :public,   false],
 | 
						|
        [:private, :enabled, :non_member,        :internal, false],
 | 
						|
        [:private, :enabled, :non_member,        :private,  false],
 | 
						|
 | 
						|
        [:private, :enabled, :member,            :public,   true],
 | 
						|
        [:private, :enabled, :member,            :internal, true],
 | 
						|
        [:private, :enabled, :member,            :private,  true],
 | 
						|
 | 
						|
        [:private, :enabled, :author,            :public,   true],
 | 
						|
        [:private, :enabled, :author,            :internal, true],
 | 
						|
        [:private, :enabled, :author,            :private,  true],
 | 
						|
 | 
						|
        [:private, :private, :unauthenticated,   :public,   false],
 | 
						|
        [:private, :private, :unauthenticated,   :internal, false],
 | 
						|
        [:private, :private, :unauthenticated,   :private,  false],
 | 
						|
 | 
						|
        [:private, :private, :external,          :public,   true],
 | 
						|
        [:private, :private, :external,          :internal, true],
 | 
						|
        [:private, :private, :external,          :private,  true],
 | 
						|
 | 
						|
        [:private, :private, :non_member,        :public,   false],
 | 
						|
        [:private, :private, :non_member,        :internal, false],
 | 
						|
        [:private, :private, :non_member,        :private,  false],
 | 
						|
 | 
						|
        [:private, :private, :member,            :public,   true],
 | 
						|
        [:private, :private, :member,            :internal, true],
 | 
						|
        [:private, :private, :member,            :private,  true],
 | 
						|
 | 
						|
        [:private, :private, :author,            :public,   true],
 | 
						|
        [:private, :private, :author,            :internal, true],
 | 
						|
        [:private, :private, :author,            :private,  true],
 | 
						|
 | 
						|
        [:private, :disabled, :unauthenticated,  :public,   false],
 | 
						|
        [:private, :disabled, :unauthenticated,  :internal, false],
 | 
						|
        [:private, :disabled, :unauthenticated,  :private,  false],
 | 
						|
 | 
						|
        [:private, :disabled, :external,         :public,   false],
 | 
						|
        [:private, :disabled, :external,         :internal, false],
 | 
						|
        [:private, :disabled, :external,         :private,  false],
 | 
						|
 | 
						|
        [:private, :disabled, :non_member,       :public,   false],
 | 
						|
        [:private, :disabled, :non_member,       :internal, false],
 | 
						|
        [:private, :disabled, :non_member,       :private,  false],
 | 
						|
 | 
						|
        [:private, :disabled, :member,           :public,   false],
 | 
						|
        [:private, :disabled, :member,           :internal, false],
 | 
						|
        [:private, :disabled, :member,           :private,  false],
 | 
						|
 | 
						|
        [:private, :disabled, :author,           :public,   false],
 | 
						|
        [:private, :disabled, :author,           :internal, false],
 | 
						|
        [:private, :disabled, :author,           :private,  false]
 | 
						|
      ]
 | 
						|
    end
 | 
						|
 | 
						|
    with_them do
 | 
						|
      let!(:project) { create(:project, visibility_level: project_type_visibilities[project_type]) }
 | 
						|
      let!(:project_feature) { project.project_feature.update_column(:snippets_access_level, project_feature_visibilities[feature_visibility]) }
 | 
						|
      let!(:user) { users[user_type] }
 | 
						|
      let!(:snippet) { create(:project_snippet, visibility_level: snippet_type_visibilities[snippet_type], project: project, author: author) }
 | 
						|
      let!(:members) do
 | 
						|
        project.add_developer(author)
 | 
						|
        project.add_developer(member)
 | 
						|
        project.add_developer(external) if project.private?
 | 
						|
      end
 | 
						|
 | 
						|
      context "For #{params[:project_type]} project and #{params[:user_type]} users" do
 | 
						|
        it 'should agree with the read_project_snippet policy' do
 | 
						|
          expect(can?(user, :read_project_snippet, snippet)).to eq(outcome)
 | 
						|
        end
 | 
						|
 | 
						|
        it 'should return proper outcome' do
 | 
						|
          results = described_class.new(user, project: project).execute
 | 
						|
          expect(results.include?(snippet)).to eq(outcome)
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context "Without a given project and #{params[:user_type]} users" do
 | 
						|
        it 'should return proper outcome' do
 | 
						|
          results = described_class.new(user).execute
 | 
						|
          expect(results.include?(snippet)).to eq(outcome)
 | 
						|
        end
 | 
						|
 | 
						|
        it 'returns no snippets when the user cannot read cross project' do
 | 
						|
          allow(Ability).to receive(:allowed?).and_call_original
 | 
						|
          allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
 | 
						|
 | 
						|
          snippets = described_class.new(user).execute
 | 
						|
 | 
						|
          expect(snippets).to be_empty
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  context 'For personal snippets' do
 | 
						|
    let!(:users) do
 | 
						|
      {
 | 
						|
        unauthenticated: nil,
 | 
						|
        external: external,
 | 
						|
        non_member: create(:user),
 | 
						|
        author: author
 | 
						|
      }
 | 
						|
    end
 | 
						|
 | 
						|
    where(:snippet_visibility, :user_type, :outcome) do
 | 
						|
      [
 | 
						|
        [:public,   :unauthenticated, true],
 | 
						|
        [:public,   :external,        true],
 | 
						|
        [:public,   :non_member,      true],
 | 
						|
        [:public,   :author,          true],
 | 
						|
 | 
						|
        [:internal, :unauthenticated, false],
 | 
						|
        [:internal, :external,        false],
 | 
						|
        [:internal, :non_member,      true],
 | 
						|
        [:internal, :author,          true],
 | 
						|
 | 
						|
        [:private,  :unauthenticated, false],
 | 
						|
        [:private,  :external,        false],
 | 
						|
        [:private,  :non_member,      false],
 | 
						|
        [:private,  :author,          true]
 | 
						|
      ]
 | 
						|
    end
 | 
						|
 | 
						|
    with_them do
 | 
						|
      let!(:user) { users[user_type] }
 | 
						|
      let!(:snippet) { create(:personal_snippet, visibility_level: snippet_type_visibilities[snippet_visibility], author: author) }
 | 
						|
 | 
						|
      context "For personal and #{params[:snippet_visibility]} snippets with #{params[:user_type]} user" do
 | 
						|
        it 'should agree with read_personal_snippet policy' do
 | 
						|
          expect(can?(user, :read_personal_snippet, snippet)).to eq(outcome)
 | 
						|
        end
 | 
						|
 | 
						|
        it 'should return proper outcome' do
 | 
						|
          results = described_class.new(user).execute
 | 
						|
          expect(results.include?(snippet)).to eq(outcome)
 | 
						|
        end
 | 
						|
 | 
						|
        it 'should return personal snippets when the user cannot read cross project' do
 | 
						|
          allow(Ability).to receive(:allowed?).and_call_original
 | 
						|
          allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
 | 
						|
 | 
						|
          results = described_class.new(user).execute
 | 
						|
 | 
						|
          expect(results.include?(snippet)).to eq(outcome)
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |