Skip to content
Snippets Groups Projects
Commit ca4f4fac authored by Pascal Engélibert's avatar Pascal Engélibert :bicyclist:
Browse files

WIP feat(identity): del_all_rights

parent 8dcb2f57
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !12. Comments created here will be created in the context of that merge request.
......@@ -36,7 +36,7 @@ use crate::traits::*;
use codec::Codec;
use frame_support::dispatch::Weight;
use frame_system::RawOrigin;
use sp_runtime::traits::{AtLeast32BitUnsigned, One, Saturating, Zero};
use sp_runtime::traits::{AtLeast32BitUnsigned, IdentifyAccount, One, Saturating, Zero};
use sp_std::fmt::Debug;
use sp_std::prelude::*;
......@@ -45,6 +45,7 @@ pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_support::traits::StorageVersion;
use frame_system::offchain::SignedPayload;
use frame_system::pallet_prelude::*;
use sp_membership::traits::MembershipAction as _;
......@@ -59,7 +60,7 @@ pub mod pallet {
// CONFIG //
#[pallet::config]
pub trait Config: frame_system::Config {
pub trait Config: frame_system::Config + frame_system::offchain::SigningTypes {
#[pallet::constant]
/// Period during which the owner can confirm the new identity.
type ConfirmPeriod: Get<Self::BlockNumber>;
......@@ -251,7 +252,11 @@ pub mod pallet {
// These functions materialize as "extrinsics", which are often compared to transactions.
// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
#[pallet::call]
impl<T: Config> Pallet<T> {
impl<T: Config> Pallet<T>
where
<T as frame_system::offchain::SigningTypes>::Public:
IdentifyAccount<AccountId = T::AccountId>,
{
#[pallet::weight(0)]
pub fn create_identity(
origin: OriginFor<T>,
......@@ -549,6 +554,65 @@ pub mod pallet {
}
}
#[pallet::weight(0)]
pub fn revoke_identity(
origin: OriginFor<T>,
payload: RevocationPayload<
<T as frame_system::offchain::SigningTypes>::Public,
T::IdtyIndex,
>,
payload_sig: <T as frame_system::offchain::SigningTypes>::Signature,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
if !payload.verify(payload_sig) {
return Err(Error::<T>::BadProof.into());
}
let idty_index = payload.idty;
if let Ok(mut idty_value) = <Identities<T>>::try_get(idty_index) {
if idty_value.owner_key != payload.owner_key.into_account() {
return Err(Error::<T>::RequireToBeOwner.into());
}
if idty_value.status != IdtyStatus::Validated {
return Err(Error::<T>::IdtyNotValidated.into());
}
for (right, subkey_opt) in idty_value.rights.drain(..) {
let name = idty_value.name.clone();
let old_key_opt = if let Some(ref subkey) = subkey_opt {
Some(subkey.clone())
} else if right.allow_owner_key() {
Some(idty_value.owner_key.clone())
} else {
None
};
Self::deposit_event(Event::<T>::IdtyLostRight(name, right));
if old_key_opt.is_some() {
T::OnRightKeyChange::on_right_key_change(
idty_index,
right,
old_key_opt,
None,
);
}
}
let block_number = frame_system::pallet::Pallet::<T>::block_number();
let removable_on = block_number + T::MaxNoRightPeriod::get();
idty_value.removable_on = removable_on;
<IdentitiesRemovableOn<T>>::append(
removable_on,
(idty_index, IdtyStatus::Validated),
);
<Identities<T>>::insert(idty_index, idty_value);
Ok(().into())
} else {
Err(Error::<T>::IdtyNotFound.into())
}
}
#[pallet::weight(0)]
pub fn set_right_subkey(
origin: OriginFor<T>,
idty_index: T::IdtyIndex,
......@@ -608,6 +672,7 @@ pub mod pallet {
#[pallet::error]
pub enum Error<T> {
BadProof,
/// Creator not exist
CreatorNotExist,
/// Creator not allowed to create identities
......
......@@ -247,3 +247,58 @@ fn test_two_identities() {
assert_eq!(idty2.removable_on, 7);
});
}
#[test]
fn test_revoke_identity() {
let identities = vec![crate::IdtyValue {
name: IdtyName(vec![0]),
expire_on: 5,
owner_key: 1,
removable_on: 0,
renewable_on: 3,
rights: vec![(Right::Right1, None), (Right::Right2, Some(10))],
status: crate::IdtyStatus::Validated,
data: (),
}];
new_test_ext(IdentityConfig { identities }).execute_with(|| {
// Should have one identity
assert_eq!(Identity::identities_count(), 1);
// We need to initialize at least one block before any call
run_to_block(1);
// Delete right Right1 for IdtyName(vec![1])
// Should succes and trigger the correct event
assert_ok!(Identity::revoke_identity(Origin::root(), 1));
let events = System::events();
assert_eq!(events.len(), 2);
assert_eq!(
events[0],
EventRecord {
phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyLostRight(
IdtyName(vec![0]),
Right::Right1
)),
topics: vec![],
}
);
assert_eq!(
events[1],
EventRecord {
phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyLostRight(
IdtyName(vec![0]),
Right::Right2
)),
topics: vec![],
}
);
// The identity has no more rights, the inactivity period must start to run
let idty = Identity::identity(1).expect("idty not found");
assert!(idty.rights.is_empty());
assert_eq!(idty.removable_on, 5);
});
}
......@@ -113,3 +113,21 @@ where
}
}
}
#[derive(Clone, Encode, Decode, PartialEq, Eq, TypeInfo, RuntimeDebug)]
pub struct RevocationPayload<
AccountId: Decode + Encode + TypeInfo,
IdtyIndex: Decode + Encode + TypeInfo,
> {
pub owner_key: AccountId,
pub idty: IdtyIndex,
}
impl<T: frame_system::offchain::SigningTypes, IdtyIndex: Decode + Encode + TypeInfo>
frame_system::offchain::SignedPayload<T>
for RevocationPayload<<T as frame_system::offchain::SigningTypes>::Public, IdtyIndex>
{
fn public(&self) -> <T as frame_system::offchain::SigningTypes>::Public {
self.owner_key.clone()
}
}
......@@ -202,6 +202,10 @@ macro_rules! pallets_config {
type MaxNoRightPeriod = MaxNoRightPeriod;
type Membership = Membership;
}
impl SigningTypes for Runtime {
type Public = <Signature as Verify>::Signer;
type Signature = Signature;
}
impl pallet_membership::Config<frame_support::instances::Instance1> for Runtime {
type IsIdtyAllowedToClaimMembership = ();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment