pub mod routes;
pub mod stats;
use crate::backend::CacheBackend;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct AdminConfig {
pub enabled: bool,
pub auth_token: Option<String>,
pub require_auth: bool,
pub mount_path: String,
pub max_keys_per_request: usize,
pub max_hot_keys: usize,
}
impl Default for AdminConfig {
fn default() -> Self {
Self {
enabled: false,
auth_token: None,
require_auth: true,
mount_path: "/admin/cache".to_string(),
max_keys_per_request: 100,
max_hot_keys: 20,
}
}
}
impl AdminConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
pub fn with_auth_token(mut self, token: impl Into<String>) -> Self {
self.auth_token = Some(token.into());
self
}
pub fn with_require_auth(mut self, require: bool) -> Self {
self.require_auth = require;
self
}
pub fn with_mount_path(mut self, path: impl Into<String>) -> Self {
self.mount_path = path.into();
self
}
pub fn validate_token(&self, provided: Option<&str>) -> bool {
if !self.require_auth {
return true;
}
match (&self.auth_token, provided) {
(Some(expected), Some(provided)) => expected == provided,
(None, _) => !self.require_auth,
_ => false,
}
}
}
#[derive(Clone)]
pub struct AdminState<B: CacheBackend> {
pub backend: B,
pub config: Arc<AdminConfig>,
pub stats: Arc<stats::GlobalStats>,
}
impl<B: CacheBackend> AdminState<B> {
pub fn new(backend: B, config: AdminConfig) -> Self {
Self {
backend,
config: Arc::new(config),
stats: Arc::new(stats::GlobalStats::new()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn admin_config_default() {
let config = AdminConfig::default();
assert!(!config.enabled);
assert!(config.require_auth);
assert_eq!(config.mount_path, "/admin/cache");
}
#[test]
fn admin_config_builder() {
let config = AdminConfig::new()
.with_enabled(true)
.with_auth_token("secret")
.with_require_auth(false)
.with_mount_path("/cache/admin");
assert!(config.enabled);
assert_eq!(config.auth_token, Some("secret".to_string()));
assert!(!config.require_auth);
assert_eq!(config.mount_path, "/cache/admin");
}
#[test]
fn validate_token_success() {
let config = AdminConfig::new()
.with_auth_token("secret")
.with_require_auth(true);
assert!(config.validate_token(Some("secret")));
}
#[test]
fn validate_token_failure() {
let config = AdminConfig::new()
.with_auth_token("secret")
.with_require_auth(true);
assert!(!config.validate_token(Some("wrong")));
assert!(!config.validate_token(None));
}
#[test]
fn validate_token_no_auth_required() {
let config = AdminConfig::new().with_require_auth(false);
assert!(config.validate_token(None));
assert!(config.validate_token(Some("anything")));
}
}