use drasi_lib::bootstrap::BootstrapProvider;
use drasi_plugin_sdk::prelude::*;
use utoipa::OpenApi;
use crate::{AuthMode, EncryptionMode, MsSqlBootstrapProvider, MsSqlSourceConfig, TableKeyConfig};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, utoipa::ToSchema)]
#[schema(as = bootstrap::mssql::AuthMode)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum AuthModeDto {
#[default]
SqlServer,
Windows,
AzureAd,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, utoipa::ToSchema)]
#[schema(as = bootstrap::mssql::EncryptionMode)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum EncryptionModeDto {
Off,
On,
#[default]
NotSupported,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, utoipa::ToSchema)]
#[schema(as = bootstrap::mssql::MsSqlTableKeyConfig)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct MsSqlTableKeyConfigDto {
pub table: String,
pub key_columns: Vec<String>,
}
fn default_host() -> ConfigValue<String> {
ConfigValue::Static("localhost".to_string()) }
fn default_port() -> ConfigValue<u16> {
ConfigValue::Static(1433)
}
fn default_password() -> ConfigValue<String> {
ConfigValue::Static(String::new())
}
fn default_auth_mode() -> ConfigValue<AuthModeDto> {
ConfigValue::Static(AuthModeDto::default())
}
fn default_encryption() -> ConfigValue<EncryptionModeDto> {
ConfigValue::Static(EncryptionModeDto::default())
}
fn default_trust_server_certificate() -> ConfigValue<bool> {
ConfigValue::Static(false)
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, utoipa::ToSchema)]
#[schema(as = bootstrap::mssql::MsSqlBootstrapConfig)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct MsSqlBootstrapConfigDto {
#[serde(default = "default_host")]
#[schema(value_type = ConfigValueString)]
pub host: ConfigValue<String>,
#[serde(default = "default_port")]
#[schema(value_type = ConfigValueU16)]
pub port: ConfigValue<u16>,
#[schema(value_type = ConfigValueString)]
pub database: ConfigValue<String>,
#[schema(value_type = ConfigValueString)]
pub user: ConfigValue<String>,
#[serde(default = "default_password")]
#[schema(value_type = ConfigValueString)]
pub password: ConfigValue<String>,
#[serde(default = "default_auth_mode")]
#[schema(value_type = ConfigValue<bootstrap::mssql::AuthMode>)]
pub auth_mode: ConfigValue<AuthModeDto>,
#[serde(default)]
pub tables: Vec<String>,
#[serde(default = "default_encryption")]
#[schema(value_type = ConfigValue<bootstrap::mssql::EncryptionMode>)]
pub encryption: ConfigValue<EncryptionModeDto>,
#[serde(default = "default_trust_server_certificate")]
#[schema(value_type = ConfigValueBool)]
pub trust_server_certificate: ConfigValue<bool>,
#[serde(default)]
#[schema(value_type = Vec<bootstrap::mssql::MsSqlTableKeyConfig>)]
pub table_keys: Vec<MsSqlTableKeyConfigDto>,
}
#[derive(OpenApi)]
#[openapi(components(schemas(
MsSqlBootstrapConfigDto,
AuthModeDto,
EncryptionModeDto,
MsSqlTableKeyConfigDto,
)))]
struct MsSqlBootstrapSchemas;
pub struct MsSqlBootstrapDescriptor;
#[async_trait]
impl BootstrapPluginDescriptor for MsSqlBootstrapDescriptor {
fn kind(&self) -> &str {
"mssql"
}
fn config_version(&self) -> &str {
"1.0.0"
}
fn config_schema_name(&self) -> &str {
"bootstrap.mssql.MsSqlBootstrapConfig"
}
fn config_schema_json(&self) -> String {
let api = MsSqlBootstrapSchemas::openapi();
serde_json::to_string(
&api.components
.as_ref()
.expect("OpenAPI components missing")
.schemas,
)
.expect("Failed to serialize config schema")
}
async fn create_bootstrap_provider(
&self,
config_json: &serde_json::Value,
_source_config_json: &serde_json::Value,
) -> anyhow::Result<Box<dyn BootstrapProvider>> {
let dto: MsSqlBootstrapConfigDto = serde_json::from_value(config_json.clone())?;
let mapper = DtoMapper::new();
let auth_mode = match dto.auth_mode {
ConfigValue::Static(v) => match v {
AuthModeDto::SqlServer => AuthMode::SqlServer,
AuthModeDto::Windows => AuthMode::Windows,
AuthModeDto::AzureAd => AuthMode::AzureAd,
},
_ => AuthMode::default(),
};
let encryption = match dto.encryption {
ConfigValue::Static(v) => match v {
EncryptionModeDto::Off => EncryptionMode::Off,
EncryptionModeDto::On => EncryptionMode::On,
EncryptionModeDto::NotSupported => EncryptionMode::NotSupported,
},
_ => EncryptionMode::default(),
};
let table_keys = dto
.table_keys
.into_iter()
.map(|tk| TableKeyConfig {
table: tk.table,
key_columns: tk.key_columns,
})
.collect();
let config = MsSqlSourceConfig {
host: mapper.resolve_string(&dto.host)?,
port: mapper.resolve_typed(&dto.port)?,
database: mapper.resolve_string(&dto.database)?,
user: mapper.resolve_string(&dto.user)?,
password: mapper.resolve_string(&dto.password)?,
auth_mode,
tables: dto.tables,
poll_interval_ms: 1000,
encryption,
trust_server_certificate: mapper.resolve_typed(&dto.trust_server_certificate)?,
table_keys,
start_position: Default::default(),
};
let provider = MsSqlBootstrapProvider::new("mssql-bootstrap", config);
Ok(Box::new(provider))
}
}