Skip to main content

authorized/
lib.rs

1
2//! Authorized is a library helping you authorize behaviour on struct by defining allowed or denied
3//! scopes.
4//!
5//! You can use this to only expose field's value to authorized scopes
6
7#![warn(
8    clippy::all,
9    // clippy::restriction,
10    clippy::pedantic,
11    clippy::nursery,
12    // clippy::cargo
13)]
14#![recursion_limit = "256"]
15
16
17pub mod scope;
18
19mod error;
20mod result;
21#[cfg(feature = "with_serde")]
22mod serde;
23
24pub mod prelude;
25
26use scope::IntoScope;
27use scope::Scope;
28
29use error::*;
30use result::*;
31
32pub type UnAuthorizedFields<'a> = Vec<&'a str>;
33
34pub trait Authorizable {
35    type Authorized;
36
37    fn filter_unauthorized_fields<'a>(&'a self, scope: &Scope) -> UnAuthorizedFields<'a>;
38    fn authorize<'a>(
39        &'a self,
40        authorizer: &Scope,
41    ) -> Result<AuthorizedResult<'a, Self::Authorized>, AuthorizedError>;
42}
43
44
45/// Authorizor exposed mthods to help you authorize structures which implement
46/// [Authorizable](trait.Authorizable.html) trait.
47pub struct Authorizor {}
48
49impl Authorizor {
50    /// Create an authorized version of the input structure validated by the scope implementing
51    /// [`IntoScope`](scope/trait.IntoScope.html).
52    ///
53    /// It returns an [`AuthorizedResult`](struct.AuthorizedResult.html) which allow you to know
54    /// which fields have been secured and if the whole structure is authorized or not.
55    pub fn authorize<'a, A: Authorizable, T: IntoScope>(
56        inner: &'a A,
57        scope: &T,
58    ) -> Result<AuthorizedResult<'a, A::Authorized>, AuthorizedError> {
59        let scope: Scope = scope.into_scope()?;
60
61        inner.authorize(&scope)
62    }
63}
64
65pub trait Authorized {
66    #[cfg(feature = "with_serde")]
67    type Source: Authorizable + ::serde::ser::Serialize;
68    #[cfg(not(feature = "with_serde"))]
69    type Source: Authorizable;
70
71    fn build_serialize_struct<E>(&self, unauthorized_fields: &[&str]) -> Result<Self::Source, E>;
72}
73
74// #[cfg(test)]
75// mod tests {
76//     use super::*;
77
78//     #[test]
79//     fn it_works() {
80//         let based_user = MyUser {
81//             name: "name".into(),
82//             pass: "pass".into(),
83//             email: "email".into(),
84//         };
85
86//         let user: AuthorizedResult<AuthorizedUser> = based_user
87//             .authorize(&"user read:user".parse::<Scope>().unwrap())
88//             .unwrap();
89
90//         assert_eq!(user.status, AuthorizationStatus::Authorized);
91//         assert_eq!(user.inner.name, Some("name".to_owned()));
92//         assert_eq!(user.inner.pass, Some("pass".to_owned()));
93
94//         let json = serde_json::to_string(&user).unwrap();
95//         assert_eq!(
96//             json,
97//             serde_json::to_string(&json!({"name": "name"})).unwrap()
98//         );
99
100//         let user: AuthorizedResult<AuthorizedUser> = based_user
101//             .authorize(&"guest".parse::<Scope>().unwrap())
102//             .unwrap();
103
104//         assert_eq!(user.status, AuthorizationStatus::UnAuthorized);
105
106//         assert_eq!(user.inner.name, None);
107//         assert_eq!(user.inner.pass, None);
108
109//         let json = serde_json::to_string(&user).unwrap();
110//         assert_eq!(json, serde_json::to_string(&json!({})).unwrap());
111
112//         let user: AuthorizedResult<AuthorizedUser> = based_user
113//             .authorize(&"read:user admin".parse::<Scope>().unwrap())
114//             .unwrap();
115
116//         assert_eq!(user.status, AuthorizationStatus::Authorized);
117//         assert_eq!(user.inner.name, Some("name".to_owned()));
118//         assert_eq!(user.inner.pass, Some("pass".to_owned()));
119
120//         let json = serde_json::to_string(&user).unwrap();
121//         assert_eq!(
122//             json,
123//             serde_json::to_string(&json!({"name": "name", "pass": "pass"})).unwrap()
124//         );
125
126//         let user = Authorizor::authorize(&based_user, "read:user admin").unwrap();
127
128//         assert_eq!(user.status, AuthorizationStatus::Authorized);
129//         assert_eq!(user.inner.name, Some("name".to_owned()));
130//         assert_eq!(user.inner.pass, Some("pass".to_owned()));
131
132//         let json = serde_json::to_string(&user).unwrap();
133//         assert_eq!(
134//             json,
135//             serde_json::to_string(&json!({"name": "name", "pass": "pass"})).unwrap()
136//         );
137//     }
138// }