in_toto/models/layout/
metadata.rs

1//! in-toto layoput metadata.
2
3use chrono::{DateTime, Duration, Utc};
4use serde::de::{Deserialize, Deserializer, Error as DeserializeError};
5use serde::ser::{Error as SerializeError, Serialize, Serializer};
6
7use std::collections::HashMap;
8
9use crate::crypto::KeyId;
10use crate::crypto::PublicKey;
11use crate::interchange::{DataInterchange, Json};
12use crate::models::{Metadata, MetadataType, MetadataWrapper};
13use crate::Result;
14
15use super::Layout;
16use super::{inspection::Inspection, step::Step};
17
18/// Helper to construct `LayoutMetadata`
19pub struct LayoutMetadataBuilder {
20    expires: DateTime<Utc>,
21    readme: String,
22    keys: HashMap<KeyId, PublicKey>,
23    steps: Vec<Step>,
24    inspect: Vec<Inspection>,
25}
26
27impl Default for LayoutMetadataBuilder {
28    fn default() -> Self {
29        LayoutMetadataBuilder::new()
30    }
31}
32
33impl LayoutMetadataBuilder {
34    /// Create a new `LayoutMetadataBuilder`. It defaults to:
35    ///
36    /// * expires: 365 days from the current time.
37    /// * readme: ""
38    pub fn new() -> Self {
39        LayoutMetadataBuilder {
40            steps: Vec::new(),
41            inspect: Vec::new(),
42            keys: HashMap::new(),
43            expires: Utc::now() + Duration::days(365),
44            readme: String::new(),
45        }
46    }
47
48    /// Set expire time for this layout
49    pub fn expires(mut self, expires: DateTime<Utc>) -> Self {
50        self.expires = expires;
51        self
52    }
53
54    /// Set readme field fot this layout
55    pub fn readme(mut self, readme: String) -> Self {
56        self.readme = readme;
57        self
58    }
59
60    /// Add new step to this layout
61    pub fn add_step(mut self, step: Step) -> Self {
62        self.steps.push(step);
63        self
64    }
65
66    /// Add new steps to this layout
67    pub fn add_steps(mut self, mut steps: Vec<Step>) -> Self {
68        self.steps.append(&mut steps);
69        self
70    }
71
72    /// Set steps to this layout
73    pub fn steps(mut self, steps: Vec<Step>) -> Self {
74        self.steps = steps;
75        self
76    }
77
78    /// Add new inspect to this layout
79    pub fn add_inspect(mut self, inspect: Inspection) -> Self {
80        self.inspect.push(inspect);
81        self
82    }
83
84    /// Add new inspects to this layout
85    pub fn add_inspects(mut self, mut inspects: Vec<Inspection>) -> Self {
86        self.inspect.append(&mut inspects);
87        self
88    }
89
90    /// Set inspects to this layout
91    pub fn inspects(mut self, step: Vec<Inspection>) -> Self {
92        self.inspect = step;
93        self
94    }
95
96    /// Add a new pubkey to this layout
97    pub fn add_key(mut self, key: PublicKey) -> Self {
98        self.keys.insert(key.key_id().clone(), key);
99        self
100    }
101
102    pub fn build(self) -> Result<LayoutMetadata> {
103        Ok(LayoutMetadata::new(
104            self.expires,
105            self.readme,
106            self.keys,
107            self.steps,
108            self.inspect,
109        ))
110    }
111}
112
113/// layout metadata
114#[derive(Debug, Clone, PartialEq, Eq)]
115pub struct LayoutMetadata {
116    pub steps: Vec<Step>,
117    pub inspect: Vec<Inspection>,
118    pub keys: HashMap<KeyId, PublicKey>,
119    pub expires: DateTime<Utc>,
120    pub readme: String,
121}
122
123impl LayoutMetadata {
124    pub fn new(
125        expires: DateTime<Utc>,
126        readme: String,
127        keys: HashMap<KeyId, PublicKey>,
128        steps: Vec<Step>,
129        inspect: Vec<Inspection>,
130    ) -> Self {
131        LayoutMetadata {
132            steps,
133            inspect,
134            keys,
135            expires,
136            readme,
137        }
138    }
139}
140
141impl Metadata for LayoutMetadata {
142    fn typ(&self) -> MetadataType {
143        MetadataType::Layout
144    }
145
146    fn into_enum(self: Box<Self>) -> MetadataWrapper {
147        MetadataWrapper::Layout(*self)
148    }
149
150    fn to_bytes(&self) -> Result<Vec<u8>> {
151        Json::canonicalize(&Json::serialize(self)?)
152    }
153}
154
155impl Serialize for LayoutMetadata {
156    fn serialize<S>(&self, ser: S) -> ::std::result::Result<S::Ok, S::Error>
157    where
158        S: Serializer,
159    {
160        Layout::from(self)
161            .map_err(|e| SerializeError::custom(format!("{:?}", e)))?
162            .serialize(ser)
163    }
164}
165
166impl<'de> Deserialize<'de> for LayoutMetadata {
167    fn deserialize<D: Deserializer<'de>>(
168        de: D,
169    ) -> ::std::result::Result<Self, D::Error> {
170        let intermediate: Layout = Deserialize::deserialize(de)?;
171        intermediate
172            .try_into()
173            .map_err(|e| DeserializeError::custom(format!("{:?}", e)))
174    }
175}