tower_oauth2_resource_server/
builder.rs1use std::{marker::PhantomData, sync::Arc};
2
3use serde::de::DeserializeOwned;
4
5use crate::{
6 auth_resolver::{AuthorizerResolver, IssuerAuthorizerResolver, SingleAuthorizerResolver},
7 error::StartupError,
8 server::OAuth2ResourceServer,
9 tenant::TenantConfiguration,
10};
11
12#[derive(Debug)]
13pub struct OAuth2ResourceServerBuilder<Claims>
14where
15 Claims: Clone + DeserializeOwned + Send + Sync + 'static,
16{
17 tenant_configurations: Vec<TenantConfiguration>,
18 auth_resolver: Option<Arc<dyn AuthorizerResolver<Claims>>>,
19 phantom: PhantomData<Claims>,
20}
21
22impl<Claims> OAuth2ResourceServer<Claims>
23where
24 Claims: Clone + DeserializeOwned + Send + Sync + 'static,
25{
26 pub fn builder() -> OAuth2ResourceServerBuilder<Claims> {
27 OAuth2ResourceServerBuilder::new()
28 }
29}
30
31impl<Claims> OAuth2ResourceServerBuilder<Claims>
32where
33 Claims: Clone + DeserializeOwned + Send + Sync + 'static,
34{
35 fn new() -> Self {
36 OAuth2ResourceServerBuilder::<Claims> {
37 tenant_configurations: Vec::new(),
38 auth_resolver: None,
39 phantom: PhantomData,
40 }
41 }
42
43 pub fn add_tenant(mut self, tenant_configuration: TenantConfiguration) -> Self {
45 self.tenant_configurations.push(tenant_configuration);
46 self
47 }
48
49 pub fn auth_resolver(mut self, auth_resolver: Arc<dyn AuthorizerResolver<Claims>>) -> Self {
55 self.auth_resolver = Some(auth_resolver);
56 self
57 }
58
59 pub async fn build(self) -> Result<OAuth2ResourceServer<Claims>, StartupError> {
65 if self.tenant_configurations.is_empty() {
66 return Err(StartupError::InvalidParameter(
67 "At least one TenantConfiguration is required".to_owned(),
68 ));
69 }
70 let num_tenants = self.tenant_configurations.len();
71 let auth_resolver = self.auth_resolver.unwrap_or_else(|| {
72 if num_tenants == 1 {
73 Arc::new(SingleAuthorizerResolver {})
74 } else {
75 Arc::new(IssuerAuthorizerResolver {})
76 }
77 });
78 OAuth2ResourceServer::new(self.tenant_configurations, auth_resolver).await
79 }
80}
81
82impl<Claims> Default for OAuth2ResourceServerBuilder<Claims>
83where
84 Claims: Clone + DeserializeOwned + Send + Sync + 'static,
85{
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use serde::Deserialize;
94
95 use super::*;
96
97 #[derive(Clone, Debug, Deserialize)]
98 struct Claims {}
99
100 #[tokio::test]
101 async fn should_require_tenant_configurations() {
102 let result = OAuth2ResourceServerBuilder::<Claims>::new().build().await;
103 assert!(result.is_err());
104 assert_eq!(
105 result.unwrap_err(),
106 StartupError::InvalidParameter(
107 "At least one TenantConfiguration is required".to_owned()
108 )
109 )
110 }
111}