Commit b94f9c91 authored by Stan Hu's avatar Stan Hu

Merge branch '300100_allow_guests_to_define_metadata_on_issue_create' into 'master'

Allow guest user to assign issue metadata on issue create

See merge request gitlab-org/gitlab!62816
parents 2f550f60 ae50169e
...@@ -15,6 +15,9 @@ class IssuePolicy < IssuablePolicy ...@@ -15,6 +15,9 @@ class IssuePolicy < IssuablePolicy
desc "Issue is confidential" desc "Issue is confidential"
condition(:confidential, scope: :subject) { @subject.confidential? } condition(:confidential, scope: :subject) { @subject.confidential? }
desc "Issue is persisted"
condition(:persisted, scope: :subject) { @subject.persisted? }
rule { confidential & ~can_read_confidential }.policy do rule { confidential & ~can_read_confidential }.policy do
prevent(*create_read_update_admin_destroy(:issue)) prevent(*create_read_update_admin_destroy(:issue))
prevent :read_issue_iid prevent :read_issue_iid
...@@ -40,6 +43,14 @@ class IssuePolicy < IssuablePolicy ...@@ -40,6 +43,14 @@ class IssuePolicy < IssuablePolicy
enable :create_todo enable :create_todo
enable :update_subscription enable :update_subscription
end end
rule { ~persisted & can?(:guest_access) }.policy do
enable :set_issue_metadata
end
rule { persisted & can?(:admin_issue) }.policy do
enable :set_issue_metadata
end
end end
IssuePolicy.prepend_mod_with('IssuePolicy') IssuePolicy.prepend_mod_with('IssuePolicy')
...@@ -28,6 +28,10 @@ class MergeRequestPolicy < IssuablePolicy ...@@ -28,6 +28,10 @@ class MergeRequestPolicy < IssuablePolicy
rule { can_merge }.policy do rule { can_merge }.policy do
enable :accept_merge_request enable :accept_merge_request
end end
rule { can?(:admin_merge_request) }.policy do
enable :set_merge_request_metadata
end
end end
MergeRequestPolicy.prepend_mod_with('MergeRequestPolicy') MergeRequestPolicy.prepend_mod_with('MergeRequestPolicy')
...@@ -27,8 +27,14 @@ class IssuableBaseService < ::BaseProjectService ...@@ -27,8 +27,14 @@ class IssuableBaseService < ::BaseProjectService
can?(current_user, ability_name, issuable) can?(current_user, ability_name, issuable)
end end
def can_set_issuable_metadata?(issuable)
ability_name = :"set_#{issuable.to_ability_name}_metadata"
can?(current_user, ability_name, issuable)
end
def filter_params(issuable) def filter_params(issuable)
unless can_admin_issuable?(issuable) unless can_set_issuable_metadata?(issuable)
params.delete(:milestone) params.delete(:milestone)
params.delete(:milestone_id) params.delete(:milestone_id)
params.delete(:labels) params.delete(:labels)
...@@ -45,6 +51,7 @@ class IssuableBaseService < ::BaseProjectService ...@@ -45,6 +51,7 @@ class IssuableBaseService < ::BaseProjectService
params.delete(:canonical_issue_id) params.delete(:canonical_issue_id)
params.delete(:project) params.delete(:project)
params.delete(:discussion_locked) params.delete(:discussion_locked)
params.delete(:confidential)
end end
filter_assignees(issuable) filter_assignees(issuable)
......
...@@ -20,17 +20,6 @@ module Issues ...@@ -20,17 +20,6 @@ module Issues
super super
end end
override :filter_params
def filter_params(issue)
super
# filter confidential in `Issues::UpdateService` and not in `IssuableBaseService#filter_params`
# because we do allow users that cannot admin issues to set confidential flag when creating an issue
unless can_admin_issuable?(issue)
params.delete(:confidential)
end
end
def before_update(issue, skip_spam_check: false) def before_update(issue, skip_spam_check: false)
return if skip_spam_check return if skip_spam_check
......
...@@ -24,14 +24,6 @@ ...@@ -24,14 +24,6 @@
= render 'shared/form_elements/description', model: issuable, form: form, project: project = render 'shared/form_elements/description', model: issuable, form: form, project: project
- if issuable.respond_to?(:confidential)
.form-group.row
.offset-sm-2.col-sm-10
.form-check
= form.check_box :confidential, class: 'form-check-input'
= form.label :confidential, class: 'form-check-label' do
This issue is confidential and should only be visible to team members with at least Reporter access.
= render 'shared/issuable/form/metadata', issuable: issuable, form: form, project: project, presenter: presenter = render 'shared/issuable/form/metadata', issuable: issuable, form: form, project: project, presenter: presenter
= render_if_exists 'shared/issuable/approvals', issuable: issuable, presenter: presenter, form: form = render_if_exists 'shared/issuable/approvals', issuable: issuable, presenter: presenter, form: form
......
...@@ -2,11 +2,19 @@ ...@@ -2,11 +2,19 @@
- issuable = local_assigns.fetch(:issuable) - issuable = local_assigns.fetch(:issuable)
- presenter = local_assigns.fetch(:presenter) - presenter = local_assigns.fetch(:presenter)
- return unless can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project) - return unless can?(current_user, :"set_#{issuable.to_ability_name}_metadata", issuable)
- has_due_date = issuable.has_attribute?(:due_date) - has_due_date = issuable.has_attribute?(:due_date)
- form = local_assigns.fetch(:form) - form = local_assigns.fetch(:form)
- if issuable.respond_to?(:confidential)
.form-group.row
.offset-sm-2.col-sm-10
.form-check
= form.check_box :confidential, class: 'form-check-input'
= form.label :confidential, class: 'form-check-label' do
This issue is confidential and should only be visible to team members with at least Reporter access.
%hr %hr
.row .row
%div{ class: (has_due_date ? "col-lg-6" : "col-12") } %div{ class: (has_due_date ? "col-lg-6" : "col-12") }
......
...@@ -35,4 +35,8 @@ class EpicPolicy < BasePolicy ...@@ -35,4 +35,8 @@ class EpicPolicy < BasePolicy
rule { ~anonymous & can?(:read_epic) }.policy do rule { ~anonymous & can?(:read_epic) }.policy do
enable :create_todo enable :create_todo
end end
rule { can?(:admin_epic) }.policy do
enable :set_epic_metadata
end
end end
...@@ -12,6 +12,11 @@ RSpec.describe Epics::CreateService do ...@@ -12,6 +12,11 @@ RSpec.describe Epics::CreateService do
subject { described_class.new(group: group, current_user: user, params: params).execute } subject { described_class.new(group: group, current_user: user, params: params).execute }
describe '#execute' do describe '#execute' do
before do
group.add_reporter(user)
stub_licensed_features(epics: true, subepics: true)
end
it 'creates one epic correctly' do it 'creates one epic correctly' do
allow(NewEpicWorker).to receive(:perform_async) allow(NewEpicWorker).to receive(:perform_async)
...@@ -26,116 +31,111 @@ RSpec.describe Epics::CreateService do ...@@ -26,116 +31,111 @@ RSpec.describe Epics::CreateService do
expect(epic.confidential).to be_truthy expect(epic.confidential).to be_truthy
expect(NewEpicWorker).to have_received(:perform_async).with(epic.id, user.id) expect(NewEpicWorker).to have_received(:perform_async).with(epic.id, user.id)
end end
end
context 'handling fixed dates' do context 'handling fixed dates' do
it 'sets the fixed date correctly' do it 'sets the fixed date correctly' do
date = Date.new(2019, 10, 10) date = Date.new(2019, 10, 10)
params[:start_date_fixed] = date params[:start_date_fixed] = date
params[:start_date_is_fixed] = true params[:start_date_is_fixed] = true
subject subject
epic = Epic.last epic = Epic.last
expect(epic.start_date).to eq(date) expect(epic.start_date).to eq(date)
expect(epic.start_date_fixed).to eq(date) expect(epic.start_date_fixed).to eq(date)
expect(epic.start_date_is_fixed).to be_truthy expect(epic.start_date_is_fixed).to be_truthy
end
end end
end
context 'after_save callback to store_mentions' do context 'after_save callback to store_mentions' do
let(:labels) { create_pair(:group_label, group: group) } let(:labels) { create_pair(:group_label, group: group) }
context 'when mentionable attributes change' do context 'when mentionable attributes change' do
context 'when content has no mentions' do context 'when content has no mentions' do
let(:params) { { title: 'Title', description: "Description with no mentions" } } let(:params) { { title: 'Title', description: "Description with no mentions" } }
it 'calls store_mentions! and saves no mentions' do
expect_next_instance_of(Epic) do |instance|
expect(instance).to receive(:store_mentions!).and_call_original
end
expect { subject }.not_to change { EpicUserMention.count } it 'calls store_mentions! and saves no mentions' do
end expect_next_instance_of(Epic) do |instance|
end expect(instance).to receive(:store_mentions!).and_call_original
end
context 'when content has mentions' do
let(:params) { { title: 'Title', description: "Description with #{user.to_reference}" } }
it 'calls store_mentions! and saves mentions' do expect { subject }.not_to change { EpicUserMention.count }
expect_next_instance_of(Epic) do |instance|
expect(instance).to receive(:store_mentions!).and_call_original
end end
expect { subject }.to change { EpicUserMention.count }.by(1)
end end
end
context 'when mentionable.save fails' do context 'when content has mentions' do
let(:params) { { title: '', label_ids: labels.map(&:id) } } let(:params) { { title: 'Title', description: "Description with #{user.to_reference}" } }
it 'does not call store_mentions and saves no mentions' do it 'calls store_mentions! and saves mentions' do
expect_next_instance_of(Epic) do |instance| expect_next_instance_of(Epic) do |instance|
expect(instance).not_to receive(:store_mentions!).and_call_original expect(instance).to receive(:store_mentions!).and_call_original
end end
expect { subject }.not_to change { EpicUserMention.count }
expect(subject.valid?).to be false
end
end
context 'when description param has quick action' do expect { subject }.to change { EpicUserMention.count }.by(1)
before do end
stub_licensed_features(epics: true, subepics: true)
group.add_developer(user)
end end
context 'for /parent_epic' do context 'when mentionable.save fails' do
it 'assigns parent epic' do let(:params) { { title: '', label_ids: labels.map(&:id) } }
parent_epic = create(:epic, group: group)
description = "/parent_epic #{parent_epic.to_reference}"
params = { title: 'New epic with parent', description: description }
epic = described_class.new(group: group, current_user: user, params: params).execute it 'does not call store_mentions and saves no mentions' do
expect_next_instance_of(Epic) do |instance|
expect(instance).not_to receive(:store_mentions!).and_call_original
end
expect(epic.parent).to eq(parent_epic) expect { subject }.not_to change { EpicUserMention.count }
expect(subject.valid?).to be false
end end
end
context 'when parent epic cannot be assigned' do context 'when description param has quick action' do
it 'does not assign parent epic' do context 'for /parent_epic' do
other_group = create(:group, :private) it 'assigns parent epic' do
parent_epic = create(:epic, group: other_group) parent_epic = create(:epic, group: group)
description = "/parent_epic #{parent_epic.to_reference(group)}" description = "/parent_epic #{parent_epic.to_reference}"
params = { title: 'New epic with parent', description: description } params = { title: 'New epic with parent', description: description }
epic = described_class.new(group: group, current_user: user, params: params).execute epic = described_class.new(group: group, current_user: user, params: params).execute
expect(epic.parent).to eq(nil) expect(epic.parent).to eq(parent_epic)
end end
end
end
context 'for /child_epic' do context 'when parent epic cannot be assigned' do
it 'sets a child epic' do it 'does not assign parent epic' do
child_epic = create(:epic, group: group) other_group = create(:group, :private)
description = "/child_epic #{child_epic.to_reference}" parent_epic = create(:epic, group: other_group)
params = { title: 'New epic with child', description: description } description = "/parent_epic #{parent_epic.to_reference(group)}"
params = { title: 'New epic with parent', description: description }
epic = described_class.new(group: group, current_user: user, params: params).execute epic = described_class.new(group: group, current_user: user, params: params).execute
expect(epic.reload.children).to include(child_epic) expect(epic.parent).to eq(nil)
end
end
end end
context 'when child epic cannot be assigned' do context 'for /child_epic' do
it 'does not set child epic' do it 'sets a child epic' do
other_group = create(:group, :private) child_epic = create(:epic, group: group)
child_epic = create(:epic, group: other_group) description = "/child_epic #{child_epic.to_reference}"
description = "/child_epic #{child_epic.to_reference(group)}"
params = { title: 'New epic with child', description: description } params = { title: 'New epic with child', description: description }
epic = described_class.new(group: group, current_user: user, params: params).execute epic = described_class.new(group: group, current_user: user, params: params).execute
expect(epic.reload.children).to be_empty expect(epic.reload.children).to include(child_epic)
end
context 'when child epic cannot be assigned' do
it 'does not set child epic' do
other_group = create(:group, :private)
child_epic = create(:epic, group: other_group)
description = "/child_epic #{child_epic.to_reference(group)}"
params = { title: 'New epic with child', description: description }
epic = described_class.new(group: group, current_user: user, params: params).execute
expect(epic.reload.children).to be_empty
end
end end
end end
end end
......
...@@ -30,7 +30,7 @@ RSpec.describe "User creates issue" do ...@@ -30,7 +30,7 @@ RSpec.describe "User creates issue" do
end end
end end
context "when signed in as guest" do context "when signed in as guest", :js do
before do before do
project.add_guest(user) project.add_guest(user)
sign_in(user) sign_in(user)
...@@ -38,41 +38,19 @@ RSpec.describe "User creates issue" do ...@@ -38,41 +38,19 @@ RSpec.describe "User creates issue" do
visit(new_project_issue_path(project)) visit(new_project_issue_path(project))
end end
it "creates issue", :js do context 'available metadata' do
page.within(".issue-form") do it 'allows guest to set issue metadata' do
expect(page).to have_no_content("Assign to") page.within(".issue-form") do
.and have_no_content("Labels") expect(page).to have_content("Title")
.and have_no_content("Milestone") .and have_content("Description")
.and have_content("Type")
expect(page.find('#issue_title')['placeholder']).to eq 'Title' .and have_content("Assignee")
expect(page.find('#issue_description')['placeholder']).to eq 'Write a description or drag your files here…' .and have_content("Milestone")
.and have_content("Labels")
.and have_content("Due date")
.and have_content("This issue is confidential and should only be visible to team members with at least Reporter access.")
end
end end
issue_title = "500 error on profile"
fill_in("Title", with: issue_title)
first('.js-md').click
first('.rspec-issuable-form-description').native.send_keys('Description')
click_button("Create issue")
expect(page).to have_content(issue_title)
.and have_content(user.name)
.and have_content(project.name)
expect(page).to have_selector('strong', text: 'Description')
end
it 'does not render the issue type dropdown' do
expect(page).not_to have_selector('.s-issuable-type-filter-dropdown-wrap')
end
end
context "when signed in as developer", :js do
before do
project.add_developer(user)
sign_in(user)
visit(new_project_issue_path(project))
end end
context "when previewing" do context "when previewing" do
......
...@@ -21,6 +21,7 @@ RSpec.describe IssuePolicy do ...@@ -21,6 +21,7 @@ RSpec.describe IssuePolicy do
let(:project) { create(:project, :private) } let(:project) { create(:project, :private) }
let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) } let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) }
let(:issue_no_assignee) { create(:issue, project: project) } let(:issue_no_assignee) { create(:issue, project: project) }
let(:new_issue) { build(:issue, project: project, assignees: [assignee], author: author) }
before do before do
project.add_guest(guest) project.add_guest(guest)
...@@ -34,42 +35,51 @@ RSpec.describe IssuePolicy do ...@@ -34,42 +35,51 @@ RSpec.describe IssuePolicy do
end end
it 'does not allow non-members to read issues' do it 'does not allow non-members to read issues' do
expect(permissions(non_member, issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(non_member, issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(non_member, issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(non_member, issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(non_member, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata)
end end
it 'allows guests to read issues' do it 'allows guests to read issues' do
expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue) expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue) expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(guest, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows reporters to read, update, and admin issues' do it 'allows reporters to read, update, and admin issues' do
expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows reporters from group links to read, update, and admin issues' do it 'allows reporters from group links to read, update, and admin issues' do
expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter_from_group_link, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows issue authors to read and update their issues' do it 'allows issue authors to read and update their issues' do
expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(author, issue)).to be_disallowed(:admin_issue) expect(permissions(author, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue) expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(author, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows issue assignees to read and update their issues' do it 'allows issue assignees to read and update their issues' do
expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(assignee, issue)).to be_disallowed(:admin_issue) expect(permissions(assignee, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue) expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(assignee, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
context 'with confidential issues' do context 'with confidential issues' do
...@@ -78,48 +88,49 @@ RSpec.describe IssuePolicy do ...@@ -78,48 +88,49 @@ RSpec.describe IssuePolicy do
it 'does not allow non-members to read confidential issues' do it 'does not allow non-members to read confidential issues' do
expect(permissions(non_member, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(non_member, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'does not allow guests to read confidential issues' do it 'does not allow guests to read confidential issues' do
expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'allows reporters to read, update, and admin confidential issues' do it 'allows reporters to read, update, and admin confidential issues' do
expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'allows reporters from group links to read, update, and admin confidential issues' do it 'allows reporters from group links to read, update, and admin confidential issues' do
expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'allows issue authors to read and update their confidential issues' do it 'allows issue authors to read and update their confidential issues' do
expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue) expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:admin_issue, :set_issue_metadata)
end end
it 'does not allow issue author to read or update confidential issue moved to an private project' do it 'does not allow issue author to read or update confidential issue moved to an private project' do
confidential_issue.project = create(:project, :private) confidential_issue.project = create(:project, :private)
expect(permissions(author, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(author, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata)
end end
it 'allows issue assignees to read and update their confidential issues' do it 'allows issue assignees to read and update their confidential issues' do
expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue) expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'does not allow issue assignees to read or update confidential issue moved to an private project' do it 'does not allow issue assignees to read or update confidential issue moved to an private project' do
confidential_issue.project = create(:project, :private) confidential_issue.project = create(:project, :private)
expect(permissions(assignee, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(assignee, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :set_issue_metadata)
end end
end end
end end
...@@ -129,6 +140,7 @@ RSpec.describe IssuePolicy do ...@@ -129,6 +140,7 @@ RSpec.describe IssuePolicy do
let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) } let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) }
let(:issue_no_assignee) { create(:issue, project: project) } let(:issue_no_assignee) { create(:issue, project: project) }
let(:issue_locked) { create(:issue, :locked, project: project, author: author, assignees: [assignee]) } let(:issue_locked) { create(:issue, :locked, project: project, author: author, assignees: [assignee]) }
let(:new_issue) { build(:issue, project: project) }
before do before do
project.add_guest(guest) project.add_guest(guest)
...@@ -141,55 +153,63 @@ RSpec.describe IssuePolicy do ...@@ -141,55 +153,63 @@ RSpec.describe IssuePolicy do
it 'does not allow anonymous user to create todos' do it 'does not allow anonymous user to create todos' do
expect(permissions(nil, issue)).to be_allowed(:read_issue) expect(permissions(nil, issue)).to be_allowed(:read_issue)
expect(permissions(nil, issue)).to be_disallowed(:create_todo) expect(permissions(nil, issue)).to be_disallowed(:create_todo, :update_subscription, :set_issue_metadata)
expect(permissions(nil, issue)).to be_disallowed(:update_subscription) expect(permissions(nil, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata)
end end
it 'allows guests to read issues' do it 'allows guests to read issues' do
expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :create_todo, :update_subscription) expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :create_todo, :update_subscription)
expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue) expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue) expect(permissions(guest, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(guest, issue_locked)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(guest, issue_locked)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(guest, issue_locked)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue) expect(permissions(guest, issue_locked)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(guest, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows reporters to read, update, reopen, and admin issues' do it 'allows reporters to read, update, reopen, and admin issues' do
expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue) expect(permissions(reporter, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue) expect(permissions(reporter, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(reporter, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter, issue_locked)).to be_disallowed(:reopen_issue) expect(permissions(reporter, issue_locked)).to be_disallowed(:reopen_issue)
expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows reporters from group links to read, update, reopen and admin issues' do it 'allows reporters from group links to read, update, reopen and admin issues' do
expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue) expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue) expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(reporter_from_group_link, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter_from_group_link, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
expect(permissions(reporter_from_group_link, issue_locked)).to be_disallowed(:reopen_issue) expect(permissions(reporter_from_group_link, issue_locked)).to be_disallowed(:reopen_issue)
expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows issue authors to read, reopen and update their issues' do it 'allows issue authors to read, reopen and update their issues' do
expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue) expect(permissions(author, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue)
expect(permissions(author, issue)).to be_disallowed(:admin_issue) expect(permissions(author, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(author, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue) expect(permissions(author, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(author, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(author, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(author, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue) expect(permissions(author, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(author, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
it 'allows issue assignees to read, reopen and update their issues' do it 'allows issue assignees to read, reopen and update their issues' do
expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue) expect(permissions(assignee, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :reopen_issue)
expect(permissions(assignee, issue)).to be_disallowed(:admin_issue) expect(permissions(assignee, issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid) expect(permissions(assignee, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid)
expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue) expect(permissions(assignee, issue_no_assignee)).to be_disallowed(:update_issue, :admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(assignee, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(assignee, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(assignee, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue) expect(permissions(assignee, issue_locked)).to be_disallowed(:admin_issue, :reopen_issue, :set_issue_metadata)
expect(permissions(author, new_issue)).to be_allowed(:create_issue, :set_issue_metadata)
end end
context 'when issues are private' do context 'when issues are private' do
...@@ -246,31 +266,31 @@ RSpec.describe IssuePolicy do ...@@ -246,31 +266,31 @@ RSpec.describe IssuePolicy do
it 'does not allow guests to read confidential issues' do it 'does not allow guests to read confidential issues' do
expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'allows reporters to read, update, and admin confidential issues' do it 'allows reporters to read, update, and admin confidential issues' do
expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'allows reporter from group links to read, update, and admin confidential issues' do it 'allows reporter from group links to read, update, and admin confidential issues' do
expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter_from_group_link, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue)
expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'allows issue authors to read and update their confidential issues' do it 'allows issue authors to read and update their confidential issues' do
expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue) expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(author, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
it 'allows issue assignees to read and update their confidential issues' do it 'allows issue assignees to read and update their confidential issues' do
expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue) expect(permissions(assignee, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue)
expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue) expect(permissions(assignee, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata)
expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue) expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end end
end end
end end
......
...@@ -18,8 +18,8 @@ RSpec.describe Issues::CreateService do ...@@ -18,8 +18,8 @@ RSpec.describe Issues::CreateService do
let_it_be(:labels) { create_pair(:label, project: project) } let_it_be(:labels) { create_pair(:label, project: project) }
before_all do before_all do
project.add_maintainer(user) project.add_guest(user)
project.add_maintainer(assignee) project.add_guest(assignee)
end end
let(:opts) do let(:opts) do
...@@ -88,15 +88,11 @@ RSpec.describe Issues::CreateService do ...@@ -88,15 +88,11 @@ RSpec.describe Issues::CreateService do
expect { issue }.to change { project.open_issues_count }.from(0).to(1) expect { issue }.to change { project.open_issues_count }.from(0).to(1)
end end
context 'when current user cannot admin issues in the project' do context 'when current user cannot set issue metadata in the project' do
let_it_be(:guest) { create(:user) } let_it_be(:non_member) { create(:user) }
before_all do
project.add_guest(guest)
end
it 'filters out params that cannot be set without the :admin_issue permission' do it 'filters out params that cannot be set without the :set_issue_metadata permission' do
issue = described_class.new(project: project, current_user: guest, params: opts).execute issue = described_class.new(project: project, current_user: non_member, params: opts).execute
expect(issue).to be_persisted expect(issue).to be_persisted
expect(issue.title).to eq('Awesome issue') expect(issue.title).to eq('Awesome issue')
...@@ -107,8 +103,8 @@ RSpec.describe Issues::CreateService do ...@@ -107,8 +103,8 @@ RSpec.describe Issues::CreateService do
expect(issue.due_date).to be_nil expect(issue.due_date).to be_nil
end end
it 'creates confidential issues' do it 'can create confidential issues' do
issue = described_class.new(project: project, current_user: guest, params: { confidential: true }).execute issue = described_class.new(project: project, current_user: non_member, params: { confidential: true }).execute
expect(issue.confidential).to be_truthy expect(issue.confidential).to be_truthy
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment