From 0050768d744d422c5674b90cf085cfb3f4828fa8 Mon Sep 17 00:00:00 2001 From: gudaoxuri Date: Mon, 13 May 2024 10:16:00 +0800 Subject: [PATCH] Improve handling of secret attributes. --- .../basic/src/rbum/dto/rbum_item_attr_dto.rs | 4 +- backend/basic/src/rbum/serv/rbum_item_serv.rs | 128 +++++++++--------- backend/basic/src/rbum/serv/rbum_kind_serv.rs | 17 ++- backend/basic/src/rbum/serv/rbum_rel_serv.rs | 1 - backend/basic/tests/test_rbum_kind.rs | 8 +- 5 files changed, 83 insertions(+), 75 deletions(-) diff --git a/backend/basic/src/rbum/dto/rbum_item_attr_dto.rs b/backend/basic/src/rbum/dto/rbum_item_attr_dto.rs index 8510bea3a..aa10c33ba 100644 --- a/backend/basic/src/rbum/dto/rbum_item_attr_dto.rs +++ b/backend/basic/src/rbum/dto/rbum_item_attr_dto.rs @@ -53,9 +53,9 @@ pub struct RbumItemAttrsAddOrModifyReq { /// /// 添加或修改的值集合 /// - /// Format: ``{ "field name": "field value" }`` + /// Format: ``{ "attribute name": "attribute value" }`` /// - /// ``field name``: [`crate::rbum::dto::rbum_kind_attr_dto::RbumKindAttrDetailResp::name`] + /// ``attribute name``: [`crate::rbum::dto::rbum_kind_attr_dto::RbumKindAttrDetailResp::name`] pub values: HashMap, /// Associated [resource item](crate::rbum::dto::rbum_item_dto::RbumItemDetailResp) id /// diff --git a/backend/basic/src/rbum/serv/rbum_item_serv.rs b/backend/basic/src/rbum/serv/rbum_item_serv.rs index 6f977ad87..ee6d86568 100644 --- a/backend/basic/src/rbum/serv/rbum_item_serv.rs +++ b/backend/basic/src/rbum/serv/rbum_item_serv.rs @@ -1415,15 +1415,15 @@ impl RbumCrudOperation, funs: &TardisFunsInst, ctx: &TardisContext, - ) -> TardisResult> { + ) -> TardisResult<(String, Vec)> { let rel_rbum_kind_id = RbumItemServ::peek_rbum( rbum_item_id, &RbumBasicFilterReq { @@ -1435,10 +1435,10 @@ impl RbumItemAttrServ { ) .await? .rel_rbum_kind_id; - RbumKindAttrServ::find_rbums( + let rbum_kind_attrs = RbumKindAttrServ::find_rbums( &RbumKindAttrFilterReq { basic: RbumBasicFilterReq { - rbum_kind_id: Some(rel_rbum_kind_id), + rbum_kind_id: Some(rel_rbum_kind_id.clone()), ..Default::default() }, secret, @@ -1449,7 +1449,8 @@ impl RbumItemAttrServ { funs, ctx, ) - .await + .await?; + Ok((rel_rbum_kind_id, rbum_kind_attrs)) } /// Add or modify resource item extended attributes @@ -1457,21 +1458,26 @@ impl RbumItemAttrServ { /// 添加或修改资源项扩展属性 pub async fn add_or_modify_item_attrs(add_req: &RbumItemAttrsAddOrModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { // Implicit rel_rbum_kind_attr scope check - let rbum_kind_attrs = Self::find_item_attr_defs_by_item_id(&add_req.rel_rbum_item_id, None, funs, ctx).await?; - let in_main_table_attrs = rbum_kind_attrs.iter().filter(|i| add_req.values.contains_key(&i.name) && i.main_column && !i.secret).collect::>(); - let in_ext_table_attrs = rbum_kind_attrs.iter().filter(|i| add_req.values.contains_key(&i.name) && !i.main_column && !i.secret).collect::>(); - let in_secret_table_attrs = rbum_kind_attrs.iter().filter(|i| i.secret).collect::>(); + let (rel_rbum_kind_id, rbum_kind_attrs) = Self::find_res_kind_id_and_res_kind_attrs_by_item_id(&add_req.rel_rbum_item_id, None, funs, ctx).await?; + let in_main_table_attrs = rbum_kind_attrs.iter().filter(|i| add_req.values.contains_key(&i.name) && i.main_column).collect::>(); + let in_ext_table_attrs = rbum_kind_attrs.iter().filter(|i| add_req.values.contains_key(&i.name) && !i.main_column).collect::>(); if !in_main_table_attrs.is_empty() { // Implicit rel_rbum_item scope check - let rel_rbum_kind_id = RbumItemServ::peek_rbum(&add_req.rel_rbum_item_id, &RbumBasicFilterReq::default(), funs, ctx).await?.rel_rbum_kind_id; let main_table_name = RbumKindServ::peek_rbum(&rel_rbum_kind_id, &RbumKindFilterReq::default(), funs, ctx).await?.ext_table_name; let mut update_statement = Query::update(); update_statement.table(Alias::new(&main_table_name)); for in_main_table_attr in in_main_table_attrs { + let column_val = if in_main_table_attr.secret && !in_main_table_attr.dyn_default_value.is_empty() { + Self::replace_url_placeholder(&in_main_table_attr.dyn_default_value, &add_req.values, funs).await? + } else if in_main_table_attr.secret { + in_main_table_attr.default_value.clone() + } else { + add_req.values.get(&in_main_table_attr.name).expect("ignore").clone() + }; + let column_name = Alias::new(&in_main_table_attr.name); - let column_val = add_req.values.get(&in_main_table_attr.name).expect("ignore").clone(); update_statement.value(column_name, Value::from(column_val)); } update_statement.and_where(Expr::col(ID_FIELD.clone()).eq(add_req.rel_rbum_item_id.as_str())); @@ -1480,7 +1486,14 @@ impl RbumItemAttrServ { if !in_ext_table_attrs.is_empty() { for in_ext_table_attr in in_ext_table_attrs { - let column_val = add_req.values.get(&in_ext_table_attr.name).expect("ignore").clone(); + let column_val = if in_ext_table_attr.secret && !in_ext_table_attr.dyn_default_value.is_empty() { + Self::replace_url_placeholder(&in_ext_table_attr.dyn_default_value, &add_req.values, funs).await? + } else if in_ext_table_attr.secret { + in_ext_table_attr.default_value.clone() + } else { + add_req.values.get(&in_ext_table_attr.name).expect("ignore").clone() + }; + let exist_item_attr_ids = Self::find_id_rbums( &RbumItemAttrFilterReq { basic: Default::default(), @@ -1510,66 +1523,23 @@ impl RbumItemAttrServ { } } - if !in_secret_table_attrs.is_empty() { - for in_secret_table_attr in in_secret_table_attrs { - let secret_item_attr_ids = Self::find_id_rbums( - &RbumItemAttrFilterReq { - basic: Default::default(), - rel_rbum_item_id: Some(add_req.rel_rbum_item_id.to_string()), - rel_rbum_kind_attr_id: Some(in_secret_table_attr.id.to_string()), - }, - None, - None, - funs, - ctx, - ) - .await?; - let result = if !in_secret_table_attr.dyn_default_value.is_empty() { - if RbumKindAttrServ::url_match(&in_secret_table_attr.dyn_default_value).unwrap() { - let url = RbumKindAttrServ::url_replace(&in_secret_table_attr.dyn_default_value, add_req.values.clone()).unwrap(); - if RbumKindAttrServ::url_match(&url).unwrap() { - return Err(funs.err().bad_request( - &Self::get_obj_name(), - "add_or_modify_item_attrs", - "url processing failure", - "400-rbum-kind-attr-dyn-url-illegal", - )); - } - funs.web_client().get_to_str(&url, None).await.unwrap().body.unwrap() - } else { - funs.web_client().get_to_str(&in_secret_table_attr.dyn_default_value, None).await.unwrap().body.unwrap() - } - } else { - in_secret_table_attr.default_value.clone() - }; - if secret_item_attr_ids.is_empty() { - Self::add_rbum( - &mut RbumItemAttrAddReq { - value: result.clone(), - rel_rbum_item_id: add_req.rel_rbum_item_id.to_string(), - rel_rbum_kind_attr_id: in_secret_table_attr.id.to_string(), - }, - funs, - ctx, - ) - .await?; - } else { - Self::modify_rbum(secret_item_attr_ids.first().expect("ignore"), &mut RbumItemAttrModifyReq { value: result }, funs, ctx).await?; - } - } - } - Ok(()) } + /// Get resource item extended attributes + /// + /// 获取资源项扩展属性集合 + /// + /// # Returns + /// + /// The key is the attribute name, and the value is the attribute value. pub async fn find_item_attr_values(rbum_item_id: &str, secret: Option, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult> { - let rbum_kind_attrs = Self::find_item_attr_defs_by_item_id(rbum_item_id, secret, funs, ctx).await?; + let (rel_rbum_kind_id, rbum_kind_attrs) = Self::find_res_kind_id_and_res_kind_attrs_by_item_id(rbum_item_id, secret, funs, ctx).await?; let in_main_table_attrs = rbum_kind_attrs.iter().filter(|i| i.main_column).collect::>(); let has_in_ext_table_attrs = rbum_kind_attrs.iter().any(|i| !i.main_column); let mut values: HashMap = HashMap::new(); if !in_main_table_attrs.is_empty() { - let rel_rbum_kind_id = RbumItemServ::peek_rbum(rbum_item_id, &RbumBasicFilterReq::default(), funs, ctx).await?.rel_rbum_kind_id; let ext_table_name = RbumKindServ::peek_rbum(&rel_rbum_kind_id, &RbumKindFilterReq::default(), funs, ctx).await?.ext_table_name; let mut select_statement = Query::select(); @@ -1606,6 +1576,34 @@ impl RbumItemAttrServ { } Ok(values) } + + async fn replace_url_placeholder(url: &str, values: &HashMap, funs: &TardisFunsInst) -> TardisResult { + let resp = if RbumKindAttrServ::url_has_placeholder(url)? { + let url: String = RbumKindAttrServ::url_replace(url, values)?; + if RbumKindAttrServ::url_has_placeholder(&url)? { + return Err(funs.err().bad_request( + &Self::get_obj_name(), + "replace_url_placeholder", + "url processing failure", + "400-rbum-kind-attr-dyn-url-illegal", + )); + } + funs.web_client().get_to_str(&url, None).await + } else { + funs.web_client().get_to_str(url, None).await + }; + match resp { + Ok(resp) => Ok(resp.body.unwrap_or_else(|| "".to_string())), + Err(e) => { + return Err(funs.err().bad_request( + &Self::get_obj_name(), + "replace_url_placeholder", + &format!("url processing failure: {}", e), + "400-rbum-kind-attr-dyn-url-illegal", + )); + } + } + } } #[derive(Debug, sea_orm::FromQueryResult)] diff --git a/backend/basic/src/rbum/serv/rbum_kind_serv.rs b/backend/basic/src/rbum/serv/rbum_kind_serv.rs index d5b7f35a1..0ee26b2af 100644 --- a/backend/basic/src/rbum/serv/rbum_kind_serv.rs +++ b/backend/basic/src/rbum/serv/rbum_kind_serv.rs @@ -41,7 +41,8 @@ impl RbumCrudOperation 0 + if funs.db().count(Query::select().column(rbum_kind::Column::Id).from(rbum_kind::Entity).and_where(Expr::col(rbum_kind::Column::Code).eq(add_req.code.to_string()))).await? + > 0 { return Err(funs.err().conflict(&Self::get_obj_name(), "add", &format!("code {} already exists", add_req.code), "409-rbum-*-code-exist")); } @@ -346,7 +347,14 @@ impl RbumCrudOperation) -> TardisResult { + /// URL replace + /// + /// URL替换 + /// + /// Replace ``{key}`` in the URL with the value in values. + /// + /// 将URL中的 ``{key}`` 替换为values中的值。 + pub fn url_replace(uri: &str, values: &HashMap) -> TardisResult { let mut new_uri = uri.to_string(); for mat in EXTRACT_R.captures_iter(uri) { let old_key = mat.get(0).expect("ignore").as_str(); @@ -358,7 +366,10 @@ impl RbumKindAttrServ { Ok(new_uri) } - pub fn url_match(uri: &str) -> TardisResult { + /// Whether the URL contains unreplaced placeholders + /// + /// URL中是否包含未替换的占位符 + pub fn url_has_placeholder(uri: &str) -> TardisResult { Ok(!EXTRACT_R.is_match(uri)) } } diff --git a/backend/basic/src/rbum/serv/rbum_rel_serv.rs b/backend/basic/src/rbum/serv/rbum_rel_serv.rs index fb1de4852..98d73a7dd 100644 --- a/backend/basic/src/rbum/serv/rbum_rel_serv.rs +++ b/backend/basic/src/rbum/serv/rbum_rel_serv.rs @@ -5,7 +5,6 @@ use itertools::Itertools; use tardis::basic::dto::TardisContext; use tardis::basic::result::TardisResult; use tardis::db::reldb_client::IdResp; -use tardis::db::sea_orm; use tardis::db::sea_orm::sea_query::*; use tardis::db::sea_orm::IdenStatic; use tardis::db::sea_orm::*; diff --git a/backend/basic/tests/test_rbum_kind.rs b/backend/basic/tests/test_rbum_kind.rs index 2a84f66df..1f3ac5b1f 100644 --- a/backend/basic/tests/test_rbum_kind.rs +++ b/backend/basic/tests/test_rbum_kind.rs @@ -21,20 +21,20 @@ pub async fn test(context: &TardisContext) -> TardisResult<()> { } async fn test_rbum_kind_url() -> TardisResult<()> { - assert!(!RbumKindAttrServ::url_match("http://iam/{key}?{key}=1&{key2}=2").unwrap()); + assert!(!RbumKindAttrServ::url_has_placeholder("http://iam/{key}?{key}=1&{key2}=2").unwrap()); assert_eq!( "http://iam/t1?t1=1&t2=2", RbumKindAttrServ::url_replace( "http://iam/{key}?{key}=1&{key2}=2", - HashMap::from([("key".to_string(), "t1".to_string()), ("key2".to_string(), "t2".to_string())]), + &HashMap::from([("key".to_string(), "t1".to_string()), ("key2".to_string(), "t2".to_string())]), ) .unwrap() .as_str() ); - assert!(RbumKindAttrServ::url_match( + assert!(RbumKindAttrServ::url_has_placeholder( RbumKindAttrServ::url_replace( "http://iam/{key}?{key}=1&{key2}=2", - HashMap::from([("key".to_string(), "t1".to_string()), ("key2".to_string(), "t2".to_string())]), + &HashMap::from([("key".to_string(), "t1".to_string()), ("key2".to_string(), "t2".to_string())]), ) .unwrap() .as_str(),