Commit aa89bd58 authored by Alexander Turinske's avatar Alexander Turinske

Add group level policy new page

- create initial backend helpers
- create update js pages to accomodate different types
  of namespaces
- update policy selection to navigate directly to a new
  scan execution policy for a group
- update tests
parent d2b2e94e
import initPolicyEditorApp from 'ee/threat_monitoring/policy_editor';
import { NAMESPACE_TYPES } from 'ee/threat_monitoring/constants';
initPolicyEditorApp(document.getElementById('js-group-policy-builder-app'), NAMESPACE_TYPES.GROUP);
import initPolicyEditorApp from 'ee/threat_monitoring/policy_editor';
import { NAMESPACE_TYPES } from 'ee/threat_monitoring/constants';
initPolicyEditorApp();
initPolicyEditorApp(document.getElementById('js-policy-builder-app'), NAMESPACE_TYPES.PROJECT);
import initPolicyEditorApp from 'ee/threat_monitoring/policy_editor';
import { NAMESPACE_TYPES } from 'ee/threat_monitoring/constants';
initPolicyEditorApp();
initPolicyEditorApp(document.getElementById('js-policy-builder-app'), NAMESPACE_TYPES.PROJECT);
......@@ -3,6 +3,7 @@ import { GlPath } from '@gitlab/ui';
import { s__ } from '~/locale';
import { getParameterByName, removeParams, visitUrl } from '~/lib/utils/url_utility';
import { POLICY_TYPE_COMPONENT_OPTIONS } from '../constants';
import { NAMESPACE_TYPES } from '../../constants';
import PolicySelection from './policy_selection.vue';
import PolicyEditor from './policy_editor_v2.vue';
......@@ -12,6 +13,7 @@ export default {
PolicyEditor,
PolicySelection,
},
inject: ['namespaceType'],
// TODO: move this `inject` instead of `props`. We're using it in multiple levels.
props: {
assignedPolicyProject: {
......@@ -26,10 +28,16 @@ export default {
},
data() {
return {
selectedPolicy: this.policyFromUrl(),
selectedPolicy:
this.namespaceType === NAMESPACE_TYPES.GROUP
? POLICY_TYPE_COMPONENT_OPTIONS.scanExecution
: this.policyFromUrl(),
};
},
computed: {
enableWizard() {
return this.namespaceType === NAMESPACE_TYPES.PROJECT && !this.existingPolicy;
},
glPathItems() {
const hasPolicy = Boolean(this.selectedPolicy);
......@@ -105,7 +113,7 @@ export default {
<div>
<header class="gl-pb-5 gl-border-b-none">
<h3>{{ title }}</h3>
<gl-path v-if="!existingPolicy" :items="glPathItems" @selected="handlePathSelection" />
<gl-path v-if="enableWizard" :items="glPathItems" @selected="handlePathSelection" />
</header>
<policy-selection v-if="!selectedPolicy" />
<policy-editor
......
......@@ -13,8 +13,7 @@ const apolloProvider = new VueApollo({
defaultClient: gqClient,
});
export default () => {
const el = document.querySelector('#js-policy-builder-app');
export default (el, namespaceType) => {
const {
assignedPolicyProject,
defaultEnvironmentId,
......@@ -75,6 +74,7 @@ export default () => {
provide: {
createAgentHelpPath,
disableScanPolicyUpdate: parseBoolean(disableScanPolicyUpdate),
namespaceType,
networkDocumentationPath,
policyEditorEmptyStateSvgPath,
policyType,
......
# frozen_string_literal: true
module EE
module SecurityOrchestrationHelper
def security_orchestration_policy_data(
namespace,
policy_type = nil,
policy = nil,
approvers = nil
)
return unless namespace
{
assigned_policy_project: 'null',
disable_scan_policy_update: false,
create_agent_help_path: help_page_url('user/clusters/agent/install/index'),
policy: policy&.to_json,
policy_editor_empty_state_svg_path: image_path('illustrations/monitoring/unable_to_connect.svg'),
policy_type: policy_type,
policies_path: nil,
scan_policy_documentation_path: help_page_path('user/application_security/policies/index'),
scan_result_approvers: approvers&.to_json
}
end
end
end
- add_to_breadcrumbs s_("SecurityOrchestration|Policies"), group_security_policies_path(@group)
- breadcrumb_title s_("SecurityOrchestration|New policy")
- page_title s_("SecurityOrchestration|Policy editor")
- data = security_orchestration_policy_data(@group)
#js-group-policy-builder-app
#js-group-policy-builder-app{ data: data }
......@@ -2,6 +2,7 @@ import { GlPath } from '@gitlab/ui';
import * as urlUtils from '~/lib/utils/url_utility';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { POLICY_TYPE_COMPONENT_OPTIONS } from 'ee/threat_monitoring/components/constants';
import { NAMESPACE_TYPES } from 'ee/threat_monitoring/constants';
import NewPolicy from 'ee/threat_monitoring/components/policy_editor/new_policy.vue';
import PolicySelection from 'ee/threat_monitoring/components/policy_editor/policy_selection.vue';
import PolicyEditor from 'ee/threat_monitoring/components/policy_editor/policy_editor_v2.vue';
......@@ -13,12 +14,13 @@ describe('NewPolicy component', () => {
const findPolicyEditor = () => wrapper.findComponent(PolicyEditor);
const findPath = () => wrapper.findComponent(GlPath);
const factory = ({ propsData } = {}) => {
const factory = ({ propsData = {}, provide = {} } = {}) => {
wrapper = shallowMountExtended(NewPolicy, {
propsData: {
assignedPolicyProject: {},
...propsData,
},
provide,
stubs: { GlPath: true },
});
};
......@@ -28,31 +30,52 @@ describe('NewPolicy component', () => {
});
describe('when there is no type query parameter', () => {
beforeEach(() => {
factory();
});
describe('projects', () => {
beforeEach(() => {
factory({ provide: { namespaceType: NAMESPACE_TYPES.PROJECT } });
});
it('should display the title correctly', () => {
expect(wrapper.findByText(NewPolicy.i18n.titles.default).exists()).toBe(true);
});
it('should display the title correctly', () => {
expect(wrapper.findByText(NewPolicy.i18n.titles.default).exists()).toBe(true);
});
it('should display the path items correctly', () => {
expect(findPath().props('items')).toMatchObject([
{
selected: true,
title: NewPolicy.i18n.choosePolicyType,
},
{
disabled: true,
selected: false,
title: NewPolicy.i18n.policyDetails,
},
]);
it('should display the path items correctly', () => {
expect(findPath().props('items')).toMatchObject([
{
selected: true,
title: NewPolicy.i18n.choosePolicyType,
},
{
disabled: true,
selected: false,
title: NewPolicy.i18n.policyDetails,
},
]);
});
it('should display the correct view', () => {
expect(findPolicySelection().exists()).toBe(true);
expect(findPolicyEditor().exists()).toBe(false);
});
});
it('should display the correct view', () => {
expect(findPolicySelection().exists()).toBe(true);
expect(findPolicyEditor().exists()).toBe(false);
describe('groups', () => {
beforeEach(() => {
factory({ provide: { namespaceType: NAMESPACE_TYPES.GROUP } });
});
it('should display the title correctly', () => {
expect(wrapper.findByText(NewPolicy.i18n.titles.scanExecution).exists()).toBe(true);
});
it('should not display the GlPath component when there is an existing policy', () => {
expect(findPath().exists()).toBe(false);
});
it('should display the correct view according to the selected policy', () => {
expect(findPolicySelection().exists()).toBe(false);
expect(findPolicyEditor().exists()).toBe(true);
});
});
});
......@@ -67,6 +90,7 @@ describe('NewPolicy component', () => {
id: 'policy-id',
},
},
provide: { namespaceType: NAMESPACE_TYPES.PROJECT },
});
});
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe EE::SecurityOrchestrationHelper do
let_it_be_with_reload(:namespace) { create(:group, :public) }
describe '#security_orchestration_policy_data' do
let(:approvers) { %w(approver1 approver2) }
let(:owner) { namespace.first_owner }
let(:base_data) do
{
assigned_policy_project: "null",
disable_scan_policy_update: false,
create_agent_help_path: kind_of(String),
policy: policy&.to_json,
policy_editor_empty_state_svg_path: kind_of(String),
policy_type: policy_type,
policies_path: nil,
scan_policy_documentation_path: kind_of(String),
scan_result_approvers: approvers&.to_json
}
end
before do
allow(helper).to receive(:current_user) { owner }
end
subject { helper.security_orchestration_policy_data(namespace, policy_type, policy, approvers) }
context 'when a new policy is being created' do
let(:policy) { nil }
let(:policy_type) { nil }
let(:approvers) { nil }
it { is_expected.to match(base_data) }
end
context 'when an existing policy is being edited' do
let(:policy_type) { 'scan_execution_policy' }
let(:policy) do
Gitlab::Kubernetes::CiliumNetworkPolicy.new(
name: 'policy',
namespace: 'another',
selector: { matchLabels: { role: 'db' } },
ingress: [{ from: [{ namespaceSelector: { matchLabels: { group: 'mygroup' } } }] }]
)
end
it { is_expected.to match(base_data) }
end
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