Skip to content

Commit 506494c

Browse files
authored
Merge pull request #183 from syalioune/feature/dynamic-configurable-templates
Make notification template editable
2 parents be4a7b8 + 159b606 commit 506494c

File tree

5 files changed

+311
-13
lines changed

5 files changed

+311
-13
lines changed

src/i18n/locales/en.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,23 @@
531531
"repository_deleted": "Repository deleted",
532532
"portfolio_access_control": "Portfolio Access Control",
533533
"project_access": "Project access",
534-
"select_project": "Select Project"
534+
"select_project": "Select Project",
535+
"create_template": "Create Template",
536+
"template_created": "Template created",
537+
"delete_template": "Delete Template",
538+
"template_deleted": "Template deleted",
539+
"template_basedir": "Template base directory",
540+
"template_basedir_tooltip": "This property is used as base directory for notification templates search",
541+
"general_template_configuration": "General template configuration",
542+
"template_override_description": "Switching the template override control on and providing a template base directory allow you to override Dependency Track default notification publisher templates.",
543+
"template_override_file_hierarchy": "Any Pebble templates available in the template base directory with the appropriate directory hierarchy and naming scheme (e.g ${base directory}/templates/notification/publisher/email.peb) will override Dependency Track default one.",
544+
"template_override_security_warning": "You must set appropriate rights to the template base directory to prevent untrusted third party from supplying fraudulent Pebble templates that could lead to potential remote code execution.",
545+
"template_override_restart_needed": "Dependency Track restart is required for the modifications to be taken into account.",
546+
"enable_default_template_override": "Enable default template override",
547+
"restore_default_template": "Restore default templates",
548+
"default_template_restored": "Default templates restored",
549+
"clone_template": "Clone Template",
550+
"template_cloned": "Template cloned"
535551
},
536552
"condition": {
537553
"warning": "Warning",

src/views/administration/notifications/CreateAlertModal.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@
7979
scope: this.scope,
8080
notificationLevel: this.notificationLevel,
8181
publisher: { uuid: this.publisher }
82-
}).then((response) => {
82+
}).then(() => {
8383
this.$emit('refreshTable');
8484
this.$toastr.s(this.$t('admin.alert_created'));
85-
}).catch((error) => {
85+
}).catch(() => {
8686
this.$toastr.w(this.$t('condition.unsuccessful_action'));
8787
});
8888
this.resetValues();
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<template>
2+
<b-modal id="createTemplateModal" size="md" hide-header-close no-stacking :title="$t('admin.create_template')">
3+
<b-form-group
4+
id="fieldset-1"
5+
:label="this.$t('message.name')"
6+
label-for="input-1"
7+
label-class="required">
8+
<b-form-input id="input-1" v-model="name" class="required" required trim />
9+
</b-form-group>
10+
<b-form-group
11+
id="fieldset-2"
12+
:label="this.$t('admin.publisher_class')"
13+
label-for="input-2"
14+
label-class="required">
15+
<b-form-input id="input-2" v-model="publisherClass" class="required" required trim />
16+
</b-form-group>
17+
<b-form-group
18+
id="fieldset-3"
19+
:label="this.$t('message.description')"
20+
label-for="input-3"
21+
label-class="required">
22+
<b-form-textarea id="input-3" v-model="description" class="required" rows="4" required trim />
23+
</b-form-group>
24+
<b-form-group
25+
id="fieldset-4"
26+
:label="this.$t('admin.mime_type')"
27+
label-for="input-4"
28+
label-class="required">
29+
<b-form-input id="input-4" v-model="mimeType" class="required" required trim />
30+
</b-form-group>
31+
<b-form-group
32+
id="fieldset-5"
33+
:label="this.$t('admin.template')"
34+
label-for="input-5"
35+
label-class="required">
36+
<b-form-textarea id="input-5" v-model="template" class="required" rows="10" required trim />
37+
</b-form-group>
38+
<template v-slot:modal-footer="{ cancel }">
39+
<b-button size="md" variant="secondary" @click="cancel()">{{ $t('message.close') }}</b-button>
40+
<b-button size="md" variant="primary" @click="createTemplate()">{{ $t('message.create') }}</b-button>
41+
</template>
42+
</b-modal>
43+
</template>
44+
45+
<script>
46+
import permissionsMixin from "../../../mixins/permissionsMixin";
47+
import EventBus from "../../../shared/eventbus";
48+
49+
export default {
50+
mixins: [permissionsMixin],
51+
mounted() {
52+
EventBus.$on('admin:templates:cloneTemplate', (template) => {
53+
this.name = `${template.name} - clone`;
54+
this.publisherClass = template.publisherClass;
55+
this.description = template.description;
56+
this.mimeType = template.templateMimeType;
57+
this.template = template.template;
58+
});
59+
this.$root.$on('bv::modal::hide', (_, modalId) => {
60+
if(modalId == 'createTemplateModal') {
61+
this.resetValues();
62+
}
63+
});
64+
},
65+
data() {
66+
return {
67+
name: null,
68+
publisherClass: null,
69+
description: null,
70+
mimeType: null,
71+
template: null
72+
}
73+
},
74+
methods: {
75+
createTemplate: function() {
76+
let url = `${this.$api.BASE_URL}/${this.$api.URL_NOTIFICATION_PUBLISHER}`;
77+
this.axios.put(url, {
78+
name: this.name,
79+
description: this.description,
80+
publisherClass: this.publisherClass,
81+
template: this.template,
82+
templateMimeType: this.mimeType,
83+
defaultPublisher: false
84+
}).then(() => {
85+
this.$emit('refreshTable');
86+
this.$toastr.s(this.$t('admin.template_created'));
87+
}).catch(() => {
88+
this.$toastr.w(this.$t('condition.unsuccessful_action'));
89+
});
90+
this.$root.$emit('bv::hide::modal', 'createTemplateModal');
91+
},
92+
resetValues: function () {
93+
this.name = null;
94+
this.publisherClass = null;
95+
this.description = null;
96+
this.mimeType = null;
97+
this.template = null;
98+
}
99+
}
100+
}
101+
</script>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<template>
2+
<b-modal id="generalTemplateConfigurationModal" size="lg" hide-header-close no-stacking :title="$t('admin.general_template_configuration')" @show="loadConfigProperties">
3+
<p>{{ $t('admin.template_override_description') }}</p>
4+
<p>{{ $t('admin.template_override_file_hierarchy') }}</p>
5+
<p>{{ $t('admin.template_override_security_warning') }}</p>
6+
<p>{{ $t('admin.template_override_restart_needed') }}</p>
7+
<b-form-group>
8+
<c-switch id="template_override" color="primary" v-model="enableDefaultTemplatesOverride" label v-bind="labelIcon"/>
9+
{{ $t('admin.enable_default_template_override') }}
10+
</b-form-group>
11+
<b-validated-input-group-form-input
12+
id="template_basedir"
13+
:label="$t('admin.template_basedir')"
14+
input-group-size="mb-3"
15+
rules="required"
16+
type="text"
17+
v-model="templateBasedir"
18+
:tooltip="$t('admin.template_basedir_tooltip')"
19+
/>
20+
<template v-slot:modal-footer="{ cancel }">
21+
<b-button size="md" variant="secondary" @click="cancel()">{{ $t('message.close') }}</b-button>
22+
<b-button size="md" variant="primary" @click="updateConfiguration()">{{ $t('message.update') }}</b-button>
23+
<b-button size="md" variant="warning" @click="restoreDefaultTemplates()">{{ $t('admin.restore_default_template') }}</b-button>
24+
</template>
25+
</b-modal>
26+
</template>
27+
<script>
28+
import configPropertyMixin from "../mixins/configPropertyMixin";
29+
import { Switch as cSwitch } from '@coreui/vue';
30+
import common from "../../../shared/common";
31+
import BValidatedInputGroupFormInput from '../../../forms/BValidatedInputGroupFormInput';
32+
33+
export default {
34+
mixins: [configPropertyMixin],
35+
components: {
36+
cSwitch,
37+
BValidatedInputGroupFormInput
38+
},
39+
data() {
40+
return {
41+
enableDefaultTemplatesOverride: null,
42+
templateBasedir: null
43+
}
44+
},
45+
methods: {
46+
updateConfiguration: function() {
47+
this.$root.$emit('bv::hide::modal', 'generalTemplateConfigurationModal');
48+
this.updateConfigProperties([
49+
{groupName: 'notification', propertyName: 'template.baseDir', propertyValue: this.templateBasedir},
50+
{groupName: 'notification', propertyName: 'template.default.override.enabled', propertyValue: this.enableDefaultTemplatesOverride}
51+
]);
52+
},
53+
restoreDefaultTemplates: function() {
54+
this.$root.$emit('bv::hide::modal', 'generalTemplateConfigurationModal');
55+
let url = `${this.$api.BASE_URL}/${this.$api.URL_NOTIFICATION_PUBLISHER}/restoreDefaultTemplates`;
56+
this.axios.post(url).then(() => {
57+
this.$emit('refreshTable');
58+
this.$toastr.s(this.$t('admin.default_template_restored'));
59+
}).catch(() => {
60+
this.$toastr.w(this.$t('condition.unsuccessful_action'));
61+
});
62+
},
63+
loadConfigProperties () {
64+
this.axios.get(this.configUrl).then((response) => {
65+
let configItems = response.data.filter(function (item) { return item.groupName === "notification" });
66+
for (let i=0; i<configItems.length; i++) {
67+
let item = configItems[i];
68+
switch (item.propertyName) {
69+
case "template.baseDir":
70+
this.templateBasedir = item.propertyValue; break;
71+
case "template.default.override.enabled":
72+
this.enableDefaultTemplatesOverride = common.toBoolean(item.propertyValue); break;
73+
}
74+
}
75+
});
76+
}
77+
}
78+
}
79+
</script>

0 commit comments

Comments
 (0)