diff --git a/contracts/identity-registry-contract/src/contract.rs b/contracts/identity-registry-contract/src/contract.rs index e5eb67e..6939685 100644 --- a/contracts/identity-registry-contract/src/contract.rs +++ b/contracts/identity-registry-contract/src/contract.rs @@ -117,6 +117,32 @@ pub fn ban_expert(env: &Env, expert: &Address) -> Result<(), RegistryError> { Ok(()) } +/// Unban an expert by reverting their status to Verified (Admin only) +pub fn unban_expert(env: &Env, expert: &Address) -> Result<(), RegistryError> { + let admin = storage::get_admin(env).ok_or(RegistryError::NotInitialized)?; + admin.require_auth(); + + let current_status = storage::get_expert_status(env, expert); + + if current_status != ExpertStatus::Banned { + return Err(RegistryError::NotBanned); + } + + // Preserve existing data_uri when unbanning + let existing = storage::get_expert_record(env, expert); + storage::set_expert_record(env, expert, ExpertStatus::Verified, existing.data_uri); + + events::emit_status_change( + env, + expert.clone(), + current_status, + ExpertStatus::Verified, + admin, + ); + + Ok(()) +} + /// Get the total number of verified experts ever indexed pub fn get_total_experts(env: &Env) -> u64 { storage::get_total_experts(env) diff --git a/contracts/identity-registry-contract/src/error.rs b/contracts/identity-registry-contract/src/error.rs index e4462b5..5ba9d39 100644 --- a/contracts/identity-registry-contract/src/error.rs +++ b/contracts/identity-registry-contract/src/error.rs @@ -18,4 +18,5 @@ pub enum RegistryError { ExpertVecMax = 7, NotVerified = 8, UriTooLong = 9, + NotBanned = 10, } diff --git a/contracts/identity-registry-contract/src/lib.rs b/contracts/identity-registry-contract/src/lib.rs index c2d5f7b..3504ccb 100644 --- a/contracts/identity-registry-contract/src/lib.rs +++ b/contracts/identity-registry-contract/src/lib.rs @@ -43,6 +43,11 @@ impl IdentityRegistryContract { contract::ban_expert(&env, &expert) } + /// Unban an expert and restore their verification status (Admin only) + pub fn unban_expert(env: Env, expert: Address) -> Result<(), RegistryError> { + contract::unban_expert(&env, &expert) + } + /// Get the total number of verified experts ever added to the directory pub fn get_total_experts(env: Env) -> u64 { contract::get_total_experts(&env) diff --git a/contracts/identity-registry-contract/src/test.rs b/contracts/identity-registry-contract/src/test.rs index 02c6a41..b153af2 100644 --- a/contracts/identity-registry-contract/src/test.rs +++ b/contracts/identity-registry-contract/src/test.rs @@ -746,3 +746,44 @@ fn test_expert_pagination() { } } +#[test] +fn test_unban_expert() { + let env = Env::default(); + let contract_id = env.register(IdentityRegistryContract, ()); + let client = IdentityRegistryContractClient::new(&env, &contract_id); + + let admin = Address::generate(&env); + let expert = Address::generate(&env); + + client.init(&admin); + + env.mock_all_auths(); + let data_uri = String::from_str(&env, "ipfs://unban"); + client.add_expert(&expert, &data_uri); + + // Initial status: Verified + assert_eq!(client.get_status(&expert), ExpertStatus::Verified); + let initial_total = client.get_total_experts(); + + // Ban the expert + client.ban_expert(&expert); + assert_eq!(client.get_status(&expert), ExpertStatus::Banned); + + // Unban the expert + client.unban_expert(&expert); + assert_eq!(client.get_status(&expert), ExpertStatus::Verified); + + // Data URI should be preserved + env.as_contract(&contract_id, || { + let rec = storage::get_expert_record(&env, &expert); + assert_eq!(rec.data_uri, data_uri); + }); + + // Total experts should NOT have increased + assert_eq!(client.get_total_experts(), initial_total); + + // Test: Try to unban a non-banned expert (should fail with NotBanned) + let result = client.try_unban_expert(&expert); + assert_eq!(result, Err(Ok(RegistryError::NotBanned))); +} +