siera_agent/modules/
proof.rs

1use crate::error::{Error, Result};
2use async_trait::async_trait;
3use serde::Deserialize;
4use serde::Serialize;
5use serde_json::Value;
6use std::str::FromStr;
7
8/// Response from the cloudagent when a proof request is created
9#[derive(Default, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
10pub struct ProofRequestResponse {
11    /// The state of the proof request
12    pub state: String,
13
14    /// The presentation request as an object
15    pub presentation_request: Value,
16
17    /// The last time the proof request was updated
18    pub updated_at: String,
19
20    /// The connection id to which the proof request is send to
21    pub connection_id: String,
22
23    /// The thread id that can be used to reference this proof request
24    pub thread_id: String,
25
26    /// A dictionary of the presentation request
27    pub presentation_request_dict: Value,
28
29    /// Your role in the proof request flow
30    pub role: String,
31
32    /// Whether it should automatically respond in the proof request flow
33    pub auto_present: bool,
34
35    /// The presentation exhange id that can be used in the other presentation exchange steps
36    pub presentation_exchange_id: String,
37
38    /// When the proof request was created
39    pub created_at: String,
40
41    /// Who the initiator was of the proof request
42    pub initiator: String,
43}
44
45/// A simple predicate enum
46/// The first string is the name of the key/value pair
47/// The second string is the operator that is used `>=`, `<=`, `=`, `>` or `>`
48/// The third string is the the value that should be evaluated with
49#[derive(Debug, Clone)]
50pub struct Predicate(pub String, pub String, pub String);
51
52impl FromStr for Predicate {
53    type Err = Error;
54    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
55        let mut res = s.split(',');
56        let name = res
57            .next()
58            .ok_or_else(|| Error::UnableToParseOutValue(s.to_owned()))?;
59        let operator = res
60            .next()
61            .ok_or_else(|| Error::UnableToParseOutValue(s.to_owned()))?;
62        let value = res
63            .next()
64            .ok_or_else(|| Error::UnableToParseOutValue(s.to_owned()))?;
65
66        validate_operator(operator).map_err(|_| Error::InvalidOperator(operator.to_owned()))?;
67        Ok(Self(name.to_owned(), operator.to_owned(), value.to_owned()))
68    }
69}
70
71/// Simple validation to check if the supplied operator is valid
72fn validate_operator(op: &str) -> Result<()> {
73    if vec![">=", "<=", "=", ">", "<"]
74        .iter()
75        .map(|o| String::from(*o))
76        .any(|o| o == *op)
77    {
78        return Ok(());
79    };
80    Err(Error::InvalidOperator(op.to_owned()).into())
81}
82
83/// Options supplied when a proof request is created
84pub struct ProofRequestOptions {
85    /// The connection id to which the proof request is send to
86    pub connection_id: String,
87
88    /// The name of the proof request
89    pub name: String,
90
91    /// All the attributes that are requested from the other agent
92    pub attributes: Vec<String>,
93
94    /// All the predicates that are requested from the other agent
95    pub predicates: Vec<(String, String, i32)>,
96}
97
98/// Generic cloudagent proof module
99#[async_trait]
100pub trait ProofModule {
101    /// Send a proof request via the connection id to another agent
102    async fn send_request(&self, options: ProofRequestOptions) -> Result<ProofRequestResponse>;
103}