Commit b5888f5f authored by Fernando's avatar Fernando

Move security rule specific logic into its own component

* Isolate and extract logic into seperate wrapper component
* Set endpoint url at store creation and not in Vue lifecycle hook
* Remove uneeded 'this' in 'some' call
* Remove rules.?
parent 4aaca884
<script> <script>
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { s__, n__, sprintf } from '~/locale'; import { n__, sprintf } from '~/locale';
import { import { RULE_TYPE_ANY_APPROVER, RULE_TYPE_REGULAR } from '../../constants';
RULE_TYPE_ANY_APPROVER,
RULE_TYPE_REGULAR,
LICENSE_CHECK_NAME,
VULNERABILITY_CHECK_NAME,
} from '../../constants';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue'; import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
import Rules from '../rules.vue'; import Rules from '../rules.vue';
...@@ -15,7 +10,7 @@ import RuleControls from '../rule_controls.vue'; ...@@ -15,7 +10,7 @@ import RuleControls from '../rule_controls.vue';
import EmptyRule from '../empty_rule.vue'; import EmptyRule from '../empty_rule.vue';
import RuleInput from '../mr_edit/rule_input.vue'; import RuleInput from '../mr_edit/rule_input.vue';
import RuleBranches from '../rule_branches.vue'; import RuleBranches from '../rule_branches.vue';
import UnconfiguredSecurityRule from '../security_configuration/unconfigured_security_rule.vue'; import UnconfiguredSecurityRules from '../security_configuration/unconfigured_security_rules.vue';
export default { export default {
components: { components: {
...@@ -25,38 +20,15 @@ export default { ...@@ -25,38 +20,15 @@ export default {
EmptyRule, EmptyRule,
RuleInput, RuleInput,
RuleBranches, RuleBranches,
UnconfiguredSecurityRule, UnconfiguredSecurityRules,
}, },
// TODO: Remove feature flag in https://gitlab.com/gitlab-org/gitlab/-/issues/235114 // TODO: Remove feature flag in https://gitlab.com/gitlab-org/gitlab/-/issues/235114
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
inject: {
securityConfigurationPath: {
type: String,
required: true,
from: 'securityConfigurationPath',
default: '',
},
vulnerabilityCheckHelpPagePath: {
type: String,
required: true,
from: 'vulnerabilityCheckHelpPagePath',
default: '',
},
licenseCheckHelpPagePath: {
type: String,
required: true,
from: 'licenseCheckHelpPagePath',
default: '',
},
},
computed: { computed: {
...mapState(['settings']), ...mapState(['settings']),
...mapState({ ...mapState({
rules: state => state.approvals.rules, rules: state => state.approvals.rules,
hasApprovalsLoaded: state => state.approvals.hasLoaded,
hasSecurityConfigurationLoaded: state => state.securityConfiguration.hasLoaded,
}), }),
...mapState('securityConfiguration', ['configuration']),
hasNamedRule() { hasNamedRule() {
return this.rules.some(rule => rule.ruleType === RULE_TYPE_REGULAR); return this.rules.some(rule => rule.ruleType === RULE_TYPE_REGULAR);
}, },
...@@ -66,33 +38,6 @@ export default { ...@@ -66,33 +38,6 @@ export default {
!this.rules.some(rule => rule.ruleType === RULE_TYPE_ANY_APPROVER) !this.rules.some(rule => rule.ruleType === RULE_TYPE_ANY_APPROVER)
); );
}, },
isRulesLoading() {
return !this.hasApprovalsLoaded || !this.hasSecurityConfigurationLoaded;
},
securityRules() {
return [
{
name: VULNERABILITY_CHECK_NAME,
description: s__(
'SecurityApprovals|One or more of the security scanners must be enabled %{linkStart}more information%{linkEnd}',
),
enableDescription: s__(
'SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity %{linkStart}more information%{linkEnd}',
),
docsPath: this.vulnerabilityCheckHelpPagePath,
},
{
name: LICENSE_CHECK_NAME,
description: s__(
'SecurityApprovals|License Scanning must be enabled %{linkStart}more information%{linkEnd}',
),
enableDescription: s__(
'SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied %{linkStart}more information%{linkEnd}',
),
docsPath: this.licenseCheckHelpPagePath,
},
];
},
}, },
watch: { watch: {
rules: { rules: {
...@@ -107,20 +52,8 @@ export default { ...@@ -107,20 +52,8 @@ export default {
immediate: true, immediate: true,
}, },
}, },
created() {
// TODO: Remove feature flag in https://gitlab.com/gitlab-org/gitlab/-/issues/235114
if (this.glFeatures.approvalSuggestions) {
this.setSecurityConfigurationEndpoint(this.securityConfigurationPath);
this.fetchSecurityConfiguration();
}
},
methods: { methods: {
...mapActions(['addEmptyRule']), ...mapActions(['addEmptyRule']),
...mapActions({ openCreateModal: 'createModal/open' }),
...mapActions('securityConfiguration', [
'setSecurityConfigurationEndpoint',
'fetchSecurityConfiguration',
]),
summaryText(rule) { summaryText(rule) {
return this.settings.allowMultiRule return this.settings.allowMultiRule
? this.summaryMultipleRulesText(rule) ? this.summaryMultipleRulesText(rule)
...@@ -191,7 +124,10 @@ export default { ...@@ -191,7 +124,10 @@ export default {
/> />
<tr v-else :key="index"> <tr v-else :key="index">
<td class="js-name">{{ rule.name }}</td> <td class="js-name">{{ rule.name }}</td>
<td class="js-members" :class="settings.allowMultiRule ? 'd-none d-sm-table-cell' : null"> <td
class="js-members"
:class="settings.allowMultiRule ? 'd-none d-sm-table-cell' : null"
>
<user-avatar-list :items="rule.approvers" :img-size="24" empty-text="" /> <user-avatar-list :items="rule.approvers" :img-size="24" empty-text="" />
</td> </td>
<td v-if="settings.allowMultiRule" class="js-branches"> <td v-if="settings.allowMultiRule" class="js-branches">
...@@ -208,18 +144,6 @@ export default { ...@@ -208,18 +144,6 @@ export default {
</template> </template>
</rules> </rules>
<!-- TODO: Remove feature flag in https://gitlab.com/gitlab-org/gitlab/-/issues/235114 --> <!-- TODO: Remove feature flag in https://gitlab.com/gitlab-org/gitlab/-/issues/235114 -->
<table class="table m-0" v-if="glFeatures.approvalSuggestions"> <unconfigured-security-rules v-if="glFeatures.approvalSuggestions" />
<tbody>
<unconfigured-security-rule
v-for="securityRule in securityRules"
:key="securityRule.name"
:configuration="configuration"
:rules="rules"
:is-loading="isRulesLoading"
:match-rule="securityRule"
@enable="openCreateModal({ defaultRuleName: securityRule.name })"
/>
</tbody>
</table>
</div> </div>
</template> </template>
...@@ -41,9 +41,9 @@ export default { ...@@ -41,9 +41,9 @@ export default {
}, },
computed: { computed: {
hasApprovalRuleDefined() { hasApprovalRuleDefined() {
return this.rules?.some(rule => { return this.rules.some(rule => {
return this.matchRule.name === rule.name; return this.matchRule.name === rule.name;
}, this); });
}, },
hasConfiguredJob() { hasConfiguredJob() {
const { features = [] } = this.configuration; const { features = [] } = this.configuration;
...@@ -76,6 +76,7 @@ export default { ...@@ -76,6 +76,7 @@ export default {
</td> </td>
<template v-else> <template v-else>
<!-- Suggested approval rule creation row -->
<template v-if="hasConfiguredJob"> <template v-if="hasConfiguredJob">
<td class="js-name" colspan="4"> <td class="js-name" colspan="4">
<div>{{ matchRule.name }}</div> <div>{{ matchRule.name }}</div>
...@@ -94,6 +95,7 @@ export default { ...@@ -94,6 +95,7 @@ export default {
</td> </td>
</template> </template>
<!-- Approval rule suggestion when lacking appropriate CI job for the rule -->
<td v-else class="js-name" colspan="5"> <td v-else class="js-name" colspan="5">
<div>{{ matchRule.name }}</div> <div>{{ matchRule.name }}</div>
<div class="gl-text-gray-500"> <div class="gl-text-gray-500">
......
<script>
import { mapState, mapActions } from 'vuex';
import { LICENSE_CHECK_NAME, VULNERABILITY_CHECK_NAME } from 'ee/approvals/constants';
import { s__ } from '~/locale';
import UnconfiguredSecurityRule from './unconfigured_security_rule.vue';
export default {
components: {
UnconfiguredSecurityRule,
},
props: {},
inject: {
vulnerabilityCheckHelpPagePath: {
from: 'vulnerabilityCheckHelpPagePath',
default: '',
},
licenseCheckHelpPagePath: {
from: 'licenseCheckHelpPagePath',
default: '',
},
},
computed: {
...mapState('securityConfiguration', ['configuration']),
...mapState({
rules: state => state.approvals.rules,
hasApprovalsLoaded: state => state.approvals.hasLoaded,
hasSecurityConfigurationLoaded: state => state.securityConfiguration.hasLoaded,
}),
isRulesLoading() {
return !this.hasApprovalsLoaded || !this.hasSecurityConfigurationLoaded;
},
securityRules() {
return [
{
name: VULNERABILITY_CHECK_NAME,
description: s__(
'SecurityApprovals|One or more of the security scanners must be enabled %{linkStart}more information%{linkEnd}',
),
enableDescription: s__(
'SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity %{linkStart}more information%{linkEnd}',
),
docsPath: this.vulnerabilityCheckHelpPagePath,
},
{
name: LICENSE_CHECK_NAME,
description: s__(
'SecurityApprovals|License Scanning must be enabled %{linkStart}more information%{linkEnd}',
),
enableDescription: s__(
'SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied %{linkStart}more information%{linkEnd}',
),
docsPath: this.licenseCheckHelpPagePath,
},
];
},
},
created() {
this.fetchSecurityConfiguration();
},
methods: {
...mapActions('securityConfiguration', ['fetchSecurityConfiguration']),
...mapActions({ openCreateModal: 'createModal/open' }),
},
};
</script>
<template>
<table class="table m-0">
<tbody>
<unconfigured-security-rule
v-for="securityRule in securityRules"
:key="securityRule.name"
:configuration="configuration"
:rules="rules"
:is-loading="isRulesLoading"
:match-rule="securityRule"
@enable="openCreateModal({ defaultRuleName: securityRule.name })"
/>
</tbody>
</table>
</template>
...@@ -12,11 +12,7 @@ export default function mountProjectSettingsApprovals(el) { ...@@ -12,11 +12,7 @@ export default function mountProjectSettingsApprovals(el) {
return null; return null;
} }
const { const { vulnerabilityCheckHelpPagePath, licenseCheckHelpPagePath } = el.dataset;
securityConfigurationPath,
vulnerabilityCheckHelpPagePath,
licenseCheckHelpPagePath,
} = el.dataset;
const store = createStore(projectSettingsModule(), { const store = createStore(projectSettingsModule(), {
...el.dataset, ...el.dataset,
...@@ -29,7 +25,6 @@ export default function mountProjectSettingsApprovals(el) { ...@@ -29,7 +25,6 @@ export default function mountProjectSettingsApprovals(el) {
el, el,
store, store,
provide: { provide: {
securityConfigurationPath,
vulnerabilityCheckHelpPagePath, vulnerabilityCheckHelpPagePath,
licenseCheckHelpPagePath, licenseCheckHelpPagePath,
}, },
......
...@@ -9,7 +9,9 @@ export const createStoreOptions = (approvalsModule, settings) => ({ ...@@ -9,7 +9,9 @@ export const createStoreOptions = (approvalsModule, settings) => ({
...(approvalsModule ? { approvals: approvalsModule } : {}), ...(approvalsModule ? { approvals: approvalsModule } : {}),
createModal: modalModule(), createModal: modalModule(),
deleteModal: modalModule(), deleteModal: modalModule(),
securityConfiguration: securityConfigurationModule(), securityConfiguration: securityConfigurationModule({
securityConfigurationPath: settings.securityConfigurationPath,
}),
}, },
}); });
......
import state from './state'; import createState from './state';
import mutations from './mutations'; import mutations from './mutations';
import * as actions from './actions'; import * as actions from './actions';
export default () => ({ export default ({ securityConfigurationPath = '' }) => ({
namespaced: true, namespaced: true,
state, state: createState({ securityConfigurationPath }),
mutations, mutations,
actions, actions,
}); });
export default () => ({ export default ({ securityConfigurationPath }) => ({
securityConfigurationPath: '', securityConfigurationPath,
isLoading: false, isLoading: false,
hasLoaded: false, hasLoaded: false,
errorLoading: false, errorLoading: false,
......
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