Skip to content
代码片段 群组 项目
提交 2a093233 编辑于 作者: Artur Fedorov's avatar Artur Fedorov 提交者: Alexander Turinske
浏览文件

This MR adds policy scope section

New section for policy scope and
compliance frameworks

Changelog: added
EE: true
上级 5bd0b37f
No related branches found
No related tags found
无相关合并请求
...@@ -82,7 +82,7 @@ export const ACTIONS_LABEL = s__('SecurityOrchestration|Actions'); ...@@ -82,7 +82,7 @@ export const ACTIONS_LABEL = s__('SecurityOrchestration|Actions');
export const RULE_IF_LABEL = __('if'); export const RULE_IF_LABEL = __('if');
export const RULE_OR_LABEL = __('or'); export const RULE_OR_LABEL = __('or');
export const SCOPE_LABEL = s__('SecurityOrchestration|Policy scope');
export const ACTION_AND_LABEL = __('and'); export const ACTION_AND_LABEL = __('and');
export const RULE_MODE_SCANNERS = { export const RULE_MODE_SCANNERS = {
......
...@@ -12,7 +12,10 @@ import { ...@@ -12,7 +12,10 @@ import {
GlTooltipDirective, GlTooltipDirective,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale'; import { __, s__, sprintf } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import SegmentedControlButtonGroup from '~/vue_shared/components/segmented_control_button_group.vue'; import SegmentedControlButtonGroup from '~/vue_shared/components/segmented_control_button_group.vue';
import DimDisableContainer from 'ee/security_orchestration/components/policy_editor/dim_disable_container.vue';
import PolicyScope from 'ee/security_orchestration/components/policy_editor/scope/policy_scope.vue';
import { NAMESPACE_TYPES } from '../../constants'; import { NAMESPACE_TYPES } from '../../constants';
import { POLICY_TYPE_COMPONENT_OPTIONS } from '../constants'; import { POLICY_TYPE_COMPONENT_OPTIONS } from '../constants';
import { import {
...@@ -22,6 +25,7 @@ import { ...@@ -22,6 +25,7 @@ import {
EDITOR_MODE_YAML, EDITOR_MODE_YAML,
POLICY_RUN_TIME_MESSAGE, POLICY_RUN_TIME_MESSAGE,
POLICY_RUN_TIME_TOOLTIP, POLICY_RUN_TIME_TOOLTIP,
SCOPE_LABEL,
} from './constants'; } from './constants';
export default { export default {
...@@ -29,6 +33,7 @@ export default { ...@@ -29,6 +33,7 @@ export default {
DELETE_MODAL_CONFIG, DELETE_MODAL_CONFIG,
POLICY_RUN_TIME_MESSAGE, POLICY_RUN_TIME_MESSAGE,
POLICY_RUN_TIME_TOOLTIP, POLICY_RUN_TIME_TOOLTIP,
SCOPE_LABEL,
description: __('Description'), description: __('Description'),
failedValidationText: __('This field is required'), failedValidationText: __('This field is required'),
name: __('Name'), name: __('Name'),
...@@ -40,6 +45,8 @@ export default { ...@@ -40,6 +45,8 @@ export default {
{ value: false, text: __('Disabled') }, { value: false, text: __('Disabled') },
], ],
components: { components: {
DimDisableContainer,
PolicyScope,
GlAlert, GlAlert,
GlButton, GlButton,
GlFormGroup, GlFormGroup,
...@@ -52,6 +59,7 @@ export default { ...@@ -52,6 +59,7 @@ export default {
YamlEditor: () => import(/* webpackChunkName: 'policy_yaml_editor' */ '../yaml_editor.vue'), YamlEditor: () => import(/* webpackChunkName: 'policy_yaml_editor' */ '../yaml_editor.vue'),
}, },
directives: { GlModal: GlModalDirective, GlTooltip: GlTooltipDirective }, directives: { GlModal: GlModalDirective, GlTooltip: GlTooltipDirective },
mixins: [glFeatureFlagsMixin()],
inject: ['namespaceType', 'policiesPath'], inject: ['namespaceType', 'policiesPath'],
props: { props: {
customSaveButtonText: { customSaveButtonText: {
...@@ -126,6 +134,12 @@ export default { ...@@ -126,6 +134,12 @@ export default {
}; };
}, },
computed: { computed: {
isGroupLevel() {
return this.namespaceType === NAMESPACE_TYPES.GROUP;
},
shouldShowScope() {
return this.glFeatures.securityPoliciesPolicyScope && this.isGroupLevel;
},
deleteModalTitle() { deleteModalTitle() {
return sprintf(s__('SecurityOrchestration|Delete policy: %{policy}'), { return sprintf(s__('SecurityOrchestration|Delete policy: %{policy}'), {
policy: this.policy.name, policy: this.policy.name,
...@@ -234,6 +248,18 @@ export default { ...@@ -234,6 +248,18 @@ export default {
/> />
</gl-form-group> </gl-form-group>
<dim-disable-container v-if="shouldShowScope" :disabled="hasParsingError">
<template #title>
<h4>{{ $options.i18n.SCOPE_LABEL }}</h4>
</template>
<template #disabled>
<div class="gl-bg-gray-10 gl-rounded-base gl-p-6"></div>
</template>
<policy-scope />
</dim-disable-container>
<slot name="actions-first"></slot> <slot name="actions-first"></slot>
<slot name="rules"></slot> <slot name="rules"></slot>
<slot name="actions"></slot> <slot name="actions"></slot>
......
import { s__ } from '~/locale';
export const PROJECTS_WITH_FRAMEWORK = 'projects_with_framework';
export const ALL_PROJECTS_IN_GROUP = 'all_projects_in_group';
export const SPECIFIC_PROJECTS = 'specific_projects';
export const PROJECT_SCOPE_TYPE_LISTBOX_TEXTS = {
[PROJECTS_WITH_FRAMEWORK]: s__('SecurityOrchestration|projects with compliance frameworks'),
[ALL_PROJECTS_IN_GROUP]: s__('SecurityOrchestration|all projects in this group'),
[SPECIFIC_PROJECTS]: s__('SecurityOrchestration|specific projects'),
};
export const PROJECT_SCOPE_TYPE_LISTBOX = Object.entries(PROJECT_SCOPE_TYPE_LISTBOX_TEXTS).map(
([value, text]) => ({
value,
text,
}),
);
<script>
import { GlCollapsibleListbox, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import {
PROJECTS_WITH_FRAMEWORK,
PROJECT_SCOPE_TYPE_LISTBOX,
PROJECT_SCOPE_TYPE_LISTBOX_TEXTS,
} from './constants';
export default {
PROJECT_SCOPE_TYPE_LISTBOX,
PROJECT_SCOPE_TYPE_LISTBOX_TEXTS,
i18n: {
policyScopeCopy: s__(
`SecurityOrchestration|Apply this policy to all projects %{projectScopeType} named %{exceptionType} %{projectSelector}`,
),
},
name: 'PolicyScope',
components: {
GlCollapsibleListbox,
GlSprintf,
},
data() {
return {
selectedProjectScopeType: PROJECTS_WITH_FRAMEWORK,
};
},
computed: {
selectedProjectScopeText() {
return PROJECT_SCOPE_TYPE_LISTBOX_TEXTS[this.selectedProjectScopeType];
},
},
methods: {
selectProjectScopeType(scopeType) {
this.selectedProjectScopeType = scopeType;
},
},
};
</script>
<template>
<div class="gl-mt-2 gl-mb-6">
<gl-sprintf :message="$options.i18n.policyScopeCopy">
<template #projectScopeType>
<gl-collapsible-listbox
:items="$options.PROJECT_SCOPE_TYPE_LISTBOX"
:selected="selectedProjectScopeType"
:toggle-text="selectedProjectScopeText"
@select="selectProjectScopeType"
/>
</template>
<template #exceptionType> </template>
<template #projectSelector> </template>
</gl-sprintf>
</div>
</template>
...@@ -13,6 +13,7 @@ class PoliciesController < Groups::ApplicationController ...@@ -13,6 +13,7 @@ class PoliciesController < Groups::ApplicationController
push_frontend_feature_flag(:scan_result_policies_block_unprotecting_branches, group) push_frontend_feature_flag(:scan_result_policies_block_unprotecting_branches, group)
push_frontend_feature_flag(:scan_result_any_merge_request, group) push_frontend_feature_flag(:scan_result_any_merge_request, group)
push_frontend_feature_flag(:scan_result_policies_block_force_push, group) push_frontend_feature_flag(:scan_result_policies_block_force_push, group)
push_frontend_feature_flag(:security_policies_policy_scope, group)
end end
feature_category :security_policy_management feature_category :security_policy_management
......
--- ---
name: security_policies_policy_scope name: security_policies_policy_scope
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134508 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135398
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/429912 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/429912
milestone: '16.6' milestone: '16.6'
type: development type: development
......
...@@ -17,6 +17,7 @@ import { ...@@ -17,6 +17,7 @@ import {
import { NAMESPACE_TYPES } from 'ee/security_orchestration/constants'; import { NAMESPACE_TYPES } from 'ee/security_orchestration/constants';
import SegmentedControlButtonGroup from '~/vue_shared/components/segmented_control_button_group.vue'; import SegmentedControlButtonGroup from '~/vue_shared/components/segmented_control_button_group.vue';
import EditorLayout from 'ee/security_orchestration/components/policy_editor/editor_layout.vue'; import EditorLayout from 'ee/security_orchestration/components/policy_editor/editor_layout.vue';
import PolicyScope from 'ee/security_orchestration/components/policy_editor/scope/policy_scope.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mockDastScanExecutionObject } from '../../mocks/mock_scan_execution_policy_data'; import { mockDastScanExecutionObject } from '../../mocks/mock_scan_execution_policy_data';
import { mockDefaultBranchesScanResultObject } from '../../mocks/mock_scan_result_policy_data'; import { mockDefaultBranchesScanResultObject } from '../../mocks/mock_scan_result_policy_data';
...@@ -64,6 +65,7 @@ describe('EditorLayout component', () => { ...@@ -64,6 +65,7 @@ describe('EditorLayout component', () => {
wrapper.findByTestId('scan-result-policy-run-time-info'); wrapper.findByTestId('scan-result-policy-run-time-info');
const findScanResultPolicyRunTimeTooltip = () => const findScanResultPolicyRunTimeTooltip = () =>
findScanResultPolicyRunTimeInfo().findComponent(GlIcon); findScanResultPolicyRunTimeInfo().findComponent(GlIcon);
const findPolicyScope = () => wrapper.findComponent(PolicyScope);
describe('default behavior', () => { describe('default behavior', () => {
beforeEach(() => { beforeEach(() => {
...@@ -294,4 +296,26 @@ describe('EditorLayout component', () => { ...@@ -294,4 +296,26 @@ describe('EditorLayout component', () => {
expect(findSavePolicyButton().props('disabled')).toBe(false); expect(findSavePolicyButton().props('disabled')).toBe(false);
}); });
}); });
describe('policy scope', () => {
it.each`
flagEnabled | type | expectedResult
${true} | ${NAMESPACE_TYPES.GROUP} | ${true}
${true} | ${NAMESPACE_TYPES.PROJECT} | ${false}
${false} | ${NAMESPACE_TYPES.GROUP} | ${false}
${false} | ${NAMESPACE_TYPES.PROJECT} | ${false}
`(
'renders policy scope conditionally for $namespaceType level based on feature flag',
({ flagEnabled, type, expectedResult }) => {
factory({
provide: {
namespaceType: type,
glFeatures: { securityPoliciesPolicyScope: flagEnabled },
},
});
expect(findPolicyScope().exists()).toBe(expectedResult);
},
);
});
}); });
...@@ -42809,6 +42809,9 @@ msgstr "" ...@@ -42809,6 +42809,9 @@ msgstr ""
msgid "SecurityOrchestration|Any merge request" msgid "SecurityOrchestration|Any merge request"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|Apply this policy to all projects %{projectScopeType} named %{exceptionType} %{projectSelector}"
msgstr ""
msgid "SecurityOrchestration|Are you sure you want to delete this policy? This action cannot be undone." msgid "SecurityOrchestration|Are you sure you want to delete this policy? This action cannot be undone."
msgstr "" msgstr ""
   
...@@ -43009,6 +43012,9 @@ msgstr "" ...@@ -43009,6 +43012,9 @@ msgstr ""
msgid "SecurityOrchestration|Policy editor" msgid "SecurityOrchestration|Policy editor"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|Policy scope"
msgstr ""
msgid "SecurityOrchestration|Policy status" msgid "SecurityOrchestration|Policy status"
msgstr "" msgstr ""
   
...@@ -43231,6 +43237,9 @@ msgstr "" ...@@ -43231,6 +43237,9 @@ msgstr ""
msgid "SecurityOrchestration|all namespaces" msgid "SecurityOrchestration|all namespaces"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|all projects in this group"
msgstr ""
msgid "SecurityOrchestration|any" msgid "SecurityOrchestration|any"
msgstr "" msgstr ""
   
...@@ -43279,12 +43288,18 @@ msgstr "" ...@@ -43279,12 +43288,18 @@ msgstr ""
msgid "SecurityOrchestration|or from:" msgid "SecurityOrchestration|or from:"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|projects with compliance frameworks"
msgstr ""
msgid "SecurityOrchestration|scanner finds" msgid "SecurityOrchestration|scanner finds"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|scanners find" msgid "SecurityOrchestration|scanners find"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|specific projects"
msgstr ""
msgid "SecurityOrchestration|targeting %{branchTypeText}" msgid "SecurityOrchestration|targeting %{branchTypeText}"
msgstr "" msgstr ""
   
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册