use std::sync::Arc;
use tower::Layer;
use crate::AuthProvider;
use super::AuthLayerConfig;
use super::service::AuthService;
#[derive(Debug, Clone)]
pub struct AuthLayer<P> {
provider: Arc<P>,
config: AuthLayerConfig,
}
impl<P> AuthLayer<P>
where
P: AuthProvider,
{
pub fn new(provider: P) -> Self {
Self {
provider: Arc::new(provider),
config: AuthLayerConfig::default(),
}
}
pub fn with_config(provider: P, config: AuthLayerConfig) -> Self {
Self {
provider: Arc::new(provider),
config,
}
}
pub fn from_arc(provider: Arc<P>) -> Self {
Self {
provider,
config: AuthLayerConfig::default(),
}
}
pub fn from_arc_with_config(provider: Arc<P>, config: AuthLayerConfig) -> Self {
Self { provider, config }
}
#[must_use]
pub fn config(mut self, config: AuthLayerConfig) -> Self {
self.config = config;
self
}
#[must_use]
pub fn allow_anonymous(mut self) -> Self {
self.config.allow_anonymous = true;
self
}
#[must_use]
pub fn bypass_method(mut self, method: impl Into<String>) -> Self {
self.config.bypass_methods.push(method.into());
self
}
}
impl<S, P> Layer<S> for AuthLayer<P>
where
P: AuthProvider + Clone,
{
type Service = AuthService<S, P>;
fn layer(&self, inner: S) -> Self::Service {
AuthService::new(inner, Arc::clone(&self.provider), self.config.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::providers::ApiKeyProvider;
#[test]
fn test_layer_creation() {
let provider = ApiKeyProvider::new("test-provider".to_string());
let layer = AuthLayer::new(provider);
assert!(!layer.config.allow_anonymous);
}
#[test]
fn test_layer_with_config() {
let provider = ApiKeyProvider::new("test-provider".to_string());
let config = AuthLayerConfig::allow_anonymous();
let layer = AuthLayer::with_config(provider, config);
assert!(layer.config.allow_anonymous);
}
#[test]
fn test_layer_builder_pattern() {
let provider = ApiKeyProvider::new("test-provider".to_string());
let layer = AuthLayer::new(provider)
.allow_anonymous()
.bypass_method("custom/method");
assert!(layer.config.allow_anonymous);
assert!(layer.config.should_bypass("custom/method"));
}
#[test]
fn test_layer_from_arc() {
let provider = Arc::new(ApiKeyProvider::new("test-provider".to_string()));
let layer = AuthLayer::from_arc(Arc::clone(&provider));
assert!(!layer.config.allow_anonymous);
}
}