This commit is contained in:
2026-04-23 09:22:11 +02:00
parent c36d6b9ded
commit 3b8e029cde
20 changed files with 1123 additions and 16 deletions

View File

@@ -0,0 +1,69 @@
// file: kb_lib/src/db/dtos/db_runtime_event.rs
//! Runtime event DTO.
/// Application-facing runtime event DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KbDbRuntimeEventDto {
/// Optional numeric primary key.
pub id: std::option::Option<i64>,
/// Event kind.
pub event_kind: std::string::String,
/// Severity level.
pub level: crate::KbDbRuntimeEventLevel,
/// Event source.
pub source: std::string::String,
/// Human-readable message.
pub message: std::string::String,
/// Creation timestamp.
pub created_at: chrono::DateTime<chrono::Utc>,
}
impl KbDbRuntimeEventDto {
/// Creates a new runtime event DTO with the current creation timestamp.
pub fn new(
event_kind: std::string::String,
level: crate::KbDbRuntimeEventLevel,
source: std::string::String,
message: std::string::String,
) -> Self {
Self {
id: None,
event_kind,
level,
source,
message,
created_at: chrono::Utc::now(),
}
}
}
impl TryFrom<crate::KbDbRuntimeEventEntity> for KbDbRuntimeEventDto {
type Error = crate::KbError;
fn try_from(entity: crate::KbDbRuntimeEventEntity) -> Result<Self, Self::Error> {
let created_at_result = chrono::DateTime::parse_from_rfc3339(&entity.created_at);
let created_at = match created_at_result {
Ok(created_at) => created_at.with_timezone(&chrono::Utc),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse runtime event created_at '{}': {}",
entity.created_at, error
)));
}
};
let level_result = crate::KbDbRuntimeEventLevel::from_i16(entity.level);
let level = match level_result {
Ok(level) => level,
Err(error) => return Err(error),
};
Ok(Self {
id: Some(entity.id),
event_kind: entity.event_kind,
level,
source: entity.source,
message: entity.message,
created_at,
})
}
}

View File

@@ -0,0 +1,121 @@
// file: kb_lib/src/db/dtos/known_http_endpoint.rs
//! Known HTTP endpoint DTO.
/// Application-facing known HTTP endpoint DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KbKnownHttpEndpointDto {
/// Logical endpoint name.
pub name: std::string::String,
/// Provider name.
pub provider: std::string::String,
/// Endpoint URL.
pub url: std::string::String,
/// Whether this endpoint is enabled.
pub enabled: bool,
/// Declared roles.
pub roles: std::vec::Vec<std::string::String>,
/// Optional last seen timestamp.
pub last_seen_at: std::option::Option<chrono::DateTime<chrono::Utc>>,
/// Last update timestamp.
pub updated_at: chrono::DateTime<chrono::Utc>,
}
impl KbKnownHttpEndpointDto {
/// Creates a new DTO with the current update timestamp.
pub fn new(
name: std::string::String,
provider: std::string::String,
url: std::string::String,
enabled: bool,
roles: std::vec::Vec<std::string::String>,
) -> Self {
Self {
name,
provider,
url,
enabled,
roles,
last_seen_at: None,
updated_at: chrono::Utc::now(),
}
}
}
impl TryFrom<crate::KbKnownHttpEndpointEntity> for KbKnownHttpEndpointDto {
type Error = crate::KbError;
fn try_from(entity: crate::KbKnownHttpEndpointEntity) -> Result<Self, Self::Error> {
let roles_result =
serde_json::from_str::<std::vec::Vec<std::string::String>>(&entity.roles_json);
let roles = match roles_result {
Ok(roles) => roles,
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse known http endpoint roles_json '{}': {}",
entity.roles_json, error
)));
}
};
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
let updated_at = match updated_at_result {
Ok(updated_at) => updated_at.with_timezone(&chrono::Utc),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse known http endpoint updated_at '{}': {}",
entity.updated_at, error
)));
}
};
let last_seen_at = match entity.last_seen_at {
Some(last_seen_at_text) => {
let parsed_result = chrono::DateTime::parse_from_rfc3339(&last_seen_at_text);
match parsed_result {
Ok(parsed) => Some(parsed.with_timezone(&chrono::Utc)),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse known http endpoint last_seen_at '{}': {}",
last_seen_at_text, error
)));
}
}
}
None => None,
};
Ok(Self {
name: entity.name,
provider: entity.provider,
url: entity.url,
enabled: entity.enabled != 0,
roles,
last_seen_at,
updated_at,
})
}
}
impl TryFrom<KbKnownHttpEndpointDto> for crate::KbKnownHttpEndpointEntity {
type Error = crate::KbError;
fn try_from(dto: KbKnownHttpEndpointDto) -> Result<Self, Self::Error> {
let roles_json_result = serde_json::to_string(&dto.roles);
let roles_json = match roles_json_result {
Ok(roles_json) => roles_json,
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot serialize known http endpoint roles: {}",
error
)));
}
};
Ok(Self {
name: dto.name,
provider: dto.provider,
url: dto.url,
enabled: if dto.enabled { 1 } else { 0 },
roles_json,
last_seen_at: dto.last_seen_at.map(|value| value.to_rfc3339()),
updated_at: dto.updated_at.to_rfc3339(),
})
}
}

View File

@@ -0,0 +1,121 @@
// file: kb_lib/src/db/dtos/known_ws_endpoint.rs
//! Known WebSocket endpoint DTO.
/// Application-facing known WebSocket endpoint DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KbKnownWsEndpointDto {
/// Logical endpoint name.
pub name: std::string::String,
/// Provider name.
pub provider: std::string::String,
/// Endpoint URL.
pub url: std::string::String,
/// Whether this endpoint is enabled.
pub enabled: bool,
/// Declared roles.
pub roles: std::vec::Vec<std::string::String>,
/// Optional last seen timestamp.
pub last_seen_at: std::option::Option<chrono::DateTime<chrono::Utc>>,
/// Last update timestamp.
pub updated_at: chrono::DateTime<chrono::Utc>,
}
impl KbKnownWsEndpointDto {
/// Creates a new DTO with the current update timestamp.
pub fn new(
name: std::string::String,
provider: std::string::String,
url: std::string::String,
enabled: bool,
roles: std::vec::Vec<std::string::String>,
) -> Self {
Self {
name,
provider,
url,
enabled,
roles,
last_seen_at: None,
updated_at: chrono::Utc::now(),
}
}
}
impl TryFrom<crate::KbKnownWsEndpointEntity> for KbKnownWsEndpointDto {
type Error = crate::KbError;
fn try_from(entity: crate::KbKnownWsEndpointEntity) -> Result<Self, Self::Error> {
let roles_result =
serde_json::from_str::<std::vec::Vec<std::string::String>>(&entity.roles_json);
let roles = match roles_result {
Ok(roles) => roles,
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse known ws endpoint roles_json '{}': {}",
entity.roles_json, error
)));
}
};
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
let updated_at = match updated_at_result {
Ok(updated_at) => updated_at.with_timezone(&chrono::Utc),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse known ws endpoint updated_at '{}': {}",
entity.updated_at, error
)));
}
};
let last_seen_at = match entity.last_seen_at {
Some(last_seen_at_text) => {
let parsed_result = chrono::DateTime::parse_from_rfc3339(&last_seen_at_text);
match parsed_result {
Ok(parsed) => Some(parsed.with_timezone(&chrono::Utc)),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse known ws endpoint last_seen_at '{}': {}",
last_seen_at_text, error
)));
}
}
}
None => None,
};
Ok(Self {
name: entity.name,
provider: entity.provider,
url: entity.url,
enabled: entity.enabled != 0,
roles,
last_seen_at,
updated_at,
})
}
}
impl TryFrom<KbKnownWsEndpointDto> for crate::KbKnownWsEndpointEntity {
type Error = crate::KbError;
fn try_from(dto: KbKnownWsEndpointDto) -> Result<Self, Self::Error> {
let roles_json_result = serde_json::to_string(&dto.roles);
let roles_json = match roles_json_result {
Ok(roles_json) => roles_json,
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot serialize known ws endpoint roles: {}",
error
)));
}
};
Ok(Self {
name: dto.name,
provider: dto.provider,
url: dto.url,
enabled: if dto.enabled { 1 } else { 0 },
roles_json,
last_seen_at: dto.last_seen_at.map(|value| value.to_rfc3339()),
updated_at: dto.updated_at.to_rfc3339(),
})
}
}