@@ -21,8 +21,23 @@ export class SearchOptions {
2121 sort : { } [ ] ;
2222 from : number ;
2323 size : number ;
24+ searchFields : Array < string > ;
25+ filters : Array < object > ;
26+ resultsPerPage : number ;
27+ rangeObjects : Array < rangeObject >
28+ rangeStart : Date ;
29+ rangeEnd : Date ;
30+ rangeField : string ;
31+
2432}
2533
34+ //support for date ranges
35+ export class rangeObject {
36+ rangeField : string ;
37+ rangeStart : Date ;
38+ rangeEnd : Date ;
39+
40+ }
2641
2742/** A manager class that provides basic search capabilities
2843 * including a flexible search() that provides consistent
@@ -68,4 +83,121 @@ export class BasicSearchManager {
6883 return result
6984 }
7085
86+ /** search for text at search provider
87+ * @param searchText the text string to search for
88+ * @param options options to specify how to search, with well-defined defaults
89+ */
90+ async apiSearch ( searchText : string , options : Partial < SearchOptions > = undefined , queryStrings ?: Array < object > ) : Promise < CveResult > {
91+ let response = undefined ;
92+
93+ if ( ! options ) {
94+ options = {
95+ useCache : true ,
96+ searchFields : null ,
97+ filters : null ,
98+ resultsPerPage : 20 ,
99+ rangeObjects : null ,
100+ rangeStart : null ,
101+ rangeEnd : null ,
102+ rangeField : null ,
103+ track_total_hits : true ,
104+ default_operator : "AND" ,
105+ metadataOnly : false ,
106+ fields : [ ]
107+ } ;
108+ }
109+
110+ let validateResult = this . validateSearchText ( searchText , options . filters )
111+
112+ //Build range object to add to the query
113+ let rangeObj = null ;
114+ let rangeArray = [ ] ;
115+
116+ if ( options . rangeObjects ) {
117+ options . rangeObjects . forEach ( rangeObject => {
118+ rangeObj = {
119+ range : {
120+ [ rangeObject . rangeField ] : {
121+ "gte" : rangeObject . rangeStart ,
122+ "lte" : rangeObject . rangeEnd ,
123+ }
124+ }
125+ } ;
126+ rangeArray . push ( rangeObj ) ;
127+ } )
128+
129+ }
130+ //Build query object
131+ const queryObj = {
132+ must : [ ] ,
133+ filter : [
134+ ...options . filters
135+ ] ,
136+ } ;
137+
138+ //Add rangeObj only if it exists
139+ if ( rangeArray ) {
140+ queryObj . filter . push ( ...rangeArray ) ;
141+ }
142+
143+ if ( searchText != null ) {
144+ queryObj . must = [
145+ {
146+ query_string : {
147+ query : searchText ,
148+ fields : [ "containers.cna.descriptions.value" ]
149+ } ,
150+ }
151+ ] ;
152+ }
153+
154+ //Add query_string only if there is text to search
155+ else if ( queryStrings != null ) {
156+ queryObj . must = [
157+ ...queryStrings
158+ ] ;
159+ } else {
160+ delete queryObj . must
161+ }
162+
163+ if ( validateResult . isOk ( ) ) {
164+
165+ response = await this . _searchReader . _client . search ( {
166+ index : this . _searchReader . _cveIndex ,
167+ body : {
168+ query : {
169+ bool : queryObj
170+
171+ } ,
172+ track_total_hits : true ,
173+ size : options . resultsPerPage
174+ }
175+ } ) ;
176+
177+ return CveResult . ok ( response . body as SearchResultData ) ;
178+ }
179+ else {
180+ // return CveResult.error(new CveError(1, `Unknown error when searching for ${text}`));
181+ return validateResult
182+ }
183+ }
184+
185+ /** validates search text string and marks up CveResult
186+ * with errors and/or notes, if any
187+ */
188+ // @todo
189+ validateSearchText ( text : string , filters : Array < object > ) : CveResult {
190+
191+ let result : CveResult
192+ if ( ! text && ! filters ) {
193+ result = CveResult . error ( 9002 )
194+ }
195+ else {
196+ result = CveResult . ok ( "" , [ "no validation was done" ] )
197+ }
198+
199+ return result
200+ }
201+
202+
71203}
0 commit comments