Files
Infrastruktur-Monitoring-Sy…/backend/crates/domain/src/ports.rs
Dennis Nemec 7b6d242988
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / ui (push) Has been cancelled
WP-10: contract and failing tests for OS and package inventory
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 22:19:25 +02:00

93 lines
3.5 KiB
Rust

//! Ports implemented by the infrastructure layer.
use async_trait::async_trait;
use uuid::Uuid;
use crate::auth::{AccessClaims, AuthEvent, RefreshToken};
use crate::host::{Inventory, OsInfo, Package};
use crate::jobs::{JobKind, JobRun, JobStatus};
use crate::settings::SmtpSettings;
use crate::user::{User, UserUpdate};
use crate::DomainError;
#[async_trait]
pub trait UserRepository: Send + Sync {
async fn find_by_id(&self, id: Uuid) -> Result<Option<User>, DomainError>;
async fn find_by_email(&self, email: &str) -> Result<Option<User>, DomainError>;
async fn list(&self) -> Result<Vec<User>, DomainError>;
async fn count(&self) -> Result<u64, DomainError>;
async fn count_active_admins(&self) -> Result<u64, DomainError>;
async fn insert(&self, user: &User) -> Result<(), DomainError>;
async fn update(&self, id: Uuid, update: &UserUpdate) -> Result<User, DomainError>;
async fn set_password_hash(&self, id: Uuid, hash: &str) -> Result<(), DomainError>;
}
#[async_trait]
pub trait RefreshTokenRepository: Send + Sync {
async fn insert(&self, token: &RefreshToken) -> Result<(), DomainError>;
async fn find_by_hash(&self, hash: &str) -> Result<Option<RefreshToken>, DomainError>;
async fn revoke(&self, id: Uuid) -> Result<(), DomainError>;
async fn revoke_family(&self, family: Uuid) -> Result<(), DomainError>;
}
#[async_trait]
pub trait AuditLog: Send + Sync {
async fn record(&self, event: &AuthEvent) -> Result<(), DomainError>;
}
pub trait PasswordHasher: Send + Sync {
fn hash(&self, password: &str) -> Result<String, DomainError>;
fn verify(&self, password: &str, hash: &str) -> bool;
}
pub trait AccessTokenIssuer: Send + Sync {
fn issue(&self, user: &User) -> Result<String, DomainError>;
fn verify(&self, token: &str) -> Result<AccessClaims, DomainError>;
}
#[async_trait]
pub trait SettingsRepository: Send + Sync {
async fn get(&self, key: &str) -> Result<Option<String>, DomainError>;
async fn set(&self, key: &str, value: &str) -> Result<(), DomainError>;
}
/// Symmetric encryption for secrets at rest.
pub trait Cipher: Send + Sync {
fn encrypt(&self, plain: &str) -> Result<String, DomainError>;
fn decrypt(&self, cipher_text: &str) -> Result<String, DomainError>;
}
#[async_trait]
pub trait Mailer: Send + Sync {
async fn send(
&self,
smtp: &SmtpSettings,
to: &[String],
subject: &str,
body: &str,
) -> Result<(), DomainError>;
}
#[async_trait]
pub trait JobRunRepository: Send + Sync {
async fn insert(&self, run: &JobRun) -> Result<(), DomainError>;
async fn append_log(&self, id: Uuid, line: &str) -> Result<(), DomainError>;
async fn finish(&self, id: Uuid, status: JobStatus) -> Result<(), DomainError>;
async fn get(&self, id: Uuid) -> Result<Option<JobRun>, DomainError>;
async fn list(&self, limit: u32) -> Result<Vec<JobRun>, DomainError>;
async fn find_running(&self, kind: JobKind) -> Result<Option<JobRun>, DomainError>;
async fn last_finished(&self, kind: JobKind) -> Result<Option<JobRun>, DomainError>;
}
/// Reads the state of the Debian host.
#[async_trait]
pub trait HostInspector: Send + Sync {
async fn os_info(&self) -> Result<OsInfo, DomainError>;
async fn packages(&self) -> Result<Vec<Package>, DomainError>;
}
#[async_trait]
pub trait InventoryRepository: Send + Sync {
async fn save(&self, inventory: &Inventory) -> Result<(), DomainError>;
async fn load(&self) -> Result<Option<Inventory>, DomainError>;
}