Skip to content

Commit

Permalink
Merge pull request #17565 from opf/bugfix/60479-relations-tab-permiss…
Browse files Browse the repository at this point in the history
…ions

[60479] Only show relations the user has permission to see
  • Loading branch information
cbliard authored Jan 9, 2025
2 parents 43e1e63 + 4fedb5b commit bff24c8
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 17 deletions.
11 changes: 6 additions & 5 deletions app/controllers/work_package_relations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ def create
if service_result.success?
@work_package.reload
component = WorkPackageRelationsTab::IndexComponent.new(work_package: @work_package,
relations: @work_package.relations,
children: @work_package.children)
relations: @work_package.relations.visible,
children: @work_package.children.visible)
replace_via_turbo_stream(component:)
respond_with_turbo_streams
else
Expand All @@ -80,8 +80,8 @@ def update
if service_result.success?
@work_package.reload
component = WorkPackageRelationsTab::IndexComponent.new(work_package: @work_package,
relations: @work_package.relations,
children: @work_package.children)
relations: @work_package.relations.visible,
children: @work_package.children.visible)
replace_via_turbo_stream(component:)
respond_with_turbo_streams
else
Expand All @@ -93,11 +93,12 @@ def destroy
service_result = Relations::DeleteService.new(user: current_user, model: @relation).call

if service_result.success?
@children = WorkPackage.where(parent_id: @work_package.id)
@children = WorkPackage.where(parent_id: @work_package.id).visible
@relations = @work_package
.relations
.reload
.includes(:to, :from)
.visible

component = WorkPackageRelationsTab::IndexComponent.new(work_package: @work_package,
relations: @relations,
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/work_package_relations_tab_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ class WorkPackageRelationsTabController < ApplicationController
before_action :authorize_global

def index
@children = WorkPackage.where(parent_id: @work_package.id)
@children = WorkPackage.where(parent_id: @work_package.id).visible
@relations = @work_package
.relations
.visible
.includes(:to, :from)

component = WorkPackageRelationsTab::IndexComponent.new(
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/menus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@
{ tab: :relations },
skip_permissions_check: true,
badge: ->(work_package:, **) {
work_package.relations.count + work_package.children.count
work_package.relations.visible.count + work_package.children.visible.count
},
caption: :"js.work_packages.tabs.relations"
menu.push :watchers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,34 @@
:js, :with_cuprite do
include Components::Autocompleter::NgSelectAutocompleteHelpers

shared_let(:user) { create(:admin) }
shared_let(:project) { create(:project) }
shared_let(:user) do
create(:user,
member_with_permissions: {
project => %i[add_work_packages
manage_subtasks
manage_work_package_relations
view_work_packages]
})
end

before_all do
set_factory_default(:user, user)
set_factory_default(:project, project)
set_factory_default(:project_with_types, project)
end

shared_let(:parent_work_package) { create(:work_package, subject: "parent") }
shared_let(:work_package) { create(:work_package, subject: "main", parent: parent_work_package) }
shared_let(:parent_work_package) { create(:work_package, subject: "parent_work_package") }
shared_let(:work_package) { create(:work_package, subject: "work_package (main)", parent: parent_work_package) }
shared_let(:type1) { create(:type) }
shared_let(:type2) { create(:type) }

shared_let(:wp_predecessor) do
create(:work_package, type: type1, subject: "predecessor of main",
create(:work_package, type: type1, subject: "wp_predecessor",
start_date: Date.current, due_date: Date.current + 1.week)
end
shared_let(:wp_related) { create(:work_package, type: type2, subject: "related to main") }
shared_let(:wp_blocker) { create(:work_package, type: type1, subject: "blocks main") }
shared_let(:wp_related) { create(:work_package, type: type2, subject: "wp_related") }
shared_let(:wp_blocker) { create(:work_package, type: type1, subject: "wp_blocker") }

shared_let(:relation_follows) do
create(:relation,
Expand All @@ -73,16 +81,39 @@
end
shared_let(:child_wp) do
create(:work_package,
subject: "child_wp",
parent: work_package,
type: type1,
project: project)
end
shared_let(:not_yet_child_wp) do
shared_let(:not_child_yet_wp) do
create(:work_package,
subject: "not_child_yet_wp",
type: type1,
project:)
end

# The user should not be able to see any relations to work packages from this
# project because the user does not have the permissions to view this project
shared_let(:restricted_project) { create(:project) }
shared_let(:restricted_work_package) do
create(:work_package,
subject: "restricted_work_package",
project: restricted_project)
end
shared_let(:restricted_child_work_package) do
create(:work_package,
subject: "restricted_child_work_package",
parent: work_package,
project: restricted_project)
end
shared_let(:restricted_relation_relates) do
create(:relation,
from: work_package,
to: restricted_work_package,
relation_type: Relation::TYPE_RELATES)
end

let(:full_wp_view) { Pages::FullWorkPackage.new(work_package) }
let(:relations_tab) { Components::WorkPackages::Relations.new(work_package) }
let(:relations_panel_selector) { ".detail-panel--relations" }
Expand Down Expand Up @@ -116,6 +147,10 @@ def label_for_relation_type(relation_type)
relations_tab.expect_relation(relation_follows)
relations_tab.expect_relation(relation_relates)
relations_tab.expect_relation(relation_blocked)

# Relations not visible due to lack of permissions on the project
relations_tab.expect_no_relation(restricted_relation_relates)
relations_tab.expect_no_relation(restricted_child_work_package)
end
end

Expand All @@ -130,6 +165,10 @@ def label_for_relation_type(relation_type)
expect { relation_follows.reload }.to raise_error(ActiveRecord::RecordNotFound)

tabs.expect_counter("relations", 3)

# Relations not visible due to lack of permissions on the project
relations_tab.expect_no_relation(restricted_relation_relates)
relations_tab.expect_no_relation(restricted_child_work_package)
end

it "can delete children" do
Expand All @@ -141,6 +180,10 @@ def label_for_relation_type(relation_type)
expect(child_wp.reload.parent).to be_nil

tabs.expect_counter("relations", 3)

# Relations not visible due to lack of permissions on the project
relations_tab.expect_no_relation(restricted_relation_relates)
relations_tab.expect_no_relation(restricted_child_work_package)
end
end

Expand All @@ -159,6 +202,8 @@ def label_for_relation_type(relation_type)

# Unchanged
tabs.expect_counter("relations", 4)
relations_tab.expect_no_relation(restricted_relation_relates)
relations_tab.expect_no_relation(restricted_child_work_package)

# Edit again
relations_tab.edit_relation_description(relation_follows, "And they can be edited!")
Expand All @@ -168,6 +213,10 @@ def label_for_relation_type(relation_type)

# Unchanged
tabs.expect_counter("relations", 4)

# Relations not visible due to lack of permissions on the project
relations_tab.expect_no_relation(restricted_relation_relates)
relations_tab.expect_no_relation(restricted_child_work_package)
end

it "does not have an edit action for children" do
Expand Down Expand Up @@ -231,6 +280,10 @@ def label_for_relation_type(relation_type)
tabs.expect_counter("relations", 5)
# Relation is created
expect(Relation.follows.where(from: wp_successor, to: work_package)).to exist

# Relations not visible due to lack of permissions on the project
relations_tab.expect_no_relation(restricted_relation_relates)
relations_tab.expect_no_relation(restricted_child_work_package)
end

it "does not autocomplete unrelatable work packages" do
Expand Down Expand Up @@ -263,11 +316,18 @@ def label_for_relation_type(relation_type)

tabs.expect_counter("relations", 4)

relations_tab.add_existing_child(not_yet_child_wp)
relations_tab.expect_child(not_yet_child_wp)
relations_tab.add_existing_child(not_child_yet_wp)
relations_tab.expect_child(not_child_yet_wp)

# Bumped by one
tabs.expect_counter("relations", 5)

# Child relation is created
expect(not_child_yet_wp.reload.parent).to eq work_package

# Relations not visible due to lack of permissions on the project
relations_tab.expect_no_relation(restricted_relation_relates)
relations_tab.expect_no_relation(restricted_child_work_package)
end

it "doesn't autocomplete parent, children, and WP itself" do
Expand Down
4 changes: 3 additions & 1 deletion spec/support/components/work_packages/relations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ def expect_row(work_package)

def expect_no_row(relatable)
actual_relatable = find_relatable(relatable)
expect(page).not_to have_test_selector("op-relation-row-#{actual_relatable.id}")
expect(page).not_to have_test_selector("op-relation-row-#{actual_relatable.id}"),
"expected no relation row for work package " \
"##{actual_relatable.id} #{actual_relatable.subject.inspect}"
end

def select_relation_type(relation_type)
Expand Down

0 comments on commit bff24c8

Please sign in to comment.