1use crate::attributes::{AttributeSearchQuery, AttributesClient};
4use crate::error::MispError;
5use crate::events::{EventSearchQuery, EventsClient};
6use crate::models::{Attribute, Event};
7
8pub struct SearchBuilder<'a> {
9 events_client: &'a EventsClient,
10 attributes_client: &'a AttributesClient,
11}
12
13impl<'a> SearchBuilder<'a> {
14 pub fn new(events: &'a EventsClient, attributes: &'a AttributesClient) -> Self {
15 Self {
16 events_client: events,
17 attributes_client: attributes,
18 }
19 }
20
21 pub fn ioc(&self, value: &str) -> IocSearch<'a> {
22 IocSearch {
23 attributes_client: self.attributes_client,
24 value: value.to_string(),
25 attr_types: None,
26 tags: None,
27 not_tags: None,
28 from: None,
29 to: None,
30 to_ids_only: false,
31 include_sightings: false,
32 include_galaxies: false,
33 limit: None,
34 }
35 }
36
37 pub fn by_tag(&self, tag: &str) -> TagSearch<'a> {
38 TagSearch {
39 events_client: self.events_client,
40 attributes_client: self.attributes_client,
41 tags: vec![tag.to_string()],
42 not_tags: Vec::new(),
43 from: None,
44 to: None,
45 published_only: false,
46 limit: None,
47 }
48 }
49
50 pub fn recent(&self, duration: &str) -> RecentSearch<'a> {
51 RecentSearch {
52 events_client: self.events_client,
53 attributes_client: self.attributes_client,
54 duration: duration.to_string(),
55 tags: None,
56 attr_types: None,
57 to_ids_only: false,
58 limit: None,
59 }
60 }
61
62 pub fn threat_actor(&self, name: &str) -> ThreatActorSearch<'a> {
63 ThreatActorSearch {
64 events_client: self.events_client,
65 actor_name: name.to_string(),
66 include_attributes: true,
67 limit: None,
68 }
69 }
70}
71
72pub struct IocSearch<'a> {
73 attributes_client: &'a AttributesClient,
74 value: String,
75 attr_types: Option<Vec<String>>,
76 tags: Option<Vec<String>>,
77 not_tags: Option<Vec<String>>,
78 from: Option<String>,
79 to: Option<String>,
80 to_ids_only: bool,
81 include_sightings: bool,
82 include_galaxies: bool,
83 limit: Option<u32>,
84}
85
86impl<'a> IocSearch<'a> {
87 pub fn types(mut self, types: Vec<&str>) -> Self {
88 self.attr_types = Some(types.into_iter().map(String::from).collect());
89 self
90 }
91
92 pub fn tags(mut self, tags: Vec<&str>) -> Self {
93 self.tags = Some(tags.into_iter().map(String::from).collect());
94 self
95 }
96
97 pub fn exclude_tags(mut self, tags: Vec<&str>) -> Self {
98 self.not_tags = Some(tags.into_iter().map(String::from).collect());
99 self
100 }
101
102 pub fn from_date(mut self, from: &str) -> Self {
103 self.from = Some(from.to_string());
104 self
105 }
106
107 pub fn to_date(mut self, to: &str) -> Self {
108 self.to = Some(to.to_string());
109 self
110 }
111
112 pub fn to_ids_only(mut self) -> Self {
113 self.to_ids_only = true;
114 self
115 }
116
117 pub fn with_sightings(mut self) -> Self {
118 self.include_sightings = true;
119 self
120 }
121
122 pub fn with_galaxies(mut self) -> Self {
123 self.include_galaxies = true;
124 self
125 }
126
127 pub fn limit(mut self, limit: u32) -> Self {
128 self.limit = Some(limit);
129 self
130 }
131
132 pub async fn execute(self) -> Result<Vec<Attribute>, MispError> {
133 let mut query = AttributeSearchQuery::new().value(&self.value);
134
135 if let Some(tags) = self.tags {
136 query = query.tags(tags);
137 }
138 if let Some(not_tags) = self.not_tags {
139 query = query.exclude_tags(not_tags);
140 }
141 if let Some(from) = self.from {
142 query = query.from_date(from);
143 }
144 if let Some(to) = self.to {
145 query = query.to_date(to);
146 }
147 if self.to_ids_only {
148 query = query.to_ids(true);
149 }
150 if self.include_sightings {
151 query = query.include_sightings();
152 }
153 if self.include_galaxies {
154 query = query.include_galaxy();
155 }
156 if let Some(limit) = self.limit {
157 query = query.limit(limit);
158 }
159
160 let mut results = self.attributes_client.search(query).await?;
161
162 if let Some(ref types) = self.attr_types {
163 results.retain(|a| types.contains(&a.attr_type));
164 }
165
166 Ok(results)
167 }
168}
169
170pub struct TagSearch<'a> {
171 events_client: &'a EventsClient,
172 attributes_client: &'a AttributesClient,
173 tags: Vec<String>,
174 not_tags: Vec<String>,
175 from: Option<String>,
176 to: Option<String>,
177 published_only: bool,
178 limit: Option<u32>,
179}
180
181impl<'a> TagSearch<'a> {
182 pub fn and_tag(mut self, tag: &str) -> Self {
183 self.tags.push(tag.to_string());
184 self
185 }
186
187 pub fn exclude_tag(mut self, tag: &str) -> Self {
188 self.not_tags.push(tag.to_string());
189 self
190 }
191
192 pub fn from_date(mut self, from: &str) -> Self {
193 self.from = Some(from.to_string());
194 self
195 }
196
197 pub fn to_date(mut self, to: &str) -> Self {
198 self.to = Some(to.to_string());
199 self
200 }
201
202 pub fn published_only(mut self) -> Self {
203 self.published_only = true;
204 self
205 }
206
207 pub fn limit(mut self, limit: u32) -> Self {
208 self.limit = Some(limit);
209 self
210 }
211
212 pub async fn events(self) -> Result<Vec<Event>, MispError> {
213 let mut query = EventSearchQuery::new().tags(self.tags.clone());
214
215 if !self.not_tags.is_empty() {
216 query = query.exclude_tags(self.not_tags.clone());
217 }
218 if let Some(from) = self.from.clone() {
219 query = query.from_date(from);
220 }
221 if let Some(to) = self.to.clone() {
222 query = query.to_date(to);
223 }
224 if self.published_only {
225 query = query.published(true);
226 }
227 if let Some(limit) = self.limit {
228 query = query.limit(limit);
229 }
230
231 self.events_client.search(query).await
232 }
233
234 pub async fn attributes(self) -> Result<Vec<Attribute>, MispError> {
235 let mut query = AttributeSearchQuery::new().tags(self.tags.clone());
236
237 if !self.not_tags.is_empty() {
238 query = query.exclude_tags(self.not_tags.clone());
239 }
240 if let Some(from) = self.from.clone() {
241 query = query.from_date(from);
242 }
243 if let Some(to) = self.to.clone() {
244 query = query.to_date(to);
245 }
246 if self.published_only {
247 query = query.published(true);
248 }
249 if let Some(limit) = self.limit {
250 query = query.limit(limit);
251 }
252
253 self.attributes_client.search(query).await
254 }
255}
256
257pub struct RecentSearch<'a> {
258 events_client: &'a EventsClient,
259 attributes_client: &'a AttributesClient,
260 duration: String,
261 tags: Option<Vec<String>>,
262 attr_types: Option<Vec<String>>,
263 to_ids_only: bool,
264 limit: Option<u32>,
265}
266
267impl<'a> RecentSearch<'a> {
268 pub fn tags(mut self, tags: Vec<&str>) -> Self {
269 self.tags = Some(tags.into_iter().map(String::from).collect());
270 self
271 }
272
273 pub fn types(mut self, types: Vec<&str>) -> Self {
274 self.attr_types = Some(types.into_iter().map(String::from).collect());
275 self
276 }
277
278 pub fn to_ids_only(mut self) -> Self {
279 self.to_ids_only = true;
280 self
281 }
282
283 pub fn limit(mut self, limit: u32) -> Self {
284 self.limit = Some(limit);
285 self
286 }
287
288 pub async fn events(self) -> Result<Vec<Event>, MispError> {
289 let mut query = EventSearchQuery::new().last(&self.duration);
290
291 if let Some(tags) = self.tags.clone() {
292 query = query.tags(tags);
293 }
294 if let Some(limit) = self.limit {
295 query = query.limit(limit);
296 }
297
298 self.events_client.search(query).await
299 }
300
301 pub async fn attributes(self) -> Result<Vec<Attribute>, MispError> {
302 let mut query = AttributeSearchQuery::new().last(&self.duration);
303
304 if let Some(tags) = self.tags.clone() {
305 query = query.tags(tags);
306 }
307 if self.to_ids_only {
308 query = query.to_ids(true);
309 }
310 if let Some(limit) = self.limit {
311 query = query.limit(limit);
312 }
313
314 let mut results = self.attributes_client.search(query).await?;
315
316 if let Some(ref types) = self.attr_types {
317 results.retain(|a| types.contains(&a.attr_type));
318 }
319
320 Ok(results)
321 }
322}
323
324pub struct ThreatActorSearch<'a> {
325 events_client: &'a EventsClient,
326 actor_name: String,
327 include_attributes: bool,
328 limit: Option<u32>,
329}
330
331impl<'a> ThreatActorSearch<'a> {
332 pub fn without_attributes(mut self) -> Self {
333 self.include_attributes = false;
334 self
335 }
336
337 pub fn limit(mut self, limit: u32) -> Self {
338 self.limit = Some(limit);
339 self
340 }
341
342 pub async fn execute(self) -> Result<Vec<Event>, MispError> {
343 let tag = format!("misp-galaxy:threat-actor=\"{}\"", self.actor_name);
344 let mut query = EventSearchQuery::new().tags(vec![tag]);
345
346 if self.include_attributes {
347 query = query.include_attributes();
348 }
349 if let Some(limit) = self.limit {
350 query = query.limit(limit);
351 }
352
353 self.events_client.search(query).await
354 }
355}