Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions near-plugins-derive/src/access_controllable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,11 @@ pub fn access_controllable(attrs: TokenStream, item: TokenStream) -> TokenStream
(#storage_prefix).as_bytes()
}

#[private]
fn acl_init_super_admin(&mut self, account_id: ::near_sdk::AccountId) -> bool {
self.#acl_field.init_super_admin(&account_id)
}

fn acl_is_super_admin(&self, account_id: ::near_sdk::AccountId) -> bool {
self.#acl_field.is_super_admin(&account_id)
}
Expand Down
12 changes: 12 additions & 0 deletions near-plugins/src/access_controllable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ pub trait AccessControllable {
/// Returns the storage prefix for collections related to access control.
fn acl_storage_prefix() -> &'static [u8];

/// Adds `account_id` as super-admin __without__ checking any permissions in
/// case there are no super-admins. This function can be used to add a
/// super-admin during contract initialization. Moreover, it may provide a
/// recovery mechanism if (mistakenly) all super-admins have been removed.
///
/// The return value indicates whether `account_id` was added as
/// super-admin.
///
/// It is `#[private]` in the implementation provided by this trait, i.e.
/// only the contract itself may call this method.
fn acl_init_super_admin(&mut self, account_id: AccountId) -> bool;

/// Returns whether `account_id` is a super-admin.
fn acl_is_super_admin(&self, account_id: AccountId) -> bool;

Expand Down
24 changes: 8 additions & 16 deletions near-plugins/tests/contracts/access_controllable/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,22 @@ pub struct StatusMessage {

#[near_bindgen]
impl StatusMessage {
// Initially adding (super-)admins is done via internal methods, for
// example:
//
// ```
// self.__acl.add_super_admin_unchecked(account_id);
// self.__acl.add_admin_unchecked(role, account_id);
// ```
//
// **Attention**: Contracts should call `__acl.*_unchecked` methods only
// from within methods with attribute `#[init]` or `#[private]`.
// Adding an initial super-admin can be done via trait method
// `AccessControllable::acl_init_super_admin`, which is automatically
// implemented and exported for the contract by `#[access_controllable]`.
//
// Once an account is (super-)admin, it may add other admins and grant
// roles.
//
// If needed, It's also possible to grant a role without checks:
// In addition, there are internal `*_unchecked` methods for example:
//
// ```
// self.__acl.add_admin_unchecked(role, account_id);
// self.__acl.grant_role_unchecked(role, account_id);
// ```
//
// **Attention**: Contracts should call `__acl.*_unchecked` methods only
// from within methods with attribute `#[init]` or `#[private]`.

#[payable]
pub fn set_status(&mut self, message: String) {
Expand Down Expand Up @@ -75,11 +72,6 @@ impl StatusMessage {
/// Exposing internal methods to facilitate integration testing.
#[near_bindgen]
impl StatusMessage {
#[private]
pub fn acl_init_super_admin(&mut self, account_id: ::near_sdk::AccountId) -> bool {
self.__acl.init_super_admin(&account_id)
}

#[private]
pub fn acl_add_super_admin_unchecked(&mut self, account_id: AccountId) -> bool {
self.__acl.add_super_admin_unchecked(&account_id)
Expand Down