diff --git a/src/application/datakey.rs b/src/application/datakey.rs index 7740ad146b455cc7cb300c6f0f5ba27f63d00f01..21bfa239a8a49137638ed3e8f90bb149a4def4a9 100644 --- a/src/application/datakey.rs +++ b/src/application/datakey.rs @@ -34,9 +34,8 @@ use crate::presentation::handler::control::model::user::dto::UserIdentity; pub trait KeyService: Send + Sync{ async fn create(&self, user: UserIdentity, data: &mut DataKey) -> Result; async fn import(&self, data: &mut DataKey) -> Result; - async fn get_by_name(&self, name: &str) -> Result; + async fn get_raw_key_by_name(&self, name: &str) -> Result; - async fn check_name_exists(&self, name: &str) -> Result; async fn get_all(&self, key_type: Option, visibility: Visibility, user_id: i32) -> Result>; async fn get_one(&self, user: Option, id_or_name: String) -> Result; //get keys content @@ -86,14 +85,14 @@ impl DBKeyService } } - async fn get_and_check_permission(&self, user: Option, id_or_name: String, action: KeyAction) -> Result { + async fn get_and_check_permission(&self, user: Option, id_or_name: String, action: KeyAction, raw_key: bool) -> Result { let id = id_or_name.parse::(); let data_key: DataKey = match id { Ok(id) => { - self.repository.get_by_id(id).await? + self.repository.get_by_id_or_name(Some(id), None, raw_key).await? } Err(_) => { - self.repository.get_by_name(&id_or_name).await? + self.repository.get_by_id_or_name(None, Some(id_or_name), raw_key).await? } }; //check permission for private keys @@ -149,7 +148,7 @@ impl DBKeyService Ok(()) } async fn check_key_hierarchy(&self, user: UserIdentity, data: &DataKey, parent_id: i32) -> Result<()> { - let parent_key = self.repository.get_by_id(parent_id).await?; + let parent_key = self.repository.get_by_id_or_name(Some(parent_id), None, true).await?; //check permission for private keys if parent_key.visibility == Visibility::Private && parent_key.user != user.id { return Err(Error::UnprivilegedError); @@ -188,7 +187,7 @@ where self.check_key_hierarchy(user, data, parent_id).await?; } //check datakey existence - if self.repository.get_by_name(&data.name).await.is_ok() { + if self.repository.get_by_id_or_name(None, Some(data.name.clone()), true).await.is_ok() { return Err(Error::ParameterError(format!("datakey '{}' already exists", data.name))); } //we need to create a key in database first, then generate sensitive data @@ -210,12 +209,8 @@ where self.repository.create(data.clone()).await } - async fn get_by_name(&self, name: &str) -> Result { - self.repository.get_by_name(name).await - } - - async fn check_name_exists(&self, name: &str) -> Result { - self.repository.check_name_exists(name).await + async fn get_raw_key_by_name(&self, name: &str) -> Result { + self.repository.get_by_id_or_name(None, Some(name.to_owned()), true).await } async fn get_all(&self, key_type: Option, visibility: Visibility, user_id: i32) -> Result> { @@ -223,19 +218,19 @@ where } async fn get_one(&self, user: Option, id_or_name: String) -> Result { - let datakey = self.get_and_check_permission(user, id_or_name, KeyAction::Read).await?; + let datakey = self.get_and_check_permission(user, id_or_name, KeyAction::Read, false).await?; Ok(datakey) } async fn export_one(&self, user: Option, id_or_name: String) -> Result { - let mut key = self.get_and_check_permission(user, id_or_name, KeyAction::Read).await?; + let mut key = self.get_and_check_permission(user, id_or_name, KeyAction::Read, true).await?; self.sign_service.read().await.decode_public_keys(&mut key).await?; Ok(key) } async fn export_cert_crl(&self, user: Option, id_or_name: String) -> Result { - let key = self.get_and_check_permission(user, id_or_name, KeyAction::Read).await?; + let key = self.get_and_check_permission(user, id_or_name, KeyAction::Read, true).await?; let crl = self.repository.get_x509_crl_by_ca_id(key.id).await?; Ok(crl) } @@ -243,7 +238,7 @@ where async fn request_delete(&self, user: UserIdentity, id_or_name: String) -> Result<()> { let user_id = user.id; let user_email = user.email.clone(); - let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::Delete).await?; + let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::Delete, true).await?; //check if the ca/ica key is used by other keys if key.key_type == KeyType::X509ICA || key.key_type == KeyType::X509CA { let children = self.repository.get_by_parent_id(key.id).await?; @@ -256,32 +251,32 @@ where async fn cancel_delete(&self, user: UserIdentity, id_or_name: String) -> Result<()> { let user_id = user.id; - let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::CancelDelete).await?; + let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::CancelDelete, true).await?; self.repository.cancel_delete_key(user_id, key.id).await } async fn request_revoke(&self, user: UserIdentity, id_or_name: String, reason: X509RevokeReason) -> Result<()> { let user_id = user.id; let user_email = user.email.clone(); - let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::Revoke).await?; + let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::Revoke, true).await?; self.repository.request_revoke_key(user_id, user_email, key.id, key.parent_id.unwrap(), reason, key.visibility == Visibility::Public).await?; Ok(()) } async fn cancel_revoke(&self, user: UserIdentity, id_or_name: String) -> Result<()> { let user_id = user.id; - let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::CancelRevoke).await?; + let key = self.get_and_check_permission(Some(user), id_or_name, KeyAction::CancelRevoke, true).await?; self.repository.cancel_revoke_key(user_id, key.id, key.parent_id.unwrap()).await?; Ok(()) } async fn enable(&self, user: Option, id_or_name: String) -> Result<()> { - let key = self.get_and_check_permission(user, id_or_name, KeyAction::Enable).await?; + let key = self.get_and_check_permission(user, id_or_name, KeyAction::Enable, true).await?; self.repository.update_state(key.id, KeyState::Enabled).await } async fn disable(&self, user: Option, id_or_name: String) -> Result<()> { - let key = self.get_and_check_permission(user, id_or_name, KeyAction::Disable).await?; + let key = self.get_and_check_permission(user, id_or_name, KeyAction::Disable, true).await?; self.repository.update_state(key.id, KeyState::Disabled).await } diff --git a/src/domain/datakey/repository.rs b/src/domain/datakey/repository.rs index e4f083e52abbccb05200b88640ddfdb8d5c80804..714d8b674a29bfd463f78fa443141fa578edcec6 100644 --- a/src/domain/datakey/repository.rs +++ b/src/domain/datakey/repository.rs @@ -25,12 +25,10 @@ pub trait Repository: Send + Sync { async fn create(&self, data_key: DataKey) -> Result; async fn delete(&self, id: i32) -> Result<()>; async fn get_all_keys(&self, key_type: Option, visibility: Visibility, user_id: i32) -> Result>; - async fn get_by_id(&self, id: i32) -> Result; - async fn get_by_name(&self, name: &str) -> Result; - async fn check_name_exists(&self, name: &str) -> Result; + async fn get_by_id_or_name(&self, id: Option, name: Option, raw_datakey: bool) -> Result; async fn update_state(&self, id: i32, state: KeyState) -> Result<()>; async fn update_key_data(&self, data_key: DataKey) -> Result<()>; - async fn get_enabled_key_by_type_and_name(&self, key_type: String, name: String) -> Result; + async fn get_enabled_key_by_type_and_name_with_parent_key(&self, key_type: String, name: String) -> Result; async fn request_delete_key(&self, user_id: i32, user_email: String, id: i32, public_key: bool) -> Result<()>; async fn request_revoke_key(&self, user_id: i32, user_email: String, id: i32, parent_id: i32, reason: X509RevokeReason, public_key: bool) -> Result<()>; async fn cancel_delete_key(&self, user_id: i32, id: i32) -> Result<()>; diff --git a/src/infra/database/model/datakey/repository.rs b/src/infra/database/model/datakey/repository.rs index 237c9541c871074e549fe7a95135c822086e0d99..9845c00fa3587f2cb288abfb375aec21c2849b49 100644 --- a/src/infra/database/model/datakey/repository.rs +++ b/src/infra/database/model/datakey/repository.rs @@ -106,7 +106,7 @@ impl<'a> DataKeyRepository<'a> { async fn _obtain_datakey_parent(&self, datakey: &mut DataKey) -> Result<()> { if let Some(parent) = datakey.parent_id { - let result = self.get_by_id(parent).await; + let result = self.get_by_id_or_name(Some(parent), None, true).await; match result { Ok(parent) => { datakey.parent_key = Some(ParentKey { @@ -132,7 +132,7 @@ impl<'a> Repository for DataKeyRepository<'a> { let dto = datakey_dto::ActiveModel::try_from(data_key)?; let insert_result =datakey_dto::Entity::insert(dto).exec(self.db_connection).await?; - let mut datakey = self.get_by_id(insert_result.last_insert_id).await?; + let mut datakey = self.get_by_id_or_name(Some(insert_result.last_insert_id), None, true).await?; //fetch parent key if 'parent_id' exists. if let Err(err) = self._obtain_datakey_parent(&mut datakey).await { warn!("failed to create datakey {} {}", datakey.name, err); @@ -160,10 +160,7 @@ impl<'a> Repository for DataKeyRepository<'a> { } match datakey_dto::Entity::find().select_only().columns( datakey_dto::Column::iter().filter(|col| - match col { - datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt => false, - _ => true, - })).exprs( + !matches!(col, datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt))).exprs( [Expr::cust("user_table.email as user_email"), Expr::cust("GROUP_CONCAT(request_delete_table.user_email) as request_delete_users"), Expr::cust("GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users")]).join_as_rev( @@ -190,10 +187,7 @@ impl<'a> Repository for DataKeyRepository<'a> { let now = Utc::now(); match datakey_dto::Entity::find().select_only().columns( datakey_dto::Column::iter().filter(|col| - match col { - datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt => false, - _ => true, - })).column_as( + !matches!(col, datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt))).column_as( Expr::col((Alias::new("crl_table"), crl_content_dto::Column::UpdateAt)), "x509_crl_update_at").join_as_rev( JoinType::LeftJoin, crl_content_dto::Relation::Datakey.def(), Alias::new("crl_table")).filter( Condition::all().add( @@ -255,41 +249,55 @@ impl<'a> Repository for DataKeyRepository<'a> { } } - async fn get_by_id(&self, id: i32) -> Result { - match datakey_dto::Entity::find().select_only().columns( - datakey_dto::Column::iter().filter(|col| - match col { - datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt => false, - _ => true, - })).exprs( - [Expr::cust("user_table.email as user_email"), - Expr::cust("GROUP_CONCAT(request_delete_table.user_email) as request_delete_users"), - Expr::cust("GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users")]).join_as_rev( - JoinType::InnerJoin, user_dto::Relation::Datakey.def(), Alias::new("user_table")).join_as_rev( - JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Delete).into(), - Alias::new("request_delete_table")).join_as_rev( - JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Revoke).into(), - Alias::new("request_revoke_table")).group_by(datakey_dto::Column::Id).filter( - Condition::all().add( - datakey_dto::Column::Id.eq(id)).add( - datakey_dto::Column::KeyState.ne(KeyState::Deleted.to_string())) - ).one(self.db_connection).await? { - None => { - Err(Error::NotFoundError) + async fn get_by_id_or_name(&self, id: Option, name: Option, raw_datakey: bool) -> Result { + let mut conditions = Condition::all(); + if let Some(key_id) = id { + conditions = conditions.add(datakey_dto::Column::Id.eq(key_id)) + } else if let Some(key_name) = name { + conditions = conditions.add(datakey_dto::Column::Name.eq(key_name)) + } else { + return Err(Error::ParameterError("both datakey name and id are empty".to_string())) + } + conditions = conditions.add(datakey_dto::Column::KeyState.ne(KeyState::Deleted.to_string())); + if !raw_datakey { + match datakey_dto::Entity::find().select_only().columns( + datakey_dto::Column::iter().filter(|col| + !matches!(col, datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt))).exprs( + [Expr::cust("user_table.email as user_email"), + Expr::cust("GROUP_CONCAT(request_delete_table.user_email) as request_delete_users"), + Expr::cust("GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users")]).join_as_rev( + JoinType::InnerJoin, user_dto::Relation::Datakey.def(), Alias::new("user_table")).join_as_rev( + JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Delete).into(), + Alias::new("request_delete_table")).join_as_rev( + JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Revoke).into(), + Alias::new("request_revoke_table")).group_by(datakey_dto::Column::Id).filter( + conditions).one(self.db_connection).await? { + None => { + Err(Error::NotFoundError) + } + Some(datakey) => { + Ok(DataKey::try_from(datakey)?) + } } - Some(datakey) => { - Ok(DataKey::try_from(datakey)?) + } else { + match datakey_dto::Entity::find().select_only().columns( + datakey_dto::Column::iter().filter(|col| + !matches!(col, datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt))).filter(conditions).one(self.db_connection).await? { + None => { + Err(Error::NotFoundError) + } + Some(datakey) => { + Ok(DataKey::try_from(datakey)?) + } } } + } async fn get_by_parent_id(&self, parent_id: i32) -> Result> { match datakey_dto::Entity::find().select_only().columns( datakey_dto::Column::iter().filter(|col| - match col { - datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt => false, - _ => true, - })).exprs( + !matches!(col, datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt))).exprs( [Expr::cust("user_table.email as user_email"), Expr::cust("GROUP_CONCAT(request_delete_table.user_email) as request_delete_users"), Expr::cust("GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users")]).join_as_rev( @@ -316,52 +324,6 @@ impl<'a> Repository for DataKeyRepository<'a> { } } - async fn check_name_exists(&self, name: &str) -> Result{ - match datakey_dto::Entity::find().select_only().columns( - datakey_dto::Column::iter().filter(|col| - match col { - datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt => false, - _ => true, - })).filter(Condition::all().add( - datakey_dto::Column::Name.eq(name)).add( - datakey_dto::Column::KeyState.ne(KeyState::Deleted.to_string()))).one(self.db_connection).await? { - None => { - Err(Error::NotFoundError) - } - Some(datakey) => { - Ok(DataKey::try_from(datakey)?) - } - } - } - - async fn get_by_name(&self, name: &str) -> Result { - match datakey_dto::Entity::find().select_only().columns( - datakey_dto::Column::iter().filter(|col| - match col { - datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt => false, - _ => true, - })).exprs( - [Expr::cust("user_table.email as user_email"), - Expr::cust("GROUP_CONCAT(request_delete_table.user_email) as request_delete_users"), - Expr::cust("GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users")]).join_as_rev( - JoinType::InnerJoin, user_dto::Relation::Datakey.def(), Alias::new("user_table")).join_as_rev( - JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Delete).into(), - Alias::new("request_delete_table")).join_as_rev( - JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Revoke).into(), - Alias::new("request_revoke_table")).group_by(datakey_dto::Column::Id).filter( - Condition::all().add( - datakey_dto::Column::Name.eq(name)).add( - datakey_dto::Column::KeyState.ne(KeyState::Deleted.to_string())) - ).one(self.db_connection).await? { - None => { - Err(Error::NotFoundError) - } - Some(datakey) => { - Ok(DataKey::try_from(datakey)?) - } - } - } - async fn update_state(&self, id: i32, state: KeyState) -> Result<()> { //Note: if the key in deleted status, it cannot be updated to other states let _ = datakey_dto::Entity::update_many().col_expr( @@ -392,21 +354,10 @@ impl<'a> Repository for DataKeyRepository<'a> { Ok(()) } - async fn get_enabled_key_by_type_and_name(&self, key_type: String, name: String) -> Result { + async fn get_enabled_key_by_type_and_name_with_parent_key(&self, key_type: String, name: String) -> Result { match datakey_dto::Entity::find().select_only().columns( datakey_dto::Column::iter().filter(|col| - match col { - datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt => false, - _ => true, - })).exprs( - [Expr::cust("user_table.email as user_email"), - Expr::cust("GROUP_CONCAT(request_delete_table.user_email) as request_delete_users"), - Expr::cust("GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users")]).join_as_rev( - JoinType::InnerJoin, user_dto::Relation::Datakey.def(), Alias::new("user_table")).join_as_rev( - JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Delete).into(), - Alias::new("request_delete_table")).join_as_rev( - JoinType::LeftJoin, self.get_pending_operation_relation(RequestType::Revoke).into(), - Alias::new("request_revoke_table")).group_by(datakey_dto::Column::Id).filter( + !matches!(col, datakey_dto::Column::UserEmail | datakey_dto::Column::RequestDeleteUsers | datakey_dto::Column::RequestRevokeUsers | datakey_dto::Column::X509CrlUpdateAt))).filter( Condition::all().add( datakey_dto::Column::Name.eq(name)).add( datakey_dto::Column::KeyType.eq(key_type)).add( @@ -416,7 +367,9 @@ impl<'a> Repository for DataKeyRepository<'a> { Err(Error::NotFoundError) } Some(datakey) => { - Ok(DataKey::try_from(datakey)?) + let mut result = DataKey::try_from(datakey)?; + self._obtain_datakey_parent(&mut result).await?; + Ok(result) } } } @@ -519,7 +472,7 @@ impl<'a> Repository for DataKeyRepository<'a> { } async fn upsert_x509_crl(&self, crl: X509CRL) -> Result<()> { - let ca_id = crl.ca_id.clone(); + let ca_id = crl.ca_id; let crl_model = crl_content_dto::ActiveModel { id: Set(crl.id), ca_id: Set(crl.ca_id), @@ -740,7 +693,7 @@ mod tests { parent_key: None, }; assert_eq!( - datakey_repository.get_by_id(1).await?, user + datakey_repository.get_by_id_or_name(Some(1), None, false).await?, user ); assert_eq!( db.into_transaction_log(), @@ -923,7 +876,7 @@ mod tests { } #[tokio::test] - async fn test_datakey_repository_check_name_exists_sql_statement() -> Result<()> { + async fn test_datakey_get_raw_key_sql_statement() -> Result<()> { let now = chrono::Utc::now(); let db = MockDatabase::new(DatabaseBackend::MySql) .append_query_results([ @@ -975,7 +928,7 @@ mod tests { parent_key: None, }; assert_eq!( - datakey_repository.check_name_exists("Test Key").await?, user + datakey_repository.get_by_id_or_name(None, Some("Test Key".to_string()), true).await?, user ); assert_eq!( db.into_transaction_log(), @@ -1044,7 +997,7 @@ mod tests { parent_key: None, }; assert_eq!( - datakey_repository.get_by_name("Test Key").await?, user + datakey_repository.get_by_id_or_name(None, Some("Test Key".to_string()), false).await?, user ); assert_eq!( db.into_transaction_log(), @@ -1101,6 +1054,28 @@ mod tests { user: 0, attributes: "{}".to_string(), key_type: "pgp".to_string(), + parent_id: Some(2), + fingerprint: "".to_string(), + serial_number: None, + private_key: "0708090A".to_string(), + public_key: "040506".to_string(), + certificate: "010203".to_string(), + create_at: now.clone(), + expire_at: now.clone(), + key_state: "disabled".to_string(), + user_email: None, + request_delete_users: None, + request_revoke_users: None, + x509_crl_update_at: None, + }], + vec![dto::Model { + id: 2, + name: "Parent Key".to_string(), + description: "".to_string(), + visibility: Visibility::Public.to_string(), + user: 0, + attributes: "{}".to_string(), + key_type: "pgp".to_string(), parent_id: None, fingerprint: "".to_string(), serial_number: None, @@ -1126,7 +1101,7 @@ mod tests { user: 0, attributes: HashMap::new(), key_type: KeyType::OpenPGP, - parent_id: None, + parent_id: Some(2), fingerprint: "".to_string(), serial_number: None, private_key: vec![7,8,9,10], @@ -1138,18 +1113,29 @@ mod tests { user_email: None, request_delete_users: None, request_revoke_users: None, - parent_key: None, + parent_key: Some(ParentKey{ + name: "Parent Key".to_string(), + attributes: HashMap::new(), + private_key: vec![7,8,9,10], + public_key: vec![4,5,6], + certificate: vec![1,2,3], + }), }; assert_eq!( - datakey_repository.get_enabled_key_by_type_and_name("openpgp".to_string(), "fake_name".to_string()).await?, user + datakey_repository.get_enabled_key_by_type_and_name_with_parent_key("openpgp".to_string(), "fake_name".to_string()).await?, user ); assert_eq!( db.into_transaction_log(), [ Transaction::from_sql_and_values( DatabaseBackend::MySql, - r#"SELECT `data_key`.`id`, `data_key`.`name`, `data_key`.`description`, `data_key`.`visibility`, `data_key`.`user`, `data_key`.`attributes`, `data_key`.`key_type`, `data_key`.`parent_id`, `data_key`.`fingerprint`, `data_key`.`serial_number`, `data_key`.`private_key`, `data_key`.`public_key`, `data_key`.`certificate`, `data_key`.`create_at`, `data_key`.`expire_at`, `data_key`.`key_state`, user_table.email as user_email, GROUP_CONCAT(request_delete_table.user_email) as request_delete_users, GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users FROM `data_key` INNER JOIN `user` AS `user_table` ON `user_table`.`id` = `data_key`.`user` LEFT JOIN `pending_operation` AS `request_delete_table` ON `request_delete_table`.`key_id` = `data_key`.`id` AND `request_delete_table`.`request_type` = ? LEFT JOIN `pending_operation` AS `request_revoke_table` ON `request_revoke_table`.`key_id` = `data_key`.`id` AND `request_revoke_table`.`request_type` = ? WHERE `data_key`.`name` = ? AND `data_key`.`key_type` = ? AND `data_key`.`key_state` = ? GROUP BY `data_key`.`id` LIMIT ?"#, - ["delete".into(), "revoke".into(), "fake_name".into(), "openpgp".into(), "enabled".into(), 1u64.into()] + r#"SELECT `data_key`.`id`, `data_key`.`name`, `data_key`.`description`, `data_key`.`visibility`, `data_key`.`user`, `data_key`.`attributes`, `data_key`.`key_type`, `data_key`.`parent_id`, `data_key`.`fingerprint`, `data_key`.`serial_number`, `data_key`.`private_key`, `data_key`.`public_key`, `data_key`.`certificate`, `data_key`.`create_at`, `data_key`.`expire_at`, `data_key`.`key_state` FROM `data_key` WHERE `data_key`.`name` = ? AND `data_key`.`key_type` = ? AND `data_key`.`key_state` = ? LIMIT ?"#, + ["fake_name".into(), "openpgp".into(), "enabled".into(), 1u64.into()] + ), + Transaction::from_sql_and_values( + DatabaseBackend::MySql, + r#"SELECT `data_key`.`id`, `data_key`.`name`, `data_key`.`description`, `data_key`.`visibility`, `data_key`.`user`, `data_key`.`attributes`, `data_key`.`key_type`, `data_key`.`parent_id`, `data_key`.`fingerprint`, `data_key`.`serial_number`, `data_key`.`private_key`, `data_key`.`public_key`, `data_key`.`certificate`, `data_key`.`create_at`, `data_key`.`expire_at`, `data_key`.`key_state` FROM `data_key` WHERE `data_key`.`id` = ? AND `data_key`.`key_state` <> ? LIMIT ?"#, + [2i32.into(), "deleted".into(), 1u64.into()] ), ] ); @@ -1255,13 +1241,13 @@ mod tests { ), Transaction::from_sql_and_values( DatabaseBackend::MySql, - r#"SELECT `data_key`.`id`, `data_key`.`name`, `data_key`.`description`, `data_key`.`visibility`, `data_key`.`user`, `data_key`.`attributes`, `data_key`.`key_type`, `data_key`.`parent_id`, `data_key`.`fingerprint`, `data_key`.`serial_number`, `data_key`.`private_key`, `data_key`.`public_key`, `data_key`.`certificate`, `data_key`.`create_at`, `data_key`.`expire_at`, `data_key`.`key_state`, user_table.email as user_email, GROUP_CONCAT(request_delete_table.user_email) as request_delete_users, GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users FROM `data_key` INNER JOIN `user` AS `user_table` ON `user_table`.`id` = `data_key`.`user` LEFT JOIN `pending_operation` AS `request_delete_table` ON `request_delete_table`.`key_id` = `data_key`.`id` AND `request_delete_table`.`request_type` = ? LEFT JOIN `pending_operation` AS `request_revoke_table` ON `request_revoke_table`.`key_id` = `data_key`.`id` AND `request_revoke_table`.`request_type` = ? WHERE `data_key`.`id` = ? AND `data_key`.`key_state` <> ? GROUP BY `data_key`.`id` LIMIT ?"#, - ["delete".into(), "revoke".into(), 1i32.into(), "deleted".into(), 1u64.into()] + r#"SELECT `data_key`.`id`, `data_key`.`name`, `data_key`.`description`, `data_key`.`visibility`, `data_key`.`user`, `data_key`.`attributes`, `data_key`.`key_type`, `data_key`.`parent_id`, `data_key`.`fingerprint`, `data_key`.`serial_number`, `data_key`.`private_key`, `data_key`.`public_key`, `data_key`.`certificate`, `data_key`.`create_at`, `data_key`.`expire_at`, `data_key`.`key_state` FROM `data_key` WHERE `data_key`.`id` = ? AND `data_key`.`key_state` <> ? LIMIT ?"#, + [1i32.into(), "deleted".into(), 1u64.into()] ), Transaction::from_sql_and_values( DatabaseBackend::MySql, - r#"SELECT `data_key`.`id`, `data_key`.`name`, `data_key`.`description`, `data_key`.`visibility`, `data_key`.`user`, `data_key`.`attributes`, `data_key`.`key_type`, `data_key`.`parent_id`, `data_key`.`fingerprint`, `data_key`.`serial_number`, `data_key`.`private_key`, `data_key`.`public_key`, `data_key`.`certificate`, `data_key`.`create_at`, `data_key`.`expire_at`, `data_key`.`key_state`, user_table.email as user_email, GROUP_CONCAT(request_delete_table.user_email) as request_delete_users, GROUP_CONCAT(request_revoke_table.user_email) as request_revoke_users FROM `data_key` INNER JOIN `user` AS `user_table` ON `user_table`.`id` = `data_key`.`user` LEFT JOIN `pending_operation` AS `request_delete_table` ON `request_delete_table`.`key_id` = `data_key`.`id` AND `request_delete_table`.`request_type` = ? LEFT JOIN `pending_operation` AS `request_revoke_table` ON `request_revoke_table`.`key_id` = `data_key`.`id` AND `request_revoke_table`.`request_type` = ? WHERE `data_key`.`id` = ? AND `data_key`.`key_state` <> ? GROUP BY `data_key`.`id` LIMIT ?"#, - ["delete".into(), "revoke".into(), 2i32.into(), "deleted".into(), 1u64.into()] + r#"SELECT `data_key`.`id`, `data_key`.`name`, `data_key`.`description`, `data_key`.`visibility`, `data_key`.`user`, `data_key`.`attributes`, `data_key`.`key_type`, `data_key`.`parent_id`, `data_key`.`fingerprint`, `data_key`.`serial_number`, `data_key`.`private_key`, `data_key`.`public_key`, `data_key`.`certificate`, `data_key`.`create_at`, `data_key`.`expire_at`, `data_key`.`key_state` FROM `data_key` WHERE `data_key`.`id` = ? AND `data_key`.`key_state` <> ? LIMIT ?"#, + [2i32.into(), "deleted".into(), 1u64.into()] ) ] ); diff --git a/src/presentation/handler/control/datakey_handler.rs b/src/presentation/handler/control/datakey_handler.rs index 115c08e9af406961f4deb9bf291626d3c6768c97..7a7d1be08346612e8512da13eea52e4462363d1d 100644 --- a/src/presentation/handler/control/datakey_handler.rs +++ b/src/presentation/handler/control/datakey_handler.rs @@ -493,7 +493,7 @@ async fn key_name_identical(user: UserIdentity, key_service: web::Data Ok(HttpResponse::Conflict()), Err(_) => Ok(HttpResponse::Ok()), } diff --git a/src/presentation/server/control_server.rs b/src/presentation/server/control_server.rs index 5ca1983e20ebb541263344b0e1fb4f37d5342721..49f391681d743545652fae2216c05f86dc3d505b 100644 --- a/src/presentation/server/control_server.rs +++ b/src/presentation/server/control_server.rs @@ -202,7 +202,8 @@ impl ControlServer { //in the case of signed double submit cookie ,disable updating csrf token in middleware automatically //now and open it if we have to. //.wrap(from_fn(UserIdentity::append_csrf_cookie)) - .wrap(middleware::Logger::default()) + //NOTE: we skipped logging the api health endpoint. + .wrap(middleware::Logger::default().exclude("/api/health/")) .wrap(IdentityMiddleware::default()) //rate limiter handler .wrap(RateLimiter::default()) @@ -268,7 +269,7 @@ impl ControlServer { //used for control admin cmd pub async fn get_key_by_name(&self, name: &str) -> Result { - self.key_service.get_by_name(name).await + self.key_service.get_raw_key_by_name(name).await } pub async fn get_user_by_email(&self, email: &str) -> Result { diff --git a/src/util/signer_container.rs b/src/util/signer_container.rs index 589bc9ba4f098d33b02f02659d26b766d31c1628..8161c2593c582094da6f49b5d3ad88571461ced0 100644 --- a/src/util/signer_container.rs +++ b/src/util/signer_container.rs @@ -46,7 +46,7 @@ where if let Some(dk) = self.containers.read().await.get(&identity) { return Ok((*dk).clone()) } - let data_key = self.repository.get_enabled_key_by_type_and_name(key_type, key_name).await?; + let data_key = self.repository.get_enabled_key_by_type_and_name_with_parent_key(key_type, key_name).await?; self.containers.write().await.insert(identity, data_key.clone()); Ok(data_key) }