diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 778ddd6082c6..85384f3b0cab 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -155,7 +155,8 @@ def group_members end def visible_group_members? - current_user.allowed_in_any_project?(:manage_members) || + current_user.admin? || + current_user.allowed_in_any_project?(:manage_members) || Group.in_project(Project.allowed_to(current_user, :view_members)).exists? end diff --git a/app/models/project.rb b/app/models/project.rb index cd7c1a4cf46a..dbb53cbdefc6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -252,6 +252,13 @@ def enabled_module_names enabled_modules.map(&:name) end + def reload(*) + @allowed_permissions = nil + @allowed_actions = nil + + super + end + def allowed_permissions @allowed_permissions ||= begin diff --git a/app/models/users/permission_checks.rb b/app/models/users/permission_checks.rb index 9fe321cb7d78..3c60d3377de8 100644 --- a/app/models/users/permission_checks.rb +++ b/app/models/users/permission_checks.rb @@ -106,14 +106,24 @@ def member_of?(project) roles_for_project(project).any?(&:member?) end + # Returns all permissions the user may have for a given context. + # "May" because this method does not check e.g. whether the module + # the permission belongs to is active. def all_permissions_for(context) - Authorization - .roles(self, context) - .includes(:role_permissions) - .pluck(:permission) - .compact - .map(&:to_sym) - .uniq + if admin? + OpenProject::AccessControl + .permissions + .select { |p| p.permissible_on?(context) && p.grant_to_admin? } + .map(&:name) + else + Authorization + .roles(self, context) + .includes(:role_permissions) + .pluck(:permission) + .compact + .map(&:to_sym) + .uniq + end end # Helper method to be used in places where we just throw anything into the permission check and don't know what diff --git a/app/services/authorization/user_permissible_service.rb b/app/services/authorization/user_permissible_service.rb index 133a16a26523..a3c8e2629b14 100644 --- a/app/services/authorization/user_permissible_service.rb +++ b/app/services/authorization/user_permissible_service.rb @@ -9,7 +9,6 @@ def initialize(user) def allowed_globally?(permission) perms = contextual_permissions(permission, :global) return false unless authorizable_user? - return true if admin_and_all_granted_to_admin?(perms) cached_permissions(nil).intersect?(perms.map(&:name)) end @@ -19,9 +18,7 @@ def allowed_in_project?(permission, projects_to_check) return false if projects_to_check.blank? return false unless authorizable_user? - projects = Array(projects_to_check) - - projects.all? do |project| + Array(projects_to_check).all? do |project| allowed_in_single_project?(perms, project) end end @@ -29,7 +26,6 @@ def allowed_in_project?(permission, projects_to_check) def allowed_in_any_project?(permission) perms = contextual_permissions(permission, :project) return false unless authorizable_user? - return true if admin_and_all_granted_to_admin?(perms) cached_in_any_project?(perms) end @@ -51,7 +47,6 @@ def allowed_in_any_entity?(permission, entity_class, in_project: nil) perms = contextual_permissions(permission, context_name(entity_class)) return false unless authorizable_user? return false if in_project && !(in_project.active? || in_project.being_archived?) - return true if admin_and_all_granted_to_admin?(perms) if entity_is_project_scoped?(entity_class) allowed_in_any_project_scoped_entity?(perms, entity_class, in_project:) @@ -85,7 +80,6 @@ def allowed_in_single_project?(permissions, project) permissions_filtered_for_project = permissions_by_enabled_project_modules(project, permissions) return false if permissions_filtered_for_project.empty? - return true if admin_and_all_granted_to_admin?(permissions) cached_permissions(project).intersect?(permissions_filtered_for_project) end @@ -106,7 +100,6 @@ def allowed_in_single_project_scoped_entity?(permissions, entity) permissions_filtered_for_project = permissions_by_enabled_project_modules(entity.project, permissions) return false if permissions_filtered_for_project.empty? - return true if admin_and_all_granted_to_admin?(permissions) # The combination of this is better then doing # EntityClass.allowed_to(user, permission).exists?. diff --git a/lib/open_project/access_control/permission.rb b/lib/open_project/access_control/permission.rb index 73157c9e1b3a..a059a0bc0e6b 100644 --- a/lib/open_project/access_control/permission.rb +++ b/lib/open_project/access_control/permission.rb @@ -89,7 +89,28 @@ def project_query? end def permissible_on?(context_type) - @permissible_on.include?(context_type) + # Sometimes the context_type passed in is a decorated object. + # Most of the times, this would then be an 'EagerLoadingWrapper' instance. + # We need to unwrap the object to get the actual object. + # Checking for `context_type.is_a?(SimpleDelegator)` fails for unknown reasons. + context_type = context_type.__getobj__ if context_type.class.ancestors.include?(SimpleDelegator) + + context_symbol = case context_type + when WorkPackage + :work_package + when Project + :project + when ::Queries::Projects::ProjectQuery + :project_query + when Symbol + context_type + when nil + :global + else + raise "Unknown context: #{context_type}" + end + + @permissible_on.include?(context_symbol) end def grant_to_admin? diff --git a/modules/boards/spec/features/menu_items/global_menu_item_spec.rb b/modules/boards/spec/features/menu_items/global_menu_item_spec.rb index 03323da73ebd..5be14c14044a 100644 --- a/modules/boards/spec/features/menu_items/global_menu_item_spec.rb +++ b/modules/boards/spec/features/menu_items/global_menu_item_spec.rb @@ -32,6 +32,7 @@ require "spec_helper" RSpec.describe "Global menu item for boards", :js, :with_cuprite do + shared_let(:project) { create(:project) } let(:boards_label) { I18n.t("boards.label_boards") } before do diff --git a/modules/boards/spec/features/menu_items/top_menu_item_spec.rb b/modules/boards/spec/features/menu_items/top_menu_item_spec.rb index 45a15304f0e1..a2a61a69b660 100644 --- a/modules/boards/spec/features/menu_items/top_menu_item_spec.rb +++ b/modules/boards/spec/features/menu_items/top_menu_item_spec.rb @@ -29,14 +29,14 @@ require "spec_helper" RSpec.describe "Top menu item for boards", :js, :with_cuprite do - let(:user) { create(:admin) } + shared_let(:admin) { create(:admin) } + shared_let(:user) { create(:user) } + shared_let(:project) { create(:project) } let(:menu) { find(".op-app-menu a[title='#{I18n.t('label_modules')}']") } let(:boards) { I18n.t("boards.label_boards") } - before do - allow(User).to receive(:current).and_return user - end + current_user { admin } shared_examples_for "the boards menu item" do it "sends the user to the boards overview when clicked" do @@ -52,8 +52,6 @@ end context "when in the project settings" do - let!(:project) { create(:project) } - before do visit "/projects/#{project.identifier}/settings/general" end @@ -69,7 +67,7 @@ it_behaves_like "the boards menu item" context "with missing permissions" do - let(:user) { create(:user) } + current_user { user } it "does not display the menu item" do within "#more-menu", visible: false do diff --git a/modules/meeting/spec/controllers/meetings_controller_spec.rb b/modules/meeting/spec/controllers/meetings_controller_spec.rb index 07f605110ea2..c4543bf4a062 100644 --- a/modules/meeting/spec/controllers/meetings_controller_spec.rb +++ b/modules/meeting/spec/controllers/meetings_controller_spec.rb @@ -29,19 +29,11 @@ require "#{File.dirname(__FILE__)}/../spec_helper" RSpec.describe MeetingsController do - let(:user) { create(:admin) } - let(:project) { create(:project) } - let(:other_project) { create(:project) } + shared_let(:user) { create(:admin) } + shared_let(:project) { create(:project) } + shared_let(:other_project) { create(:project) } - before do - allow(User).to receive(:current).and_return user - - allow(Project).to receive(:find).and_return(project) - - allow(controller).to receive(:authorize) - allow(controller).to receive(:authorize_global) - allow(controller).to receive(:check_if_login_required) - end + current_user { user } describe "GET" do describe "index" do @@ -161,8 +153,6 @@ let(:meeting_params) { base_meeting_params } before do - allow(Project).to receive(:find).and_return(project) - post :create, params: end diff --git a/modules/meeting/spec/features/meetings_global_menu_item_spec.rb b/modules/meeting/spec/features/meetings_global_menu_item_spec.rb index c489fb98320a..972eb8c567fc 100644 --- a/modules/meeting/spec/features/meetings_global_menu_item_spec.rb +++ b/modules/meeting/spec/features/meetings_global_menu_item_spec.rb @@ -36,6 +36,7 @@ :with_cuprite do shared_let(:user_without_permissions) { create(:user) } shared_let(:admin) { create(:admin) } + shared_let(:project) { create(:project) } shared_let(:meetings_label) { I18n.t(:label_meeting_plural) } let(:meetings_page) { Pages::Meetings::Index.new(project: nil) } diff --git a/modules/reporting/spec/features/top_menu_item_spec.rb b/modules/reporting/spec/features/top_menu_item_spec.rb index 137fcc62e31c..b368fccf03cf 100644 --- a/modules/reporting/spec/features/top_menu_item_spec.rb +++ b/modules/reporting/spec/features/top_menu_item_spec.rb @@ -29,6 +29,8 @@ require "spec_helper" RSpec.describe "Top menu items", :js do + shared_let(:project) { create(:project) } + let(:user) { create(:user) } let(:open_menu) { true } diff --git a/modules/reporting/spec/workers/cost_query/export_job_spec.rb b/modules/reporting/spec/workers/cost_query/export_job_spec.rb index c54892d0b432..870212529413 100644 --- a/modules/reporting/spec/workers/cost_query/export_job_spec.rb +++ b/modules/reporting/spec/workers/cost_query/export_job_spec.rb @@ -31,7 +31,7 @@ require "spec_helper" RSpec.describe CostQuery::ExportJob do - let(:user) { build_stubbed(:admin) } + let(:user) { build_stubbed(:user) } let(:project) { build_stubbed(:project) } let(:initial_filter_params) do @@ -46,6 +46,10 @@ } end + before do + mock_permissions_for(user, &:allow_everything) + end + # Performs a cost export with the given extra filters. # # @param extra_filters [Hash] A hash of attribute names and operator/value diff --git a/spec/controllers/activities_controller_spec.rb b/spec/controllers/activities_controller_spec.rb index 4c657ca01535..cbbf527eaf64 100644 --- a/spec/controllers/activities_controller_spec.rb +++ b/spec/controllers/activities_controller_spec.rb @@ -30,6 +30,8 @@ RSpec.describe ActivitiesController do shared_let(:admin) { create(:admin) } + shared_let(:project) { create(:project) } + current_user { admin } before do diff --git a/spec/controllers/news_controller_spec.rb b/spec/controllers/news_controller_spec.rb index daebacc36056..803b68ac5b0a 100644 --- a/spec/controllers/news_controller_spec.rb +++ b/spec/controllers/news_controller_spec.rb @@ -33,15 +33,10 @@ include BecomeMember - let(:user) do - create(:admin) - end - let(:project) { create(:project) } let(:news) { create(:news) } - before do - allow(User).to receive(:current).and_return user - end + shared_let(:project) { create(:project) } + shared_current_user { create(:admin) } describe "#index" do it "renders index" do @@ -101,7 +96,7 @@ describe "#create" do context "with news_added notifications" do it "persists a news item" do - become_member(project, user) + become_member(project, current_user) post :create, params: { @@ -117,7 +112,7 @@ news = News.find_by!(title: "NewsControllerTest") expect(news).not_to be_nil expect(news.description).to eq "This is the description" - expect(news.author).to eq user + expect(news.author).to eq current_user expect(news.project).to eq project end end diff --git a/spec/features/custom_fields/create_long_text_spec.rb b/spec/features/custom_fields/create_long_text_spec.rb index c05c405168b6..8aee873dcc70 100644 --- a/spec/features/custom_fields/create_long_text_spec.rb +++ b/spec/features/custom_fields/create_long_text_spec.rb @@ -6,7 +6,7 @@ let(:cf_page) { Pages::CustomFields.new } let(:editor) { Components::WysiwygEditor.new "#custom_field_form" } let(:type) { create(:type_task) } - let(:project) { create(:project, enabled_module_names: %i[work_package_tracking], types: [type]) } + let!(:project) { create(:project, enabled_module_names: %i[work_package_tracking], types: [type]) } let(:wp_page) { Pages::FullWorkPackageCreate.new project: } diff --git a/spec/features/news/global_menu_item_spec.rb b/spec/features/news/global_menu_item_spec.rb index 10dd02d67c2f..44de7333c072 100644 --- a/spec/features/news/global_menu_item_spec.rb +++ b/spec/features/news/global_menu_item_spec.rb @@ -34,6 +34,7 @@ RSpec.describe "News global menu item spec", :js, :with_cuprite do shared_let(:admin) { create(:admin) } shared_let(:user_without_permissions) { create(:user) } + shared_let(:project) { create(:project) } before do login_as current_user diff --git a/spec/features/projects/global_menu_item_spec.rb b/spec/features/projects/global_menu_item_spec.rb index 7bf2ab370209..e15f6f50d7e1 100644 --- a/spec/features/projects/global_menu_item_spec.rb +++ b/spec/features/projects/global_menu_item_spec.rb @@ -32,10 +32,12 @@ require "spec_helper" RSpec.describe "Projects global menu item", :js, :with_cuprite do - let(:user) { create(:user) } + shared_let(:user) { create(:user) } + shared_let(:admin) { create(:admin) } + + current_user { user } before do - login_as user visit root_path end @@ -65,7 +67,7 @@ end context "with an admin user" do - let(:user) { create(:admin) } + current_user { admin } it "renders the archived filter as well" do within "#main-menu" do diff --git a/spec/features/types/form_configuration_spec.rb b/spec/features/types/form_configuration_spec.rb index fd4751c28241..1dd212d4d2e0 100644 --- a/spec/features/types/form_configuration_spec.rb +++ b/spec/features/types/form_configuration_spec.rb @@ -32,7 +32,7 @@ shared_let(:admin) { create(:admin) } let(:type) { create(:type) } - let(:project) { create(:project, types: [type]) } + let!(:project) { create(:project, types: [type]) } let(:category) { create(:category, project:) } let(:work_package) do create(:work_package, diff --git a/spec/features/work_packages/work_package_index_spec.rb b/spec/features/work_packages/work_package_index_spec.rb index 14f9bd54160c..0bad6de1dcc7 100644 --- a/spec/features/work_packages/work_package_index_spec.rb +++ b/spec/features/work_packages/work_package_index_spec.rb @@ -29,13 +29,12 @@ require "spec_helper" RSpec.describe "Work Packages", "index view", :js, :with_cuprite do - let(:user) { create(:admin) } - let(:project) { create(:project, enabled_module_names: %w[work_package_tracking]) } + shared_let(:user) { create(:admin) } + shared_let(:project) { create(:project, enabled_module_names: %w[work_package_tracking]) } + let(:wp_table) { Pages::WorkPackagesTable.new(project) } - before do - login_as(user) - end + current_user { user } context "within a global context" do before do diff --git a/spec/lib/open_project/access_control/permission_spec.rb b/spec/lib/open_project/access_control/permission_spec.rb index de9eb7ea7b59..964bf621b88f 100644 --- a/spec/lib/open_project/access_control/permission_spec.rb +++ b/spec/lib/open_project/access_control/permission_spec.rb @@ -79,6 +79,68 @@ end end + describe "#permissible_on?" do + context "when marked as permissible on work package roles" do + subject(:permission) do + described_class.new(:perm, { cont: [:action] }, permissible_on: :work_package) + end + + it { expect(permission).to be_permissible_on(WorkPackage.new) } + it { expect(permission).not_to be_permissible_on(Project.new) } + it { expect(permission).not_to be_permissible_on(nil) } + it { expect(permission).not_to be_permissible_on(Queries::Projects::ProjectQuery.new) } + it { expect(permission).to be_permissible_on(:work_package) } + it { expect(permission).not_to be_permissible_on(:project) } + it { expect(permission).not_to be_permissible_on(:global) } + it { expect(permission).not_to be_permissible_on(:project_query) } + end + + context "when marked as permissible on project roles" do + subject(:permission) do + described_class.new(:perm, { cont: [:action] }, permissible_on: :project) + end + + it { expect(permission).not_to be_permissible_on(WorkPackage.new) } + it { expect(permission).to be_permissible_on(Project.new) } + it { expect(permission).not_to be_permissible_on(nil) } + it { expect(permission).not_to be_permissible_on(Queries::Projects::ProjectQuery.new) } + it { expect(permission).not_to be_permissible_on(:work_package) } + it { expect(permission).to be_permissible_on(:project) } + it { expect(permission).not_to be_permissible_on(:global) } + it { expect(permission).not_to be_permissible_on(:project_query) } + end + + context "when marked as permissible on global roles" do + subject(:permission) do + described_class.new(:perm, { cont: [:action] }, permissible_on: :global) + end + + it { expect(permission).not_to be_permissible_on(WorkPackage.new) } + it { expect(permission).not_to be_permissible_on(Project.new) } + it { expect(permission).to be_permissible_on(nil) } + it { expect(permission).not_to be_permissible_on(Queries::Projects::ProjectQuery.new) } + it { expect(permission).not_to be_permissible_on(:work_package) } + it { expect(permission).not_to be_permissible_on(:project) } + it { expect(permission).to be_permissible_on(:global) } + it { expect(permission).not_to be_permissible_on(:project_query) } + end + + context "when marked as permissible on project queries" do + subject(:permission) do + described_class.new(:perm, { cont: [:action] }, permissible_on: :project_query) + end + + it { expect(permission).not_to be_permissible_on(WorkPackage.new) } + it { expect(permission).not_to be_permissible_on(Project.new) } + it { expect(permission).not_to be_permissible_on(nil) } + it { expect(permission).to be_permissible_on(Queries::Projects::ProjectQuery.new) } + it { expect(permission).not_to be_permissible_on(:work_package) } + it { expect(permission).not_to be_permissible_on(:project) } + it { expect(permission).not_to be_permissible_on(:global) } + it { expect(permission).to be_permissible_on(:project_query) } + end + end + describe "marking it as permissible on multiple role types" do subject(:permission) do described_class.new(:perm, { cont: [:action] }, permissible_on: %i[work_package project]) diff --git a/spec/models/users/permission_checks_spec.rb b/spec/models/users/permission_checks_spec.rb index 765b04560cd9..3a5a9082548f 100644 --- a/spec/models/users/permission_checks_spec.rb +++ b/spec/models/users/permission_checks_spec.rb @@ -179,31 +179,55 @@ let(:public_permissions) { OpenProject::AccessControl.public_permissions.map(&:name) } - subject do - create(:user, global_permissions: [:create_user], - member_with_permissions: { project => %i[view_work_packages edit_work_packages] }) - end + context "for a non admin user" do + subject do + create(:user, global_permissions: [:create_user], + member_with_permissions: { project => %i[view_work_packages edit_work_packages] }) + end - it "returns all permissions given on the project" do - expect(subject.all_permissions_for(project)).to match_array(%i[view_work_packages edit_work_packages] + public_permissions) - end + it "returns all permissions given on the project" do + expect(subject.all_permissions_for(project)) + .to match_array(%i[view_work_packages edit_work_packages] + public_permissions) + end - it "returns non-member permissions given on the project the user is not a member of" do - expect(subject.all_permissions_for(other_project)).to match_array(%i[view_work_packages - manage_members] + public_permissions) - end + it "returns non-member permissions given on the project the user is not a member of" do + expect(subject.all_permissions_for(other_project)).to match_array(%i[view_work_packages + manage_members] + public_permissions) + end - it "returns all global permissions" do - skip "Current implementation of the Authorization.roles query returns ALL permissions the user has, not only global ones. " \ - "We should change this in the fututre, thats why this test is already in here." + it "returns all global permissions" do + skip "Current implementation of the Authorization.roles query returns ALL permissions the user has, " \ + "not only global ones. We should change this in the future, that's why this test is already in here." + + expect(subject.all_permissions_for(nil)).to match_array(%i[create_user]) + end - expect(subject.all_permissions_for(nil)).to match_array(%i[create_user]) + it "returns all permissions the user has (with project and global permissions)" do + expect(subject.all_permissions_for(nil)).to match_array(%i[create_user + view_work_packages edit_work_packages + manage_members] + public_permissions) + end end - it "returns all permissions the user has (with project and global permissions)" do - expect(subject.all_permissions_for(nil)).to match_array(%i[create_user - view_work_packages edit_work_packages - manage_members] + public_permissions) + context "for an admin user" do + subject do + create(:admin) + end + + it "returns all permissions given on the project" do + expect(subject.all_permissions_for(project)) + .to include(:view_work_packages, :edit_work_packages, *public_permissions) + end + + it "returns all permissions given globally" do + expect(subject.all_permissions_for(nil)) + .to include(:create_user) + end + + it "returns all permissions given on a work package" do + expect(subject.all_permissions_for(WorkPackage.new)) + .to include(:view_work_packages, :edit_work_packages) + end end end diff --git a/spec/models/work_packages/scopes/allowed_to_spec.rb b/spec/models/work_packages/scopes/allowed_to_spec.rb index 7346616d0798..39f1c6e793e0 100644 --- a/spec/models/work_packages/scopes/allowed_to_spec.rb +++ b/spec/models/work_packages/scopes/allowed_to_spec.rb @@ -29,15 +29,14 @@ require "spec_helper" RSpec.describe WorkPackage, ".allowed_to" do - let(:user) { create(:user) } + shared_let(:user) { create(:user) } + shared_let(:project_status) { true } + shared_let(:private_project) { create(:project, public: false, active: project_status) } + shared_let(:public_project) { create(:project, public: true, active: project_status) } - let!(:private_project) { create(:project, public: false, active: project_status) } - let!(:public_project) { create(:project, public: true, active: project_status) } - let(:project_status) { true } - - let!(:work_package_in_public_project) { create(:work_package, project: public_project) } - let!(:work_package_in_private_project) { create(:work_package, project: private_project) } - let!(:other_work_package_in_private_project) { create(:work_package, project: private_project) } + shared_let(:work_package_in_public_project) { create(:work_package, project: public_project) } + shared_let(:work_package_in_private_project) { create(:work_package, project: private_project) } + shared_let(:other_work_package_in_private_project) { create(:work_package, project: private_project) } let(:project_permissions) { [] } let(:project_role) { create(:project_role, permissions: project_permissions) } @@ -106,6 +105,16 @@ expect(subject).to be_empty end end + + context "when the module the permission belongs to is disabled" do + before do + private_project.enabled_module_names = private_project.enabled_module_names - ["work_package_tracking"] + end + + it "excludes work packages where the module is disabled in" do + expect(subject).to contain_exactly(work_package_in_public_project) + end + end end context "when the user has the permission directly on the work package" do diff --git a/spec/requests/rate_limiting/api_v3_rate_limiting_spec.rb b/spec/requests/rate_limiting/api_v3_rate_limiting_spec.rb index 118f59eb379b..4e65686b60b3 100644 --- a/spec/requests/rate_limiting/api_v3_rate_limiting_spec.rb +++ b/spec/requests/rate_limiting/api_v3_rate_limiting_spec.rb @@ -33,6 +33,7 @@ include Rack::Test::Methods include API::V3::Utilities::PathHelper + shared_let(:project) { create(:project) } current_user { create(:admin) } context "when enabled", with_config: { rate_limiting: { api_v3: true } } do diff --git a/spec/services/authorization/user_permissible_service_spec.rb b/spec/services/authorization/user_permissible_service_spec.rb index 5ca25900434c..75b22c978e48 100644 --- a/spec/services/authorization/user_permissible_service_spec.rb +++ b/spec/services/authorization/user_permissible_service_spec.rb @@ -2,6 +2,7 @@ RSpec.describe Authorization::UserPermissibleService do shared_let(:user) { create(:user) } + shared_let(:admin) { create(:admin) } shared_let(:anonymous_user) { create(:anonymous) } shared_let(:project) { create(:project) } shared_let(:work_package) { create(:work_package, project:) } @@ -161,6 +162,27 @@ it { is_expected.to be_allowed_in_project(permission, project) } end end + + context "and the user is admin" do + let(:queried_user) { admin } + + it { is_expected.to be_allowed_in_project(permission, project) } + + context "and the account is locked" do + before { admin.locked! } + + it { is_expected.not_to be_allowed_in_project(permission, project) } + end + + context "and the module the permission belongs to is disabled" do + before do + project.enabled_module_names = project.enabled_module_names - ["work_package_tracking"] + project.reload + end + + it { is_expected.not_to be_allowed_in_project(permission, project) } + end + end end context "and the user is a member of a project" do @@ -226,6 +248,27 @@ it { is_expected.not_to be_allowed_in_any_project(permission) } end end + + context "and the user is admin" do + let(:queried_user) { admin } + + it { is_expected.to be_allowed_in_any_project(permission) } + + context "and the account is locked" do + before { admin.locked! } + + it { is_expected.not_to be_allowed_in_any_project(permission) } + end + + context "and the module the permission belongs to is disabled" do + before do + project.enabled_module_names = project.enabled_module_names - ["work_package_tracking"] + project.reload + end + + it { is_expected.not_to be_allowed_in_any_project(permission) } + end + end end context "and the user is a member of a project" do @@ -292,6 +335,27 @@ it { is_expected.not_to be_allowed_in_entity(permission, work_package, WorkPackage) } end + context "and the user is admin" do + let(:queried_user) { admin } + + it { is_expected.to be_allowed_in_entity(permission, work_package, WorkPackage) } + + context "and the account is locked" do + before { admin.locked! } + + it { is_expected.not_to be_allowed_in_entity(permission, work_package, WorkPackage) } + end + + context "and the module the permission belongs to is disabled" do + before do + project.enabled_module_names = project.enabled_module_names - ["work_package_tracking"] + project.reload + end + + it { is_expected.not_to be_allowed_in_entity(permission, work_package, WorkPackage) } + end + end + context "and the user is a member of the project" do let(:role) { create(:project_role, permissions: [permission]) } let!(:project_member) { create(:member, user:, project:, roles: [role]) } @@ -305,7 +369,10 @@ end context "without the module enabled in the project" do - before { project.enabled_module_names = project.enabled_modules - [:work_package_tracking] } + before do + project.enabled_module_names = project.enabled_module_names - ["work_package_tracking"] + project.reload + end it { is_expected.not_to be_allowed_in_entity(permission, work_package, WorkPackage) } end @@ -369,6 +436,30 @@ it { is_expected.not_to be_allowed_in_any_entity(permission, WorkPackage) } end + context "and the user is admin" do + let(:queried_user) { admin } + + it { is_expected.to be_allowed_in_any_entity(permission, WorkPackage) } + it { is_expected.to be_allowed_in_any_entity(permission, WorkPackage, in_project: project) } + + context "and the account is locked" do + before { admin.locked! } + + it { is_expected.not_to be_allowed_in_any_entity(permission, WorkPackage) } + it { is_expected.not_to be_allowed_in_any_entity(permission, WorkPackage, in_project: project) } + end + + context "and the module the permission belongs to is disabled" do + before do + project.enabled_module_names = project.enabled_module_names - ["work_package_tracking"] + project.reload + end + + it { is_expected.not_to be_allowed_in_any_entity(permission, WorkPackage) } + it { is_expected.not_to be_allowed_in_any_entity(permission, WorkPackage, in_project: project) } + end + end + context "and the user is a member of a project" do let(:role) { create(:project_role, permissions: [permission]) } let!(:project_member) { create(:member, user:, project:, roles: [role]) }