A smart contract that allows the decentralised management of groups. Built for the Aleph Zero blockchain, it's initial purpose is to use with a decentralised smart contract hub. The idea is to increase trust for users, by being able to associate an address with a group e.g. an upload by an address that is part of the Aleph Zero Foundation group will be more trustable.
pub enum Role {
Banned,
Applicant,
Member,
Admin,
SuperAdmin,
}
impl Role {
fn to_int(&self) -> u8 {
match *self {
Role::Banned => 0,
Role::Applicant => 1,
Role::Member => 2,
Role::Admin => 3,
Role::SuperAdmin => 4,
}
}
}
Creating a group:
- Names must unique (case-insensitive).
- Names will have whitespace removed from start and end.
fn groups_create(&mut self, name: String) -> Result<Group, AZGroupsError>
Updating a group:
- Super admin can change the name and enabled status of the group.
fn groups_update(&mut self, id: u32, name: String, enabled: bool) -> Result<Group, AZGroupsError>
Joining:
- Any non-member can apply to join. They can't be invited.
fn group_users_create(&mut self, group_id: u32) -> Result<GroupUser, AZGroupsError>
Kicking:
- Admin and super admin can kick members of the same role or less.
fn group_users_destroy(&mut self, group_id: u32, user: AccountId) -> Result<(), AZGroupsError>
Leaving:
- All members except for banned and super admin can leave a group.
- Super admin can't leave as it may leave a group without a super admin.
fn group_users_destroy(&mut self, group_id: u32, user: AccountId) -> Result<(), AZGroupsError>
Updating roles:
- Admin and super admin can update the role of members with the same role or less.
pub fn group_users_update(&mut self, group_id: u32, user: AccountId, role: Role) -> Result<GroupUser, AZGroupsError>
Please use the group's id where possible as the name can be changed.
To verify a user's membership, you would have to check that the group is enabled and that the user has a role >= 2. This can be done through:
pub fn validate_membership(&self, group_id: u32, user: AccountId) -> Result<Role, AZGroupsError>
Here is an example of a cross contract call:
fn validate_membership(
&self,
group_id: u32,
user: AccountId,
) -> Result<Role, AZSmartContractHubError> {
match cfg!(test) {
true => unimplemented!(
"`invoke_contract()` not being supported (tests end up panicking)"
),
false => {
use ink::env::call::{build_call, ExecutionInput, Selector};
const VALIDATE_MEMBERSHIP_SELECTOR: [u8; 4] =
ink::selector_bytes!("validate_membership");
Ok(build_call::<Environment>()
.call(self.az_groups_address)
.exec_input(
ExecutionInput::new(Selector::new(VALIDATE_MEMBERSHIP_SELECTOR))
.push_arg(group_id)
.push_arg(user),
)
.returns::<core::result::Result<Role, AZGroupsError>>()
.invoke()?)
}
}
}
cargo install --force --locked cargo-contract --version 2.0.1
cargo checkmate
cargo sort
- Build contract:
cargo contract build --release
- If setting up locally, start a local development chain. Recommended swanky-node v0.13.0:
~/Desktop/swanky-node/target/release/swanky-node --dev --tmp -lruntime=trace -lruntime::contracts=debug -lerror
- Upload, initialise and interact with contract at Contracts UI.