Commit ef8cb9e0 authored by Avielle Wolfe's avatar Avielle Wolfe Committed by Dmytro Zaporozhets

Update instance security dashboard permissions

This commit updates the instance security dashboard controllers to get
their permission scheme from the same concern as the group and project
security dashboard controllers.
parent 798ae8b6
...@@ -19,6 +19,6 @@ module SecurityDashboardsPermissions ...@@ -19,6 +19,6 @@ module SecurityDashboardsPermissions
end end
def read_security_dashboard def read_security_dashboard
"read_#{vulnerable.class.name.downcase}_security_dashboard".to_sym "read_#{vulnerable.class.name.underscore}_security_dashboard".to_sym
end end
end end
...@@ -2,16 +2,21 @@ ...@@ -2,16 +2,21 @@
module Security module Security
class ApplicationController < ::ApplicationController class ApplicationController < ::ApplicationController
before_action :authorize_read_security_dashboard! include SecurityDashboardsPermissions
before_action :check_feature_enabled!
before_action do before_action do
push_frontend_feature_flag(:security_dashboard, default_enabled: true) push_frontend_feature_flag(:security_dashboard, default_enabled: true)
end end
private protected
def check_feature_enabled!
render_404 unless Feature.enabled?(:security_dashboard, default_enabled: true)
end
def authorize_read_security_dashboard! def vulnerable
render_404 unless Feature.enabled?(:security_dashboard, default_enabled: true) && @vulnerable ||= ApplicationInstance.new
can?(current_user, :read_security_dashboard)
end end
end end
end end
...@@ -22,10 +22,6 @@ module Security ...@@ -22,10 +22,6 @@ module Security
end end
end end
def vulnerable
@vulnerable ||= ApplicationInstance.new
end
def valid_project_ids def valid_project_ids
return security_dashboard_project_ids if request_project_ids.empty? return security_dashboard_project_ids if request_project_ids.empty?
......
...@@ -55,10 +55,18 @@ module EE ...@@ -55,10 +55,18 @@ module EE
links << :operations links << :operations
end end
if ::Feature.enabled?(:security_dashboard, default_enabled: true) && can?(current_user, :read_security_dashboard) if security_dashboard_available?
links << :security links << :security
end end
end end
end end
def security_dashboard_available?
app_instance = ApplicationInstance.new
::Feature.enabled?(:security_dashboard, default_enabled: true) &&
app_instance.feature_available?(:security_dashboard) &&
can?(current_user, :read_application_instance_security_dashboard, app_instance)
end
end end
end end
...@@ -7,4 +7,8 @@ class ApplicationInstance ...@@ -7,4 +7,8 @@ class ApplicationInstance
def all_pipelines def all_pipelines
::Ci::Pipeline.all ::Ci::Pipeline.all
end end
def feature_available?(feature)
License.feature_available?(feature)
end
end end
# frozen_string_literal: true
class ApplicationInstancePolicy < BasePolicy
rule { ~anonymous }.enable :read_application_instance_security_dashboard
end
...@@ -9,16 +9,11 @@ module EE ...@@ -9,16 +9,11 @@ module EE
License.feature_available?(:operations_dashboard) License.feature_available?(:operations_dashboard)
end end
condition(:security_dashboard_available) do
License.feature_available?(:security_dashboard)
end
condition(:pages_size_limit_available) do condition(:pages_size_limit_available) do
License.feature_available?(:pages_size_limit) License.feature_available?(:pages_size_limit)
end end
rule { ~anonymous & operations_dashboard_available }.enable :read_operations_dashboard rule { ~anonymous & operations_dashboard_available }.enable :read_operations_dashboard
rule { ~anonymous & security_dashboard_available }.enable :read_security_dashboard
rule { admin }.policy do rule { admin }.policy do
enable :read_licenses enable :read_licenses
......
...@@ -53,22 +53,80 @@ describe DashboardHelper, type: :helper do ...@@ -53,22 +53,80 @@ describe DashboardHelper, type: :helper do
describe 'operations, environments and security' do describe 'operations, environments and security' do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
before do
allow(helper).to receive(:can?).and_return(false)
end
where(:ability, :feature_flag, :nav_link) do where(:ability, :feature_flag, :nav_link) do
:read_operations_dashboard | nil | :operations :read_operations_dashboard | nil | :operations
:read_operations_dashboard | :environments_dashboard | :environments :read_operations_dashboard | :environments_dashboard | :environments
:read_security_dashboard | :security_dashboard | :security :read_application_instance_security_dashboard | :security_dashboard | :security
end end
with_them do with_them do
describe 'when the feature is enabled' do describe 'when the feature is enabled' do
before do before do
stub_feature_flags(feature_flag => true) unless feature_flag.nil? stub_feature_flags(feature_flag => true) unless feature_flag.nil?
allow(helper).to receive(:can?).and_return(false)
allow(helper).to receive(:can?).with(user, ability).and_return(true)
end end
it 'includes the nav link' do context 'and the feature is available on the license' do
expect(helper.dashboard_nav_links).to include(nav_link) context 'and the user is authenticated' do
before do
stub_resource_visibility(
feature_flag,
read_other_resources: true,
read_security_dashboard: true,
security_dashboard_available: true
)
end
it 'includes the nav link' do
expect(helper.dashboard_nav_links).to include(nav_link)
end
end
context 'and the user is not authenticated' do
let(:user) { nil }
before do
stub_resource_visibility(
feature_flag,
read_other_resources: false,
read_security_dashboard: false,
security_dashboard_available: true
)
end
it 'does not include the nav link' do
expect(helper.dashboard_nav_links).not_to include(nav_link)
end
end
end
context 'and the feature is not available on the license' do
before do
stub_resource_visibility(
feature_flag,
read_other_resources: false,
read_security_dashboard: true,
security_dashboard_available: false
)
end
it 'does not include the nav link' do
expect(helper.dashboard_nav_links).not_to include(nav_link)
end
end
def stub_resource_visibility(feature_flag, read_other_resources:, read_security_dashboard:, security_dashboard_available:)
if feature_flag == :security_dashboard
app_instance = double(ApplicationInstance, feature_available?: security_dashboard_available)
allow(ApplicationInstance).to receive(:new).and_return(app_instance)
allow(helper).to receive(:can?).with(user, ability, app_instance).and_return(read_security_dashboard)
else
allow(helper).to receive(:can?).with(user, ability).and_return(read_other_resources)
end
end end
end end
......
...@@ -16,4 +16,28 @@ describe ApplicationInstance do ...@@ -16,4 +16,28 @@ describe ApplicationInstance do
expect(::Ci::Pipeline).to have_received(:all) expect(::Ci::Pipeline).to have_received(:all)
end end
end end
describe '#feature_available?' do
subject { described_class.new.feature_available?(:security_dashboard) }
context "when the feature is available for the instance's license" do
before do
stub_licensed_features(security_dashboard: true)
end
it 'returns true' do
is_expected.to be_truthy
end
end
context "when the feature is not available for the instance's license" do
before do
stub_licensed_features(security_dashboard: false)
end
it 'returns false' do
is_expected.to be_falsy
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
describe ApplicationInstancePolicy do
let(:current_user) { create(:user) }
let(:user) { create(:user) }
before do
stub_licensed_features(security_dashboard: true)
end
subject { described_class.new(current_user, [user]) }
describe 'read_application_instance_security_dashboard' do
context 'when the user is not logged in' do
let(:current_user) { nil }
it { is_expected.not_to be_allowed(:read_application_instance_security_dashboard) }
end
context 'when the user is logged in' do
it { is_expected.to be_allowed(:read_application_instance_security_dashboard) }
end
end
end
...@@ -60,32 +60,6 @@ describe GlobalPolicy do ...@@ -60,32 +60,6 @@ describe GlobalPolicy do
include_examples 'analytics policy', :view_productivity_analytics include_examples 'analytics policy', :view_productivity_analytics
end end
describe 'read_security_dashboard' do
context 'when the instance has an Ultimate license' do
before do
stub_licensed_features(security_dashboard: true)
end
context 'and the user is not logged in' do
let(:current_user) { nil }
it { is_expected.not_to be_allowed(:read_security_dashboard) }
end
context 'and the user is logged in' do
it { is_expected.to be_allowed(:read_security_dashboard) }
end
end
context 'when the instance does not have an Ultimate license' do
before do
stub_licensed_features(security_dashboard: false)
end
it { is_expected.not_to be_allowed(:read_security_dashboard) }
end
end
describe 'update_max_pages_size' do describe 'update_max_pages_size' do
context 'when feature is enabled' do context 'when feature is enabled' do
before do before do
......
...@@ -109,7 +109,7 @@ shared_examples 'instance security dashboard vulnerability findings endpoint' do ...@@ -109,7 +109,7 @@ shared_examples 'instance security dashboard vulnerability findings endpoint' do
end end
describe 'GET /-/security/vulnerability_findings' do describe 'GET /-/security/vulnerability_findings' do
it_behaves_like 'instance security dashboard JSON endpoint' do it_behaves_like 'security dashboard JSON endpoint' do
let(:security_dashboard_request) do let(:security_dashboard_request) do
get security_vulnerability_findings_path, headers: { 'ACCEPT' => 'application/json' } get security_vulnerability_findings_path, headers: { 'ACCEPT' => 'application/json' }
end end
...@@ -234,7 +234,7 @@ describe 'GET /-/security/vulnerability_findings' do ...@@ -234,7 +234,7 @@ describe 'GET /-/security/vulnerability_findings' do
end end
describe 'GET /-/security/vulnerability_findings/summary' do describe 'GET /-/security/vulnerability_findings/summary' do
it_behaves_like 'instance security dashboard JSON endpoint' do it_behaves_like 'security dashboard JSON endpoint' do
let(:security_dashboard_request) do let(:security_dashboard_request) do
get summary_security_vulnerability_findings_path, headers: { 'ACCEPT' => 'application/json' } get summary_security_vulnerability_findings_path, headers: { 'ACCEPT' => 'application/json' }
end end
...@@ -297,7 +297,7 @@ describe 'GET /-/security/vulnerability_findings/summary' do ...@@ -297,7 +297,7 @@ describe 'GET /-/security/vulnerability_findings/summary' do
end end
describe 'GET /-/security/vulnerability_findings/history' do describe 'GET /-/security/vulnerability_findings/history' do
it_behaves_like 'instance security dashboard JSON endpoint' do it_behaves_like 'security dashboard JSON endpoint' do
let(:security_dashboard_request) do let(:security_dashboard_request) do
get( get(
history_security_vulnerability_findings_path, history_security_vulnerability_findings_path,
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'instance security dashboard JSON endpoint' do shared_examples 'security dashboard JSON endpoint' do
context 'when the user is authenticated' do context 'when the user is authenticated' do
let(:security_application_controller_user) { create(:user) } let(:security_application_controller_user) { create(:user) }
......
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