1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use iref::Iri;
use ssi_claims_core::ProofValidationError;

use crate::{ProofPurpose, ProofPurposes};

/// Verification method controller.
///
/// A verification method controller stores the proof purposes for its
/// controlled verification methods.
/// The [`VerificationMethod::controller`] method returns
/// an identifier for its controller, which can then be retrieved using a
/// [`ControllerProvider`].
///
/// [`VerificationMethod::controller`]: crate::VerificationMethod::controller
pub trait Controller {
    /// Checks that the controller allows using the verification method for the
    /// given proof purposes.
    fn allows_verification_method(&self, id: &Iri, proof_purposes: ProofPurposes) -> bool;
}

impl<'a, T: Controller> Controller for &'a T {
    fn allows_verification_method(&self, id: &Iri, proof_purposes: ProofPurposes) -> bool {
        T::allows_verification_method(*self, id, proof_purposes)
    }
}

/// Controller provider.
///
/// A provider is in charge of retrieving the verification method controllers
/// from their identifiers.
pub trait ControllerProvider {
    /// Controller reference type.
    type Controller<'a>: Controller
    where
        Self: 'a;

    /// Returns the controller with the given identifier, if it can be found.
    #[allow(async_fn_in_trait)]
    async fn get_controller<'a>(
        &'a self,
        id: &'a Iri,
    ) -> Result<Option<Self::Controller<'a>>, ControllerError>;

    /// Returns the controller with the given identifier, or fails if it cannot
    /// be found.
    #[allow(async_fn_in_trait)]
    async fn require_controller<'a>(
        &'a self,
        id: &'a Iri,
    ) -> Result<Self::Controller<'a>, ControllerError> {
        self.get_controller(id)
            .await?
            .ok_or_else(|| ControllerError::NotFound(id.to_string()))
    }

    /// Checks that the controller identified by `controller_id` allows the use
    /// of the verification method `method_id` with the given proof purposes.
    #[allow(async_fn_in_trait)]
    async fn allows_verification_method<'a>(
        &'a self,
        controller_id: &'a Iri,
        method_id: &'a Iri,
        proof_purposes: ProofPurposes,
    ) -> Result<bool, ControllerError> {
        let controller = self.require_controller(controller_id).await?;
        Ok(controller.allows_verification_method(method_id, proof_purposes))
    }

    /// Ensures that the controller identified by `controller_id` allows the use
    /// of the verification method `method_id` with the given proof purposes.
    ///
    /// Contrarily to the [`allows_verification_method`] function, this function
    /// returns an error if one of the input proof purposes is not allowed.
    ///
    /// [`allows_verification_method`]: ControllerProvider::allows_verification_method
    #[allow(async_fn_in_trait)]
    async fn ensure_allows_verification_method<'a>(
        &'a self,
        controller_id: &'a Iri,
        method_id: &'a Iri,
        proof_purpose: ProofPurpose,
    ) -> Result<(), ProofValidationError> {
        let controller = self.require_controller(controller_id).await?;
        if controller.allows_verification_method(method_id, proof_purpose.into()) {
            Ok(())
        } else {
            Err(ProofValidationError::InvalidKeyUse)
        }
    }
}

/// Error that can be returned by a controller provider.
pub enum ControllerError {
    /// Controller was not found.
    ///
    /// The controller identifier is provided as argument.
    NotFound(String),

    /// Invalid controller.
    ///
    /// The controller was found, but could not be interpreted as a valid
    /// controller.
    Invalid,

    /// Unsupported controller identifier.
    Unsupported(String),

    /// Custom error from the controller provider.
    InternalError(String),
}

impl From<ControllerError> for ProofValidationError {
    fn from(value: ControllerError) -> Self {
        match value {
            ControllerError::NotFound(id) => Self::KeyControllerNotFound(id),
            ControllerError::Invalid => Self::InvalidKeyController,
            ControllerError::Unsupported(s) => Self::UnsupportedKeyController(s),
            ControllerError::InternalError(e) => Self::Other(e),
        }
    }
}