Skip to content

Commit

Permalink
Migrate from near_sdk::collections to near_sdk::store (Near-One#37)
Browse files Browse the repository at this point in the history
* Migrate bearer set to use `near_sdk::store`

* Migrate bearers map to use `near_sdk::store`

* Migrate permissions map to use `near_sdk::store`
  • Loading branch information
mooori authored Nov 5, 2022
1 parent 5579de4 commit 7454bbc
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 38 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ keywords = ["near", "smart contract", "plugin"]

[workspace.dependencies]
bitflags = "1.3"
near-sdk = "4.0.0"
# Feature `unstable` is required to use `near_sdk::store`.
near-sdk = { version = "4.0.0", features = ["unstable"] }
near-plugins-derive = { path = "near-plugins-derive" }
serde = "1"
anyhow = "1.0"
Expand Down
72 changes: 35 additions & 37 deletions near-plugins-derive/src/access_controllable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,25 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
#[derive(::near_sdk::borsh::BorshDeserialize, ::near_sdk::borsh::BorshSerialize)]
struct #acl_type {
/// Stores permissions per account.
permissions: ::near_sdk::collections::UnorderedMap<
permissions: ::near_sdk::store::UnorderedMap<
::near_sdk::AccountId,
#bitflags_type,
>,
/// Stores the set of accounts that bear a permission.
bearers: ::near_sdk::collections::UnorderedMap<
bearers: ::near_sdk::store::UnorderedMap<
#bitflags_type,
::near_sdk::collections::UnorderedSet<::near_sdk::AccountId>,
::near_sdk::store::UnorderedSet<::near_sdk::AccountId>,
>,
}

impl Default for #acl_type {
fn default() -> Self {
let base_prefix = <#ident as AccessControllable>::acl_storage_prefix();
Self {
permissions: ::near_sdk::collections::UnorderedMap::new(
permissions: ::near_sdk::store::UnorderedMap::new(
__acl_storage_prefix(base_prefix, __AclStorageKey::Permissions),
),
bearers: ::near_sdk::collections::UnorderedMap::new(
bearers: ::near_sdk::store::UnorderedMap::new(
__acl_storage_prefix(base_prefix, __AclStorageKey::Bearers),
),
}
Expand All @@ -99,17 +99,14 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
}

impl #acl_type {
fn new_bearers_set(permission: #bitflags_type) -> ::near_sdk::collections::UnorderedSet<::near_sdk::AccountId> {
fn new_bearers_set(permission: #bitflags_type) -> ::near_sdk::store::UnorderedSet<::near_sdk::AccountId> {
let base_prefix = <#ident as AccessControllable>::acl_storage_prefix();
let specifier = __AclStorageKey::BearersSet { permission };
::near_sdk::collections::UnorderedSet::new(__acl_storage_prefix(base_prefix, specifier))
::near_sdk::store::UnorderedSet::new(__acl_storage_prefix(base_prefix, specifier))
}

fn get_or_init_permissions(&self, account_id: &::near_sdk::AccountId) -> #bitflags_type {
match self.permissions.get(account_id) {
Some(permissions) => permissions,
None => <#bitflags_type>::empty(),
}
fn get_or_insert_permissions(&mut self, account_id: ::near_sdk::AccountId) -> &mut #bitflags_type {
self.permissions.entry(account_id).or_insert_with(|| #bitflags_type::empty())
}

fn init_super_admin(&mut self, account_id: &::near_sdk::AccountId) -> bool {
Expand All @@ -136,12 +133,11 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
fn add_super_admin_unchecked(&mut self, account_id: &::near_sdk::AccountId) -> bool {
let flag = <#bitflags_type>::from_bits(<#role_type>::acl_super_admin_permission())
.unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG));
let mut permissions = self.get_or_init_permissions(account_id);
let mut permissions = self.get_or_insert_permissions(account_id.clone());

let is_new_super_admin = !permissions.contains(flag);
if is_new_super_admin {
permissions.insert(flag);
self.permissions.insert(account_id, &permissions);
self.add_bearer(flag, account_id);

let event = ::#cratename::access_controllable::events::SuperAdminAdded {
Expand Down Expand Up @@ -171,12 +167,14 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
fn revoke_super_admin_unchecked(&mut self, account_id: &::near_sdk::AccountId) -> bool {
let flag = <#bitflags_type>::from_bits(<#role_type>::acl_super_admin_permission())
.unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG));
let mut permissions = self.get_or_init_permissions(account_id);
let mut permissions = match self.permissions.get_mut(account_id) {
Some(permissions) => permissions,
None => return false, // nothing to do, account has no permissions
};

let was_super_admin = permissions.contains(flag);
if was_super_admin {
permissions.remove(flag);
self.permissions.insert(account_id, &permissions);
self.remove_bearer(flag, account_id);

let event = ::#cratename::access_controllable::events::SuperAdminRevoked {
Expand All @@ -203,12 +201,11 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
fn add_admin_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool {
let flag = <#bitflags_type>::from_bits(role.acl_admin_permission())
.unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG));
let mut permissions = self.get_or_init_permissions(account_id);
let mut permissions = self.get_or_insert_permissions(account_id.clone());

let is_new_admin = !permissions.contains(flag);
if is_new_admin {
permissions.insert(flag);
self.permissions.insert(account_id, &permissions);
self.add_bearer(flag, account_id);

let event = ::#cratename::access_controllable::events::AdminAdded {
Expand Down Expand Up @@ -252,12 +249,14 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
fn revoke_admin_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool {
let flag = <#bitflags_type>::from_bits(role.acl_admin_permission())
.unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG));
let mut permissions = self.get_or_init_permissions(account_id);
let mut permissions = match self.permissions.get_mut(account_id) {
Some(permissions) => permissions,
None => return false, // nothing to do, account has no permissions
};

let was_admin = permissions.contains(flag);
if was_admin {
permissions.remove(flag);
self.permissions.insert(account_id, &permissions);
self.remove_bearer(flag, account_id);

let event = ::#cratename::access_controllable::events::AdminRevoked {
Expand All @@ -283,12 +282,11 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
fn grant_role_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool {
let flag = <#bitflags_type>::from_bits(role.acl_permission())
.unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG));
let mut permissions = self.get_or_init_permissions(account_id);
let mut permissions = self.get_or_insert_permissions(account_id.clone());

let is_new_grantee = !permissions.contains(flag);
if is_new_grantee {
permissions.insert(flag);
self.permissions.insert(account_id, &permissions);
self.add_bearer(flag, account_id);

let event = ::#cratename::access_controllable::events::RoleGranted {
Expand Down Expand Up @@ -316,12 +314,14 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
fn revoke_role_unchecked(&mut self, role: #role_type, account_id: &::near_sdk::AccountId) -> bool {
let flag = <#bitflags_type>::from_bits(role.acl_permission())
.unwrap_or_else(|| ::near_sdk::env::panic_str(#ERR_PARSE_BITFLAG));
let mut permissions = self.get_or_init_permissions(account_id);
let mut permissions = match self.permissions.get_mut(account_id) {
Some(permissions) => permissions,
None => return false, // nothing to do, account has no permissions
};

let was_grantee = permissions.contains(flag);
if was_grantee {
permissions.remove(flag);
self.permissions.insert(account_id, &permissions);
self.remove_bearer(flag, account_id);

let event = ::#cratename::access_controllable::events::RoleRevoked {
Expand Down Expand Up @@ -365,7 +365,10 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
}

fn has_any_permission(&self, target: #bitflags_type, account_id: &::near_sdk::AccountId) -> bool {
let permissions = self.get_or_init_permissions(account_id);
let permissions = match self.permissions.get(account_id) {
Some(&permissions) => permissions,
None => return false,
};
target.intersects(permissions)
}

Expand All @@ -383,13 +386,10 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
permission.bits().is_power_of_two(),
"Adding a bearer is allowed only for permissions with exactly one active bit"
);
let mut set = match self.bearers.get(&permission) {
Some(set) => set,
None => Self::new_bearers_set(permission),
};
if let true = set.insert(account_id) {
self.bearers.insert(&permission, &set);
}
let mut set = self.bearers.entry(permission).or_insert_with(|| {
Self::new_bearers_set(permission)
});
set.insert(account_id.clone());
}

/// Enables paginated retrieval of bearers. Returns up to `limit`
Expand All @@ -405,20 +405,18 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
Some(set) => set,
None => return vec![],
};
set.iter().skip(skip).take(limit).collect()
set.iter().skip(skip).take(limit).cloned().collect()
}

/// Removes `account_id` from the set of `permission` bearers.
fn remove_bearer(&mut self, permission: #bitflags_type, account_id: &::near_sdk::AccountId) {
// If `permission` is invalid (more than one active bit), this
// function is a no-op, due to the check in `add_bearer`.
let mut set = match self.bearers.get(&permission) {
let mut set = match self.bearers.get_mut(&permission) {
Some(set) => set,
None => return,
};
if let true = set.remove(account_id) {
self.bearers.insert(&permission, &set);
}
set.remove(account_id);
}
}

Expand Down

0 comments on commit 7454bbc

Please sign in to comment.