use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use tracing::{debug, warn};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationResult {
pub is_valid: bool,
pub violations: Vec<String>,
pub warnings: Vec<String>,
pub expires_at: Option<DateTime<Utc>>,
pub days_remaining: Option<i64>,
pub features: Vec<String>,
}
impl ValidationResult {
pub fn new() -> Self {
Self {
is_valid: true,
violations: Vec::new(),
warnings: Vec::new(),
expires_at: None,
days_remaining: None,
features: Vec::new(),
}
}
pub fn add_violation(&mut self, violation: String) {
self.violations.push(violation);
self.is_valid = false;
}
pub fn add_warning(&mut self, warning: String) {
self.warnings.push(warning);
}
pub fn is_valid(&self) -> bool {
self.is_valid
}
}
pub struct LicenseValidator {
pub allow_offline: bool,
pub grace_period_days: u32,
pub require_hardware_check: bool,
}
impl LicenseValidator {
pub fn validate_license(
&self,
license: &crate::license::License,
hardware_fingerprint: Option<&str>,
is_online: bool,
) -> ValidationResult {
let mut result = ValidationResult::new();
if license.is_expired() {
result.add_violation("License has expired".to_string());
} else {
result.expires_at = Some(license.expires_at());
result.days_remaining = Some(license.days_remaining());
}
result.features = license.features().to_vec();
if self.require_hardware_check && hardware_fingerprint.is_none() {
result.add_violation("Hardware fingerprint required".to_string());
}
if !self.allow_offline && !is_online {
result.add_violation("Online validation required".to_string());
}
if !result.is_valid {
warn!("License validation failed: {:?}", result.violations);
} else {
debug!("License validation passed");
}
result
}
}