oxide_auth/frontends/simple/extensions/
list.rs

1use std::fmt;
2use std::sync::Arc;
3
4use super::{AuthorizationAddon, AccessTokenAddon, AddonResult, ClientCredentialsAddon};
5use crate::code_grant::accesstoken::{Extension as AccessTokenExtension, Request};
6use crate::code_grant::authorization::{Extension as AuthorizationExtension, Request as AuthRequest};
7use crate::code_grant::client_credentials::{
8    Extension as ClientCredentialsExtension, Request as ClientCredentialsRequest,
9};
10use crate::endpoint::Extension;
11use crate::primitives::grant::{Extensions, GrantExtension};
12
13/// A simple list of loosely related authorization and access addons.
14///
15/// The owning representation of access extensions can be switched out to `Box<_>`, `Rc<_>` or
16/// other types.
17#[derive(Clone)]
18pub struct AddonList {
19    /// Extension to be applied on authorize. This field is `pub` for `oxide-auth-async` be able to
20    /// implement async version of some traits.
21    pub authorization: Vec<Arc<dyn AuthorizationAddon + Send + Sync + 'static>>,
22
23    /// Extension to be applied on get token. This field is `pub` for `oxide-auth-async` be able to
24    /// implement async version of some traits.
25    pub access_token: Vec<Arc<dyn AccessTokenAddon + Send + Sync + 'static>>,
26
27    /// Extension to be applied on get token. This field is `pub` for `oxide-auth-async` be able to
28    /// implement async version of some traits.
29    pub client_credentials: Vec<Arc<dyn ClientCredentialsAddon + Send + Sync + 'static>>,
30}
31
32impl AddonList {
33    /// Create an empty extension system.
34    pub fn new() -> Self {
35        AddonList {
36            authorization: vec![],
37            access_token: vec![],
38            client_credentials: vec![],
39        }
40    }
41
42    /// Add an addon that only applies to authorization.
43    pub fn push_authorization<A>(&mut self, addon: A)
44    where
45        A: AuthorizationAddon + Send + Sync + 'static,
46    {
47        self.authorization.push(Arc::new(addon))
48    }
49
50    /// Add an addon that only applies to access_token.
51    pub fn push_access_token<A>(&mut self, addon: A)
52    where
53        A: AccessTokenAddon + Send + Sync + 'static,
54    {
55        self.access_token.push(Arc::new(addon))
56    }
57
58    /// Add an addon that only applies to client_credentials.
59    pub fn push_client_credentials<A>(&mut self, addon: A)
60    where
61        A: ClientCredentialsAddon + Send + Sync + 'static,
62    {
63        self.client_credentials.push(Arc::new(addon))
64    }
65
66    /// Add an addon that applies to the whole code grant flow.
67    ///
68    /// The addon gets added both the authorization and access token addons.
69    pub fn push_code<A>(&mut self, addon: A)
70    where
71        A: AuthorizationAddon + AccessTokenAddon + Send + Sync + 'static,
72    {
73        let arc = Arc::new(addon);
74        self.authorization.push(arc.clone());
75        self.access_token.push(arc)
76    }
77}
78
79impl Default for AddonList {
80    fn default() -> Self {
81        AddonList::new()
82    }
83}
84
85impl Extension for AddonList {
86    fn authorization(&mut self) -> Option<&mut dyn AuthorizationExtension> {
87        Some(self)
88    }
89
90    fn access_token(&mut self) -> Option<&mut dyn AccessTokenExtension> {
91        Some(self)
92    }
93
94    fn client_credentials(&mut self) -> Option<&mut dyn ClientCredentialsExtension> {
95        Some(self)
96    }
97}
98
99impl Extension for &mut AddonList {
100    fn authorization(&mut self) -> Option<&mut dyn AuthorizationExtension> {
101        Some(self)
102    }
103
104    fn access_token(&mut self) -> Option<&mut dyn AccessTokenExtension> {
105        Some(self)
106    }
107
108    fn client_credentials(&mut self) -> Option<&mut dyn ClientCredentialsExtension> {
109        Some(self)
110    }
111}
112
113impl AccessTokenExtension for AddonList {
114    fn extend(
115        &mut self, request: &dyn Request, mut data: Extensions,
116    ) -> std::result::Result<Extensions, ()> {
117        let mut result_data = Extensions::new();
118
119        for ext in self.access_token.iter() {
120            let ext_data = data.remove(ext);
121            let result = ext.execute(request, ext_data);
122
123            match result {
124                AddonResult::Ok => (),
125                AddonResult::Data(data) => result_data.set(ext, data),
126                AddonResult::Err => return Err(()),
127            }
128        }
129
130        Ok(result_data)
131    }
132}
133
134impl AccessTokenExtension for &mut AddonList {
135    fn extend(&mut self, request: &dyn Request, data: Extensions) -> Result<Extensions, ()> {
136        AccessTokenExtension::extend(*self, request, data)
137    }
138}
139
140impl AuthorizationExtension for AddonList {
141    fn extend(&mut self, request: &dyn AuthRequest) -> Result<Extensions, ()> {
142        let mut result_data = Extensions::new();
143
144        for ext in self.authorization.iter() {
145            let result = ext.execute(request);
146
147            match result {
148                AddonResult::Ok => (),
149                AddonResult::Data(data) => result_data.set(ext, data),
150                AddonResult::Err => return Err(()),
151            }
152        }
153
154        Ok(result_data)
155    }
156}
157
158impl AuthorizationExtension for &mut AddonList {
159    fn extend(&mut self, request: &dyn AuthRequest) -> Result<Extensions, ()> {
160        AuthorizationExtension::extend(*self, request)
161    }
162}
163
164impl ClientCredentialsExtension for AddonList {
165    fn extend(&mut self, request: &dyn ClientCredentialsRequest) -> Result<Extensions, ()> {
166        let mut result_data = Extensions::new();
167
168        for ext in self.client_credentials.iter() {
169            let result = ext.execute(request);
170
171            match result {
172                AddonResult::Ok => (),
173                AddonResult::Data(data) => result_data.set(ext, data),
174                AddonResult::Err => return Err(()),
175            }
176        }
177
178        Ok(result_data)
179    }
180}
181
182impl ClientCredentialsExtension for &mut AddonList {
183    fn extend(&mut self, request: &dyn ClientCredentialsRequest) -> Result<Extensions, ()> {
184        ClientCredentialsExtension::extend(*self, request)
185    }
186}
187
188impl fmt::Debug for AddonList {
189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190        use std::slice::Iter;
191        struct ExtIter<'a, T: GrantExtension + 'a>(Iter<'a, T>);
192
193        impl<'a, T: GrantExtension> fmt::Debug for ExtIter<'a, T> {
194            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
195                f.debug_list().entries(self.0.clone().map(T::identifier)).finish()
196            }
197        }
198
199        f.debug_struct("AddonList")
200            .field("authorization", &ExtIter(self.authorization.iter()))
201            .field("access_token", &ExtIter(self.access_token.iter()))
202            .field("client_credentials", &ExtIter(self.client_credentials.iter()))
203            .finish()
204    }
205}