gitlab-org--gitlab-foss/app/assets/javascripts/clusters/components/ingress_modsecurity_setting...

257 lines
7.6 KiB
Vue

<script>
import {
GlAlert,
GlSprintf,
GlLink,
GlToggle,
GlButton,
GlDropdown,
GlDropdownItem,
GlIcon,
} from '@gitlab/ui';
import { escape } from 'lodash';
import modSecurityLogo from 'images/cluster_app_logos/gitlab.png';
import { APPLICATION_STATUS, INGRESS, LOGGING_MODE, BLOCKING_MODE } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
import { s__, __ } from '../../locale';
const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS;
export default {
title: __('Web Application Firewall'),
modsecurityUrl: 'https://modsecurity.org/about.html',
components: {
GlAlert,
GlSprintf,
GlLink,
GlToggle,
GlButton,
GlDropdown,
GlDropdownItem,
GlIcon,
},
props: {
ingress: {
type: Object,
required: true,
},
ingressModSecurityHelpPath: {
type: String,
required: false,
default: '',
},
modes: {
type: Object,
required: false,
default: () => ({
[LOGGING_MODE]: {
name: s__('ClusterIntegration|Logging mode'),
},
[BLOCKING_MODE]: {
name: s__('ClusterIntegration|Blocking mode'),
},
}),
},
},
data: () => ({
modSecurityLogo,
initialValue: null,
initialMode: null,
}),
computed: {
modSecurityEnabled: {
get() {
return this.ingress.modsecurity_enabled;
},
set(isEnabled) {
if (this.initialValue === null) {
this.initialValue = this.ingress.modsecurity_enabled;
}
eventHub.$emit('setIngressModSecurityEnabled', {
id: INGRESS,
modSecurityEnabled: isEnabled,
});
},
},
hasValueChanged() {
return this.modSecurityEnabledChanged || this.modSecurityModeChanged;
},
modSecurityEnabledChanged() {
return this.initialValue !== null && this.initialValue !== this.ingress.modsecurity_enabled;
},
modSecurityModeChanged() {
return (
this.ingress.modsecurity_enabled &&
this.initialMode !== null &&
this.initialMode !== this.ingress.modsecurity_mode
);
},
ingressModSecurityDescription() {
return escape(this.ingressModSecurityHelpPath);
},
saving() {
return [UPDATING].includes(this.ingress.status);
},
saveButtonDisabled() {
return (
[UNINSTALLING, UPDATING, INSTALLING].includes(this.ingress.status) ||
this.ingress.updateAvailable
);
},
saveButtonLabel() {
return this.saving ? __('Saving') : __('Save changes');
},
/**
* Returns true either when:
* - The application is getting updated.
* - The user has changed some of the settings for an application which is
* neither getting installed nor updated.
*/
showButtons() {
return this.saving || this.valuesChangedByUser;
},
modSecurityModeName() {
return this.modes[this.ingress.modsecurity_mode].name;
},
valuesChangedByUser() {
return this.hasValueChanged && [INSTALLED, UPDATED].includes(this.ingress.status);
},
},
methods: {
updateApplication() {
eventHub.$emit('updateApplication', {
id: INGRESS,
params: {
modsecurity_enabled: this.ingress.modsecurity_enabled,
modsecurity_mode: this.ingress.modsecurity_mode,
},
});
this.resetStatus();
},
resetStatus() {
if (this.initialMode !== null) {
// eslint-disable-next-line vue/no-mutating-props
this.ingress.modsecurity_mode = this.initialMode;
}
if (this.initialValue !== null) {
// eslint-disable-next-line vue/no-mutating-props
this.ingress.modsecurity_enabled = this.initialValue;
}
this.initialValue = null;
this.initialMode = null;
eventHub.$emit('resetIngressModSecurityChanges', INGRESS);
},
selectMode(modeKey) {
if (this.initialMode === null) {
this.initialMode = this.ingress.modsecurity_mode;
}
eventHub.$emit('setIngressModSecurityMode', {
id: INGRESS,
modSecurityMode: modeKey,
});
},
},
};
</script>
<template>
<div>
<gl-alert
v-if="ingress.updateFailed"
class="mb-3"
variant="danger"
:dismissible="false"
@dismiss="alert = null"
>
{{
s__(
'ClusterIntegration|Something went wrong while trying to save your settings. Please try again.',
)
}}
</gl-alert>
<div class="gl-responsive-table-row-layout" role="row">
<div class="table-section gl-mr-3 section-align-top" role="gridcell">
<img
:src="modSecurityLogo"
:alt="`${$options.title} logo`"
class="cluster-application-logo avatar s40"
/>
</div>
<div class="table-section section-wrap" role="gridcell">
<strong>
<gl-link :href="$options.modsecurityUrl" target="_blank">{{ $options.title }} </gl-link>
</strong>
<div class="form-group">
<p class="form-text text-muted">
<strong>
<gl-sprintf
:message="
s__(
'ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}',
)
"
>
<template #link="{ content }">
<gl-link :href="ingressModSecurityDescription" target="_blank"
>{{ content }}
</gl-link>
</template>
</gl-sprintf>
</strong>
</p>
<div class="form-check form-check-inline mt-3">
<gl-toggle v-model="modSecurityEnabled" :disabled="saveButtonDisabled" />
</div>
<div
v-if="ingress.modsecurity_enabled"
class="gl-responsive-table-row-layout mt-3"
role="row"
>
<div class="table-section section-wrap" role="gridcell">
<strong>
{{ s__('ClusterIntegration|Global default') }}
<gl-icon name="earth" class="align-text-bottom" />
</strong>
<div class="form-group">
<p class="form-text text-muted">
<strong>
{{
s__(
'ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level.',
)
}}
</strong>
</p>
</div>
<gl-dropdown :text="modSecurityModeName" :disabled="saveButtonDisabled">
<gl-dropdown-item v-for="(mode, key) in modes" :key="key" @click="selectMode(key)">
{{ mode.name }}
</gl-dropdown-item>
</gl-dropdown>
</div>
</div>
<div v-if="showButtons" class="gl-mt-5 gl-display-flex">
<gl-button
variant="success"
category="primary"
data-qa-selector="save_ingress_modsecurity_settings"
:loading="saving"
:disabled="saveButtonDisabled"
@click="updateApplication"
>
{{ saveButtonLabel }}
</gl-button>
<gl-button
data-qa-selector="cancel_ingress_modsecurity_settings"
:disabled="saveButtonDisabled"
@click="resetStatus"
>
{{ __('Cancel') }}
</gl-button>
</div>
</div>
</div>
</div>
</div>
</template>