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