From 52ab467eafbea5f01a2f35cdbbceae0d5263336d Mon Sep 17 00:00:00 2001 From: TommyLike Date: Tue, 3 Oct 2023 07:11:56 +0800 Subject: [PATCH] Add more testcases --- .../database/model/datakey/repository.rs | 28 +- .../handler/control/model/datakey/dto.rs | 352 ++++++++++++++++++ .../handler/control/model/token/dto.rs | 18 +- .../handler/control/model/user/dto.rs | 16 + src/util/key.rs | 7 +- 5 files changed, 402 insertions(+), 19 deletions(-) diff --git a/src/infra/database/model/datakey/repository.rs b/src/infra/database/model/datakey/repository.rs index 32f9ba9..bfd1c1a 100644 --- a/src/infra/database/model/datakey/repository.rs +++ b/src/infra/database/model/datakey/repository.rs @@ -46,7 +46,7 @@ impl<'a> DataKeyRepository<'a> { } } - async fn create_pending_operation(&self, pending_operation: request_dto::Model, tx: &mut DatabaseTransaction) -> Result<()> { + async fn create_pending_operation(&self, pending_operation: request_dto::Model, tx: &DatabaseTransaction) -> Result<()> { let operation = request_dto::ActiveModel { user_id: Set(pending_operation.user_id), key_id: Set(pending_operation.key_id), @@ -62,7 +62,7 @@ impl<'a> DataKeyRepository<'a> { Ok(()) } - async fn delete_pending_operation(&self, user_id: i32, id: i32, request_type: RequestType, tx: &mut DatabaseTransaction) -> Result<()> { + async fn delete_pending_operation(&self, user_id: i32, id: i32, request_type: RequestType, tx: &DatabaseTransaction) -> Result<()> { let _ = request_dto::Entity::delete_many().filter(Condition::all() .add(request_dto::Column::UserId.eq(user_id)) .add(request_dto::Column::RequestType.eq(request_type.to_string())) @@ -71,7 +71,7 @@ impl<'a> DataKeyRepository<'a> { Ok(()) } - async fn create_revoke_record(&self, key_id: i32, ca_id: i32, reason: X509RevokeReason, tx: &mut DatabaseTransaction) -> Result<()> { + async fn create_revoke_record(&self, key_id: i32, ca_id: i32, reason: X509RevokeReason, tx: &DatabaseTransaction) -> Result<()> { let revoked = revoked_key_dto::ActiveModel{ id: Default::default(), key_id: Set(key_id), @@ -87,7 +87,7 @@ impl<'a> DataKeyRepository<'a> { Ok(()) } - async fn delete_revoke_record(&self, key_id: i32, ca_id: i32, tx: &mut DatabaseTransaction) -> Result<()> { + async fn delete_revoke_record(&self, key_id: i32, ca_id: i32, tx: &DatabaseTransaction) -> Result<()> { let _ = revoked_key_dto::Entity::delete_many().filter(Condition::all() .add(revoked_key_dto::Column::KeyId.eq(key_id)) .add(revoked_key_dto::Column::CaId.eq(ca_id))).exec(tx) @@ -380,7 +380,7 @@ impl<'a> Repository for DataKeyRepository<'a> { } async fn request_delete_key(&self, user_id: i32, user_email: String, id: i32, public_key: bool) -> Result<()> { - let mut txn = self.db_connection.begin().await?; + let txn = self.db_connection.begin().await?; let threshold = if public_key { PUBLIC_KEY_PENDING_THRESHOLD } else { PRIVATE_KEY_PENDING_THRESHOLD }; //1. update key state to pending delete if needed. let _ = datakey_dto::Entity::update_many().col_expr( @@ -388,7 +388,7 @@ impl<'a> Repository for DataKeyRepository<'a> { ).filter(datakey_dto::Column::Id.eq(id)).exec(&txn).await?; //2. add request delete record let pending_delete = request_dto::Model::new_for_delete(id, user_id, user_email); - self.create_pending_operation(pending_delete, &mut txn).await?; + self.create_pending_operation(pending_delete, &txn).await?; //3. delete datakey if pending delete count >= threshold let _: ExecResult = txn.execute(Statement::from_sql_and_values( DatabaseBackend::MySql, @@ -402,7 +402,7 @@ impl<'a> Repository for DataKeyRepository<'a> { } async fn request_revoke_key(&self, user_id: i32, user_email: String, id: i32, parent_id: i32, reason: X509RevokeReason, public_key: bool) -> Result<()> { - let mut txn = self.db_connection.begin().await?; + let txn = self.db_connection.begin().await?; let threshold = if public_key { PUBLIC_KEY_PENDING_THRESHOLD } else { PRIVATE_KEY_PENDING_THRESHOLD }; //1. update key state to pending delete if needed. let _ = datakey_dto::Entity::update_many().col_expr( @@ -410,9 +410,9 @@ impl<'a> Repository for DataKeyRepository<'a> { ).filter(datakey_dto::Column::Id.eq(id)).exec(&txn).await?; //2. add request revoke pending record let pending_revoke = request_dto::Model::new_for_revoke(id, user_id, user_email); - self.create_pending_operation(pending_revoke, &mut txn).await?; + self.create_pending_operation(pending_revoke, &txn).await?; //3. add revoked record - self.create_revoke_record(id, parent_id, reason, &mut txn).await?; + self.create_revoke_record(id, parent_id, reason, &txn).await?; //4. mark datakey revoked if pending revoke count >= threshold let _: ExecResult = txn.execute(Statement::from_sql_and_values( DatabaseBackend::MySql, @@ -426,10 +426,10 @@ impl<'a> Repository for DataKeyRepository<'a> { } async fn cancel_delete_key(&self, user_id: i32, id: i32) -> Result<()> { - let mut txn = self.db_connection.begin().await?; + let txn = self.db_connection.begin().await?; //1. delete pending delete record self.delete_pending_operation( - user_id, id, RequestType::Delete, &mut txn).await?; + user_id, id, RequestType::Delete, &txn).await?; //2. update status if there is not any pending delete record. let _: ExecResult = txn.execute(Statement::from_sql_and_values( DatabaseBackend::MySql, @@ -444,11 +444,11 @@ impl<'a> Repository for DataKeyRepository<'a> { } async fn cancel_revoke_key(&self, user_id: i32, id: i32, parent_id: i32) -> Result<()> { - let mut txn = self.db_connection.begin().await?; + let txn = self.db_connection.begin().await?; //1. delete pending delete record - self.delete_pending_operation(user_id, id, RequestType::Revoke, &mut txn).await?; + self.delete_pending_operation(user_id, id, RequestType::Revoke, &txn).await?; //2. delete revoked record - self.delete_revoke_record(id, parent_id, &mut txn).await?; + self.delete_revoke_record(id, parent_id, &txn).await?; //3. update status if there is not any pending delete record. let _: ExecResult = txn.execute(Statement::from_sql_and_values( DatabaseBackend::MySql, diff --git a/src/presentation/handler/control/model/datakey/dto.rs b/src/presentation/handler/control/model/datakey/dto.rs index 666046c..ba32aab 100644 --- a/src/presentation/handler/control/model/datakey/dto.rs +++ b/src/presentation/handler/control/model/datakey/dto.rs @@ -1,3 +1,19 @@ +/* + * + * * // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. + * * // + * * // signatrust is licensed under Mulan PSL v2. + * * // You can use this software according to the terms and conditions of the Mulan + * * // PSL v2. + * * // You may obtain a copy of Mulan PSL v2 at: + * * // http://license.coscl.org.cn/MulanPSL2 + * * // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY + * * // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * * // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * * // See the Mulan PSL v2 for more details. + * + */ + use crate::domain::datakey::entity::{DataKey, DatakeyPaginationQuery, KeyState, PagedDatakey, Visibility, X509CRL}; use crate::domain::datakey::entity::KeyType; use crate::util::error::Result; @@ -356,3 +372,339 @@ impl TryFrom for DataKeyDTO { }) } } + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_public_key_content_from_datakey() { + let key1 = DataKey{ + id: 1, + name: "Test Key".to_string(), + description: "".to_string(), + visibility: Visibility::Public, + user: 0, + attributes: HashMap::new(), + key_type: KeyType::OpenPGP, + parent_id: Some(2), + fingerprint: "".to_string(), + serial_number: None, + private_key: vec![7,8,9,10], + public_key: vec![4,5,6], + certificate: vec![1,2,3], + create_at: Default::default(), + expire_at: Default::default(), + key_state: KeyState::Disabled, + user_email: None, + request_delete_users: None, + request_revoke_users: None, + parent_key: None, + }; + let public_key_content = PublicKeyContent::try_from(key1).unwrap(); + assert_eq!(public_key_content.content, "\u{4}\u{5}\u{6}".to_string()) + } + + #[test] + fn test_certificate_content_from_datakey() { + let key1 = DataKey{ + id: 1, + name: "Test Key".to_string(), + description: "".to_string(), + visibility: Visibility::Public, + user: 0, + attributes: HashMap::new(), + key_type: KeyType::OpenPGP, + parent_id: Some(2), + fingerprint: "".to_string(), + serial_number: None, + private_key: vec![7,8,9,10], + public_key: vec![4,5,6], + certificate: vec![1,2,3], + create_at: Default::default(), + expire_at: Default::default(), + key_state: KeyState::Disabled, + user_email: None, + request_delete_users: None, + request_revoke_users: None, + parent_key: None, + }; + let certificate_content = CertificateContent::try_from(key1).unwrap(); + assert_eq!(certificate_content.content, "\u{1}\u{2}\u{3}".to_string()) + } + + #[test] + fn test_datakey_dto_from_datakey() { + let key1 = DataKey{ + id: 1, + name: "Test Key".to_string(), + description: "".to_string(), + visibility: Visibility::Public, + user: 0, + attributes: HashMap::new(), + key_type: KeyType::OpenPGP, + parent_id: Some(2), + fingerprint: "".to_string(), + serial_number: None, + private_key: vec![7,8,9,10], + public_key: vec![4,5,6], + certificate: vec![1,2,3], + create_at: Default::default(), + expire_at: Default::default(), + key_state: KeyState::Disabled, + user_email: None, + request_delete_users: None, + request_revoke_users: None, + parent_key: None, + }; + assert!(DataKeyDTO::try_from(key1).is_ok()); + } + + #[test] + fn test_crl_content_from_crl_model() { + let crl = X509CRL{ + id: 1, + ca_id: 2, + data: vec![1,2,3], + create_at: Default::default(), + update_at: Default::default(), + }; + let crl_content = CRLContent::try_from(crl).unwrap(); + assert_eq!(crl_content.content, "\u{1}\u{2}\u{3}".to_string()) + } + + #[test] + fn test_list_key_query() { + let page_query_invalid1 = ListKeyQuery{ + key_type: Some("x509ee".to_string()), + visibility: Some("public".to_string()), + name: Some("test".to_string()), + description: Some("test".to_string()), + page_size: 9, + page_number: 1, + }; + assert!(page_query_invalid1.validate().is_err()); + let page_query_invalid2 = ListKeyQuery{ + key_type: Some("x509ee".to_string()), + visibility: Some("public".to_string()), + name: Some("test".to_string()), + description: Some("test".to_string()), + page_size: 101, + page_number: 1, + }; + assert!(page_query_invalid2.validate().is_err()); + let page_query_invalid3 = ListKeyQuery{ + key_type: Some("x509ee".to_string()), + visibility: Some("public".to_string()), + name: Some("test".to_string()), + description: Some("test".to_string()), + page_size: 100, + page_number: 0, + }; + assert!(page_query_invalid3.validate().is_err()); + let page_query_invalid4 = ListKeyQuery{ + key_type: Some("x509ee".to_string()), + visibility: Some("public".to_string()), + name: Some("test".to_string()), + description: Some("test".to_string()), + page_size: 100, + page_number: 1001, + }; + assert!(page_query_invalid4.validate().is_err()); + let query = ListKeyQuery{ + key_type: Some("x509ee".to_string()), + visibility: Some("public".to_string()), + name: Some("test".to_string()), + description: Some("test".to_string()), + page_size: 10, + page_number: 1, + }; + let datakey_query = DatakeyPaginationQuery::from(query); + assert_eq!(datakey_query.key_type, Some("x509ee".to_string())); + assert_eq!(datakey_query.visibility, Some("public".to_string())); + assert_eq!(datakey_query.name, Some("test".to_string())); + assert_eq!(datakey_query.description, Some("test".to_string())); + assert_eq!(datakey_query.page_size, 10); + assert_eq!(datakey_query.page_number, 1); + } + + #[test] + fn test_create_datakey_dto() { + let invalid_name1 = CreateDataKeyDTO{ + name: "Tes".to_string(), + description: "".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + parent_id: Some(2), + expire_at: Default::default(), + }; + assert!(invalid_name1.validate().is_err()); + let invalid_name2 = CreateDataKeyDTO{ + name: "1234567890123456789012345678901234567890123456789012345678901234\ + 567890123456789012345678901234567890123456789012345678901234567890123456\ + 7890123456789012345678901234567890123456789012345678901234567890123456789\ + 012345678901234567890123456789012345678901234567890".to_string(), + description: "".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + parent_id: Some(2), + expire_at: Default::default(), + }; + assert!(invalid_name2.validate().is_err()); + let invalid_desc1 = CreateDataKeyDTO{ + name: "Test".to_string(), + description: "1234567890123456789012345678901234567890123456789012345678901234\ + 567890123456789012345678901234567890123456789012345678901234567890123456\ + 7890123456789012345678901234567890123456789012345678901234567890123456789\ + 012345678901234567890123456789012345678901234567890".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + parent_id: Some(2), + expire_at: Default::default(), + }; + assert!(invalid_desc1.validate().is_err()); + let invalid_visibility = CreateDataKeyDTO{ + name: "Test".to_string(), + description: "test descr".to_string(), + visibility: Some("123".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + parent_id: Some(2), + expire_at: Default::default(), + }; + assert!(invalid_visibility.validate().is_err()); + + let invalid_type = CreateDataKeyDTO{ + name: "Test".to_string(), + description: "test descr".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp1".to_string(), + parent_id: Some(2), + expire_at: Default::default(), + }; + assert!(invalid_type.validate().is_err()); + + let invalid_expire = CreateDataKeyDTO{ + name: "Test".to_string(), + description: "test descr".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + parent_id: Some(2), + expire_at: "fake time".to_string(), + }; + assert!(invalid_expire.validate().is_err()); + + let dto = CreateDataKeyDTO{ + name: "Test".to_string(), + description: "test descr".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + parent_id: Some(2), + expire_at: Utc::now().to_string(), + }; + let identity = UserIdentity{ + email: "email1".to_string(), + id: 1, + csrf_generation_token: None, + csrf_token: None, + }; + let key = DataKey::create_from(dto, identity.clone()).unwrap(); + assert_eq!(key.user, identity.id); + assert_eq!(key.key_state, KeyState::Disabled); + assert_eq!(key.key_type, KeyType::OpenPGP); + assert_eq!(key.attributes.keys().len(), 3); + } + + #[test] + fn test_import_datakey_dto() { + let invalid_name1 = ImportDataKeyDTO{ + name: "Tes".to_string(), + description: "".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + certificate: "1234".to_string(), + public_key: "1234".to_string(), + private_key: "1234".to_string(), + }; + assert!(invalid_name1.validate().is_err()); + let invalid_name2 = ImportDataKeyDTO{ + name: "1234567890123456789012345678901234567890123456789012345678901234\ + 567890123456789012345678901234567890123456789012345678901234567890123456\ + 7890123456789012345678901234567890123456789012345678901234567890123456789\ + 012345678901234567890123456789012345678901234567890".to_string(), + description: "".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + certificate: "1234".to_string(), + public_key: "1234".to_string(), + private_key: "1234".to_string(), + }; + assert!(invalid_name2.validate().is_err()); + let invalid_desc1 = ImportDataKeyDTO{ + name: "Test".to_string(), + description: "1234567890123456789012345678901234567890123456789012345678901234\ + 567890123456789012345678901234567890123456789012345678901234567890123456\ + 7890123456789012345678901234567890123456789012345678901234567890123456789\ + 012345678901234567890123456789012345678901234567890".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + certificate: "1234".to_string(), + public_key: "1234".to_string(), + private_key: "1234".to_string(), + }; + assert!(invalid_desc1.validate().is_err()); + let invalid_visibility = ImportDataKeyDTO{ + name: "Test".to_string(), + description: "test descr".to_string(), + visibility: Some("123".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + certificate: "1234".to_string(), + public_key: "1234".to_string(), + private_key: "1234".to_string(), + }; + assert!(invalid_visibility.validate().is_err()); + + let invalid_type = ImportDataKeyDTO{ + name: "Test".to_string(), + description: "test descr".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp1".to_string(), + certificate: "1234".to_string(), + public_key: "1234".to_string(), + private_key: "1234".to_string(), + }; + assert!(invalid_type.validate().is_err()); + + let dto = ImportDataKeyDTO{ + name: "Test".to_string(), + description: "test descr".to_string(), + visibility: Some("public".to_string()), + attributes: HashMap::new(), + key_type: "pgp".to_string(), + certificate: "1234".to_string(), + public_key: "1234".to_string(), + private_key: "1234".to_string(), + }; + let identity = UserIdentity{ + email: "email1".to_string(), + id: 1, + csrf_generation_token: None, + csrf_token: None, + }; + let key = DataKey::import_from(dto, identity.clone()).unwrap(); + assert_eq!(key.user, identity.id); + assert_eq!(key.key_state, KeyState::Disabled); + assert_eq!(key.key_type, KeyType::OpenPGP); + assert_eq!(key.attributes.keys().len(), 2); + } +} diff --git a/src/presentation/handler/control/model/token/dto.rs b/src/presentation/handler/control/model/token/dto.rs index 45723ad..e61b76b 100644 --- a/src/presentation/handler/control/model/token/dto.rs +++ b/src/presentation/handler/control/model/token/dto.rs @@ -1,6 +1,18 @@ - - - +/* + * + * * // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. + * * // + * * // signatrust is licensed under Mulan PSL v2. + * * // You can use this software according to the terms and conditions of the Mulan + * * // PSL v2. + * * // You may obtain a copy of Mulan PSL v2 at: + * * // http://license.coscl.org.cn/MulanPSL2 + * * // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY + * * // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * * // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * * // See the Mulan PSL v2 for more details. + * + */ use serde::{Deserialize, Serialize}; use std::convert::From; diff --git a/src/presentation/handler/control/model/user/dto.rs b/src/presentation/handler/control/model/user/dto.rs index 10667ab..48d2bc9 100644 --- a/src/presentation/handler/control/model/user/dto.rs +++ b/src/presentation/handler/control/model/user/dto.rs @@ -1,3 +1,19 @@ +/* + * + * * // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. + * * // + * * // signatrust is licensed under Mulan PSL v2. + * * // You can use this software according to the terms and conditions of the Mulan + * * // PSL v2. + * * // You may obtain a copy of Mulan PSL v2 at: + * * // http://license.coscl.org.cn/MulanPSL2 + * * // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY + * * // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * * // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * * // See the Mulan PSL v2 for more details. + * + */ + use actix_web::{Result, HttpRequest, FromRequest, dev::Payload, dev::ServiceRequest, body::MessageBody,dev::ServiceResponse}; use crate::util::error::{Error, Result as SignatrustResult}; use std::convert::TryInto; diff --git a/src/util/key.rs b/src/util/key.rs index 57802b3..2d4eb9d 100644 --- a/src/util/key.rs +++ b/src/util/key.rs @@ -21,14 +21,17 @@ use serde::{Serialize, Serializer}; use std::collections::{HashMap, BTreeMap}; use std::path::Path; use sha2::{Sha256, Digest}; +use std::fmt::Write; use crate::domain::datakey::entity::Visibility; use crate::util::error::{Error, Result as LibraryResult}; pub fn encode_u8_to_hex_string(value: &[u8]) -> String { value .iter() - .map(|n| format!("{:02X}", n)) - .collect::() + .fold(String::new(), |mut result, n| { + let _ = write!(result, "{n:02X}"); + result + }) } pub fn get_datakey_full_name(name: &str, email: &str, visibility: &Visibility) -> LibraryResult { -- Gitee