use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::time::SystemTime;
use thiserror::Error;
use uvb_core::TenantId;
#[derive(Debug, Error)]
pub enum EnrollmentError {
#[error("enrollment not found")]
NotFound,
#[error("already enrolled")]
AlreadyEnrolled,
#[error("storage error: {0}")]
Storage(String),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EnrollmentRecord {
pub id: String,
pub user_id: String,
pub tenant_id: TenantId,
pub factor_id: String,
pub status: EnrollmentStatus,
pub display_name: Option<String>, pub metadata: serde_json::Value,
pub enrolled_at: SystemTime,
pub last_used_at: Option<SystemTime>,
pub use_count: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum EnrollmentStatus {
Active,
Suspended,
Revoked,
}
#[async_trait]
pub trait EnrollmentStore: Send + Sync {
async fn create(&self, record: EnrollmentRecord) -> Result<String, EnrollmentError>;
async fn get(&self, id: &str) -> Result<Option<EnrollmentRecord>, EnrollmentError>;
async fn is_enrolled(
&self,
user_id: &str,
tenant_id: &TenantId,
factor_id: &str,
) -> Result<bool, EnrollmentError>;
async fn list_by_user(
&self,
user_id: &str,
tenant_id: &TenantId,
) -> Result<Vec<EnrollmentRecord>, EnrollmentError>;
async fn update(&self, record: EnrollmentRecord) -> Result<(), EnrollmentError>;
async fn delete(&self, id: &str) -> Result<(), EnrollmentError>;
async fn record_usage(&self, id: &str) -> Result<(), EnrollmentError>;
}