#![cfg_attr(not(feature = "std"), no_std)]
pub use pallet::*;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
mod functions;
pub mod types;
#[frame_support::pallet]
pub mod pallet {
use crate::types::*;
use frame_support::pallet_prelude::{ValueQuery, *};
use frame_system::pallet_prelude::*;
use sp_runtime::sp_std::vec::Vec;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
#[pallet::config]
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type RemoveOrigin: EnsureOrigin<Self::RuntimeOrigin>;
#[pallet::constant]
type MaxScopesPerPallet: Get<u32>;
#[pallet::constant]
type MaxRolesPerPallet: Get<u32>;
#[pallet::constant]
type RoleMaxLen: Get<u32>;
#[pallet::constant]
type PermissionMaxLen: Get<u32>;
#[pallet::constant]
type MaxPermissionsPerRole: Get<u32>;
#[pallet::constant]
type MaxRolesPerUser: Get<u32>;
#[pallet::constant]
type MaxUsersPerRole: Get<u32>;
}
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::storage]
#[pallet::getter(fn scopes)]
pub(super) type Scopes<T: Config> = StorageMap<
_,
Identity,
PalletId, BoundedVec<ScopeId, T::MaxScopesPerPallet>, ValueQuery,
>;
#[pallet::storage]
#[pallet::getter(fn roles)]
pub(super) type Roles<T: Config> = StorageMap<
_,
Identity,
RoleId, BoundedVec<u8, T::RoleMaxLen>, OptionQuery,
>;
#[pallet::storage]
#[pallet::getter(fn pallet_roles)]
pub(super) type PalletRoles<T: Config> = StorageMap<
_,
Identity,
PalletId, BoundedVec<RoleId, T::MaxRolesPerPallet>, ValueQuery,
>;
#[pallet::storage]
#[pallet::getter(fn permissions)]
pub(super) type Permissions<T: Config> = StorageDoubleMap<
_,
Identity,
PalletId, Identity,
PermissionId, BoundedVec<u8, T::PermissionMaxLen>, ValueQuery,
>;
#[pallet::storage]
#[pallet::getter(fn permissions_by_role)]
pub(super) type PermissionsByRole<T: Config> = StorageDoubleMap<
_,
Identity,
PalletId, Identity,
RoleId, BoundedVec<PermissionId, T::MaxPermissionsPerRole>, ValueQuery,
>;
#[pallet::storage]
#[pallet::getter(fn roles_by_user)]
pub(super) type RolesByUser<T: Config> = StorageNMap<
_,
(
NMapKey<Blake2_128Concat, T::AccountId>, NMapKey<Identity, PalletId>, NMapKey<Identity, ScopeId>, ),
BoundedVec<RoleId, T::MaxRolesPerUser>, ValueQuery,
>;
#[pallet::storage]
#[pallet::getter(fn users_by_scope)]
pub(super) type UsersByScope<T: Config> = StorageNMap<
_,
(
NMapKey<Identity, PalletId>, NMapKey<Identity, ScopeId>, NMapKey<Identity, RoleId>, ),
BoundedVec<T::AccountId, T::MaxUsersPerRole>, ValueQuery,
>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
RolesStored(PalletId, BoundedVec<RoleId, T::MaxRolesPerPallet>),
PermissionsCreatedAndSet(PalletId, RoleId, BoundedVec<PermissionId, T::MaxPermissionsPerRole>),
RoleRemovedFromUser(PalletId, ScopeId, RoleId, T::AccountId),
RoleAssignedToUser(PalletId, ScopeId, RoleId, T::AccountId),
PermissionRevokedFromRole(PalletId, RoleId, PermissionId),
PermissionRemovedFromPallet(PalletId, PermissionId, BoundedVec<RoleId, T::MaxRolesPerPallet>),
}
#[pallet::error]
pub enum Error<T> {
NoneValue,
ScopeNotFound,
ScopeAlreadyExists,
RoleNotFound,
PermissionNotFound,
UserNotFound,
DuplicateRole,
DuplicatePermission,
UserAlreadyHasRole,
RoleAlreadyLinkedToPallet,
RoleNotLinkedToPallet,
PermissionAlreadyLinkedToRole,
PermissionNotLinkedToRole,
UserHasNoRoles,
RoleHasNoUsers,
ExceedPalletNameMaxLen,
ExceedMaxScopesPerPallet,
ExceedMaxRolesPerPallet,
ExceedMaxPermissionsPerRole,
ExceedMaxRolesPerUser,
ExceedMaxUsersPerRole,
ExceedRoleMaxLen,
ExceedPermissionMaxLen,
NotAuthorized,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(Weight::from_ref_time(10_000) + T::DbWeight::get().writes(1))]
pub fn tx_create_and_set_roles(
origin: OriginFor<T>,
pallet: IdOrVec,
roles: Vec<Vec<u8>>,
) -> DispatchResult {
ensure!(T::RemoveOrigin::ensure_origin(origin.clone()).is_ok(), Error::<T>::NotAuthorized);
Self::create_and_set_roles(pallet, roles)?;
Ok(())
}
#[pallet::call_index(1)]
#[pallet::weight(Weight::from_ref_time(10_000) + T::DbWeight::get().writes(1))]
pub fn tx_remove_role_from_user(
origin: OriginFor<T>,
user: T::AccountId,
pallet: IdOrVec,
scope_id: ScopeId,
role_id: RoleId,
) -> DispatchResult {
ensure!(T::RemoveOrigin::ensure_origin(origin.clone()).is_ok(), Error::<T>::NotAuthorized);
Self::remove_role_from_user(user, pallet, &scope_id, role_id)?;
Ok(())
}
#[pallet::call_index(2)]
#[pallet::weight(Weight::from_ref_time(10_000) + T::DbWeight::get().writes(1))]
pub fn tx_create_and_set_permissions(
origin: OriginFor<T>,
pallet: IdOrVec,
role_id: RoleId,
permissions: Vec<Vec<u8>>,
) -> DispatchResult {
ensure!(T::RemoveOrigin::ensure_origin(origin.clone()).is_ok(), Error::<T>::NotAuthorized);
Self::create_and_set_permissions(pallet, role_id, permissions)?;
Ok(())
}
#[pallet::call_index(3)]
#[pallet::weight(Weight::from_ref_time(10_000) + T::DbWeight::get().writes(1))]
pub fn tx_assign_role_to_user(
origin: OriginFor<T>,
user: T::AccountId,
pallet: IdOrVec,
scope_id: ScopeId,
role_id: RoleId,
) -> DispatchResult {
ensure!(T::RemoveOrigin::ensure_origin(origin.clone()).is_ok(), Error::<T>::NotAuthorized);
Self::assign_role_to_user(user, pallet, &scope_id, role_id)?;
Ok(())
}
#[pallet::call_index(4)]
#[pallet::weight(Weight::from_ref_time(10_000) + T::DbWeight::get().writes(1))]
pub fn revoke_permission_from_role(
origin: OriginFor<T>,
pallet: IdOrVec,
role_id: RoleId,
permission_id: PermissionId,
) -> DispatchResult {
ensure!(T::RemoveOrigin::ensure_origin(origin.clone()).is_ok(), Error::<T>::NotAuthorized);
Self::do_revoke_permission_from_role(pallet, role_id, permission_id)?;
Ok(())
}
#[pallet::call_index(5)]
#[pallet::weight(Weight::from_ref_time(10_000) + T::DbWeight::get().writes(1))]
pub fn remove_permission_from_pallet(
origin: OriginFor<T>,
pallet: IdOrVec,
permission_id: PermissionId,
) -> DispatchResult {
ensure!(T::RemoveOrigin::ensure_origin(origin.clone()).is_ok(), Error::<T>::NotAuthorized);
Self::do_remove_permission_from_pallet(pallet, permission_id)?;
Ok(())
}
}
}