diff --git a/contracts/router-access/src/lib.rs b/contracts/router-access/src/lib.rs index 4e1d3ab..297d764 100644 --- a/contracts/router-access/src/lib.rs +++ b/contracts/router-access/src/lib.rs @@ -60,8 +60,16 @@ impl RouterAccess { account: Address, role: String, expires_in: Option, - ) { + ) -> Result<(), AccessError> { admin.require_auth(); + Self::require_role_manager(&env, &admin, &role)?; + + if Self::is_blacklisted_internal(&env, &account) { + return Err(AccessError::Blacklisted); + } + if Self::has_role_internal(&env, &account, &role) { + return Err(AccessError::AlreadyHasRole); + } let expiry_timestamp = match expires_in { Some(seconds) => env.ledger().timestamp() + seconds, @@ -75,6 +83,7 @@ impl RouterAccess { (Symbol::new(&env, "role_grant"),), (account, role, expiry_timestamp), ); + Ok(()) } /// Removes `role` from `target`. @@ -362,6 +371,41 @@ mod tests { assert!(!client.has_role(&user, &role)); } + #[test] + fn test_grant_role_blacklisted_account_fails() { + let (env, admin, client) = setup(); + let role = String::from_str(&env, "operator"); + let user = Address::generate(&env); + + client.blacklist(&admin, &user); + + let result = client.try_grant_role(&admin, &user, &role, &Some(10)); + assert_eq!(result, Err(Ok(AccessError::Blacklisted))); + } + + #[test] + fn test_grant_role_already_has_role_fails() { + let (env, admin, client) = setup(); + let role = String::from_str(&env, "operator"); + let user = Address::generate(&env); + + client.grant_role(&admin, &user, &role, &Some(10)); + + let result = client.try_grant_role(&admin, &user, &role, &Some(20)); + assert_eq!(result, Err(Ok(AccessError::AlreadyHasRole))); + } + + #[test] + fn test_grant_role_returns_error_on_unauthorized() { + let (env, _admin, client) = setup(); + let attacker = Address::generate(&env); + let user = Address::generate(&env); + let role = String::from_str(&env, "operator"); + + let result = client.try_grant_role(&attacker, &user, &role, &Some(10)); + assert_eq!(result, Err(Ok(AccessError::Unauthorized))); + } + #[test] fn test_set_role_admin_emits_event() { let (env, admin, client) = setup();