Skip to content

Commit

Permalink
Merge pull request #3150 from CVEProject/dr_legacy_lookup
Browse files Browse the repository at this point in the history
Add the ability to switch between Lookup and Search
  • Loading branch information
athu-tran authored Oct 11, 2024
2 parents d815acc + 258bbab commit 0d4e248
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 44 deletions.
3 changes: 2 additions & 1 deletion src/components/AdpVulnerabilityEnrichment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@

<script>
import { usecveRecordStore } from '@/stores/cveRecord.ts';
import { useGenericGlobalsStore } from '@/stores/genericGlobals';
import ProductStatus from '@/components/ProductStatus.vue';
import CveRecordReferences from './CveRecordReferences.vue';
Expand Down Expand Up @@ -252,7 +253,7 @@ export default {
//to do
adpShortName: this.containerObject.providerMetadata.shortName,
dateUpdated: '',
cveServicesBaseUrl: import.meta.env.VITE_CVE_SERVICES_BASE_URL,
cveServicesBaseUrl: useGenericGlobalsStore().currentServicesUrl,
usecveRecordStore: usecveRecordStore(),
}
},
Expand Down
130 changes: 97 additions & 33 deletions src/components/cveRecordSearchModule.vue
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
<template>
<div class="field mt-1">
<div class="field has-addons mb-1">
<div class="field has-addons">
<div class="control">
<span v-if="websiteEnv !== 'prd'" class="select cve-search-selector">
<select v-model="searchType">
<option>Search CVE List (Beta)</option>
<option>Find a Test CVE Record/ID (Legacy)</option>
</select>
</span>
</div>
<div class="control is-expanded">
<input v-model.trim="queryString" @keyup.enter="onKeyUpEnter" @keyup="validateQueryString" type="text" class="input cve-id-input"
placeholder="Enter keywords (e.g.: CVE ID, sql injection, etc.)"/>
<input v-if="searchTypeBoolean" v-model.trim="queryString" @keyup.enter="onKeyUpEnter"
@keyup="validateQueryString" type="text" class="input cve-id-input"
placeholder="Enter keywords (e.g.: CVE ID, sql injection, etc.)" />
<input v-else v-model="cveId" @keyup.enter="onKeyUpEnter" @keyup="validateQueryString" @blur="removeHelpText"
type="text" class="input cve-id-input" placeholder="Enter CVE ID (CVE-YYYY-NNNN)" />
</div>
<div class="control">
<button @click="validate"
class="button cve-button cve-button-accent-warm"
:class="{'is-loading': cveListSearchStore.isSearching, 'disabled': cveListSearchStore.isSeachButtonDisabled}"
<button @click="validate" class="button cve-button cve-button-accent-warm"
:class="{ 'is-loading': cveListSearchStore.isSearching, 'disabled': cveListSearchStore.isSeachButtonDisabled }"
:aria-disabled="cveListSearchStore.isSeachButtonDisabled">
Search {{ websiteEnv === 'test' ? 'CVE List in Test' : ''}}
Search {{ websiteEnv === 'test' ? 'CVE List in Test' : '' }}
</button>
</div>
</div>
<div class="notification is-warning is-light" role="alert" v-if="errorMessage.length > 0">
<div class="is-flex is-align-content-flex-start">
<p id="alertIcon" class="is-hidden">alert</p>
<font-awesome-icon style="flex: 0 0 40px; margin-top:3px" size="lg" icon="exclamation-triangle" role="alert"
<font-awesome-icon style="flex: 0 0 40px; margin-top:3px" size="lg" icon="exclamation-triangle" role="alert"
aria-labelledby="alertIcon" aria-hidden="false" />
<p class="cve-help-text">
{{errorMessage}}
<router-link to="/About/Process#request"> Learn more</router-link>
</p>
<p class="cve-help-text">
{{ errorMessage }}
<router-link to="/About/Process#request"> Learn more</router-link>
</p>
</div>
</div>
</div>
Expand All @@ -32,17 +42,32 @@
import { useCveListSearchStore } from '@/stores/cveListSearch';
import { computed, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
// Legacy Search Import
import { usecveRecordStore } from '@/stores/cveRecord';
import { useGenericGlobalsStore } from '@/stores/genericGlobals';
let cveListSearchStore = useCveListSearchStore();
const route = useRoute();
const router = useRouter();
let queryString = ref('');
let errorMessage = ref('');
let cveGenericGlobalsStore = useGenericGlobalsStore();
let cveRecordStore = usecveRecordStore();
let searchType = ref('Search CVE List (Beta)');
let cveId = cveRecordStore.cveId;
// this seems redundant, but it fixes an edge case.
// if a user searches for a particular field, then on the results page flips the toggle, THEN refreshes without searching, this will keep the correct helper text showing.
let searchTypeBoolean = computed(() => {
return searchType.value == 'Search CVE List (Beta)' ? true : false;
});
watch(
() => route.query,
() => {
if (route.query?.query){
if (route.query?.query) {
queryString.value = route.query.query.trim();
validate();
} else {
Expand All @@ -54,33 +79,66 @@ watch(
function startSearch() {
if (queryString.value !== cveListSearchStore.query) {
cveListSearchStore.$reset();
cveListSearchStore.query = queryString.value;
// We only want to flip the search item _When we actually do a search_ otherwise we should default back to what we were on a page refresh
if (searchTypeBoolean.value) {
cveGenericGlobalsStore.setUseSearch(true);
cveGenericGlobalsStore.setCurrentServicesUrl(`https://${import.meta.env.VITE_CVE_SERVICES_BASE_URL}`)
}
else {
cveGenericGlobalsStore.setUseSearch(false);
cveGenericGlobalsStore.setCurrentServicesUrl(cveGenericGlobalsStore.cveServiceTestBaseUrl)
}
if (cveGenericGlobalsStore.useSearch) {
if (queryString.value !== cveListSearchStore.query) {
cveListSearchStore.$reset();
cveListSearchStore.query = queryString.value;
router.push({
name: 'SearchResults',
query: {query: cveListSearchStore.query}
query: { query: cveListSearchStore.query }
});
cveListSearchStore.search();
}
} else {
const lookupPath = `/CVERecord?id=${cveId}`;
router.push(lookupPath)
}
}
function validateQueryString() {
const alphaNumericDashPattern = new RegExp(/^[a-zA-Z0-9 ]+$/, 'i').test(queryString.value);
const cveIdPattern = new RegExp(/^CVE-\d{4}-\d{4,7}$/, 'i').test(queryString.value);
if (queryString.value.length > 0 && !alphaNumericDashPattern && !cveIdPattern) {
cveListSearchStore.isSeachButtonDisabled = true;
errorMessage.value = 'Only letters, numbers, and CVE IDs (CVE-YYYY-NNNN) are allowed.';
cveListSearchStore.showHelpText = true;
} else if (queryString.value.length === 0) {
cveListSearchStore.isSeachButtonDisabled = true;
errorMessage.value = '';
cveListSearchStore.showHelpText = false;
if (searchTypeBoolean.value) {
const alphaNumericDashPattern = new RegExp(/^[a-zA-Z0-9 ]+$/, 'i').test(queryString.value);
const cveIdPattern = new RegExp(/^CVE-\d{4}-\d{4,7}$/, 'i').test(queryString.value);
if (queryString.value.length > 0 && !alphaNumericDashPattern && !cveIdPattern) {
cveListSearchStore.isSeachButtonDisabled = true;
errorMessage.value = 'Only letters, numbers, and CVE IDs (CVE-YYYY-NNNN) are allowed.';
cveListSearchStore.showHelpText = true;
} else if (queryString.value.length === 0) {
cveListSearchStore.isSeachButtonDisabled = true;
errorMessage.value = '';
cveListSearchStore.showHelpText = false;
} else {
cveListSearchStore.isSeachButtonDisabled = false;
errorMessage.value = '';
cveListSearchStore.showHelpText = false;
}
} else {
cveListSearchStore.isSeachButtonDisabled = false;
errorMessage.value = '';
cveListSearchStore.showHelpText = false;
//Basic Checking
const cveIdPattern = new RegExp(/^CVE-\d{4}-\d{4,7}$/, 'i').test(cveId);
if (cveId.length > 0 && !cveIdPattern) {
cveListSearchStore.isSeachButtonDisabled = true;
errorMessage.value = 'Only CVE IDs (CVE-YYYY-NNNN) are allowed.';
cveListSearchStore.showHelpText = true;
} else if (cveId.length === 0) {
cveListSearchStore.isSeachButtonDisabled = true;
errorMessage.value = '';
cveListSearchStore.showHelpText = false;
} else {
cveListSearchStore.isSeachButtonDisabled = false;
errorMessage.value = '';
cveListSearchStore.showHelpText = false;
}
}
}
Expand All @@ -89,10 +147,16 @@ function onKeyUpEnter() {
}
function validate() {
validateQueryString();
if (!cveListSearchStore.isSeachButtonDisabled) {
if (cveGenericGlobalsStore.useSearch) {
if (!cveListSearchStore.isSeachButtonDisabled) {
startSearch();
}
} else {
startSearch();
}
}
const websiteEnv = computed(() => {
Expand All @@ -111,7 +175,7 @@ const websiteEnv = computed(() => {
.notification {
margin: 0 0 2px 0 !important;
padding: 2px 10px 2px 10px !important;
padding: 2px 10px 2px 10px !important;
}
@media screen and (min-width: $desktop) {
Expand Down
2 changes: 1 addition & 1 deletion src/stores/cveListSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const useCveListSearchStore = defineStore('cveListSearch ', {
const getRecordUrl = `/api/cve/${this.cveId}`;

try {
axios.defaults.baseURL = `https://${import.meta.env.VITE_CVE_SERVICES_BASE_URL}`;
axios.defaults.baseURL = useCveListSearchStore().currentServicesUrl;
const response = await axios.get(getRecordUrl);
const cveRecordData = response?.data || {};
this.isArecord = true;
Expand Down
19 changes: 17 additions & 2 deletions src/stores/genericGlobals.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import { defineStore } from 'pinia';

export const useGenericGlobalsStore = defineStore('genericGlobals', {
state: () => {
state: () => {
const storedUseSearch = sessionStorage.getItem('useSearch');
const storedCurrentServicesUrl = sessionStorage.getItem('currentServicesUrl');
return {
useSearch: storedUseSearch ? JSON.parse(storedUseSearch) : true,
currentServicesUrl: storedCurrentServicesUrl ? JSON.parse(storedCurrentServicesUrl) : `https://${import.meta.env.VITE_CVE_SERVICES_BASE_URL}`,
cveServiceTestBaseUrl: 'https://cveawg-test.mitre.org',
legacyCveWebsiteLink: 'https://cve.mitre.org/cve/search_cve_list.html'
};
},
actions: {
setUseSearch(value) {
this.useSearch = value;
sessionStorage.setItem('useSearch', JSON.stringify(value));
},
setCurrentServicesUrl(value) {
this.currentServicesUrl = value;
sessionStorage.setItem('currentServicesUrl', JSON.stringify(value));
}
}
},
});
32 changes: 29 additions & 3 deletions src/views/CVERecord/CVERecord.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@
</div>
<div v-else>
<div v-if="usecveRecordStore.isIdOrRecordFound">
<div class="notification is-warning is-light" role="alert">
<div v-if="websiteEnv !== 'prd'" class="is-flex" style="justify-content: center;">
<p id="alertIconCveRecordsRequestErrored" class="is-hidden">alert</p>
<font-awesome-icon style="flex: 0 0 40px;" size="1x" icon="triangle-exclamation" role="img"
aria-labelledby="alertIconCveRecordsRequestErrored" aria-hidden="false" />
<p>You are viewing <strong>{{ usingProd }}</strong> data from&nbsp;</p>
<a :href="resultUrl" target="_blank"> {{ resultUrl }}
<span class="icon cve-icon-xxs">
<p id="externalLinkIcon" class="is-hidden">external website</p>
<font-awesome-icon icon="up-right-from-square"
aria-labelledby="externalLinkIcon" aria-hidden="false"/>
</span>
</a>
</div>
</div>
<PublishedRecord v-if="usecveRecordStore.isPublished"/>
<RejectedRecordOrId v-if="usecveRecordStore.isRejected"/>
<ReservedId v-if="usecveRecordStore.isReserved"/>
Expand Down Expand Up @@ -77,6 +92,9 @@ export default {
},
data() {
return {
isResultFromProd: false,
// There is a special case when the website deals with some cached data. This ensures that the correct value is shown, even though it is not pretty
resultUrl: this.GenericGlobalsStore.useSearch ? `https://${import.meta.env.VITE_CVE_SERVICES_BASE_URL}` : this.GenericGlobalsStore.cveServiceTestBaseUrl,
usecveRecordStore: usecveRecordStore(),
cveId: usecveRecordStore().cveId,
showHelpText: false,
Expand All @@ -87,6 +105,9 @@ export default {
};
},
computed: {
usingProd() {
return this.isResultFromProd ? 'Production' : 'Test'
},
isSearching() {
return usecveRecordStore().isSearching;
},
Expand Down Expand Up @@ -207,7 +228,7 @@ export default {
const getIdUrl = `/api/cve-id/${usecveRecordStore().cveId}`;
try {
axios.defaults.baseURL = `https://${import.meta.env.VITE_CVE_SERVICES_BASE_URL}`;
axios.defaults.baseURL = this.GenericGlobalsStore.currentServicesUrl;
const idData = await axios.get(getIdUrl);
this.getIdStatusCode = 200;
if (idData.status === 200 && idData?.data?.error === undefined) {
Expand Down Expand Up @@ -243,9 +264,14 @@ export default {
}
},
async getRecordData() {
const getRecordUrl = `https://${import.meta.env.VITE_CVE_SERVICES_BASE_URL}/api/cve/${usecveRecordStore().cveId}`;
const getRecordUrl = `${this.GenericGlobalsStore.currentServicesUrl}/api/cve/${usecveRecordStore().cveId}`;
if (this.GenericGlobalsStore.useSearch) {
this.isResultFromProd = true;
} else {
this.isResultFromProd = false;
}
this.resultUrl = this.GenericGlobalsStore.currentServicesUrl
const recordData = await axios.get(getRecordUrl);
if (!(typeof (recordData.data) === 'object')) {
usecveRecordStore().isPublished = false;
usecveRecordStore().isReserved = false;
Expand Down
2 changes: 1 addition & 1 deletion src/views/CVERecord/PublishedRecord.vue
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export default {
tags: [],
},
originalRecordData: usecveRecordStore().recordData || {},
cveServicesBaseUrl: import.meta.env.VITE_CVE_SERVICES_BASE_URL,
cveServicesBaseUrl: this.GenericGlobalsStore.currentServicesUrl,
usecveRecordStore: usecveRecordStore(),
cpe: {},
cnaContainer: {},
Expand Down
2 changes: 1 addition & 1 deletion src/views/CVERecord/RejectedRecordOrId.vue
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export default {
},
originalRecordData: usecveRecordStore().recordData || {},
originalIdData: usecveRecordStore().idData || {},
cveServicesBaseUrl: import.meta.env.VITE_CVE_SERVICES_BASE_URL,
cveServicesBaseUrl: this.GenericGlobalsStore.currentServicesUrl,
usecveRecordStore: usecveRecordStore()
};
},
Expand Down
2 changes: 1 addition & 1 deletion src/views/CVERecord/ReservedId.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export default {
data() {
return {
isMessageExpanded: false,
cveServicesBaseUrl: import.meta.env.VITE_CVE_SERVICES_BASE_URL,
cveServicesBaseUrl: this.GenericGlobalsStore.currentServicesUrl,
usecveRecordStore: usecveRecordStore()
};
},
Expand Down
3 changes: 2 additions & 1 deletion src/views/ReportRequest/ReportRequestForNonCNAs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ export default {
components: {
NavigationSidebar,
SurveyLinkComponent,
ServiceUnavailable
// NOTE(drocca): This was throwing a linting error, however, this is not something I touched. It was being flagged for being registered and not being used.
//ServiceUnavailable
},
data() {
return {
Expand Down

0 comments on commit 0d4e248

Please sign in to comment.