use sea_orm::{ActiveModelTrait, ActiveValue::Set, DatabaseConnection, EntityTrait, prelude::*}; use uuid::Uuid; use crate::service::proxy::types::{ OverrideRef, ProxyServiceError, ProxyServiceResult, ServerBlockConfig, }; pub struct CreateServerBlockParams { pub config_id: Uuid, pub server_name: Option>, pub listen_port: i32, pub ssl_enabled: Option, pub ssl_cert_id: Option, pub override_of_id: Option, } pub struct UpdateServerBlockParams { pub server_name: Option>>, pub listen_port: Option, pub ssl_enabled: Option>, pub ssl_cert_id: Option>, pub override_of_id: Option>, } #[cfg_attr(test, mockall::automock)] #[async_trait::async_trait] pub trait ServerBlockService: Send + Sync + 'static { async fn get(&self, id: Uuid) -> ProxyServiceResult; async fn list_by_config(&self, config_id: Uuid) -> ProxyServiceResult>; async fn create( &self, params: CreateServerBlockParams, ) -> ProxyServiceResult; async fn update( &self, id: Uuid, params: UpdateServerBlockParams, ) -> ProxyServiceResult; async fn delete(&self, id: Uuid) -> ProxyServiceResult; } pub(crate) struct ServerBlockServiceImpl { db: DatabaseConnection, } impl ServerBlockServiceImpl { pub fn new(db: DatabaseConnection) -> Self { Self { db } } async fn build_with_children( &self, model: crate::db::entities::server_block::Model, ) -> ProxyServiceResult { use crate::db::entities::{access_rule, location_block, log_setting}; let access_rules = access_rule::Entity::find() .filter(access_rule::Column::ServerId.eq(model.id)) .all(&self.db) .await? .into_iter() .map(|a| OverrideRef { id: a.id, override_of_id: a.override_of_id, }) .collect(); let location_blocks = location_block::Entity::find() .filter(location_block::Column::ServerId.eq(model.id)) .all(&self.db) .await? .into_iter() .map(|l| OverrideRef { id: l.id, override_of_id: l.override_of_id, }) .collect(); let log_settings = log_setting::Entity::find() .filter(log_setting::Column::ServerId.eq(model.id)) .all(&self.db) .await? .into_iter() .map(|l| OverrideRef { id: l.id, override_of_id: l.override_of_id, }) .collect(); let ssl_certificates = model .ssl_cert_id .map(|id| { vec![OverrideRef { id, override_of_id: None, }] }) .unwrap_or_default(); Ok(ServerBlockConfig { id: model.id, server_name: model.server_name, listen_port: model.listen_port, ssl_enabled: model.ssl_enabled, override_of_id: model.override_of_id, access_rules, location_blocks, log_settings, ssl_certificates, }) } } #[async_trait::async_trait] impl ServerBlockService for ServerBlockServiceImpl { async fn get(&self, id: Uuid) -> ProxyServiceResult { use crate::db::entities::server_block; let model = server_block::Entity::find_by_id(id) .one(&self.db) .await? .ok_or(ProxyServiceError::ConfigNotFound)?; self.build_with_children(model).await } async fn list_by_config(&self, config_id: Uuid) -> ProxyServiceResult> { use crate::db::entities::server_block; let models = server_block::Entity::find() .filter(server_block::Column::ConfigId.eq(config_id)) .all(&self.db) .await?; let mut results = Vec::with_capacity(models.len()); for m in models { results.push(self.build_with_children(m).await?); } Ok(results) } async fn create( &self, params: CreateServerBlockParams, ) -> ProxyServiceResult { use crate::db::entities::server_block::ActiveModel; let id = Uuid::new_v4(); let model = ActiveModel { id: Set(id), config_id: Set(params.config_id), server_name: Set(params.server_name), listen_port: Set(params.listen_port), ssl_enabled: Set(params.ssl_enabled), ssl_cert_id: Set(params.ssl_cert_id), override_of_id: Set(params.override_of_id), }; let result = model.insert(&self.db).await?; self.build_with_children(result).await } async fn update( &self, id: Uuid, params: UpdateServerBlockParams, ) -> ProxyServiceResult { use crate::db::entities::server_block::{ActiveModel, Entity as ServerBlockEntity}; let existing = ServerBlockEntity::find_by_id(id) .one(&self.db) .await? .ok_or(ProxyServiceError::ConfigNotFound)?; let mut model: ActiveModel = existing.into(); if let Some(server_name) = params.server_name { model.server_name = Set(server_name); } if let Some(listen_port) = params.listen_port { model.listen_port = Set(listen_port); } if let Some(ssl_enabled) = params.ssl_enabled { model.ssl_enabled = Set(ssl_enabled); } if let Some(ssl_cert_id) = params.ssl_cert_id { model.ssl_cert_id = Set(ssl_cert_id); } if let Some(override_of_id) = params.override_of_id { model.override_of_id = Set(override_of_id); } let result = model.update(&self.db).await?; self.build_with_children(result).await } async fn delete(&self, id: Uuid) -> ProxyServiceResult { let result = crate::db::entities::server_block::Entity::delete_by_id(id) .exec(&self.db) .await?; Ok(result.rows_affected > 0) } }