mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 12:07:57 +00:00
[NFTs] Rework permissions model (#13482)
* Disallow admin to transfer or burn items he doesn't own * lock_collection should be accessible by collection's owner only * Allow admin to access lock_item_properties() * Fix do_lock_item_properties * Move update_mint_settings() to Issuer * Rename check_owner to check_origin * Typo * Make admin to be in charge of managing the metadata * Make admin the main attributes manager * offchain mint should be signed by Issuer * Remove the special case when the Issuer calls the mint() function * Rework burn and destroy methods * Return back item_metadatas * Don't repatriate the deposit on transfer * A bit more tests * One more test * Add migration * Chore * Clippy * Rename to owned_item * Address comments * Replace .filter_map with .find_map * Improve version validation in pre_upgrade() * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nfts --------- Co-authored-by: parity-processbot <>
This commit is contained in:
@@ -33,17 +33,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
Error::<T, I>::MethodDisabled
|
||||
);
|
||||
|
||||
let mut collection_details =
|
||||
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
|
||||
|
||||
ensure!(
|
||||
Self::is_valid_namespace(
|
||||
&origin,
|
||||
&namespace,
|
||||
&collection,
|
||||
&collection_details.owner,
|
||||
&maybe_item,
|
||||
)?,
|
||||
Self::is_valid_namespace(&origin, &namespace, &collection, &maybe_item)?,
|
||||
Error::<T, I>::NoPermission
|
||||
);
|
||||
|
||||
@@ -66,6 +57,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let mut collection_details =
|
||||
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
|
||||
|
||||
let attribute = Attribute::<T, I>::get((collection, maybe_item, &namespace, &key));
|
||||
let attribute_exists = attribute.is_some();
|
||||
if !attribute_exists {
|
||||
@@ -219,7 +213,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
}
|
||||
|
||||
pub(crate) fn do_clear_attribute(
|
||||
maybe_check_owner: Option<T::AccountId>,
|
||||
maybe_check_origin: Option<T::AccountId>,
|
||||
collection: T::CollectionId,
|
||||
maybe_item: Option<T::ItemId>,
|
||||
namespace: AttributeNamespace<T::AccountId>,
|
||||
@@ -227,21 +221,13 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
) -> DispatchResult {
|
||||
let (_, deposit) = Attribute::<T, I>::take((collection, maybe_item, &namespace, &key))
|
||||
.ok_or(Error::<T, I>::AttributeNotFound)?;
|
||||
let mut collection_details =
|
||||
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
|
||||
|
||||
if let Some(check_owner) = &maybe_check_owner {
|
||||
if let Some(check_origin) = &maybe_check_origin {
|
||||
// validate the provided namespace when it's not a root call and the caller is not
|
||||
// the same as the `deposit.account` (e.g. the deposit was paid by different account)
|
||||
if deposit.account != maybe_check_owner {
|
||||
if deposit.account != maybe_check_origin {
|
||||
ensure!(
|
||||
Self::is_valid_namespace(
|
||||
&check_owner,
|
||||
&namespace,
|
||||
&collection,
|
||||
&collection_details.owner,
|
||||
&maybe_item,
|
||||
)?,
|
||||
Self::is_valid_namespace(&check_origin, &namespace, &collection, &maybe_item)?,
|
||||
Error::<T, I>::NoPermission
|
||||
);
|
||||
}
|
||||
@@ -264,17 +250,15 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
.map_or(None, |c| {
|
||||
Some(c.has_disabled_setting(ItemSetting::UnlockedAttributes))
|
||||
});
|
||||
match maybe_is_locked {
|
||||
Some(is_locked) => {
|
||||
// when item exists, then only the collection's owner can clear that
|
||||
// attribute
|
||||
ensure!(
|
||||
check_owner == &collection_details.owner,
|
||||
Error::<T, I>::NoPermission
|
||||
);
|
||||
ensure!(!is_locked, Error::<T, I>::LockedItemAttributes);
|
||||
},
|
||||
None => (),
|
||||
if let Some(is_locked) = maybe_is_locked {
|
||||
ensure!(!is_locked, Error::<T, I>::LockedItemAttributes);
|
||||
// Only the collection's admin can clear attributes in that namespace.
|
||||
// e.g. in off-chain mints, the attribute's depositor will be the item's
|
||||
// owner, that's why we need to do this extra check.
|
||||
ensure!(
|
||||
Self::has_role(&collection, &check_origin, CollectionRole::Admin),
|
||||
Error::<T, I>::NoPermission
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -282,6 +266,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
};
|
||||
}
|
||||
|
||||
let mut collection_details =
|
||||
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
|
||||
|
||||
collection_details.attributes.saturating_dec();
|
||||
|
||||
match deposit.account {
|
||||
@@ -372,12 +359,12 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
origin: &T::AccountId,
|
||||
namespace: &AttributeNamespace<T::AccountId>,
|
||||
collection: &T::CollectionId,
|
||||
collection_owner: &T::AccountId,
|
||||
maybe_item: &Option<T::ItemId>,
|
||||
) -> Result<bool, DispatchError> {
|
||||
let mut result = false;
|
||||
match namespace {
|
||||
AttributeNamespace::CollectionOwner => result = origin == collection_owner,
|
||||
AttributeNamespace::CollectionOwner =>
|
||||
result = Self::has_role(&collection, &origin, CollectionRole::Admin),
|
||||
AttributeNamespace::ItemOwner =>
|
||||
if let Some(item) = maybe_item {
|
||||
let item_details =
|
||||
|
||||
Reference in New Issue
Block a user