Skip to content

Commit 5a1279b

Browse files
committed
Merge branch 'master' of github.com:DependencyTrack/frontend into issue-338
2 parents a5e8e58 + 15795a1 commit 5a1279b

File tree

4 files changed

+135
-12
lines changed

4 files changed

+135
-12
lines changed

.github/workflows/nodejs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ jobs:
4242
tar zxvf ~/trivy.tar.gz -C ~/
4343
- name: Analyzing Docker container
4444
run: |
45-
~/dockle $DOCKER_REPO:$DOCKER_TAG
46-
~/trivy --exit-code 0 --quiet $DOCKER_REPO:$DOCKER_TAG
45+
# ~/dockle $DOCKER_REPO:$DOCKER_TAG
46+
~/trivy --quiet $DOCKER_REPO:$DOCKER_TAG
4747
- name: Publishing container to Docker Hub
4848
if: ((github.event_name == 'push' && github.ref == 'refs/heads/master') || github.event_name == 'workflow_dispatch') && startsWith(matrix.node-version, '12.')
4949
env:

src/i18n/locales/en.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
"project_cloning_in_progress": "The project is being created with the cloning options specified",
115115
"vulnerability": "Vulnerability",
116116
"analysis": "Analysis",
117+
"justification": "Justification",
117118
"title": "Title",
118119
"subtitle": "Subtitle",
119120
"recommendation": "Recommendation",
@@ -129,10 +130,26 @@
129130
"approved": "Approved",
130131
"rejected": "Rejected",
131132
"not_set": "Not Set",
133+
"resolved": "Resolved",
132134
"exploitable": "Exploitable",
133135
"in_triage": "In Triage",
134136
"false_positive": "False Positive",
135137
"not_affected": "Not Affected",
138+
"code_not_present": "Code not present",
139+
"code_not_reachable": "Code not reachable",
140+
"requires_configuration": "Requires configuration",
141+
"requires_dependency": "Requires dependency",
142+
"requires_environment": "Requires environment",
143+
"protected_by_compiler": "Protected by compiler",
144+
"protected_at_runtime": "Protected at runtime",
145+
"protected_at_perimeter": "Protected at perimeter",
146+
"protected_by_mitigating_control": "Protected by mitigating control",
147+
"can_not_fix": "Can not fix",
148+
"will_not_fix": "Will not fix",
149+
"rollback": "Rollback",
150+
"workaround_available": "Workaround available",
151+
"response": "Vendor Response (project)",
152+
"analysis_details": "Details (explanation, workaround details, and other impact information)",
136153
"updated": "Updated",
137154
"add_component": "Add Component",
138155
"remove_component": "Remove Component",

src/shared/common.js

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,22 +118,71 @@ $common.formatAnalyzerLabel = function formatAnalyzerLabel(analyzer, vulnId, alt
118118
};
119119

120120
/**
121-
*
121+
*
122122
* @param {*} i18n - VueI18n instance with $t translate function available
123-
* @returns a specialized label for an analysis state (NOT_SET, APPROVED, REJECTED, etc).
124-
* It must have a corresponding entry in the locales files (e.g. src/locales/en.json)
123+
* @returns a specialized label for an analysis state (NOT_SET, APPROVED, REJECTED, etc).
124+
* It must have a corresponding entry in the locales files (e.g. src/locales/en.json)
125125
* (not_set, approved, rejected, etc.)
126126
*/
127127
$common.makeAnalysisStateLabelFormatter = (i18n) => {
128128
return function (value) {
129129
switch (value) {
130130
case 'NOT_SET':
131-
case 'APPROVED':
132-
case 'REJECTED':
133131
case 'EXPLOITABLE':
134132
case 'IN_TRIAGE':
135133
case 'FALSE_POSITIVE':
136134
case 'NOT_AFFECTED':
135+
case 'RESOLVED':
136+
return i18n.$t(`message.${value.toLowerCase()}`)
137+
default:
138+
return null;
139+
}
140+
}
141+
};
142+
143+
/**
144+
*
145+
* @param {*} i18n - VueI18n instance with $t translate function available
146+
* @returns a specialized label for an analysis justification (CODE_NOT_REACHABLE, etc).
147+
* It must have a corresponding entry in the locales files (e.g. src/locales/en.json)
148+
* (code_not_reachable, etc.)
149+
*/
150+
$common.makeAnalysisJustificationLabelFormatter = (i18n) => {
151+
return function (value) {
152+
switch (value) {
153+
case 'NOT_SET':
154+
case 'CODE_NOT_PRESENT':
155+
case 'CODE_NOT_REACHABLE':
156+
case 'REQUIRES_CONFIGURATION':
157+
case 'REQUIRES_DEPENDENCY':
158+
case 'REQUIRES_ENVIRONMENT':
159+
case 'PROTECTED_BY_COMPILER':
160+
case 'PROTECTED_AT_RUNTIME':
161+
case 'PROTECTED_AT_PERIMETER':
162+
case 'PROTECTED_BY_MITIGATING_CONTROL':
163+
return i18n.$t(`message.${value.toLowerCase()}`)
164+
default:
165+
return null;
166+
}
167+
}
168+
};
169+
170+
/**
171+
*
172+
* @param {*} i18n - VueI18n instance with $t translate function available
173+
* @returns a specialized label for an analysis response (WILL_NOT_FIX, etc).
174+
* It must have a corresponding entry in the locales files (e.g. src/locales/en.json)
175+
* (will_not_fix, etc.)
176+
*/
177+
$common.makeAnalysisResponseLabelFormatter = (i18n) => {
178+
return function (value) {
179+
switch (value) {
180+
case 'NOT_SET':
181+
case 'CAN_NOT_FIX':
182+
case 'WILL_NOT_FIX':
183+
case 'UPDATE':
184+
case 'ROLLBACK':
185+
case 'WORKAROUND_AVAILABLE':
137186
return i18n.$t(`message.${value.toLowerCase()}`)
138187
default:
139188
return null;
@@ -241,6 +290,7 @@ module.exports = {
241290
formatCweLabel: $common.formatCweLabel,
242291
formatAnalyzerLabel: $common.formatAnalyzerLabel,
243292
makeAnalysisStateLabelFormatter: $common.makeAnalysisStateLabelFormatter,
293+
makeAnalysisJustificationLabelFormatter: $common.makeAnalysisJustificationLabelFormatter,
244294
formatTimestamp: $common.formatTimestamp,
245295
concatenateComponentName: $common.concatenateComponentName,
246296
valueWithDefault: $common.valueWithDefault,

src/views/portfolio/projects/ProjectFindings.vue

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,26 @@
196196
<bootstrap-toggle v-model="isSuppressed" :options="{ on: 'Suppressed', off: 'Suppress', onstyle: 'warning', offstyle: 'outline-disabled'}" :disabled="false" />
197197
</b-input-group>
198198
</b-form-group>
199+
<b-row>
200+
<b-col sm="6">
201+
<b-form-group id="fieldset-10" :label="this.$t('message.justification')" label-for="input-10">
202+
<b-input-group id="input-10">
203+
<b-form-select v-model="analysisJustification" :options="justificationChoices" @change="makeAnalysis" :disabled="analysisState !== 'NOT_AFFECTED'"/>
204+
</b-input-group>
205+
</b-form-group>
206+
</b-col>
207+
<b-col sm="6">
208+
<b-form-group id="fieldset-11" :label="this.$t('message.response')" label-for="input-11">
209+
<b-input-group id="input-11">
210+
<b-form-select v-model="analysisResponse" :options="responseChoices" @change="makeAnalysis"/>
211+
</b-input-group>
212+
</b-form-group>
213+
</b-col>
214+
</b-row>
215+
<b-form-group id="fieldset-12" :label="this.$t('message.details')" label-for="analysisDetailsField">
216+
<b-form-textarea id="analysisDetailsField" v-model="analysisDetails" rows="7" class="form-control"
217+
v-debounce:750ms="makeAnalysis" :debounce-events="'keyup'"/>
218+
</b-form-group>
199219
</b-col>
200220
</b-row>
201221
`,
@@ -209,17 +229,41 @@
209229
{ value: 'NOT_SET', text: this.$t('message.not_set') },
210230
{ value: 'EXPLOITABLE', text: this.$t('message.exploitable') },
211231
{ value: 'IN_TRIAGE', text: this.$t('message.in_triage') },
232+
{ value: 'RESOLVED', text: this.$t('message.resolved') },
212233
{ value: 'FALSE_POSITIVE', text: this.$t('message.false_positive') },
213-
{ value: 'NOT_AFFECTED', text: this.$t('message.not_affected') }
234+
{ value: 'NOT_AFFECTED', text: this.$t('message.not_affected') },
235+
],
236+
justificationChoices: [
237+
{ value: 'NOT_SET', text: this.$t('message.not_set') },
238+
{ value: 'CODE_NOT_PRESENT', text: this.$t('message.code_not_present') },
239+
{ value: 'CODE_NOT_REACHABLE', text: this.$t('message.code_not_reachable') },
240+
{ value: 'REQUIRES_CONFIGURATION', text: this.$t('message.requires_configuration') },
241+
{ value: 'REQUIRES_DEPENDENCY', text: this.$t('message.requires_dependency') },
242+
{ value: 'REQUIRES_ENVIRONMENT', text: this.$t('message.requires_environment') },
243+
{ value: 'PROTECTED_BY_COMPILER', text: this.$t('message.protected_by_compiler') },
244+
{ value: 'PROTECTED_AT_RUNTIME', text: this.$t('message.protected_at_runtime') },
245+
{ value: 'PROTECTED_AT_PERIMETER', text: this.$t('message.protected_at_perimeter') },
246+
{ value: 'PROTECTED_BY_MITIGATING_CONTROL', text: this.$t('message.protected_by_mitigating_control') }
247+
],
248+
responseChoices: [
249+
{ value: 'NOT_SET', text: this.$t('message.not_set') },
250+
{ value: 'CAN_NOT_FIX', text: this.$t('message.can_not_fix') },
251+
{ value: 'WILL_NOT_FIX', text: this.$t('message.will_not_fix') },
252+
{ value: 'UPDATE', text: this.$t('message.update') },
253+
{ value: 'ROLLBACK', text: this.$t('message.rollback') },
254+
{ value: 'WORKAROUND_AVAILABLE', text: this.$t('message.workaround_available') }
214255
],
215256
analysisState: null,
257+
analysisJustification: null,
258+
analysisResponse: null,
259+
analysisDetails: null,
216260
projectUuid: projectUuid
217261
}
218262
},
219263
watch: {
220264
isSuppressed: function (currentValue, oldValue) {
221265
if (oldValue != null) {
222-
this.callRestEndpoint(this.analysisState, null, currentValue);
266+
this.callRestEndpoint(this.analysisState, null, null, null, null, currentValue);
223267
}
224268
}
225269
},
@@ -249,27 +293,39 @@
249293
if (Object.prototype.hasOwnProperty.call(analysis, "analysisState")) {
250294
this.analysisState = analysis.analysisState;
251295
}
296+
if (Object.prototype.hasOwnProperty.call(analysis, "analysisJustification")) {
297+
this.analysisJustification = analysis.analysisJustification;
298+
}
299+
if (Object.prototype.hasOwnProperty.call(analysis, "analysisResponse")) {
300+
this.analysisResponse = analysis.analysisResponse;
301+
}
302+
if (Object.prototype.hasOwnProperty.call(analysis, "analysisDetails")) {
303+
this.analysisDetails = analysis.analysisDetails;
304+
}
252305
if (Object.prototype.hasOwnProperty.call(analysis, "isSuppressed")) {
253306
this.isSuppressed = analysis.isSuppressed;
254307
} else {
255308
this.isSuppressed = false;
256309
}
257310
},
258311
makeAnalysis: function() {
259-
this.callRestEndpoint(this.analysisState, null, null);
312+
this.callRestEndpoint(this.analysisState, this.analysisJustification, this.analysisResponse, this.analysisDetails, null, null);
260313
},
261314
addComment: function() {
262315
if (this.comment != null) {
263-
this.callRestEndpoint(this.analysisState, this.comment, null);
316+
this.callRestEndpoint(this.analysisState, this.analysisJustification, this.analysisResponse, this.analysisDetails, this.comment, null);
264317
}
265318
},
266-
callRestEndpoint: function(analysisState, comment, isSuppressed) {
319+
callRestEndpoint: function(analysisState, analysisJustification, analysisResponse, analysisDetails, comment, isSuppressed) {
267320
let url = `${this.$api.BASE_URL}/${this.$api.URL_ANALYSIS}`;
268321
this.axios.put(url, {
269322
project: projectUuid,
270323
component: this.finding.component.uuid,
271324
vulnerability: this.finding.vulnerability.uuid,
272325
analysisState: analysisState,
326+
analysisJustification: analysisJustification,
327+
analysisResponse: analysisResponse,
328+
analysisDetails: analysisDetails,
273329
comment: comment,
274330
isSuppressed: isSuppressed
275331
}).then((response) => {

0 commit comments

Comments
 (0)