From d6a7847baf6a61ef2dddacfb5b5e04b530bf3571 Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 21 Oct 2022 11:41:51 +0200 Subject: [PATCH 1/2] Add `AccessControllable::acl_get_super_admins` --- near-plugins-derive/src/access_controllable.rs | 8 ++++++++ near-plugins/src/access_controllable.rs | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/near-plugins-derive/src/access_controllable.rs b/near-plugins-derive/src/access_controllable.rs index 78c9ab4..0722817 100644 --- a/near-plugins-derive/src/access_controllable.rs +++ b/near-plugins-derive/src/access_controllable.rs @@ -493,6 +493,14 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream self.#acl_field.has_any_role(roles, &account_id) } + fn acl_get_super_admins(&self, skip: u64, limit: u64) -> Vec<::near_sdk::AccountId> { + let permission = <#bitflags_type>::from_bits( + <#role_type>::acl_super_admin_permission() + ) + .unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG)); + self.#acl_field.get_bearers(permission, skip, limit) + } + fn acl_get_admins(&self, role: String, skip: u64, limit: u64) -> Vec<::near_sdk::AccountId> { let role: #role_type = ::std::convert::TryFrom::try_from(role.as_str()).unwrap_or_else(|_| ::near_sdk::env::panic_str(#ERR_PARSE_ROLE)); let permission = <#bitflags_type>::from_bits(role.acl_admin_permission()) diff --git a/near-plugins/src/access_controllable.rs b/near-plugins/src/access_controllable.rs index e788b5b..7aa0eb2 100644 --- a/near-plugins/src/access_controllable.rs +++ b/near-plugins/src/access_controllable.rs @@ -87,7 +87,11 @@ pub trait AccessControllable { /// Returns whether `account_id` has been granted any of the `roles`. fn acl_has_any_role(&self, roles: Vec, account_id: AccountId) -> bool; - /// Enables paginated retrieval of admins of `role`. It returns upt to + /// Enables paginated retrieval of super-admins. It returns up to `limit` + /// super-admins and skips the first `skip` super-admins. + fn acl_get_super_admins(&self, skip: u64, limit: u64) -> Vec; + + /// Enables paginated retrieval of admins of `role`. It returns up to /// `limit` admins and skips the first `skip` admins. fn acl_get_admins(&self, role: String, skip: u64, limit: u64) -> Vec; From 1d2e8e9baef7e82461519561dd5891aaa3be73c1 Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 21 Oct 2022 12:01:25 +0200 Subject: [PATCH 2/2] Add `test_acl_get_super_admins` --- near-plugins/tests/access_controllable.rs | 70 +++++++++++++++++++ .../common/access_controllable_contract.rs | 21 ++++++ 2 files changed, 91 insertions(+) diff --git a/near-plugins/tests/access_controllable.rs b/near-plugins/tests/access_controllable.rs index 81aab90..a130e77 100644 --- a/near-plugins/tests/access_controllable.rs +++ b/near-plugins/tests/access_controllable.rs @@ -918,6 +918,76 @@ async fn test_acl_init_super_admin_is_private() -> anyhow::Result<()> { Ok(()) } +#[tokio::test] +async fn test_acl_get_super_admins() -> anyhow::Result<()> { + let setup = Setup::new().await?; + + let super_admin_ids = vec![ + setup.new_super_admin_account().await?, + setup.new_super_admin_account().await?, + setup.new_super_admin_account().await?, + ] + .iter() + .map(|account| account.id().clone()) + .collect::>(); + + // Behaves as expected for limit = 0. + let actual = setup + .contract + .acl_get_super_admins(setup.account.clone().into(), 0, 0) + .await?; + assert_eq!(actual, vec![],); + + // Skip outside of the number of existing super-admins. + let n = u64::try_from(super_admin_ids.len()).unwrap(); + let actual = setup + .contract + .acl_get_super_admins(setup.account.clone().into(), n, 1) + .await?; + assert_eq!(actual, vec![],); + + // Retrieve super-admins with step size 1. + for i in 0..3 { + let actual = setup + .contract + .acl_get_super_admins(setup.account.clone().into(), i, 1) + .await?; + let i = usize::try_from(i).unwrap(); + let expected = super_admin_ids[i..i + 1].to_vec(); + assert_eq!(actual, expected, "Mismatch at position {}", i,); + } + + // Retrieve super-admins with step size 2. + let actual = setup + .contract + .acl_get_super_admins(setup.account.clone().into(), 0, 2) + .await?; + let expected = super_admin_ids[0..2].to_vec(); + assert_eq!(actual, expected); + let actual = setup + .contract + .acl_get_super_admins(setup.account.clone().into(), 2, 2) + .await?; + let expected = vec![super_admin_ids[2].clone()]; + assert_eq!(actual, expected); + + // Retrieve all super-admins at once. + let actual = setup + .contract + .acl_get_super_admins(setup.account.clone().into(), 0, 3) + .await?; + assert_eq!(actual, super_admin_ids); + + // Limit larger than the number of existing super-admins. + let actual = setup + .contract + .acl_get_super_admins(setup.account.clone().into(), 0, 4) + .await?; + assert_eq!(actual, super_admin_ids); + + Ok(()) +} + #[tokio::test] async fn test_acl_get_admins() -> anyhow::Result<()> { let setup = Setup::new().await?; diff --git a/near-plugins/tests/common/access_controllable_contract.rs b/near-plugins/tests/common/access_controllable_contract.rs index dcb538c..430c5c7 100644 --- a/near-plugins/tests/common/access_controllable_contract.rs +++ b/near-plugins/tests/common/access_controllable_contract.rs @@ -342,6 +342,27 @@ impl AccessControllableContract { .await } + pub async fn acl_get_super_admins( + &self, + caller: Caller, + skip: u64, + limit: u64, + ) -> anyhow::Result> { + let res = self + .account(caller) + .call(self.contract.id(), "acl_get_super_admins") + .args_json(json!({ + "skip": skip, + "limit": limit, + })) + .max_gas() + .transact() + .await? + .into_result()? + .json::>()?; + Ok(res) + } + pub async fn acl_get_admins( &self, caller: Caller,