use std::sync::Arc;
use async_trait::async_trait;
use sea_orm::sea_query::OnConflict;
use sea_orm::{ColumnTrait, Condition, EntityTrait, Set};
use serde_json::Value as JsonValue;
use time::OffsetDateTime;
use toolkit_db::secure::{AccessScope, SecureDeleteExt, SecureEntityExt, SecureInsertExt};
use uuid::Uuid;
use crate::domain::error::ChatEngineError;
use crate::domain::ports::PluginConfigRepo;
use crate::infra::db::entity::plugin_config::{ActiveModel, Column, Entity as PluginConfigEntity};
use crate::infra::db::repo::ChatEngineDb;
pub struct SeaPluginConfigRepo {
db: Arc<ChatEngineDb>,
}
impl SeaPluginConfigRepo {
#[must_use]
pub fn new(db: Arc<ChatEngineDb>) -> Self {
Self { db }
}
}
#[async_trait]
impl PluginConfigRepo for SeaPluginConfigRepo {
async fn find(
&self,
plugin_instance_id: &str,
session_type_id: Uuid,
) -> Result<Option<JsonValue>, ChatEngineError> {
let conn = self.db.conn()?;
let scope = AccessScope::allow_all();
let row = PluginConfigEntity::find_by_id((plugin_instance_id.to_owned(), session_type_id))
.secure()
.scope_with(&scope)
.one(&conn)
.await?;
Ok(row.and_then(|m| m.config))
}
async fn upsert(
&self,
plugin_instance_id: &str,
session_type_id: Uuid,
config: JsonValue,
) -> Result<(), ChatEngineError> {
let now = OffsetDateTime::now_utc();
let am = ActiveModel {
plugin_instance_id: Set(plugin_instance_id.to_owned()),
session_type_id: Set(session_type_id),
config: Set(Some(config)),
created_at: Set(now),
updated_at: Set(now),
};
let on_conflict = OnConflict::columns([Column::PluginInstanceId, Column::SessionTypeId])
.update_columns([Column::Config, Column::UpdatedAt])
.to_owned();
let conn = self.db.conn()?;
let scope = AccessScope::allow_all();
PluginConfigEntity::insert(am)
.secure()
.scope_unchecked(&scope)?
.on_conflict_raw(on_conflict)
.exec(&conn)
.await?;
Ok(())
}
async fn delete(
&self,
plugin_instance_id: &str,
session_type_id: Uuid,
) -> Result<(), ChatEngineError> {
let conn = self.db.conn()?;
let scope = AccessScope::allow_all();
PluginConfigEntity::delete_many()
.secure()
.scope_with(&scope)
.filter(
Condition::all()
.add(Column::PluginInstanceId.eq(plugin_instance_id.to_owned()))
.add(Column::SessionTypeId.eq(session_type_id)),
)
.exec(&conn)
.await?;
Ok(())
}
}
#[cfg(test)]
#[path = "plugin_config_repo_tests.rs"]
mod plugin_config_repo_tests;