gitlab-ce/spec/policies/work_item_policy_spec.rb

207 lines
11 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
# rubocop:disable Layout/LineLength -- defined a work item for every case
RSpec.describe WorkItemPolicy, :aggregate_failures, feature_category: :team_planning do
let_it_be(:private_group) { create(:group, :private) }
let_it_be(:public_group) { create(:group, :public) }
let_it_be(:private_project) { create(:project, :private, group: private_group) }
let_it_be(:public_project) { create(:project, :public, group: public_group) }
let_it_be(:admin) { create(:user, :admin) }
let_it_be(:non_member_user) { create(:user) }
let_it_be(:author) { create(:user) }
let_it_be(:assignee) { create(:user) }
let_it_be(:support_bot) { Users::Internal.support_bot }
let_it_be(:guest) { create(:user, guest_of: [private_project, public_project]) }
let_it_be(:guest_author) { create(:user, guest_of: [private_project, public_project]) }
let_it_be(:planner) { create(:user, planner_of: [private_project, public_project]) }
let_it_be(:reporter) { create(:user, reporter_of: [private_project, public_project]) }
let_it_be(:owner) { create(:user, owner_of: [private_project, public_project]) }
let_it_be(:group_guest) { create(:user, guest_of: [private_group, public_group]) }
let_it_be(:group_planner) { create(:user, planner_of: [private_group, public_group]) }
let_it_be(:group_guest_author) { create(:user, guest_of: [private_group, public_group]) }
let_it_be(:group_reporter) { create(:user, reporter_of: [private_group, public_group]) }
def permissions(user, work_item)
described_class.new(user, work_item)
end
before do
stub_application_setting(akismet_enabled: true)
end
context 'with project level work items' do
context 'with private project' do
let(:project_work_item) { create(:work_item, project: private_project, user_agent_detail: create(:user_agent_detail)) }
let(:project_confidential_work_item) { create(:work_item, confidential: true, project: private_project, user_agent_detail: create(:user_agent_detail)) }
let(:authored_project_work_item) { create(:work_item, project: private_project, author: guest_author) }
let(:authored_project_confidential_work_item) { create(:work_item, confidential: true, project: private_project, author: guest_author) }
let(:not_persisted_project_work_item) { build(:work_item, project: private_project) }
let(:incident) { create(:work_item, :incident, project: private_project) }
let_it_be(:incident_work_item) { create(:work_item, :incident, project: private_project) }
it_behaves_like 'checks abilities for project level work items'
it_behaves_like 'prevents access to project-level {issues|work_items} with type Epic', :work_item do
let_it_be(:project) { private_project }
end
it 'checks non-member abilities' do
# disallowed
expect(permissions(non_member_user, project_work_item)).to be_disallowed(
:read_work_item, :read_issue, :read_note, :admin_work_item, :update_work_item, :delete_work_item,
:admin_parent_link, :admin_work_item_link, :create_note, :report_spam, :move_work_item, :clone_work_item,
:summarize_comments
)
expect(permissions(non_member_user, project_confidential_work_item)).to be_disallowed(
:read_work_item, :read_issue, :read_note, :admin_work_item, :update_work_item, :delete_work_item,
:admin_parent_link, :admin_work_item_link, :create_note, :report_spam, :move_work_item, :clone_work_item,
:summarize_comments
)
end
it 'checks non-admin abilities for spam reporting' do
expect(permissions(guest, project_work_item)).to be_disallowed(:report_spam)
expect(permissions(non_member_user, project_work_item)).to be_disallowed(:report_spam)
end
it 'checks admin abilities for spam reporting' do
expect(permissions(admin, project_work_item)).to be_allowed(:report_spam)
expect(permissions(admin, project_confidential_work_item)).to be_allowed(:report_spam)
end
it 'checks admin_work_item_link and admin_parent_link permissions with incident work items for guest members' do
expect(permissions(guest, incident)).to be_disallowed(:admin_work_item_link, :admin_parent_link)
end
it 'checks admin_work_item_link and admin_parent_link permissions with non-incident work items for guest members' do
expect(permissions(guest, project_work_item)).to be_allowed(:admin_work_item_link, :admin_parent_link)
end
end
context 'with public project' do
let(:project_work_item) { create(:work_item, project: public_project, user_agent_detail: create(:user_agent_detail)) }
let(:project_confidential_work_item) { create(:work_item, confidential: true, project: public_project, user_agent_detail: create(:user_agent_detail)) }
let(:authored_project_work_item) { create(:work_item, project: private_project, author: guest_author) }
let(:authored_project_confidential_work_item) { create(:work_item, confidential: true, project: private_project, author: guest_author) }
let(:not_persisted_project_work_item) { build(:work_item, project: public_project) }
let_it_be(:incident_work_item) { create(:work_item, :incident, project: public_project) }
it_behaves_like 'checks abilities for project level work items'
it_behaves_like 'prevents access to project-level {issues|work_items} with type Epic', :work_item do
let_it_be(:project) { public_project }
end
it 'checks non-member abilities' do
# allowed
expect(permissions(non_member_user, project_work_item)).to be_allowed(
:read_work_item, :read_issue, :read_note, :create_note
)
# disallowed
expect(permissions(non_member_user, project_work_item)).to be_disallowed(
:admin_work_item, :update_work_item, :delete_work_item,
:admin_parent_link, :admin_work_item_link, :report_spam, :move_work_item, :clone_work_item,
:summarize_comments
)
expect(permissions(non_member_user, project_confidential_work_item)).to be_disallowed(
:read_work_item, :read_issue, :read_note, :admin_work_item, :update_work_item, :delete_work_item,
:admin_parent_link, :admin_work_item_link, :create_note, :report_spam, :move_work_item, :clone_work_item,
:summarize_comments
)
end
it 'checks admin abilities for spam reporting' do
expect(permissions(admin, project_work_item)).to be_allowed(:report_spam)
expect(permissions(admin, project_confidential_work_item)).to be_allowed(:report_spam)
end
it 'checks admin_work_item_link and admin_parent_link permissions with incident work items for guest members' do
expect(permissions(guest, incident_work_item)).to be_disallowed(:admin_work_item_link, :admin_parent_link)
end
it 'checks admin_work_item_link and admin_parent_link permissions with non-incident work items for guest members' do
expect(permissions(non_member_user, project_work_item)).to be_disallowed(:admin_work_item_link, :admin_parent_link)
end
end
end
context 'with group level work items' do
context 'with private group' do
let(:work_item) { create(:work_item, :group_level, namespace: private_group) }
let(:confidential_work_item) { create(:work_item, :group_level, confidential: true, namespace: private_group) }
let(:authored_work_item) { create(:work_item, :group_level, namespace: private_group, author: group_guest_author) }
let(:authored_confidential_work_item) { create(:work_item, :group_level, confidential: true, namespace: private_group, author: group_guest_author) }
let(:not_persisted_work_item) { build(:work_item, :group_level, namespace: private_group) }
it_behaves_like 'abilities without group level work items license'
it_behaves_like 'abilities with group level work items license'
context 'with group level work items license', if: Gitlab.ee? do
before do
stub_licensed_features(epics: true)
end
# non-member abilities checks are extracted separately from shared examples because behaviour is different
# between public and private groups when group level work items licence is enabled.
it 'checks non-member abilities' do
# disallowed
expect(permissions(non_member_user, work_item)).to be_disallowed(
:read_work_item, :read_issue, :read_note, :admin_work_item, :update_work_item, :delete_work_item,
:admin_parent_link, :set_work_item_metadata, :admin_work_item_link, :create_note,
:move_work_item, :clone_work_item, :summarize_comments
)
expect(permissions(non_member_user, confidential_work_item)).to be_disallowed(
:read_work_item, :read_issue, :read_note, :admin_work_item, :update_work_item, :delete_work_item,
:admin_parent_link, :set_work_item_metadata, :admin_work_item_link, :create_note,
:move_work_item, :clone_work_item, :summarize_comments
)
end
end
end
context 'with public group' do
let(:work_item) { create(:work_item, :group_level, namespace: public_group) }
let(:confidential_work_item) { create(:work_item, :group_level, confidential: true, namespace: public_group) }
let(:authored_work_item) { create(:work_item, :group_level, namespace: public_group, author: group_guest_author) }
let(:authored_confidential_work_item) { create(:work_item, :group_level, confidential: true, namespace: public_group, author: group_guest_author) }
let(:not_persisted_work_item) { build(:work_item, :group_level, namespace: public_group) }
it_behaves_like 'abilities without group level work items license'
it_behaves_like 'abilities with group level work items license'
context 'with group level work items license', if: Gitlab.ee? do
before do
stub_licensed_features(epics: true)
end
# non-member abilities checks are extracted separately from shared examples because behaviour is different
# between public and private groups when group level work items licence is enabled.
it 'checks non-member abilities' do
# allowed
expect(permissions(non_member_user, work_item)).to be_allowed(
:read_work_item, :read_issue, :read_note, :create_note
)
# disallowed
expect(permissions(non_member_user, work_item)).to be_disallowed(
:admin_work_item, :update_work_item, :delete_work_item, :admin_parent_link, :set_work_item_metadata,
:admin_work_item_link, :move_work_item, :clone_work_item, :summarize_comments
)
expect(permissions(non_member_user, confidential_work_item)).to be_disallowed(
:read_work_item, :read_issue, :read_note, :admin_work_item, :update_work_item, :delete_work_item,
:admin_parent_link, :set_work_item_metadata, :admin_work_item_link, :create_note,
:move_work_item, :clone_work_item, :summarize_comments
)
end
end
end
end
end
# rubocop:enable Layout/LineLength