Browse Source

members: remove Members trait, add members genesis config to set initial members

Mokhtar Naamani 5 years ago
parent
commit
7f46de2563

+ 6 - 5
src/governance/election.rs

@@ -18,14 +18,14 @@ use super::stake::Stake;
 use super::council;
 pub use crate::currency::{BalanceOf, GovernanceCurrency};
 
-use crate::traits::Members;
+use crate::membership;
 
-pub trait Trait: system::Trait + council::Trait + GovernanceCurrency {
+pub trait Trait:
+    system::Trait + council::Trait + GovernanceCurrency + membership::members::Trait
+{
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 
     type CouncilElected: CouncilElected<Seats<Self::AccountId, BalanceOf<Self>>, Self::BlockNumber>;
-
-    type Members: Members<Self>;
 }
 
 #[derive(Clone, Copy, Encode, Decode)]
@@ -157,7 +157,8 @@ impl<T: Trait> Module<T> {
     }
 
     fn can_participate(sender: &T::AccountId) -> bool {
-        !T::Currency::free_balance(sender).is_zero() && T::Members::is_active_member(sender)
+        !T::Currency::free_balance(sender).is_zero()
+            && <membership::members::Module<T>>::is_active_member(sender)
     }
 
     // PUBLIC IMMUTABLES

+ 37 - 21
src/governance/mock.rs

@@ -2,7 +2,7 @@
 
 pub use super::{council, election, proposals};
 pub use crate::currency::GovernanceCurrency;
-use crate::traits::Members;
+use crate::membership;
 pub use system;
 
 pub use primitives::{Blake2Hasher, H256};
@@ -19,23 +19,6 @@ impl_outer_origin! {
     pub enum Origin for Test {}
 }
 
-pub struct MockMembership {}
-impl<T: system::Trait> Members<T> for MockMembership {
-    type Id = u32;
-    fn is_active_member(_who: &T::AccountId) -> bool {
-        // all accounts are considered members.
-        // There is currently no test coverage for non-members.
-        // Should add some coverage, and update this method to reflect which accounts are or are not members
-        true
-    }
-    fn lookup_member_id(_account_id: &T::AccountId) -> Result<Self::Id, &'static str> {
-        Err("not implemented!")
-    }
-    fn lookup_account_by_member_id(_id: Self::Id) -> Result<T::AccountId, &'static str> {
-        Err("not implemented!")
-    }
-}
-
 // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Test;
@@ -80,8 +63,12 @@ impl election::Trait for Test {
     type Event = ();
 
     type CouncilElected = (Council,);
-
-    type Members = MockMembership;
+}
+impl membership::members::Trait for Test {
+    type Event = ();
+    type MemberId = u32;
+    type SubscriptionId = u32;
+    type PaidTermId = u32;
 }
 
 parameter_types! {
@@ -122,10 +109,39 @@ impl GovernanceCurrency for Test {
 // This function basically just builds a genesis storage key/value store according to
 // our desired mockup.
 pub fn initial_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
-    let t = system::GenesisConfig::default()
+    let mut t = system::GenesisConfig::default()
         .build_storage::<Test>()
         .unwrap();
 
+    membership::members::GenesisConfig::<Test> {
+        first_member_id: 1,
+        default_paid_membership_fee: 0,
+        members: vec![
+            (1, "member1".into(), "".into(), "".into()),
+            (2, "member2".into(), "".into(), "".into()),
+            (3, "member3".into(), "".into(), "".into()),
+            (4, "member4".into(), "".into(), "".into()),
+            (5, "member5".into(), "".into(), "".into()),
+            (6, "member6".into(), "".into(), "".into()),
+            (7, "member7".into(), "".into(), "".into()),
+            (8, "member8".into(), "".into(), "".into()),
+            (9, "member9".into(), "".into(), "".into()),
+            (10, "member10".into(), "".into(), "".into()),
+            (11, "member11".into(), "".into(), "".into()),
+            (12, "member12".into(), "".into(), "".into()),
+            (13, "member13".into(), "".into(), "".into()),
+            (14, "member14".into(), "".into(), "".into()),
+            (15, "member15".into(), "".into(), "".into()),
+            (16, "member16".into(), "".into(), "".into()),
+            (17, "member17".into(), "".into(), "".into()),
+            (18, "member18".into(), "".into(), "".into()),
+            (19, "member19".into(), "".into(), "".into()),
+            (20, "member20".into(), "".into(), "".into()),
+        ],
+    }
+    .assimilate_storage(&mut t)
+    .unwrap();
+
     t.into()
 }
 

+ 27 - 22
src/governance/proposals.rs

@@ -16,7 +16,7 @@ use primitives::storage::well_known_keys;
 
 use super::council;
 pub use crate::currency::{BalanceOf, GovernanceCurrency};
-use crate::traits::Members;
+use crate::membership;
 
 const DEFAULT_APPROVAL_QUORUM: u32 = 60;
 const DEFAULT_MIN_STAKE: u32 = 100;
@@ -121,11 +121,11 @@ pub struct TallyResult<BlockNumber> {
     finalized_at: BlockNumber,
 }
 
-pub trait Trait: timestamp::Trait + council::Trait + GovernanceCurrency {
+pub trait Trait:
+    timestamp::Trait + council::Trait + GovernanceCurrency + membership::members::Trait
+{
     /// The overarching event type.
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
-
-    type Members: Members<Self>;
 }
 
 decl_event!(
@@ -358,7 +358,8 @@ impl<T: Trait> Module<T> {
     }
 
     fn can_participate(sender: T::AccountId) -> bool {
-        !T::Currency::free_balance(&sender).is_zero() && T::Members::is_active_member(&sender)
+        !T::Currency::free_balance(&sender).is_zero()
+            && <membership::members::Module<T>>::is_active_member(&sender)
     }
 
     fn is_councilor(sender: &T::AccountId) -> bool {
@@ -645,26 +646,15 @@ mod tests {
         type Currency = balances::Module<Self>;
     }
 
-    impl Trait for Test {
+    impl membership::members::Trait for Test {
         type Event = ();
-        type Members = MockMembership;
+        type MemberId = u32;
+        type PaidTermId = u32;
+        type SubscriptionId = u32;
     }
 
-    pub struct MockMembership {}
-    impl<T: system::Trait> Members<T> for MockMembership {
-        type Id = u32;
-        fn is_active_member(_who: &T::AccountId) -> bool {
-            // all accounts are considered members.
-            // There is currently no test coverage for non-members.
-            // Should add some coverage, and update this method to reflect which accounts are or are not members
-            true
-        }
-        fn lookup_member_id(_account_id: &T::AccountId) -> Result<Self::Id, &'static str> {
-            Err("not implemented!")
-        }
-        fn lookup_account_by_member_id(_id: Self::Id) -> Result<T::AccountId, &'static str> {
-            Err("not implemented!")
-        }
+    impl Trait for Test {
+        type Event = ();
     }
 
     type System = system::Module<Test>;
@@ -722,6 +712,21 @@ mod tests {
         .assimilate_storage(&mut t)
         .unwrap();
 
+        membership::members::GenesisConfig::<Test> {
+            first_member_id: 1,
+            default_paid_membership_fee: 0,
+            members: vec![
+                (PROPOSER1, "alice".into(), "".into(), "".into()),
+                (PROPOSER2, "bobby".into(), "".into(), "".into()),
+                (COUNCILOR1, "councilor1".into(), "".into(), "".into()),
+                (COUNCILOR2, "councilor2".into(), "".into(), "".into()),
+                (COUNCILOR3, "councilor3".into(), "".into(), "".into()),
+                (COUNCILOR4, "councilor4".into(), "".into(), "".into()),
+                (COUNCILOR5, "councilor5".into(), "".into(), "".into()),
+            ],
+        }
+        .assimilate_storage(&mut t)
+        .unwrap();
         // t.extend(GenesisConfig::<Test>{
         //     // Here we can override defaults.
         // }.build_storage().unwrap().0);

+ 0 - 5
src/lib.rs

@@ -382,13 +382,11 @@ impl currency::GovernanceCurrency for Runtime {
 
 impl governance::proposals::Trait for Runtime {
     type Event = Event;
-    type Members = Members;
 }
 
 impl governance::election::Trait for Runtime {
     type Event = Event;
     type CouncilElected = (Council,);
-    type Members = Members;
 }
 
 impl governance::council::Trait for Runtime {
@@ -409,7 +407,6 @@ impl storage::data_directory::Trait for Runtime {
     type Event = Event;
     type ContentId = ContentId;
     type SchemaId = u64;
-    type Members = Members;
     type Roles = LookupRoles;
     type IsActiveDataObjectType = DataObjectTypeRegistry;
 }
@@ -423,7 +420,6 @@ impl storage::downloads::Trait for Runtime {
 impl storage::data_object_storage_registry::Trait for Runtime {
     type Event = Event;
     type DataObjectStorageRelationshipId = u64;
-    type Members = Members;
     type Roles = LookupRoles;
     type ContentIdExists = DataDirectory;
 }
@@ -518,7 +514,6 @@ impl migration::Trait for Runtime {
 
 impl actors::Trait for Runtime {
     type Event = Event;
-    type Members = Members;
     type OnActorRemoved = HandleActorRemoved;
 }
 

+ 20 - 8
src/membership/members.rs

@@ -1,7 +1,8 @@
 use crate::currency::{BalanceOf, GovernanceCurrency};
-use crate::traits::Members;
 use codec::{Codec, Decode, Encode};
 use rstd::prelude::*;
+#[cfg(feature = "std")]
+use runtime_io::with_storage;
 use runtime_primitives::traits::{MaybeSerializeDebug, Member, SimpleArithmetic};
 use srml_support::traits::Currency;
 use srml_support::{
@@ -166,6 +167,21 @@ decl_storage! {
     }
     add_extra_genesis {
         config(default_paid_membership_fee): BalanceOf<T>;
+        config(members) : Vec<(T::AccountId, Vec<u8>, Vec<u8>, Vec<u8>)>;
+        build(|
+            storage: &mut (runtime_primitives::StorageOverlay, runtime_primitives::ChildrenStorageOverlay),
+            config: &GenesisConfig<T>
+        | {
+            with_storage(storage, || {
+                for (who, handle, avatar_uri, about) in &config.members {
+                    let user_info = CheckedUserInfo {
+                        handle: handle.clone(), avatar_uri: avatar_uri.clone(), about: about.clone()
+                    };
+                    <Module<T>>::insert_member(&who, &user_info, EntryMethod::Paid(T::PaidTermId::from(DEFAULT_PAID_TERM_ID)));
+                }
+            });
+        });
+
     }
 }
 
@@ -188,23 +204,19 @@ impl<T: Trait> Module<T> {
         let default_terms: PaidMembershipTerms<T> = Default::default();
         <PaidMembershipTermsById<T>>::insert(default_terms.id, default_terms);
     }
-}
-
-impl<T: Trait> Members<T> for Module<T> {
-    type Id = T::MemberId;
 
-    fn is_active_member(who: &T::AccountId) -> bool {
+    pub fn is_active_member(who: &T::AccountId) -> bool {
         match Self::ensure_is_member(who).and_then(|member_id| Self::ensure_profile(member_id)) {
             Ok(profile) => !profile.suspended,
             Err(_err) => false,
         }
     }
 
-    fn lookup_member_id(who: &T::AccountId) -> Result<Self::Id, &'static str> {
+    pub fn lookup_member_id(who: &T::AccountId) -> Result<T::MemberId, &'static str> {
         Self::ensure_is_member(who)
     }
 
-    fn lookup_account_by_member_id(id: Self::Id) -> Result<T::AccountId, &'static str> {
+    pub fn lookup_account_by_member_id(id: T::MemberId) -> Result<T::AccountId, &'static str> {
         if <AccountIdByMemberId<T>>::exists(&id) {
             Ok(Self::account_id_by_member_id(&id))
         } else {

+ 1 - 0
src/membership/mock.rs

@@ -125,6 +125,7 @@ impl ExtBuilder {
         members::GenesisConfig::<Test> {
             first_member_id: self.first_member_id,
             default_paid_membership_fee: self.default_paid_membership_fee,
+            members: vec![],
         }
         .assimilate_storage(&mut t)
         .unwrap();

+ 10 - 10
src/roles/actors.rs

@@ -9,7 +9,7 @@ use srml_support::traits::{
 use srml_support::{decl_event, decl_module, decl_storage, ensure, StorageMap, StorageValue};
 use system::{self, ensure_root, ensure_signed};
 
-use crate::traits::Members;
+use crate::membership;
 
 const STAKING_ID: LockIdentifier = *b"role_stk";
 
@@ -86,15 +86,15 @@ pub trait ActorRemoved<T: Trait> {
     fn actor_removed(actor: &T::AccountId);
 }
 
-pub trait Trait: system::Trait + GovernanceCurrency + MaybeDebug {
+pub trait Trait:
+    system::Trait + GovernanceCurrency + MaybeDebug + membership::members::Trait
+{
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 
-    type Members: Members<Self>;
-
     type OnActorRemoved: ActorRemoved<Self>;
 }
 
-pub type MemberId<T> = <<T as Trait>::Members as Members<T>>::Id;
+pub type MemberId<T> = <T as membership::members::Trait>::MemberId;
 // actor account, memberid, role, expires
 pub type Request<T> = (
     <T as system::Trait>::AccountId,
@@ -288,7 +288,7 @@ decl_module! {
                                     let _ = T::Currency::deposit_into_existing(&actor.account, params.reward);
                                 } else {
                                     // otherwise it should go the the member account
-                                    if let Ok(member_account) = T::Members::lookup_account_by_member_id(actor.member_id) {
+                                    if let Ok(member_account) = <membership::members::Module<T>>::lookup_account_by_member_id(actor.member_id) {
                                         let _ = T::Currency::deposit_into_existing(&member_account, params.reward);
                                     }
                                 }
@@ -302,7 +302,7 @@ decl_module! {
         pub fn role_entry_request(origin, role: Role, member_id: MemberId<T>) {
             let sender = ensure_signed(origin)?;
 
-            ensure!(T::Members::lookup_member_id(&sender).is_err(), "account is a member");
+            ensure!(<membership::members::Module<T>>::lookup_member_id(&sender).is_err(), "account is a member");
             ensure!(!Self::is_role_account(&sender), "account already used");
 
             ensure!(Self::is_role_available(role), "inactive role");
@@ -324,7 +324,7 @@ decl_module! {
         /// Member activating entry request
         pub fn stake(origin, role: Role, actor_account: T::AccountId) {
             let sender = ensure_signed(origin)?;
-            let member_id = T::Members::lookup_member_id(&sender)?;
+            let member_id = <membership::members::Module<T>>::lookup_member_id(&sender)?;
 
             if !Self::role_entry_requests()
                 .iter()
@@ -333,7 +333,7 @@ decl_module! {
                 return Err("no role entry request matches");
             }
 
-            ensure!(T::Members::lookup_member_id(&actor_account).is_err(), "account is a member");
+            ensure!(<membership::members::Module<T>>::lookup_member_id(&actor_account).is_err(), "account is a member");
             ensure!(!Self::is_role_account(&actor_account), "account already used");
 
             // make sure role is still available
@@ -372,7 +372,7 @@ decl_module! {
 
         pub fn unstake(origin, actor_account: T::AccountId) {
             let sender = ensure_signed(origin)?;
-            let member_id = T::Members::lookup_member_id(&sender)?;
+            let member_id = <membership::members::Module<T>>::lookup_member_id(&sender)?;
 
             let actor = Self::ensure_actor_is_member(&actor_account, member_id)?;
 

+ 27 - 47
src/roles/mock.rs

@@ -2,7 +2,7 @@
 
 pub use super::actors;
 pub use crate::currency::GovernanceCurrency;
-use crate::traits::Members;
+use crate::membership;
 pub use srml_support::traits::Currency;
 pub use system;
 
@@ -20,6 +20,13 @@ impl_outer_origin! {
     pub enum Origin for Test {}
 }
 
+pub fn alice_id() -> u32 {
+    1
+}
+pub fn alice_account() -> u64 {
+    1
+}
+
 // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Test;
@@ -28,6 +35,7 @@ parameter_types! {
     pub const MaximumBlockWeight: u32 = 1024;
     pub const MaximumBlockLength: u32 = 2 * 1024;
     pub const AvailableBlockRatio: Perbill = Perbill::one();
+    pub const MinimumPeriod: u64 = 5;
 }
 
 impl system::Trait for Test {
@@ -82,57 +90,21 @@ impl GovernanceCurrency for Test {
     type Currency = balances::Module<Self>;
 }
 
-pub struct MockMembers {}
-
-impl MockMembers {
-    pub fn alice_id() -> u32 {
-        1
-    }
-    pub fn alice_account() -> u64 {
-        1
-    }
-    pub fn bob_id() -> u32 {
-        2
-    }
-    pub fn bob_account() -> u64 {
-        2
-    }
+impl timestamp::Trait for Test {
+    type Moment = u64;
+    type OnTimestampSet = ();
+    type MinimumPeriod = MinimumPeriod;
 }
 
-impl Members<Test> for MockMembers {
-    type Id = u32;
-    fn is_active_member(who: &u64) -> bool {
-        if *who == Self::alice_account() {
-            return true;
-        }
-        if *who == Self::bob_account() {
-            return true;
-        }
-        false
-    }
-    fn lookup_member_id(who: &u64) -> Result<u32, &'static str> {
-        if *who == Self::alice_account() {
-            return Ok(Self::alice_id());
-        }
-        if *who == Self::bob_account() {
-            return Ok(Self::bob_id());
-        }
-        Err("member not found")
-    }
-    fn lookup_account_by_member_id(id: Self::Id) -> Result<u64, &'static str> {
-        if id == Self::alice_id() {
-            return Ok(Self::alice_account());
-        }
-        if id == Self::bob_id() {
-            return Ok(Self::bob_account());
-        }
-        Err("account not found")
-    }
+impl membership::members::Trait for Test {
+    type Event = ();
+    type MemberId = u32;
+    type SubscriptionId = u32;
+    type PaidTermId = u32;
 }
 
 impl actors::Trait for Test {
     type Event = ();
-    type Members = MockMembers;
     type OnActorRemoved = ();
 }
 
@@ -141,10 +113,18 @@ impl actors::ActorRemoved<Test> for () {
 }
 
 pub fn initial_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
-    let t = system::GenesisConfig::default()
+    let mut t = system::GenesisConfig::default()
         .build_storage::<Test>()
         .unwrap();
 
+    membership::members::GenesisConfig::<Test> {
+        first_member_id: 1,
+        default_paid_membership_fee: 0,
+        members: vec![(alice_account(), "alice".into(), "".into(), "".into())],
+    }
+    .assimilate_storage(&mut t)
+    .unwrap();
+
     t.into()
 }
 

+ 12 - 20
src/roles/tests.rs

@@ -74,7 +74,7 @@ fn make_entry_request() {
             Actors::role_entry_request(
                 Origin::signed(actor_account),
                 actors::Role::Storage,
-                MockMembers::alice_id()
+                alice_id()
             )
             .is_err(),
             ""
@@ -90,7 +90,7 @@ fn make_entry_request() {
             Actors::role_entry_request(
                 Origin::signed(actor_account),
                 actors::Role::Storage,
-                MockMembers::alice_id()
+                alice_id()
             )
             .is_ok(),
             ""
@@ -102,7 +102,7 @@ fn make_entry_request() {
         assert_eq!(requests.len(), 1);
         let request = requests[0];
         assert_eq!(request.0, actor_account);
-        assert_eq!(request.1, MockMembers::alice_id());
+        assert_eq!(request.1, alice_id());
         assert_eq!(request.2, actors::Role::Storage);
         assert_eq!(
             request.3,
@@ -119,19 +119,15 @@ fn staking() {
         let storage_params = init_storage_parmeters();
         let actor_account = 5;
 
-        let request: actors::Request<Test> = (
-            actor_account,
-            MockMembers::alice_id(),
-            actors::Role::Storage,
-            1000,
-        );
+        let request: actors::Request<Test> =
+            (actor_account, alice_id(), actors::Role::Storage, 1000);
 
         <actors::RoleEntryRequests<Test>>::put(vec![request]);
 
         let _ = Balances::deposit_creating(&actor_account, storage_params.min_stake);
 
         assert!(Actors::stake(
-            Origin::signed(MockMembers::alice_account()),
+            Origin::signed(alice_account()),
             actors::Role::Storage,
             actor_account
         )
@@ -146,7 +142,7 @@ fn staking() {
         let accounts_in_role = Actors::account_ids_by_role(actors::Role::Storage);
         assert_eq!(accounts_in_role, vec![actor_account]);
 
-        let account_ids_for_member = Actors::account_ids_by_member_id(MockMembers::alice_id());
+        let account_ids_for_member = Actors::account_ids_by_member_id(alice_id());
         assert_eq!(account_ids_for_member, vec![actor_account]);
 
         let num_of_locks = Balances::locks(&actor_account).len();
@@ -161,26 +157,22 @@ fn unstaking() {
         let storage_params = init_storage_parmeters();
         let actor_account = 5;
 
-        assert!(
-            Actors::unstake(Origin::signed(MockMembers::alice_account()), actor_account).is_err()
-        );
+        assert!(Actors::unstake(Origin::signed(alice_account()), actor_account).is_err());
 
         let actor: actors::Actor<Test> = actors::Actor {
             role: actors::Role::Storage,
-            member_id: MockMembers::alice_id(),
+            member_id: alice_id(),
             account: actor_account,
             joined_at: 1,
         };
         <actors::ActorAccountIds<Test>>::put(vec![actor_account]);
         <actors::ActorByAccountId<Test>>::insert(&actor_account, actor);
         <actors::AccountIdsByRole<Test>>::insert(actors::Role::Storage, vec![actor_account]);
-        <actors::AccountIdsByMemberId<Test>>::insert(MockMembers::alice_id(), vec![actor_account]);
+        <actors::AccountIdsByMemberId<Test>>::insert(alice_id(), vec![actor_account]);
         let current_block = 500;
 
         System::set_block_number(current_block);
-        assert!(
-            Actors::unstake(Origin::signed(MockMembers::alice_account()), actor_account).is_ok()
-        );
+        assert!(Actors::unstake(Origin::signed(alice_account()), actor_account).is_ok());
 
         assert_eq!(Actors::actor_account_ids().len(), 0);
 
@@ -190,7 +182,7 @@ fn unstaking() {
         let accounts_in_role = Actors::account_ids_by_role(actors::Role::Storage);
         assert_eq!(accounts_in_role.len(), 0);
 
-        let account_ids_for_member = Actors::account_ids_by_member_id(MockMembers::alice_id());
+        let account_ids_for_member = Actors::account_ids_by_member_id(alice_id());
         assert_eq!(account_ids_for_member.len(), 0);
 
         let lock = Balances::locks(&actor_account)[0].clone();

+ 1 - 1
src/service_discovery/discovery.rs

@@ -1,6 +1,6 @@
 use crate::traits::Roles;
 use codec::{Decode, Encode};
-use rstd::prelude::*;
+//use rstd::prelude::*;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 

+ 16 - 8
src/storage/data_directory.rs

@@ -1,6 +1,7 @@
+use crate::membership;
 use crate::roles::actors;
 use crate::storage::data_object_type_registry::Trait as DOTRTrait;
-use crate::traits::{ContentIdExists, IsActiveDataObjectType, Members, Roles};
+use crate::traits::{ContentIdExists, IsActiveDataObjectType, Roles};
 use codec::{Codec, Decode, Encode};
 use rstd::prelude::*;
 use runtime_primitives::traits::{
@@ -11,7 +12,9 @@ use srml_support::{
 };
 use system::{self, ensure_root, ensure_signed};
 
-pub trait Trait: timestamp::Trait + system::Trait + DOTRTrait + MaybeDebug {
+pub trait Trait:
+    timestamp::Trait + system::Trait + DOTRTrait + MaybeDebug + membership::members::Trait
+{
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 
     type ContentId: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + Copy + Ord + Default;
@@ -25,7 +28,6 @@ pub trait Trait: timestamp::Trait + system::Trait + DOTRTrait + MaybeDebug {
         + MaybeSerializeDebug
         + PartialEq;
 
-    type Members: Members<Self>;
     type Roles: Roles<Self>;
     type IsActiveDataObjectType: IsActiveDataObjectType<Self>;
 }
@@ -159,7 +161,7 @@ decl_module! {
             ipfs_content_id: Vec<u8>
         ) {
             let who = ensure_signed(origin)?;
-            ensure!(T::Members::is_active_member(&who), MSG_CREATOR_MUST_BE_MEMBER);
+            ensure!(<membership::members::Module<T>>::is_active_member(&who), MSG_CREATOR_MUST_BE_MEMBER);
 
             ensure!(T::IsActiveDataObjectType::is_active_data_object_type(&type_id),
                 MSG_DO_TYPE_MUST_BE_ACTIVE);
@@ -209,7 +211,7 @@ decl_module! {
             update: ContentMetadataUpdate<T>
         ) {
             let who = ensure_signed(origin)?;
-            ensure!(T::Members::is_active_member(&who),
+            ensure!(<membership::members::Module<T>>::is_active_member(&who),
                 "Only active members can add content metadata");
 
             ensure!(!<MetadataByContentId<T>>::exists(&content_id),
@@ -246,7 +248,7 @@ decl_module! {
             let who = ensure_signed(origin)?;
 
             // Even if origin is an owner of metadata, they stil need to be an active member.
-            ensure!(T::Members::is_active_member(&who),
+            ensure!(<membership::members::Module<T>>::is_active_member(&who),
                 "Only active members can update content metadata");
 
             let has_updates = update.schema.is_some() || update.json.is_some();
@@ -356,9 +358,15 @@ mod tests {
     #[test]
     fn succeed_adding_content() {
         with_default_mock_builder(|| {
+            let sender = 1 as u64;
             // Register a content with 1234 bytes of type 1, which should be recognized.
-            let res =
-                TestDataDirectory::add_content(Origin::signed(1), 1, 1234, 0, vec![1, 3, 3, 7]);
+            let res = TestDataDirectory::add_content(
+                Origin::signed(sender),
+                1,
+                1234,
+                0,
+                vec![1, 3, 3, 7],
+            );
             assert!(res.is_ok());
         });
     }

+ 1 - 2
src/storage/data_object_storage_registry.rs

@@ -1,6 +1,6 @@
 use crate::roles::actors;
 use crate::storage::data_directory::Trait as DDTrait;
-use crate::traits::{ContentHasStorage, ContentIdExists, Members, Roles};
+use crate::traits::{ContentHasStorage, ContentIdExists, Roles};
 use codec::{Codec, Decode, Encode};
 use rstd::prelude::*;
 use runtime_primitives::traits::{MaybeDebug, MaybeSerializeDebug, Member, SimpleArithmetic};
@@ -22,7 +22,6 @@ pub trait Trait: timestamp::Trait + system::Trait + DDTrait + MaybeDebug {
         + MaybeSerializeDebug
         + PartialEq;
 
-    type Members: Members<Self>;
     type Roles: Roles<Self>;
     type ContentIdExists: ContentIdExists<Self>;
 }

+ 18 - 20
src/storage/mock.rs

@@ -2,6 +2,8 @@
 
 pub use super::{data_directory, data_object_storage_registry, data_object_type_registry};
 pub use crate::currency::GovernanceCurrency;
+use crate::membership;
+use crate::membership::members;
 use crate::roles::actors;
 use crate::traits;
 use runtime_io::with_externalities;
@@ -28,6 +30,7 @@ impl_outer_event! {
         data_object_storage_registry<T>,
         actors<T>,
         balances<T>,
+        members<T>,
     }
 }
 
@@ -39,23 +42,6 @@ pub const TEST_FIRST_METADATA_ID: u64 = 4000;
 pub const TEST_MOCK_LIAISON: u64 = 0xd00du64;
 pub const TEST_MOCK_EXISTING_CID: u64 = 42;
 
-pub struct MockMembers {}
-impl<T: system::Trait> traits::Members<T> for MockMembers {
-    type Id = u64;
-
-    fn is_active_member(_who: &T::AccountId) -> bool {
-        true
-    }
-
-    fn lookup_member_id(_account_id: &T::AccountId) -> Result<Self::Id, &'static str> {
-        Err("not implemented for tests")
-    }
-
-    fn lookup_account_by_member_id(_member_id: Self::Id) -> Result<T::AccountId, &'static str> {
-        Err("not implemented for tests")
-    }
-}
-
 pub struct MockRoles {}
 impl traits::Roles<Test> for MockRoles {
     fn is_role_account(_account_id: &<Test as system::Trait>::AccountId) -> bool {
@@ -190,7 +176,6 @@ impl data_object_type_registry::Trait for Test {
 impl data_directory::Trait for Test {
     type Event = MetaEvent;
     type ContentId = u64;
-    type Members = MockMembers;
     type Roles = MockRoles;
     type IsActiveDataObjectType = AnyDataObjectTypeIsActive;
     type SchemaId = u64;
@@ -199,14 +184,19 @@ impl data_directory::Trait for Test {
 impl data_object_storage_registry::Trait for Test {
     type Event = MetaEvent;
     type DataObjectStorageRelationshipId = u64;
-    type Members = MockMembers;
     type Roles = MockRoles;
     type ContentIdExists = MockContent;
 }
 
+impl members::Trait for Test {
+    type Event = MetaEvent;
+    type MemberId = u32;
+    type SubscriptionId = u32;
+    type PaidTermId = u32;
+}
+
 impl actors::Trait for Test {
     type Event = MetaEvent;
-    type Members = MockMembers;
     type OnActorRemoved = ();
 }
 
@@ -266,6 +256,14 @@ impl ExtBuilder {
         .assimilate_storage(&mut t)
         .unwrap();
 
+        membership::members::GenesisConfig::<Test> {
+            first_member_id: 1,
+            default_paid_membership_fee: 0,
+            members: vec![(1, "alice".into(), "".into(), "".into())],
+        }
+        .assimilate_storage(&mut t)
+        .unwrap();
+
         t.into()
     }
 }

+ 0 - 34
src/traits.rs

@@ -1,41 +1,7 @@
 use crate::roles::actors;
 use crate::storage::{data_directory, data_object_storage_registry, data_object_type_registry};
-use codec::Codec;
-use runtime_primitives::traits::{MaybeSerializeDebug, Member, SimpleArithmetic};
-use srml_support::Parameter;
 use system;
 
-// Members
-pub trait Members<T: system::Trait> {
-    type Id: Parameter
-        + Member
-        + SimpleArithmetic
-        + Codec
-        + Default
-        + Copy
-        + MaybeSerializeDebug
-        + PartialEq;
-
-    fn is_active_member(account_id: &T::AccountId) -> bool;
-
-    fn lookup_member_id(account_id: &T::AccountId) -> Result<Self::Id, &'static str>;
-
-    fn lookup_account_by_member_id(member_id: Self::Id) -> Result<T::AccountId, &'static str>;
-}
-
-impl<T: system::Trait> Members<T> for () {
-    type Id = u32;
-    fn is_active_member(_account_id: &T::AccountId) -> bool {
-        false
-    }
-    fn lookup_member_id(_account_id: &T::AccountId) -> Result<Self::Id, &'static str> {
-        Err("member not found")
-    }
-    fn lookup_account_by_member_id(_member_id: Self::Id) -> Result<T::AccountId, &'static str> {
-        Err("account not found")
-    }
-}
-
 // Roles
 pub trait Roles<T: system::Trait> {
     fn is_role_account(account_id: &T::AccountId) -> bool;