use std::collections::HashMap; use tardis::basic::dto::TardisContext; use tardis::basic::field::TrimString; use tardis::basic::result::TardisResult; use tardis::db::reldb_client::TardisActiveModel; use tardis::db::sea_orm; use tardis::db::sea_orm::sea_query::Expr; use tardis::db::sea_orm::sea_query::Query; use tardis::log::info; use tardis::TardisFuns; use bios_basic::rbum::dto::rbum_domain_dto::RbumDomainAddReq; use bios_basic::rbum::dto::rbum_filer_dto::{RbumBasicFilterReq, RbumItemAttrFilterReq, RbumKindAttrFilterReq}; use bios_basic::rbum::dto::rbum_item_attr_dto::{RbumItemAttrAddReq, RbumItemAttrModifyReq, RbumItemAttrsAddOrModifyReq}; use bios_basic::rbum::dto::rbum_item_dto::{RbumItemAddReq, RbumItemKernelModifyReq}; use bios_basic::rbum::dto::rbum_kind_attr_dto::RbumKindAttrAddReq; use bios_basic::rbum::dto::rbum_kind_dto::RbumKindAddReq; use bios_basic::rbum::rbum_enumeration::{RbumDataTypeKind, RbumScopeLevelKind, RbumWidgetTypeKind}; use bios_basic::rbum::serv::rbum_crud_serv::RbumCrudOperation; use bios_basic::rbum::serv::rbum_domain_serv::RbumDomainServ; use bios_basic::rbum::serv::rbum_item_serv::{RbumItemAttrServ, RbumItemServ}; use bios_basic::rbum::serv::rbum_kind_serv::{RbumKindAttrServ, RbumKindServ}; pub async fn test(context: &TardisContext) -> TardisResult<()> { test_rbum_item(context).await?; test_rbum_item_attr(context).await?; test_rbum_item_attr_has_main_table(context).await?; test_rbum_item_with_none_owner_name(context).await?; Ok(()) } async fn test_rbum_item(context: &TardisContext) -> TardisResult<()> { let mut funs = TardisFuns::inst_with_db_conn("".to_string(), None); funs.begin().await?; info!("【test_rbum_item】 : Prepare : RbumKindServ::add_rbum"); let kind_id = RbumKindServ::add_rbum( &mut RbumKindAddReq { code: TrimString("reldb".to_string()), name: TrimString("关系型数据库".to_string()), module: None, note: None, icon: None, sort: None, ext_table_name: None, scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; info!("【test_rbum_item】 : Prepare Domain : RbumDomainServ::add_rbum"); let domain_id = RbumDomainServ::add_rbum( &mut RbumDomainAddReq { code: TrimString("mysql-dev".to_string()), name: TrimString("Mysql测试集群".to_string()), note: Some("...".to_string()), icon: Some("...".to_string()), sort: None, scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; // ----------------------------------- info!("【test_rbum_item】 : Test Add : RbumItemServ::add_rbum"); assert!(RbumItemServ::add_rbum( &mut RbumItemAddReq { id: None, code: None, name: TrimString("".to_string()), scope_level: Some(RbumScopeLevelKind::L2), disabled: None, rel_rbum_kind_id: "".to_string(), rel_rbum_domain_id: domain_id.to_string() }, &funs, context, ) .await .is_err()); assert!(RbumItemServ::add_rbum( &mut RbumItemAddReq { id: None, code: None, name: TrimString("".to_string()), scope_level: Some(RbumScopeLevelKind::L2), disabled: None, rel_rbum_kind_id: kind_id.to_string(), rel_rbum_domain_id: "".to_string() }, &funs, context, ) .await .is_err()); assert!(RbumItemServ::add_rbum( &mut RbumItemAddReq { id: None, code: None, name: TrimString("".to_string()), scope_level: Some(RbumScopeLevelKind::L2), disabled: None, rel_rbum_kind_id: "123".to_string(), rel_rbum_domain_id: "123".to_string() }, &funs, context, ) .await .is_err()); let id = RbumItemServ::add_rbum( &mut RbumItemAddReq { id: None, code: None, name: TrimString("实例1".to_string()), disabled: None, rel_rbum_kind_id: kind_id.to_string(), rel_rbum_domain_id: domain_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; info!("【test_rbum_item】 : Test Get : RbumItemServ::get_rbum"); let rbum = RbumItemServ::get_rbum(&id, &RbumBasicFilterReq::default(), &funs, context).await?; assert_eq!(rbum.id, id); assert_eq!(rbum.name, "实例1"); info!("【test_rbum_item】 : Test Modify : RbumItemServ::modify_rbum"); RbumItemServ::modify_rbum( &id, &mut RbumItemKernelModifyReq { code: None, name: Some(TrimString("数据库实例1".to_string())), disabled: None, scope_level: None, }, &funs, context, ) .await?; info!("【test_rbum_item】 : Test Find : RbumItemServ::paginate_rbums"); let rbums = RbumItemServ::paginate_rbums( &RbumBasicFilterReq { scope_level: Some(RbumScopeLevelKind::L2), name: Some("%据库%".to_string()), ..Default::default() }, 1, 10, None, None, &funs, context, ) .await?; assert_eq!(rbums.page_number, 1); assert_eq!(rbums.page_size, 10); assert_eq!(rbums.total_size, 1); assert_eq!(rbums.records.first().unwrap().name, "数据库实例1"); info!("【test_rbum_item】 : Test Delete : RbumItemServ::delete_rbum"); RbumItemServ::delete_rbum(&id, &funs, context).await?; assert!(RbumItemServ::get_rbum(&id, &RbumBasicFilterReq::default(), &funs, context).await.is_err()); funs.rollback().await?; Ok(()) } async fn test_rbum_item_attr(context: &TardisContext) -> TardisResult<()> { let mut funs = TardisFuns::inst_with_db_conn("".to_string(), None); funs.begin().await?; info!("【test_rbum_item_attr】 : Prepare : RbumKindServ::add_rbum"); let kind_id = RbumKindServ::add_rbum( &mut RbumKindAddReq { code: TrimString("reldb".to_string()), name: TrimString("关系型数据库".to_string()), module: None, note: None, icon: None, sort: None, ext_table_name: None, scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; info!("【test_rbum_item_attr】 : Prepare Kind Attr : RbumKindAttrServ::add_rbum"); let kind_attr_id = RbumKindAttrServ::add_rbum( &mut RbumKindAttrAddReq { name: TrimString("db_type".to_string()), module: None, label: "数据库类型".to_string(), data_type: RbumDataTypeKind::String, widget_type: RbumWidgetTypeKind::InputTxt, note: None, sort: None, main_column: None, position: None, capacity: None, overload: None, default_value: None, options: None, required: None, min_length: None, max_length: None, action: None, ext: None, rel_rbum_kind_id: kind_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), idx: None, hide: None, secret: None, show_by_conds: None, widget_columns: None, dyn_default_value: None, dyn_options: None, parent_attr_name: None, }, &funs, context, ) .await?; info!("【test_rbum_item_attr】 : Prepare Domain : RbumDomainServ::add_rbum"); let domain_id = RbumDomainServ::add_rbum( &mut RbumDomainAddReq { code: TrimString("mysql-dev".to_string()), name: TrimString("Mysql测试集群".to_string()), note: Some("...".to_string()), icon: Some("...".to_string()), sort: None, scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; let item_id = RbumItemServ::add_rbum( &mut RbumItemAddReq { id: None, code: None, name: TrimString("实例1".to_string()), disabled: None, rel_rbum_kind_id: kind_id.to_string(), rel_rbum_domain_id: domain_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; // ----------------------------------- info!("【test_rbum_item_attr】 : Test Add : RbumItemAttrServ::add_rbum"); assert!(RbumItemAttrServ::add_rbum( &mut RbumItemAttrAddReq { value: "数据1".to_string(), rel_rbum_item_id: "".to_string(), rel_rbum_kind_attr_id: "".to_string() }, &funs, context, ) .await .is_err()); assert!(RbumItemAttrServ::add_rbum( &mut RbumItemAttrAddReq { value: "数据1".to_string(), rel_rbum_item_id: item_id.to_string(), rel_rbum_kind_attr_id: "".to_string() }, &funs, context, ) .await .is_err()); assert!(RbumItemAttrServ::add_rbum( &mut RbumItemAttrAddReq { value: "数据1".to_string(), rel_rbum_item_id: "".to_string(), rel_rbum_kind_attr_id: kind_attr_id.to_string() }, &funs, context, ) .await .is_err()); let item_attr_id = RbumItemAttrServ::add_rbum( &mut RbumItemAttrAddReq { value: "数据1".to_string(), rel_rbum_item_id: item_id.to_string(), rel_rbum_kind_attr_id: kind_attr_id.to_string(), }, &funs, context, ) .await?; info!("【test_rbum_item_attr】 : Test Get : RbumItemAttrServ::get_rbum"); let rbum = RbumItemAttrServ::get_rbum(&item_attr_id, &RbumItemAttrFilterReq::default(), &funs, context).await?; assert_eq!(rbum.id, item_attr_id); assert_eq!(rbum.value, "数据1"); assert_eq!(rbum.rel_rbum_item_id, item_id.to_string()); assert_eq!(rbum.rel_rbum_kind_attr_id, kind_attr_id.to_string()); assert_eq!(rbum.rel_rbum_kind_attr_name, "db_type".to_string()); info!("【test_rbum_item_attr】 : Test Modify : RbumItemAttrServ::modify_rbum"); assert!(RbumItemAttrServ::modify_rbum("111", &mut RbumItemAttrModifyReq { value: "数据2".to_string() }, &funs, context).await.is_err()); RbumItemAttrServ::modify_rbum(&item_attr_id, &mut RbumItemAttrModifyReq { value: "数据3".to_string() }, &funs, context).await?; info!("【test_rbum_item_attr】 : Test Find : RbumItemAttrServ::paginate_rbums"); let rbums = RbumItemAttrServ::paginate_rbums(&RbumItemAttrFilterReq::default(), 1, 10, None, None, &funs, context).await?; assert_eq!(rbums.page_number, 1); assert_eq!(rbums.page_size, 10); assert_eq!(rbums.total_size, 1); assert_eq!(rbums.records.first().unwrap().value, "数据3"); info!("【test_rbum_item_attr】 : Test Delete : RbumItemAttrServ::delete_rbum"); RbumItemAttrServ::delete_rbum(&item_attr_id, &funs, context).await?; assert!(RbumItemAttrServ::get_rbum(&item_attr_id, &RbumItemAttrFilterReq::default(), &funs, context).await.is_err()); funs.rollback().await?; Ok(()) } async fn test_rbum_item_attr_has_main_table(context: &TardisContext) -> TardisResult<()> { let mut funs = TardisFuns::inst_with_db_conn("".to_string(), None); funs.begin().await?; let compatible_type = TardisFuns::reldb_by_module_or_default("").compatible_type(); TardisFuns::inst_with_db_conn("".to_string(), None).db().init(test_iam_account::ActiveModel::init(TardisFuns::reldb().backend(), None, compatible_type)).await?; info!("【test_rbum_item_attr】 : Prepare : RbumKindServ::add_rbum"); let kind_id = RbumKindServ::add_rbum( &mut RbumKindAddReq { code: TrimString("account".to_string()), name: TrimString("账号".to_string()), module: None, note: None, icon: None, sort: None, ext_table_name: Some("iam_account".to_string()), scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; info!("【test_rbum_item_attr】 : Prepare Kind Attr : RbumKindAttrServ::add_rbum"); RbumKindAttrServ::add_rbum( &mut RbumKindAttrAddReq { name: TrimString("ext2".to_string()), module: None, label: "图标".to_string(), data_type: RbumDataTypeKind::String, widget_type: RbumWidgetTypeKind::InputTxt, note: None, sort: None, main_column: Some(true), position: None, capacity: None, overload: None, default_value: None, options: None, required: None, min_length: None, max_length: None, action: None, ext: None, rel_rbum_kind_id: kind_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), idx: None, hide: None, secret: None, show_by_conds: None, widget_columns: None, dyn_default_value: None, dyn_options: None, parent_attr_name: None, }, &funs, context, ) .await?; RbumKindAttrServ::add_rbum( &mut RbumKindAttrAddReq { name: TrimString("ext1_idx".to_string()), module: None, label: "是否临时账号".to_string(), data_type: RbumDataTypeKind::Boolean, widget_type: RbumWidgetTypeKind::Checkbox, note: None, sort: None, main_column: Some(true), position: None, capacity: None, overload: None, default_value: None, options: None, required: None, min_length: None, max_length: None, action: None, ext: None, rel_rbum_kind_id: kind_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), idx: None, hide: None, secret: None, show_by_conds: None, widget_columns: None, dyn_default_value: None, dyn_options: None, parent_attr_name: None, }, &funs, context, ) .await?; RbumKindAttrServ::add_rbum( &mut RbumKindAttrAddReq { name: TrimString("addr".to_string()), module: None, label: "住址".to_string(), data_type: RbumDataTypeKind::String, widget_type: RbumWidgetTypeKind::InputTxt, note: None, sort: None, main_column: None, position: None, capacity: None, overload: None, default_value: None, options: None, required: None, min_length: None, max_length: None, action: None, ext: None, rel_rbum_kind_id: kind_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), idx: None, hide: None, secret: None, show_by_conds: None, widget_columns: None, dyn_default_value: None, dyn_options: None, parent_attr_name: None, }, &funs, context, ) .await?; info!("【test_rbum_item_attr】 : Prepare Domain : RbumDomainServ::add_rbum"); let domain_id = RbumDomainServ::add_rbum( &mut RbumDomainAddReq { code: TrimString("test-iam".to_string()), name: TrimString("IAM".to_string()), note: Some("...".to_string()), icon: Some("...".to_string()), sort: None, scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; let item_id = RbumItemServ::add_rbum( &mut RbumItemAddReq { id: None, code: None, name: TrimString("用户1".to_string()), disabled: None, rel_rbum_kind_id: kind_id.to_string(), rel_rbum_domain_id: domain_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), }, &funs, context, ) .await?; funs.db() .execute( Query::insert() .into_table(test_iam_account::Entity) .columns(vec![test_iam_account::Column::Id, test_iam_account::Column::Ext1Idx, test_iam_account::Column::Ext2]) .values_panic(vec![item_id.clone().into(), "".into(), "".into()]), ) .await?; // ----------------------------------- info!("【test_rbum_item_attr】 : Test RbumItemAttrServ::find_item_attr_defs"); let attr_defs = RbumKindAttrServ::find_rbums( &RbumKindAttrFilterReq { basic: RbumBasicFilterReq { rbum_kind_id: Some(kind_id.to_string()), ..Default::default() }, ..Default::default() }, None, None, &funs, context, ) .await?; assert_eq!(attr_defs.len(), 3); info!("【test_rbum_item_attr】 : Test Add : RbumItemAttrServ::add_or_modify_item_attrs"); RbumItemAttrServ::add_or_modify_item_attrs( &RbumItemAttrsAddOrModifyReq { values: HashMap::from([ ("ext1_idx".to_string(), "true".to_string()), ("ext2".to_string(), "/c/c/d/".to_string()), ("addr".to_string(), "中国杭州".to_string()), ]), rel_rbum_item_id: item_id.to_string(), }, &funs, context, ) .await?; let ext_values = RbumItemAttrServ::find_rbums( &RbumItemAttrFilterReq { basic: Default::default(), rel_rbum_item_id: Some(item_id.to_string()), ..Default::default() }, None, None, &funs, context, ) .await?; assert_eq!(ext_values.len(), 1); assert_eq!(ext_values.first().unwrap().value, "中国杭州"); let main_values = funs .db() .get_dto::( Query::select() .column(test_iam_account::Column::Id) .column(test_iam_account::Column::Ext1Idx) .column(test_iam_account::Column::Ext2) .from(test_iam_account::Entity) .and_where(Expr::col(test_iam_account::Column::Id).eq(item_id.as_str())), ) .await? .unwrap(); assert_eq!(main_values.ext1_idx, "true"); assert_eq!(main_values.ext2, "/c/c/d/"); info!("【test_rbum_item_attr】 : Test Modify : RbumItemAttrServ::add_or_modify_item_attrs"); RbumItemAttrServ::add_or_modify_item_attrs( &RbumItemAttrsAddOrModifyReq { values: HashMap::from([("ext1_idx".to_string(), "false".to_string()), ("addr".to_string(), "杭州".to_string())]), rel_rbum_item_id: item_id.to_string(), }, &funs, context, ) .await?; let ext_values = RbumItemAttrServ::find_rbums( &RbumItemAttrFilterReq { basic: Default::default(), rel_rbum_item_id: Some(item_id.to_string()), ..Default::default() }, None, None, &funs, context, ) .await?; assert_eq!(ext_values.len(), 1); assert_eq!(ext_values.first().unwrap().value, "杭州"); let main_values = funs .db() .get_dto::( Query::select() .column(test_iam_account::Column::Id) .column(test_iam_account::Column::Ext1Idx) .column(test_iam_account::Column::Ext2) .from(test_iam_account::Entity) .and_where(Expr::col(test_iam_account::Column::Id).eq(item_id.as_str())), ) .await? .unwrap(); assert_eq!(main_values.ext1_idx, "false"); assert_eq!(main_values.ext2, "/c/c/d/"); funs.rollback().await?; Ok(()) } async fn test_rbum_item_with_none_owner_name(context: &TardisContext) -> TardisResult<()> { let mut funs = TardisFuns::inst_with_db_conn("".to_string(), None); funs.begin().await?; let ctx_with_none_owner = TardisContext { own_paths: context.own_paths.to_string(), ak: context.ak.to_string(), owner: "xxxxx".to_string(), roles: context.roles.clone(), groups: context.groups.clone(), ext: context.ext.clone(), sync_task_fns: Default::default(), async_task_fns: Default::default(), }; info!("【test_rbum_item_with_none_owner_name】 : Prepare : RbumKindServ::add_rbum"); let kind_id = RbumKindServ::add_rbum( &mut RbumKindAddReq { code: TrimString("reldb".to_string()), name: TrimString("关系型数据库".to_string()), module: None, note: None, icon: None, sort: None, ext_table_name: None, scope_level: Some(RbumScopeLevelKind::L2), }, &funs, &ctx_with_none_owner, ) .await?; info!("【test_rbum_item_with_none_owner_name】 : Prepare Domain : RbumDomainServ::add_rbum"); let domain_id = RbumDomainServ::add_rbum( &mut RbumDomainAddReq { code: TrimString("mysql-dev".to_string()), name: TrimString("Mysql测试集群".to_string()), note: Some("...".to_string()), icon: Some("...".to_string()), sort: None, scope_level: Some(RbumScopeLevelKind::L2), }, &funs, &ctx_with_none_owner, ) .await?; // ----------------------------------- let id = RbumItemServ::add_rbum( &mut RbumItemAddReq { id: None, code: None, name: TrimString("实例xxx".to_string()), disabled: None, rel_rbum_kind_id: kind_id.to_string(), rel_rbum_domain_id: domain_id.to_string(), scope_level: Some(RbumScopeLevelKind::L2), }, &funs, &ctx_with_none_owner, ) .await?; info!("【test_rbum_item_with_none_owner_name】 : Test Get : RbumItemServ::get_rbum"); let rbum = RbumItemServ::get_rbum(&id, &RbumBasicFilterReq::default(), &funs, context).await?; assert_eq!(rbum.id, id); assert_eq!(rbum.name, "实例xxx"); assert_eq!(rbum.owner_name, None); funs.rollback().await?; Ok(()) } #[derive(Debug, sea_orm::FromQueryResult)] pub struct IamAccountResp { pub ext1_idx: String, pub ext2: String, } mod test_iam_account { use tardis::basic::dto::TardisContext; use tardis::db::reldb_client::TardisActiveModel; use tardis::db::sea_orm; use tardis::db::sea_orm::sea_query::{ColumnDef, Index, IndexCreateStatement, Table, TableCreateStatement}; use tardis::db::sea_orm::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] #[sea_orm(table_name = "iam_account")] pub struct Model { #[sea_orm(primary_key, auto_increment = false)] pub id: String, pub ext1_idx: String, pub ext2: String, pub own_paths: String, } impl TardisActiveModel for ActiveModel { fn fill_ctx(&mut self, ctx: &TardisContext, is_insert: bool) { if is_insert { self.own_paths = Set(ctx.own_paths.to_string()); } } fn create_table_statement(_: DbBackend) -> TableCreateStatement { Table::create() .table(Entity.table_ref()) .if_not_exists() .col(ColumnDef::new(Column::Id).not_null().string().primary_key()) .col(ColumnDef::new(Column::Ext1Idx).not_null().string()) .col(ColumnDef::new(Column::Ext2).not_null().string()) .to_owned() } fn create_index_statement() -> Vec { vec![Index::create().name(&format!("idx-{}-idx1", Entity.table_name())).table(Entity).col(Column::Ext1Idx).to_owned()] } } impl ActiveModelBehavior for ActiveModel {} #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} }