1use serde_json::{json, Value};
4use tracing::debug;
5
6use crate::client::MispClient;
7use crate::error::MispError;
8use crate::models::{Attribute, Event, Galaxy, Tag};
9
10#[derive(Clone)]
11pub struct EventsClient {
12 client: MispClient,
13}
14
15impl EventsClient {
16 pub fn new(client: MispClient) -> Self {
17 Self { client }
18 }
19
20 pub async fn get(&self, id: &str) -> Result<Event, MispError> {
21 debug!(%id, "Fetching event");
22 let resp = self.client.get(&format!("/events/view/{}", id)).await?;
23 parse_event_response(resp)
24 }
25
26 pub async fn get_by_uuid(&self, uuid: &str) -> Result<Event, MispError> {
27 self.get(uuid).await
28 }
29
30 pub async fn index(&self, params: Option<EventIndexParams>) -> Result<Vec<Event>, MispError> {
31 debug!("Listing events");
32 let body = params.map(|p| p.to_json());
33 let resp = self.client.post("/events/index", body).await?;
34 parse_events_list(resp)
35 }
36
37 pub async fn search(&self, query: EventSearchQuery) -> Result<Vec<Event>, MispError> {
38 debug!("Searching events");
39 let resp = self
40 .client
41 .post("/events/restSearch", Some(query.to_json()))
42 .await?;
43 parse_rest_search_events(resp)
44 }
45
46 pub async fn get_tags(&self, event_id: &str) -> Result<Vec<Tag>, MispError> {
47 let event = self.get(event_id).await?;
48 Ok(event.tags)
49 }
50
51 pub async fn get_attributes(&self, event_id: &str) -> Result<Vec<Attribute>, MispError> {
52 let event = self.get(event_id).await?;
53 Ok(event.attributes)
54 }
55
56 pub async fn get_galaxies(&self, event_id: &str) -> Result<Vec<Galaxy>, MispError> {
57 let event = self.get(event_id).await?;
58 Ok(event.galaxies)
59 }
60}
61
62impl std::fmt::Debug for EventsClient {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 f.debug_struct("EventsClient").finish()
65 }
66}
67
68#[derive(Debug, Default, Clone)]
69pub struct EventIndexParams {
70 pub limit: Option<u32>,
71 pub page: Option<u32>,
72 pub sort: Option<String>,
73 pub direction: Option<String>,
74 pub minimal: Option<bool>,
75 pub published: Option<bool>,
76 pub org: Option<String>,
77 pub tags: Option<Vec<String>>,
78 pub from: Option<String>,
79 pub to: Option<String>,
80}
81
82impl EventIndexParams {
83 pub fn new() -> Self {
84 Self::default()
85 }
86
87 pub fn limit(mut self, limit: u32) -> Self {
88 self.limit = Some(limit);
89 self
90 }
91
92 pub fn page(mut self, page: u32) -> Self {
93 self.page = Some(page);
94 self
95 }
96
97 pub fn published(mut self, published: bool) -> Self {
98 self.published = Some(published);
99 self
100 }
101
102 pub fn tags(mut self, tags: Vec<String>) -> Self {
103 self.tags = Some(tags);
104 self
105 }
106
107 pub fn from_date(mut self, from: impl Into<String>) -> Self {
108 self.from = Some(from.into());
109 self
110 }
111
112 pub fn to_date(mut self, to: impl Into<String>) -> Self {
113 self.to = Some(to.into());
114 self
115 }
116
117 fn to_json(&self) -> Value {
118 let mut obj = serde_json::Map::new();
119 if let Some(v) = self.limit {
120 obj.insert("limit".into(), json!(v));
121 }
122 if let Some(v) = self.page {
123 obj.insert("page".into(), json!(v));
124 }
125 if let Some(ref v) = self.sort {
126 obj.insert("sort".into(), json!(v));
127 }
128 if let Some(ref v) = self.direction {
129 obj.insert("direction".into(), json!(v));
130 }
131 if let Some(v) = self.minimal {
132 obj.insert("minimal".into(), json!(v));
133 }
134 if let Some(v) = self.published {
135 obj.insert("published".into(), json!(v));
136 }
137 if let Some(ref v) = self.org {
138 obj.insert("org".into(), json!(v));
139 }
140 if let Some(ref v) = self.tags {
141 obj.insert("tags".into(), json!(v));
142 }
143 if let Some(ref v) = self.from {
144 obj.insert("from".into(), json!(v));
145 }
146 if let Some(ref v) = self.to {
147 obj.insert("to".into(), json!(v));
148 }
149 Value::Object(obj)
150 }
151}
152
153#[derive(Debug, Default, Clone)]
154pub struct EventSearchQuery {
155 pub value: Option<String>,
156 pub event_id: Option<String>,
157 pub tags: Option<Vec<String>>,
158 pub not_tags: Option<Vec<String>>,
159 pub org: Option<String>,
160 pub from: Option<String>,
161 pub to: Option<String>,
162 pub last: Option<String>,
163 pub published: Option<bool>,
164 pub threat_level: Option<Vec<u8>>,
165 pub analysis: Option<Vec<u8>>,
166 pub include_attribute: Option<bool>,
167 pub include_galaxy: Option<bool>,
168 pub limit: Option<u32>,
169 pub page: Option<u32>,
170}
171
172impl EventSearchQuery {
173 pub fn new() -> Self {
174 Self::default()
175 }
176
177 pub fn value(mut self, v: impl Into<String>) -> Self {
178 self.value = Some(v.into());
179 self
180 }
181
182 pub fn event_id(mut self, id: impl Into<String>) -> Self {
183 self.event_id = Some(id.into());
184 self
185 }
186
187 pub fn tags(mut self, tags: Vec<String>) -> Self {
188 self.tags = Some(tags);
189 self
190 }
191
192 pub fn exclude_tags(mut self, tags: Vec<String>) -> Self {
193 self.not_tags = Some(tags);
194 self
195 }
196
197 pub fn org(mut self, org: impl Into<String>) -> Self {
198 self.org = Some(org.into());
199 self
200 }
201
202 pub fn from_date(mut self, from: impl Into<String>) -> Self {
203 self.from = Some(from.into());
204 self
205 }
206
207 pub fn to_date(mut self, to: impl Into<String>) -> Self {
208 self.to = Some(to.into());
209 self
210 }
211
212 pub fn last(mut self, duration: impl Into<String>) -> Self {
213 self.last = Some(duration.into());
214 self
215 }
216
217 pub fn published(mut self, published: bool) -> Self {
218 self.published = Some(published);
219 self
220 }
221
222 pub fn threat_level(mut self, levels: Vec<u8>) -> Self {
223 self.threat_level = Some(levels);
224 self
225 }
226
227 pub fn include_attributes(mut self) -> Self {
228 self.include_attribute = Some(true);
229 self
230 }
231
232 pub fn include_galaxies(mut self) -> Self {
233 self.include_galaxy = Some(true);
234 self
235 }
236
237 pub fn limit(mut self, limit: u32) -> Self {
238 self.limit = Some(limit);
239 self
240 }
241
242 pub fn page(mut self, page: u32) -> Self {
243 self.page = Some(page);
244 self
245 }
246
247 fn to_json(&self) -> Value {
248 let mut obj = serde_json::Map::new();
249 if let Some(ref v) = self.value {
250 obj.insert("value".into(), json!(v));
251 }
252 if let Some(ref v) = self.event_id {
253 obj.insert("eventid".into(), json!(v));
254 }
255 if let Some(ref v) = self.tags {
256 obj.insert("tags".into(), json!(v));
257 }
258 if let Some(ref v) = self.not_tags {
259 obj.insert("not_tags".into(), json!(v));
260 }
261 if let Some(ref v) = self.org {
262 obj.insert("org".into(), json!(v));
263 }
264 if let Some(ref v) = self.from {
265 obj.insert("from".into(), json!(v));
266 }
267 if let Some(ref v) = self.to {
268 obj.insert("to".into(), json!(v));
269 }
270 if let Some(ref v) = self.last {
271 obj.insert("last".into(), json!(v));
272 }
273 if let Some(v) = self.published {
274 obj.insert("published".into(), json!(v));
275 }
276 if let Some(ref v) = self.threat_level {
277 obj.insert("threat_level_id".into(), json!(v));
278 }
279 if let Some(ref v) = self.analysis {
280 obj.insert("analysis".into(), json!(v));
281 }
282 if let Some(v) = self.include_attribute {
283 obj.insert("includeAttribute".into(), json!(v));
284 }
285 if let Some(v) = self.include_galaxy {
286 obj.insert("includeGalaxy".into(), json!(v));
287 }
288 if let Some(v) = self.limit {
289 obj.insert("limit".into(), json!(v));
290 }
291 if let Some(v) = self.page {
292 obj.insert("page".into(), json!(v));
293 }
294 Value::Object(obj)
295 }
296}
297
298fn parse_event_response(resp: Value) -> Result<Event, MispError> {
299 if let Some(event) = resp.get("Event") {
300 return serde_json::from_value(event.clone()).map_err(MispError::Parse);
301 }
302 Err(MispError::InvalidResponse("missing Event wrapper".into()))
303}
304
305fn parse_events_list(resp: Value) -> Result<Vec<Event>, MispError> {
306 if let Some(arr) = resp.as_array() {
307 let events: Result<Vec<Event>, _> = arr
308 .iter()
309 .map(|v| {
310 let event_val = v.get("Event").unwrap_or(v);
311 serde_json::from_value(event_val.clone())
312 })
313 .collect();
314 return events.map_err(MispError::Parse);
315 }
316 Err(MispError::InvalidResponse("expected array".into()))
317}
318
319fn parse_rest_search_events(resp: Value) -> Result<Vec<Event>, MispError> {
320 if let Some(response) = resp.get("response") {
321 if let Some(arr) = response.as_array() {
322 let events: Result<Vec<Event>, _> = arr
323 .iter()
324 .map(|v| {
325 let event_val = v.get("Event").unwrap_or(v);
326 serde_json::from_value(event_val.clone())
327 })
328 .collect();
329 return events.map_err(MispError::Parse);
330 }
331 }
332 if resp.as_array().is_some() {
333 return parse_events_list(resp);
334 }
335 Err(MispError::InvalidResponse(
336 "unexpected response format".into(),
337 ))
338}