pub use traits::*;
pub use types::*;
pub use api_key::{AppApiKeyAuth, AppApiKeyAuthBuilder};
pub use audit::{AppAuditLogger, AppAuditLoggerBuilder};
pub use bearer::{generate_secure_jwt_secret, BearerAuth, BearerAuthBuilder};
pub use middleware::auth_middleware;
mod api_key;
mod api_key_manager;
mod audit;
mod bearer;
mod middleware;
mod traits;
mod types;
pub use api_key_manager::{
ApiKeyMetadata, ApiKeyVersion, LruCacheManager, LruConfig, LruStats, RotationConfig,
};
impl traits::ApiKeyAuth for AppApiKeyAuth {
fn validate_key(&self, key: &str, client_ip: &str) -> Option<Vec<String>> {
AppApiKeyAuth::validate_key(self, key, client_ip)
}
fn add_key(&self, key: impl Into<String>, permissions: Vec<String>) {
AppApiKeyAuth::add_key(self, key, permissions);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::security::traits::ApiKeyAuth;
#[test]
fn trait_validate_key_returns_permissions_for_valid_key() {
let auth = AppApiKeyAuth::new();
auth.add_key("test-key", vec!["read".to_string()]);
let result = <AppApiKeyAuth as ApiKeyAuth>::validate_key(&auth, "test-key", "127.0.0.1");
assert_eq!(result, Some(vec!["read".to_string()]));
}
#[test]
fn trait_validate_key_returns_none_for_unknown_key() {
let auth = AppApiKeyAuth::new();
let result = <AppApiKeyAuth as ApiKeyAuth>::validate_key(&auth, "unknown-key", "127.0.0.1");
assert_eq!(result, None);
}
#[test]
fn trait_validate_key_returns_none_for_empty_key() {
let auth = AppApiKeyAuth::new();
let result = <AppApiKeyAuth as ApiKeyAuth>::validate_key(&auth, "", "127.0.0.1");
assert_eq!(result, None);
}
#[test]
fn trait_add_key_delegates_to_inherent_method() {
let auth = AppApiKeyAuth::new();
<AppApiKeyAuth as ApiKeyAuth>::add_key(&auth, "trait-key", vec!["admin".to_string()]);
let result = <AppApiKeyAuth as ApiKeyAuth>::validate_key(&auth, "trait-key", "127.0.0.1");
assert_eq!(result, Some(vec!["admin".to_string()]));
}
#[test]
fn trait_add_key_with_string_literal_works() {
let auth = AppApiKeyAuth::new();
<AppApiKeyAuth as ApiKeyAuth>::add_key(&auth, "literal-key", vec!["read".to_string()]);
let result = <AppApiKeyAuth as ApiKeyAuth>::validate_key(&auth, "literal-key", "127.0.0.1");
assert_eq!(result, Some(vec!["read".to_string()]));
}
#[test]
fn trait_dispatch_matches_inherent_dispatch() {
let auth1 = AppApiKeyAuth::new();
let auth2 = AppApiKeyAuth::new();
let perms = vec!["read".to_string(), "write".to_string()];
auth1.add_key("shared-key", perms.clone());
<AppApiKeyAuth as ApiKeyAuth>::add_key(&auth2, "shared-key", perms);
let inherent_result = auth1.validate_key("shared-key", "127.0.0.1");
let trait_result =
<AppApiKeyAuth as ApiKeyAuth>::validate_key(&auth2, "shared-key", "127.0.0.1");
assert_eq!(inherent_result, trait_result);
}
}