crev_data/proof/
trust.rs

1use crate::{
2    proof::{self, content::ValidationResult, CommonOps, Content},
3    serde_content_serialize, serde_draft_serialize, Error, Level, ParseError, Result,
4};
5
6use derive_builder::Builder;
7use serde::{Deserialize, Serialize};
8
9use std::fmt;
10
11use super::{OverrideItem, OverrideItemDraft};
12
13const CURRENT_TRUST_PROOF_SERIALIZATION_VERSION: i64 = -1;
14
15fn cur_version() -> i64 {
16    CURRENT_TRUST_PROOF_SERIALIZATION_VERSION
17}
18
19#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq, Default)]
20#[serde(rename_all = "lowercase")]
21pub enum TrustLevel {
22    Distrust,
23    None,
24    Low,
25    #[default]
26    Medium,
27    High,
28}
29
30impl fmt::Display for TrustLevel {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        use TrustLevel::*;
33        f.pad(match self {
34            Distrust => "distrust",
35            None => "none",
36            Low => "low",
37            Medium => "medium",
38            High => "high",
39        })
40    }
41}
42
43#[derive(thiserror::Error, Debug)]
44#[error("Can't convert string to TrustLevel. Possible values are: \"none\" or \"untrust\", \"low\", \"medium\", \"high\" and \"distrust\".")]
45pub struct FromStrErr;
46
47impl std::str::FromStr for TrustLevel {
48    type Err = FromStrErr;
49
50    fn from_str(s: &str) -> std::result::Result<TrustLevel, FromStrErr> {
51        Ok(match s {
52            "none" | "untrust" => TrustLevel::None,
53            "low" => TrustLevel::Low,
54            "medium" => TrustLevel::Medium,
55            "high" => TrustLevel::High,
56            "distrust" => TrustLevel::Distrust,
57            _ => return Err(FromStrErr),
58        })
59    }
60}
61
62impl std::convert::From<Level> for TrustLevel {
63    fn from(l: Level) -> Self {
64        match l {
65            Level::None => TrustLevel::None,
66            Level::Low => TrustLevel::Low,
67            Level::Medium => TrustLevel::Medium,
68            Level::High => TrustLevel::High,
69        }
70    }
71}
72
73impl TrustLevel {
74    #[allow(unused)]
75    fn from_str(s: &str) -> Result<TrustLevel> {
76        Ok(match s {
77            "distrust" => TrustLevel::Distrust,
78            "none" => TrustLevel::None,
79            "low" => TrustLevel::Low,
80            "medium" => TrustLevel::Medium,
81            "high" => TrustLevel::High,
82            _ => return Err(Error::UnknownLevel(s.into())),
83        })
84    }
85}
86
87/// Body of a Trust Proof
88#[derive(Clone, Debug, Builder, Serialize, Deserialize)]
89pub struct Trust {
90    #[serde(flatten)]
91    pub common: proof::Common,
92    pub ids: Vec<crate::PublicId>,
93    #[builder(default = "Default::default()")]
94    pub trust: TrustLevel,
95    #[serde(skip_serializing_if = "String::is_empty", default = "Default::default")]
96    #[builder(default = "Default::default()")]
97    pub comment: String,
98    #[serde(
99        default = "Default::default",
100        skip_serializing_if = "Vec::is_empty",
101        rename = "override"
102    )]
103    #[builder(default = "Default::default()")]
104    pub override_: Vec<OverrideItem>,
105}
106
107impl TrustBuilder {
108    pub fn from<VALUE: Into<crate::PublicId>>(&mut self, value: VALUE) -> &mut Self {
109        if let Some(ref mut common) = self.common {
110            common.from = value.into();
111        } else {
112            self.common = Some(proof::Common {
113                kind: Some(Trust::KIND.into()),
114                version: cur_version(),
115                date: crev_common::now(),
116                from: value.into(),
117                original: None,
118            });
119        }
120        self
121    }
122}
123
124impl fmt::Display for Trust {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        self.serialize_to(f).map_err(|_| fmt::Error)
127    }
128}
129
130impl proof::CommonOps for Trust {
131    fn common(&self) -> &proof::Common {
132        &self.common
133    }
134
135    fn kind(&self) -> &str {
136        // Backfill the `kind` if it is empty (legacy format)
137        self.common.kind.as_deref().unwrap_or(Self::KIND)
138    }
139}
140
141impl Trust {
142    pub const KIND: &'static str = "trust";
143
144    pub fn touch_date(&mut self) {
145        self.common.date = crev_common::now();
146    }
147}
148
149/// Like `Trust` but serializes for interactive editing
150#[derive(Clone, Debug, Serialize, Deserialize)]
151pub struct Draft {
152    pub trust: TrustLevel,
153    #[serde(default = "Default::default", skip_serializing_if = "String::is_empty")]
154    comment: String,
155    #[serde(
156        default = "Default::default",
157        skip_serializing_if = "Vec::is_empty",
158        rename = "override"
159    )]
160    override_: Vec<OverrideItemDraft>,
161}
162
163impl From<Trust> for Draft {
164    fn from(trust: Trust) -> Self {
165        Draft {
166            trust: trust.trust,
167            comment: trust.comment,
168            override_: trust.override_.into_iter().map(Into::into).collect(),
169        }
170    }
171}
172
173impl fmt::Display for Draft {
174    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
175        serde_draft_serialize!(self, fmt);
176        Ok(())
177    }
178}
179
180impl proof::Content for Trust {
181    fn serialize_to(&self, fmt: &mut dyn std::fmt::Write) -> fmt::Result {
182        serde_content_serialize!(self, fmt);
183        Ok(())
184    }
185
186    fn validate_data(&self) -> ValidationResult<()> {
187        self.ensure_kind_is(Self::KIND)?;
188        Ok(())
189    }
190}
191
192impl Trust {
193    fn draft_title(&self) -> String {
194        match self.ids.len() {
195            0 => "Trust for noone?!".into(),
196            1 => format!("Trust for {} {}", self.ids[0].id, self.ids[0].url_display()),
197            n => format!(
198                "Trust for {} {} and {} other",
199                self.ids[0].id,
200                self.ids[0].url_display(),
201                n - 1
202            ),
203        }
204    }
205}
206
207impl proof::ContentWithDraft for Trust {
208    fn to_draft(&self) -> proof::Draft {
209        proof::Draft {
210            title: self.draft_title(),
211            body: Draft::from(self.clone()).to_string(),
212        }
213    }
214
215    fn apply_draft(&self, s: &str) -> Result<Self> {
216        let draft = Draft::parse(s)?;
217
218        let mut copy = self.clone();
219        copy.trust = draft.trust;
220        copy.comment = draft.comment;
221        copy.override_ = draft.override_.into_iter().map(Into::into).collect();
222
223        copy.validate_data()?;
224        Ok(copy)
225    }
226}
227
228impl Draft {
229    pub fn parse(s: &str) -> std::result::Result<Self, ParseError> {
230        serde_yaml::from_str(s).map_err(ParseError::Draft)
231    }
232}