use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::domain::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrustRecordQuery {
pub entity_id: EntityId,
pub authority_id: AuthorityId,
pub action: Action,
pub resource: Resource,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrustRecordList {
records: Vec<TrustRecord>,
}
impl TrustRecordList {
pub fn new(records: Vec<TrustRecord>) -> Self {
Self { records }
}
pub fn records(&self) -> &[TrustRecord] {
&self.records
}
pub fn into_records(self) -> Vec<TrustRecord> {
self.records
}
}
impl TrustRecordQuery {
pub fn new(
entity_id: EntityId,
authority_id: AuthorityId,
action: Action,
resource: Resource,
) -> Self {
Self {
entity_id,
authority_id,
action,
resource,
}
}
pub fn from_ids(ids: TrustRecordIds) -> Self {
let (entity_id, authority_id, action, resource) = ids.into_parts();
Self {
entity_id,
authority_id,
action,
resource,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum RepositoryError {
#[error("Connection failed: {0}")]
ConnectionFailed(String),
#[error("Query failed: {0}")]
QueryFailed(String),
#[error("Serialization failed: {0}")]
SerializationFailed(String),
#[error("Record not found: {0}")]
RecordNotFound(String),
#[error("Record already exists: {0}")]
RecordAlreadyExists(String),
#[error("Validation error: {0}")]
ValidationError(String),
#[error("Lock poisoned")]
LockPoisoned,
}
#[async_trait::async_trait]
pub trait TrustRecordRepository: Send + Sync {
async fn find_by_query(
&self,
query: TrustRecordQuery,
) -> Result<Option<TrustRecord>, RepositoryError>;
}
#[async_trait::async_trait]
pub trait TrustRecordAdminRepository: TrustRecordRepository {
async fn create(&self, record: TrustRecord) -> Result<(), RepositoryError>;
async fn update(&self, record: TrustRecord) -> Result<(), RepositoryError>;
async fn delete(&self, query: TrustRecordQuery) -> Result<(), RepositoryError>;
async fn list(&self) -> Result<TrustRecordList, RepositoryError>;
async fn read(&self, query: TrustRecordQuery) -> Result<TrustRecord, RepositoryError>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_trust_record_creation() {
let record = TrustRecordBuilder::new()
.entity_id(EntityId::new("entity-123"))
.authority_id(AuthorityId::new("authority-456"))
.action(Action::new("action-789"))
.resource(Resource::new("resource-112"))
.recognized(true)
.authorized(true)
.record_type(RecordType::Authorization)
.build()
.unwrap();
assert_eq!(record.entity_id().as_str(), "entity-123");
assert_eq!(record.record_type().to_string(), "authorization");
}
#[test]
fn test_builder_missing_fields() {
let result = TrustRecordBuilder::new()
.entity_id(EntityId::new("entity-123"))
.build();
assert!(result.is_err());
}
#[test]
fn test_query_builder() {
let query = TrustRecordQuery::new(
EntityId::new("entity-123"),
AuthorityId::new("authority-456"),
Action::new("action-789"),
Resource::new("resource-012"),
);
assert_eq!(query.entity_id.as_str(), "entity-123");
}
}