walker_extras/visitors/send/
csaf.rs

1use super::*;
2use crate::csaf::{
3    retrieve::{RetrievalContext, RetrievedAdvisory, RetrievedVisitor},
4    validation::{ValidatedAdvisory, ValidatedVisitor, ValidationContext, ValidationError},
5};
6use csaf_walker::{discover::DiscoveredAdvisory, source::Source};
7use walker_common::retrieve::RetrievalError;
8
9#[derive(Debug, thiserror::Error)]
10pub enum SendRetrievedAdvisoryError<S: Source> {
11    #[error(transparent)]
12    Store(#[from] SendError),
13    #[error(transparent)]
14    Retrieval(#[from] RetrievalError<DiscoveredAdvisory, S>),
15}
16
17impl<S: Source> RetrievedVisitor<S> for SendVisitor {
18    type Error = SendRetrievedAdvisoryError<S>;
19    type Context = ();
20
21    async fn visit_context(&self, _: &RetrievalContext<'_>) -> Result<Self::Context, Self::Error> {
22        Ok(())
23    }
24
25    async fn visit_advisory(
26        &self,
27        _context: &Self::Context,
28        result: Result<RetrievedAdvisory, RetrievalError<DiscoveredAdvisory, S>>,
29    ) -> Result<(), Self::Error> {
30        self.send_retrieved_advisory(result?).await?;
31        Ok(())
32    }
33}
34
35#[derive(Debug, thiserror::Error)]
36pub enum SendValidatedAdvisoryError<S: Source> {
37    #[error(transparent)]
38    Store(#[from] SendError),
39    #[error(transparent)]
40    Validation(#[from] ValidationError<S>),
41}
42
43impl<S: Source> ValidatedVisitor<S> for SendVisitor {
44    type Error = SendValidatedAdvisoryError<S>;
45    type Context = ();
46
47    async fn visit_context(&self, _: &ValidationContext<'_>) -> Result<Self::Context, Self::Error> {
48        Ok(())
49    }
50
51    async fn visit_advisory(
52        &self,
53        _context: &Self::Context,
54        result: Result<ValidatedAdvisory, ValidationError<S>>,
55    ) -> Result<(), Self::Error> {
56        self.send_retrieved_advisory(result?.retrieved).await?;
57        Ok(())
58    }
59}
60
61impl SendVisitor {
62    async fn send_retrieved_advisory(&self, advisory: RetrievedAdvisory) -> Result<(), SendError> {
63        log::debug!(
64            "Sending: {} (modified: {:?})",
65            advisory.url,
66            advisory.metadata.last_modification
67        );
68
69        let RetrievedAdvisory {
70            data,
71            discovered: DiscoveredAdvisory { url, .. },
72            ..
73        } = advisory;
74
75        self.send_advisory(url.as_str(), data).await
76    }
77
78    pub async fn send_advisory(&self, name: &str, data: Bytes) -> Result<(), SendError> {
79        self.send(name, data, |request| {
80            request.header(header::CONTENT_TYPE, "application/json")
81        })
82        .await
83    }
84}