Procházet zdrojové kódy

Merge pull request #962 from shamil-gadelshin/membership_refactoring

Membership module refactoring.
Mokhtar Naamani před 4 roky
rodič
revize
8f1c41a2b6
37 změnil soubory, kde provedl 870 přidání a 1356 odebrání
  1. 2 2
      Cargo.lock
  2. 1 1
      node/src/chain_spec.rs
  3. 1 1
      runtime-modules/content-working-group/Cargo.toml
  4. 42 238
      runtime-modules/content-working-group/src/lib.rs
  5. 6 30
      runtime-modules/content-working-group/src/mock.rs
  6. 21 23
      runtime-modules/content-working-group/src/tests.rs
  7. 2 4
      runtime-modules/governance/src/election.rs
  8. 2 4
      runtime-modules/governance/src/mock.rs
  9. 0 1
      runtime-modules/hiring/src/mock.rs
  10. 1 1
      runtime-modules/membership/Cargo.toml
  11. 3 4
      runtime-modules/membership/src/genesis.rs
  12. 647 3
      runtime-modules/membership/src/lib.rs
  13. 0 725
      runtime-modules/membership/src/members.rs
  14. 6 8
      runtime-modules/membership/src/mock.rs
  15. 0 64
      runtime-modules/membership/src/role_types.rs
  16. 55 135
      runtime-modules/membership/src/tests.rs
  17. 2 2
      runtime-modules/proposals/codex/src/lib.rs
  18. 1 2
      runtime-modules/proposals/codex/src/tests/mock.rs
  19. 3 3
      runtime-modules/proposals/discussion/src/lib.rs
  20. 2 3
      runtime-modules/proposals/discussion/src/tests/mock.rs
  21. 3 5
      runtime-modules/proposals/engine/src/lib.rs
  22. 2 3
      runtime-modules/proposals/engine/src/tests/mock/mod.rs
  23. 0 1
      runtime-modules/recurring-reward/src/mock/mod.rs
  24. 2 4
      runtime-modules/service-discovery/src/mock.rs
  25. 1 1
      runtime-modules/storage/src/data_directory.rs
  26. 1 1
      runtime-modules/storage/src/lib.rs
  27. 7 5
      runtime-modules/storage/src/tests/mock.rs
  28. 0 1
      runtime-modules/token-minting/src/mock.rs
  29. 5 7
      runtime-modules/working-group/src/errors.rs
  30. 16 17
      runtime-modules/working-group/src/lib.rs
  31. 3 6
      runtime-modules/working-group/src/tests/fixtures.rs
  32. 3 5
      runtime-modules/working-group/src/tests/mock.rs
  33. 1 1
      runtime/src/integration/content_working_group.rs
  34. 11 18
      runtime/src/integration/proposals/council_origin_validator.rs
  35. 10 15
      runtime/src/integration/proposals/membership_origin_validator.rs
  36. 3 5
      runtime/src/lib.rs
  37. 5 7
      runtime/src/tests/proposals_integration/mod.rs

+ 2 - 2
Cargo.lock

@@ -4694,7 +4694,7 @@ dependencies = [
 
 [[package]]
 name = "substrate-content-working-group-module"
-version = "1.0.1"
+version = "1.1.0"
 dependencies = [
  "parity-scale-codec",
  "serde",
@@ -4917,7 +4917,7 @@ dependencies = [
 
 [[package]]
 name = "substrate-membership-module"
-version = "1.0.1"
+version = "1.1.0"
 dependencies = [
  "parity-scale-codec",
  "serde",

+ 1 - 1
node/src/chain_spec.rs

@@ -255,7 +255,7 @@ pub fn testnet_genesis(
                 min_voting_stake: 1 * DOLLARS,
             },
         }),
-        members: Some(MembersConfig {
+        membership: Some(MembersConfig {
             default_paid_membership_fee: 100u128,
             members: vec![],
         }),

+ 1 - 1
runtime-modules/content-working-group/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'substrate-content-working-group-module'
-version = '1.0.1'
+version = '1.1.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 42 - 238
runtime-modules/content-working-group/src/lib.rs

@@ -19,23 +19,15 @@ pub mod genesis;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 
-use codec::{Decode, Encode}; // Codec
-                             //use rstd::collections::btree_map::BTreeMap;
-use membership::{members, role_types};
+use codec::{Decode, Encode};
 use rstd::borrow::ToOwned;
 use rstd::collections::btree_map::BTreeMap;
 use rstd::collections::btree_set::BTreeSet;
 use rstd::convert::From;
 use rstd::prelude::*;
-use sr_primitives::traits::{One, Zero}; // Member, SimpleArithmetic, MaybeSerialize
+use sr_primitives::traits::{One, Zero};
 use srml_support::traits::{Currency, ExistenceRequirement, WithdrawReasons};
-use srml_support::{
-    decl_event,
-    decl_module,
-    decl_storage,
-    dispatch, // , StorageMap, , Parameter
-    ensure,
-};
+use srml_support::{decl_event, decl_module, decl_storage, dispatch, ensure};
 use system::{self, ensure_root, ensure_signed};
 
 use common::constraints::InputValidationLengthConstraint;
@@ -48,7 +40,7 @@ pub trait Trait:
     + stake::Trait
     + hiring::Trait
     + versioned_store_permissions::Trait
-    + members::Trait
+    + membership::Trait
 {
     // + Sized
 
@@ -56,19 +48,19 @@ pub trait Trait:
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 }
 
-/// Type constraint for identifer used for actors in members module in this runtime.
-pub type ActorIdInMembersModule<T> = <T as members::Trait>::ActorId;
+/// Type constraint for identifer used for actors.
+pub type ActorId<T> = <T as membership::Trait>::ActorId;
 
 /// Type for identifier for channels.
 /// The ChannelId must be capable of behaving like an actor id for membership module,
 /// since publishers are identified by their channel id.
-pub type ChannelId<T> = ActorIdInMembersModule<T>;
+pub type ChannelId<T> = ActorId<T>;
 
 /// Type identifier for lead role, which must be same as membership actor identifeir
-pub type LeadId<T> = ActorIdInMembersModule<T>;
+pub type LeadId<T> = ActorId<T>;
 
 /// Type identifier for curator role, which must be same as membership actor identifeir
-pub type CuratorId<T> = ActorIdInMembersModule<T>;
+pub type CuratorId<T> = ActorId<T>;
 
 /// Type for the identifer for an opening for a curator.
 pub type CuratorOpeningId<T> = <T as hiring::Trait>::OpeningId;
@@ -232,9 +224,8 @@ pub static MSG_ADD_CURATOR_OPENING_ZERO_MAX_APPLICANT_COUNT: &str =
 
 // Errors for `apply_on_curator_opening`
 pub static MSG_APPLY_ON_CURATOR_OPENING_UNSIGNED_ORIGIN: &str = "Unsigned origin";
-pub static MSG_APPLY_ON_CURATOR_OPENING_MEMBER_ID_INVALID: &str = "Member id is invalid";
-pub static MSG_APPLY_ON_CURATOR_OPENING_SIGNER_NOT_CONTROLLER_ACCOUNT: &str =
-    "Signer does not match controller account";
+pub static MSG_MEMBER_ID_INVALID: &str = "Member id is invalid";
+pub static MSG_SIGNER_NOT_CONTROLLER_ACCOUNT: &str = "Signer does not match controller account";
 pub static MSG_ORIGIN_IS_NIETHER_MEMBER_CONTROLLER_OR_ROOT: &str =
     "Origin must be controller or root account of member";
 pub static MSG_MEMBER_HAS_ACTIVE_APPLICATION_ON_OPENING: &str =
@@ -276,7 +267,10 @@ impl<BlockNumber> Default for LeadRoleState<BlockNumber> {
 /// hence information about this is missing. Recurring rewards is included, somewhat arbitrarily!
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-pub struct Lead<AccountId, RewardRelationshipId, BlockNumber> {
+pub struct Lead<AccountId, RewardRelationshipId, BlockNumber, MemberId> {
+    /// Leader member id,
+    pub member_id: MemberId,
+
     /// Account used to authenticate in this role,
     pub role_account: AccountId,
 
@@ -438,9 +432,6 @@ pub struct Curator<
     /// How the curator was inducted into the working group.
     pub induction: CuratorInduction<LeadId, CuratorApplicationId, BlockNumber>,
 
-    /// Whether this curator can unilaterally alter the curation status of a channel.
-    //pub can_update_channel_curation_status: bool,
-
     /// Permissions module principal id
     pub principal_id: PrincipalId,
 }
@@ -774,27 +765,6 @@ impl<LeadId: Default, CuratorId> Default for WorkingGroupUnstaker<LeadId, Curato
     }
 }
 
-/*
-/// ...
-#[derive(Encode, Decode, Debug, Eq, PartialEq, Clone, PartialOrd, Ord)]
-pub struct OpeningHire<CuratorApplicationId, CuratorId, PrincipalId> {
-    curator_application_id: CuratorApplicationId,
-    curator_id: CuratorId,
-    principal_id: PrincipalId
-}
-*/
-
-/*
-pub enum ChannelActor<T: Trait> {
-
-    ///
-    WorkingGroupActor(WorkingGroupActor<T>),
-
-    ///
-    Owner
-}
-*/
-
 // ======================================================================== //
 // Move section below, this out in its own file later                       //
 // ======================================================================== //
@@ -936,13 +906,13 @@ impl rstd::convert::From<WrappedError<hiring::DeactivateApplicationError>> for &
     }
 }
 
-impl rstd::convert::From<WrappedError<members::ControllerAccountForMemberCheckFailed>> for &str {
-    fn from(wrapper: WrappedError<members::ControllerAccountForMemberCheckFailed>) -> Self {
+impl rstd::convert::From<WrappedError<membership::ControllerAccountForMemberCheckFailed>> for &str {
+    fn from(wrapper: WrappedError<membership::ControllerAccountForMemberCheckFailed>) -> Self {
         match wrapper.error {
-            members::ControllerAccountForMemberCheckFailed::NotMember => {
+            membership::ControllerAccountForMemberCheckFailed::NotMember => {
                 MSG_CREATE_CHANNEL_IS_NOT_MEMBER
             }
-            members::ControllerAccountForMemberCheckFailed::NotControllerAccount => {
+            membership::ControllerAccountForMemberCheckFailed::NotControllerAccount => {
                 MSG_CREATE_CHANNEL_NOT_CONTROLLER_ACCOUNT
             }
         }
@@ -974,17 +944,15 @@ impl rstd::convert::From<WrappedError<hiring::AddApplicationError>> for &str {
     }
 }
 
-impl rstd::convert::From<WrappedError<members::MemberControllerAccountDidNotSign>> for &str {
-    fn from(wrapper: WrappedError<members::MemberControllerAccountDidNotSign>) -> Self {
+impl rstd::convert::From<WrappedError<membership::MemberControllerAccountDidNotSign>> for &str {
+    fn from(wrapper: WrappedError<membership::MemberControllerAccountDidNotSign>) -> Self {
         match wrapper.error {
-            members::MemberControllerAccountDidNotSign::UnsignedOrigin => {
+            membership::MemberControllerAccountDidNotSign::UnsignedOrigin => {
                 MSG_APPLY_ON_CURATOR_OPENING_UNSIGNED_ORIGIN
             }
-            members::MemberControllerAccountDidNotSign::MemberIdInvalid => {
-                MSG_APPLY_ON_CURATOR_OPENING_MEMBER_ID_INVALID
-            }
-            members::MemberControllerAccountDidNotSign::SignerControllerAccountMismatch => {
-                MSG_APPLY_ON_CURATOR_OPENING_SIGNER_NOT_CONTROLLER_ACCOUNT
+            membership::MemberControllerAccountDidNotSign::MemberIdInvalid => MSG_MEMBER_ID_INVALID,
+            membership::MemberControllerAccountDidNotSign::SignerControllerAccountMismatch => {
+                MSG_SIGNER_NOT_CONTROLLER_ACCOUNT
             }
         }
     }
@@ -1012,7 +980,7 @@ decl_storage! {
         pub CurrentLeadId get(current_lead_id) : Option<LeadId<T>>;
 
         /// Maps identifier to corresponding lead.
-        pub LeadById get(lead_by_id): linked_map LeadId<T> => Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber>;
+        pub LeadById get(lead_by_id): linked_map LeadId<T> => Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber, T::MemberId>;
 
         /// Next identifier for new current lead.
         pub NextLeadId get(next_lead_id): LeadId<T>;
@@ -1145,13 +1113,12 @@ decl_module! {
             banner: OptionalText,
             publication_status: ChannelPublicationStatus
         ) {
-
-            // Ensure that it is signed
-            let signer_account = ensure_signed(origin)?;
-
-            // Ensure that owner member can authenticate with signer account
+            // Ensure that owner member is signed and can authenticate with signer account
             ensure_on_wrapped_error!(
-                members::Module::<T>::ensure_is_controller_account_for_member(&owner, &signer_account)
+                membership::Module::<T>::ensure_member_controller_account_signed(
+                    origin,
+                    &owner
+                )
             )?;
 
             // Ensure it is currently possible to create channels (ChannelCreationEnabled).
@@ -1160,9 +1127,6 @@ decl_module! {
                 MSG_CHANNEL_CREATION_DISABLED
             );
 
-            // Ensure prospective owner member is currently allowed to become channel owner
-            let (member_in_role, next_channel_id) = Self::ensure_can_register_channel_owner_role_on_member(&owner, None)?;
-
             // Ensure channel handle is acceptable length
             Self::ensure_channel_handle_is_valid(&handle)?;
 
@@ -1183,6 +1147,7 @@ decl_module! {
             //
 
             // Make and add new principal
+            let next_channel_id = NextChannelId::<T>::get();
             let principal_id = Self::add_new_principal(&Principal::ChannelOwner(next_channel_id));
 
             // Construct channel
@@ -1213,14 +1178,8 @@ decl_module! {
 
             // CREDENTIAL STUFF //
 
-            // Dial out to membership module and inform about new role as channe owner.
-            let registered_role = <members::Module<T>>::register_role_on_member(owner, &member_in_role).is_ok();
-
-            assert!(registered_role);
-
             // Trigger event
             Self::deposit_event(RawEvent::ChannelCreated(next_channel_id));
-
         }
 
         /// An owner transfers channel ownership to a new owner.
@@ -1233,13 +1192,6 @@ decl_module! {
             // Ensure channel owner has signed
             let channel = Self::ensure_channel_owner_signed(origin, &channel_id)?;
 
-            // Ensure prospective new owner can actually become a channel owner (with a new channel id)
-            // We do not pass the existing channel id because it is already owned and the call would
-            // return with Err, since the membership system doesn't allow the same ActorInRole to be assigned
-            // to more than one member, and we don't use the returned actor_in_role because its not
-            // for the channel being transferred.
-            Self::ensure_can_register_channel_owner_role_on_member(&new_owner, None)?;
-
             //
             // == MUTATION SAFE ==
             //
@@ -1254,26 +1206,6 @@ decl_module! {
             // Overwrite entry in ChannelById
             ChannelById::<T>::insert(channel_id, new_channel);
 
-            let role = role_types::ActorInRole::new(
-                role_types::Role::ChannelOwner,
-                channel_id
-            );
-
-            // Remove
-            let unregistered_role = <members::Module<T>>::unregister_role(
-                role
-            ).is_ok();
-
-            assert!(unregistered_role);
-
-            // Dial out to membership module and inform about new role as channel owner.
-            let registered_role = <members::Module<T>>::register_role_on_member(
-                new_owner,
-                &role
-            ).is_ok();
-
-            assert!(registered_role);
-
             // Trigger event
             Self::deposit_event(RawEvent::ChannelOwnershipTransferred(channel_id));
         }
@@ -1520,18 +1452,6 @@ decl_module! {
                                             .map(|(successful_curator_application, _, _)| successful_curator_application.application_id)
                                             .collect::<BTreeSet<_>>();
 
-            // Ensure all applications are from members that _still_ can step into the given role
-            let num_successful_applications_that_can_register_as_curator = successful_iter
-                                                                        .clone()
-                                                                        .map(|(successful_curator_application, _, _)| successful_curator_application.member_id)
-                                                                        .filter_map(|successful_member_id| Self::ensure_can_register_curator_role_on_member(&successful_member_id).ok() )
-                                                                        .count();
-
-            ensure!(
-                num_successful_applications_that_can_register_as_curator == num_provided_successful_curator_application_ids,
-                MSG_MEMBER_NO_LONGER_REGISTRABLE_AS_CURATOR
-            );
-
             // NB: Combined ensure check and mutation in hiring module
             ensure_on_wrapped_error!(
                 hiring::Module::<T>::fill_opening(
@@ -1566,10 +1486,10 @@ decl_module! {
                     let recipient = <recurringrewards::Module<T>>::add_recipient();
 
                     // member must exist, since it was checked that it can enter the role
-                    let member_profile = <members::Module<T>>::member_profile(successful_curator_application.member_id).unwrap();
+                    let membership = <membership::Module<T>>::membership(successful_curator_application.member_id);
 
                     // rewards are deposited in the member's root account
-                    let reward_destination_account = member_profile.root_account;
+                    let reward_destination_account = membership.root_account;
 
                     // values have been checked so this should not fail!
                     let relationship_id = <recurringrewards::Module<T>>::add_reward_relationship(
@@ -1624,14 +1544,6 @@ decl_module! {
                 // Store curator
                 CuratorById::<T>::insert(new_curator_id, curator);
 
-                // Register role on member
-                let registered_role = members::Module::<T>::register_role_on_member(
-                    successful_curator_application.member_id,
-                    &role_types::ActorInRole::new(role_types::Role::Curator, new_curator_id)
-                ).is_ok();
-
-                assert!(registered_role);
-
                 // Update next curator id
                 NextCuratorId::<T>::mutate(|id| *id += <CuratorId<T> as One>::one());
 
@@ -1643,20 +1555,6 @@ decl_module! {
 
         }
 
-        /*
-        /// ...
-        pub fn update_curator_reward(_origin) {
-
-        }
-        */
-
-        /*
-        /// ...
-        pub fn slash_curator(_origin) {
-
-        }
-        */
-
         pub fn withdraw_curator_application(
             origin,
             curator_application_id: CuratorApplicationId<T>
@@ -1740,17 +1638,14 @@ decl_module! {
             // and cannot specify another arbitrary account as the source account.
             // Ensure the source_account is either the controller or root account of member with given id
             ensure!(
-                members::Module::<T>::ensure_member_controller_account(&source_account, &member_id).is_ok() ||
-                members::Module::<T>::ensure_member_root_account(&source_account, &member_id).is_ok(),
+                membership::Module::<T>::ensure_member_controller_account(&source_account, &member_id).is_ok() ||
+                membership::Module::<T>::ensure_member_root_account(&source_account, &member_id).is_ok(),
                 MSG_ORIGIN_IS_NIETHER_MEMBER_CONTROLLER_OR_ROOT
             );
 
             // Ensure curator opening exists
             let (curator_opening, _opening) = Self::ensure_curator_opening_exists(&curator_opening_id)?;
 
-            // Ensure new owner can actually become a curator
-            let (_member_as_curator, _new_curator_id) = Self::ensure_can_register_curator_role_on_member(&member_id)?;
-
             // Ensure that there is sufficient balance to cover stake proposed
             Self::ensure_can_make_stake_imbalance(
                 vec![&opt_role_stake_balance, &opt_application_stake_balance],
@@ -1822,16 +1717,9 @@ decl_module! {
         ) {
             // Ensure that origin is signed by member with given id.
             ensure_on_wrapped_error!(
-                members::Module::<T>::ensure_member_controller_account_signed(origin, &member_id)
+                membership::Module::<T>::ensure_member_controller_account_signed(origin, &member_id)
             )?;
 
-            // Ensure that member is this curator
-            let actor_in_role = role_types::ActorInRole::new(role_types::Role::Curator, curator_id);
-
-            ensure!(
-                members::MembershipIdByActorInRole::<T>::get(actor_in_role) == member_id,
-                MSG_CURATOR_NOT_CONTROLLED_BY_MEMBER
-            );
 
             //
             // == MUTATION SAFE ==
@@ -2071,18 +1959,13 @@ impl<T: Trait> Module<T> {
 
         let new_lead_id = <NextLeadId<T>>::get();
 
-        let new_lead_role =
-            role_types::ActorInRole::new(role_types::Role::CuratorLead, new_lead_id);
-
         //
         // == MUTATION SAFE ==
         //
 
-        // Register in role - will fail if member cannot become lead
-        members::Module::<T>::register_role_on_member(member, &new_lead_role)?;
-
         // Construct lead
         let new_lead = Lead {
+            member_id: member,
             role_account,
             reward_relationship: None,
             inducted: <system::Module<T>>::block_number(),
@@ -2093,7 +1976,7 @@ impl<T: Trait> Module<T> {
         <LeadById<T>>::insert(new_lead_id, new_lead);
 
         // Update current lead
-        <CurrentLeadId<T>>::put(new_lead_id); // Some(new_lead_id)
+        <CurrentLeadId<T>>::put(new_lead_id);
 
         // Update next lead counter
         <NextLeadId<T>>::mutate(|id| *id += <LeadId<T> as One>::one());
@@ -2113,14 +1996,6 @@ impl<T: Trait> Module<T> {
         // == MUTATION SAFE ==
         //
 
-        // Unregister from role in membership model
-        let current_lead_role = role_types::ActorInRole {
-            role: role_types::Role::CuratorLead,
-            actor_id: lead_id,
-        };
-
-        <members::Module<T>>::unregister_role(current_lead_role)?;
-
         // Update lead stage as exited
         let current_block = <system::Module<T>>::block_number();
 
@@ -2134,7 +2009,7 @@ impl<T: Trait> Module<T> {
         <LeadById<T>>::insert(lead_id, new_lead);
 
         // Update current lead
-        <CurrentLeadId<T>>::take(); // None
+        <CurrentLeadId<T>>::take();
 
         // Trigger event
         Self::deposit_event(RawEvent::LeadUnset(lead_id));
@@ -2163,54 +2038,7 @@ impl<T: Trait> Module<T> {
         Ok(())
     }
 
-    fn ensure_can_register_role_on_member(
-        member_id: &T::MemberId,
-        role: role_types::Role,
-        actor_id: &ActorIdInMembersModule<T>,
-    ) -> Result<members::ActorInRole<ActorIdInMembersModule<T>>, &'static str> {
-        let new_actor_in_role = role_types::ActorInRole::new(role, *actor_id);
-
-        <members::Module<T>>::can_register_role_on_member(member_id, &new_actor_in_role)
-            .map(|_| new_actor_in_role)
-    }
-
-    fn ensure_can_register_curator_role_on_member(
-        member_id: &T::MemberId,
-    ) -> Result<
-        (
-            members::ActorInRole<ActorIdInMembersModule<T>>,
-            CuratorId<T>,
-        ),
-        &'static str,
-    > {
-        let next_id = <NextCuratorId<T>>::get();
-
-        Self::ensure_can_register_role_on_member(member_id, role_types::Role::Curator, &next_id)
-            .map(|curator_in_role| (curator_in_role, next_id))
-    }
-
-    fn ensure_can_register_channel_owner_role_on_member(
-        member_id: &T::MemberId,
-        opt_channel_id: Option<ChannelId<T>>,
-    ) -> Result<
-        (
-            members::ActorInRole<ActorIdInMembersModule<T>>,
-            ChannelId<T>,
-        ),
-        &'static str,
-    > {
-        let next_channel_id = opt_channel_id.unwrap_or_else(NextChannelId::<T>::get);
-
-        Self::ensure_can_register_role_on_member(
-            member_id,
-            role_types::Role::ChannelOwner,
-            &next_channel_id,
-        )
-        .map(|member_in_role| (member_in_role, next_channel_id))
-    }
-
     // TODO: convert InputConstraint ensurer routines into macroes
-
     fn ensure_channel_handle_is_valid(handle: &[u8]) -> dispatch::Result {
         ChannelHandleConstraint::get().ensure_valid(
             handle.len(),
@@ -2315,7 +2143,7 @@ impl<T: Trait> Module<T> {
     pub fn ensure_lead_is_set() -> Result<
         (
             LeadId<T>,
-            Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber>,
+            Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber, T::MemberId>,
         ),
         &'static str,
     > {
@@ -2344,7 +2172,7 @@ impl<T: Trait> Module<T> {
     ) -> Result<
         (
             LeadId<T>,
-            Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber>,
+            Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber, T::MemberId>,
         ),
         &'static str,
     > {
@@ -2359,25 +2187,7 @@ impl<T: Trait> Module<T> {
 
         Ok((lead_id, lead))
     }
-    /*
-        fn ensure_activate_opening_at_valid(activate_at: &hiring::ActivateOpeningAt<T::BlockNumber>) -> Result<T::BlockNumber, &'static str>{
 
-            let current_block = <system::Module<T>>::block_number();
-
-            let starting_block =
-                match activate_at {
-                    hiring::ActivateOpeningAt::CurrentBlock => current_block,
-                    hiring::ActivateOpeningAt::ExactBlock(block_number) => block_number.clone()
-            };
-
-            ensure!(
-                starting_block >= current_block,
-                MSG_OPENING_CANNOT_ACTIVATE_IN_THE_PAST
-            );
-
-            Ok(starting_block)
-        }
-    */
     fn ensure_curator_opening_exists(
         curator_opening_id: &CuratorOpeningId<T>,
     ) -> Result<
@@ -2542,8 +2352,6 @@ impl<T: Trait> Module<T> {
         ),
         &'static str,
     > {
-        //Result<(hiring::Application<<T as hiring::Trait>::OpeningId, T::BlockNumber, <T as stake::Trait>::StakeId>, CuratorOpening<T::OpeningId, T::BlockNumber, BalanceOf<T>, CuratorApplicationId<T>> ,hiring::Opening<BalanceOf<T>, T::BlockNumber, <T as hiring::Trait>::ApplicationId>), &'static str> {
-
         ensure!(
             CuratorApplicationById::<T>::exists(curator_application_id),
             MSG_CURATOR_APPLICATION_DOES_NOT_EXIST
@@ -2551,12 +2359,8 @@ impl<T: Trait> Module<T> {
 
         let curator_application = CuratorApplicationById::<T>::get(curator_application_id);
 
-        //let application = hiring::ApplicationById::<T>::get(curator_application.application_id);
-
         let curator_opening = CuratorOpeningById::<T>::get(curator_application.curator_opening_id);
 
-        //let opening = hiring::OpeningById::<T>::get(curator_opening.opening_id);
-
         Ok((
             curator_application,
             *curator_application_id,

+ 6 - 30
runtime-modules/content-working-group/src/mock.rs

@@ -1,6 +1,6 @@
 #![cfg(test)]
 
-pub use crate::*; // {self, Module, Trait, GenesisConfig};
+pub use crate::*;
 pub use srml_support::traits::Currency;
 pub use system;
 
@@ -16,7 +16,7 @@ use srml_support::{impl_outer_event, impl_outer_origin, parameter_types};
 
 pub use common::currency::GovernanceCurrency;
 pub use hiring;
-pub use membership::members;
+pub use membership;
 pub use minting;
 pub use recurringrewards;
 pub use stake;
@@ -36,7 +36,6 @@ parameter_types! {
     pub const CreationFee: u32 = 0;
     pub const TransactionBaseFee: u32 = 1;
     pub const TransactionByteFee: u32 = 0;
-    pub const InitialMembersBalance: u64 = 2000;
     pub const StakePoolId: [u8; 8] = *b"joystake";
 }
 
@@ -55,7 +54,7 @@ mod lib {
 impl_outer_event! {
     pub enum TestEvent for Test {
         versioned_store<T>,
-        members<T>,
+        membership<T>,
         balances<T>,
         lib<T>,
     }
@@ -124,16 +123,6 @@ impl balances::Trait for Test {
     type CreationFee = CreationFee;
 }
 
-/*
-pub trait PrincipalIdChecker<T: Trait> {
-    fn account_can_act_as_principal(account: &T::AccountId, group: T::PrincipalId) -> bool;
-}
-
-pub trait CreateClassPermissionsChecker<T: Trait> {
-    fn account_can_create_class_permissions(account: &T::AccountId) -> bool;
-}
-*/
-
 impl GovernanceCurrency for Test {
     type Currency = Balances;
 }
@@ -183,13 +172,12 @@ impl versioned_store_permissions::Trait for Test {
 }
 
 type TestMemberId = u64;
-impl members::Trait for Test {
+impl membership::Trait for Test {
     type Event = TestEvent;
     type MemberId = TestMemberId;
     type PaidTermId = u64;
     type SubscriptionId = u64;
     type ActorId = u64;
-    type InitialMembersBalance = InitialMembersBalance;
 }
 
 impl Trait for Test {
@@ -198,7 +186,7 @@ impl Trait for Test {
 
 pub struct TestExternalitiesBuilder<T: Trait> {
     system_config: Option<system::GenesisConfig>,
-    membership_config: Option<members::GenesisConfig<T>>,
+    membership_config: Option<membership::GenesisConfig<T>>,
     content_wg_config: Option<GenesisConfig<T>>,
 }
 
@@ -213,17 +201,6 @@ impl<T: Trait> Default for TestExternalitiesBuilder<T> {
 }
 
 impl<T: Trait> TestExternalitiesBuilder<T> {
-    /*
-    pub fn set_system_config(mut self, system_config: system::GenesisConfig) -> Self {
-        self.system_config = Some(system_config);
-        self
-    }
-    pub fn set_membership_config(mut self, membership_config: members::GenesisConfig<T>) -> Self {
-        self.membership_config = Some(membership_config);
-        self
-    }
-    */
-
     pub fn with_content_wg_config(mut self, conteng_wg_config: GenesisConfig<T>) -> Self {
         self.content_wg_config = Some(conteng_wg_config);
         self
@@ -239,12 +216,11 @@ impl<T: Trait> TestExternalitiesBuilder<T> {
 
         // Add membership
         self.membership_config
-            .unwrap_or(members::GenesisConfig::default())
+            .unwrap_or(membership::GenesisConfig::default())
             .assimilate_storage(&mut t)
             .unwrap();
 
         // Add content wg
-
         if self.content_wg_config.is_none() {
             genesis::GenesisConfigBuilder::<Test>::default()
                 .build()

+ 21 - 23
runtime-modules/content-working-group/src/tests.rs

@@ -2,7 +2,6 @@
 
 use super::genesis;
 use super::mock::{self, *};
-//use crate::membership;
 use hiring;
 use rstd::collections::btree_map::BTreeMap;
 use rstd::collections::btree_set::BTreeSet;
@@ -47,9 +46,9 @@ fn create_channel_is_not_a_member() {
 
             // Change to invalid member id, i.e. != channel_creator_member_id
             fixture.channel_creator_member_id = fixture.channel_creator_member_id
-                + <<Test as members::Trait>::MemberId as One>::one();
+                + <<Test as membership::Trait>::MemberId as One>::one();
 
-            fixture.call_and_assert_error(MSG_CREATE_CHANNEL_IS_NOT_MEMBER);
+            fixture.call_and_assert_error(MSG_MEMBER_ID_INVALID);
         });
 }
 
@@ -85,7 +84,7 @@ fn create_channel_with_bad_member_role_account() {
                 Some(0),
             );
 
-            fixture.call_and_assert_error(MSG_CREATE_CHANNEL_NOT_CONTROLLER_ACCOUNT);
+            fixture.call_and_assert_error(MSG_SIGNER_NOT_CONTROLLER_ACCOUNT);
         });
 }
 
@@ -862,7 +861,7 @@ fn multiple_applications_by_same_member_to_opening_fails() {
 
 struct UpdateCuratorRoleAccountFixture {
     pub origin: Origin,
-    pub member_id: <Test as members::Trait>::MemberId,
+    pub member_id: <Test as membership::Trait>::MemberId,
     pub curator_id: CuratorId<Test>,
     pub new_role_account: <Test as system::Trait>::AccountId,
 }
@@ -1152,7 +1151,7 @@ fn terminate_curator_role_success() {
 
 struct SetLeadFixture {
     pub origin: Origin,
-    pub member_id: <Test as members::Trait>::MemberId,
+    pub member_id: <Test as membership::Trait>::MemberId,
     pub new_role_account: <Test as system::Trait>::AccountId,
 }
 
@@ -1184,6 +1183,7 @@ impl SetLeadFixture {
         let new_lead = LeadById::<Test>::get(new_lead_id);
 
         let expected_new_lead = Lead {
+            member_id: self.member_id,
             role_account: self.new_role_account,
             reward_relationship: None,
             inducted: 1, // make dynamic later
@@ -1500,7 +1500,7 @@ fn add_members_and_apply_on_opening(
 
 #[derive(Clone)]
 struct NewMemberAppliedResult {
-    pub member_id: <Test as members::Trait>::MemberId,
+    pub member_id: <Test as membership::Trait>::MemberId,
     pub curator_application_id: crate::CuratorApplicationId<Test>,
 }
 
@@ -1899,7 +1899,7 @@ impl SetupLeadAndHireCuratorResult {
         }
     }
 
-    pub fn curator_member_id(&self) -> <Test as members::Trait>::MemberId {
+    pub fn curator_member_id(&self) -> <Test as membership::Trait>::MemberId {
         self.setup_and_fill_opening_result
             .setup_opening_in_review
             .added_members_application_result[0]
@@ -1924,7 +1924,7 @@ fn setup_lead_and_hire_curator() -> SetupLeadAndHireCuratorResult {
 }
 
 struct CreateChannelFixture {
-    pub channel_creator_member_id: <Test as members::Trait>::MemberId,
+    pub channel_creator_member_id: <Test as membership::Trait>::MemberId,
     pub controller_account: <Test as system::Trait>::AccountId,
     pub channel_creator_role_account: <Test as system::Trait>::AccountId,
     pub channel_handle: Vec<u8>,
@@ -1938,13 +1938,13 @@ struct CreateChannelFixture {
 
 impl CreateChannelFixture {
     pub fn make_valid_unpulished_video_channel_for(
-        channel_creator_member_id: <Test as members::Trait>::MemberId,
+        channel_creator_member_id: <Test as membership::Trait>::MemberId,
         override_controller_account: Option<<Test as system::Trait>::AccountId>,
     ) -> Self {
         let controller_account = if let Some(account) = override_controller_account {
             account
         } else {
-            members::Module::<Test>::ensure_profile(channel_creator_member_id)
+            membership::Module::<Test>::ensure_membership(channel_creator_member_id)
                 .unwrap()
                 .controller_account
         };
@@ -2062,7 +2062,7 @@ impl CreateChannelFixture {
 }
 
 struct NewMemberAsLead {
-    pub member_id: <Test as members::Trait>::MemberId,
+    pub member_id: <Test as membership::Trait>::MemberId,
     pub lead_id: LeadId<Test>,
 }
 
@@ -2079,7 +2079,7 @@ pub fn set_channel_creation_enabled(enabled: bool) {
         .unwrap()
 }
 
-pub fn add_channel_creator_member() -> <Test as members::Trait>::MemberId {
+pub fn add_channel_creator_member() -> <Test as membership::Trait>::MemberId {
     let channel_creator_member_id = add_member(
         CHANNEL_CREATOR_ROOT_AND_CONTROLLER_ACCOUNT,
         to_vec(CHANNEL_CREATOR_HANDLE),
@@ -2091,18 +2091,16 @@ pub fn add_channel_creator_member() -> <Test as members::Trait>::MemberId {
 pub fn add_member(
     root_and_controller_account: <Test as system::Trait>::AccountId,
     handle: Vec<u8>,
-) -> <Test as members::Trait>::MemberId {
-    let next_member_id = members::MembersCreated::<Test>::get();
+) -> <Test as membership::Trait>::MemberId {
+    let next_member_id = membership::NextMemberId::<Test>::get();
 
     assert_eq!(
-        members::Module::<Test>::buy_membership(
+        membership::Module::<Test>::buy_membership(
             Origin::signed(root_and_controller_account),
             0,
-            members::UserInfo {
-                handle: Some(handle),
-                avatar_uri: None,
-                about: None,
-            }
+            Some(handle),
+            None,
+            None
         )
         .unwrap(),
         ()
@@ -2112,11 +2110,11 @@ pub fn add_member(
 }
 
 pub fn set_lead(
-    member_id: <Test as members::Trait>::MemberId,
+    member_id: <Test as membership::Trait>::MemberId,
     new_role_account: <Test as system::Trait>::AccountId,
 ) -> LeadId<Test> {
     // Get controller account
-    //let lead_member_controller_account = members::Module::<Test>::ensure_profile(member_id).unwrap().controller_account;
+    //let lead_member_controller_account = membership::Module::<Test>::ensure_membership(member_id).unwrap().controller_account;
 
     let expected_lead_id = NextLeadId::<Test>::get();
 

+ 2 - 4
runtime-modules/governance/src/election.rs

@@ -48,9 +48,7 @@ use super::council;
 use crate::election_params::ElectionParameters;
 pub use common::currency::{BalanceOf, GovernanceCurrency};
 
-pub trait Trait:
-    system::Trait + council::Trait + GovernanceCurrency + membership::members::Trait
-{
+pub trait Trait: system::Trait + council::Trait + GovernanceCurrency + membership::Trait {
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 
     type CouncilElected: CouncilElected<Seats<Self::AccountId, BalanceOf<Self>>, Self::BlockNumber>;
@@ -213,7 +211,7 @@ impl<T: Trait> Module<T> {
 
     fn can_participate(sender: &T::AccountId) -> bool {
         !<T as GovernanceCurrency>::Currency::free_balance(sender).is_zero()
-            && <membership::members::Module<T>>::is_member_account(sender)
+            && <membership::Module<T>>::is_member_account(sender)
     }
 
     // PUBLIC IMMUTABLES

+ 2 - 4
runtime-modules/governance/src/mock.rs

@@ -62,13 +62,12 @@ impl election::Trait for Test {
 
     type CouncilElected = (Council,);
 }
-impl membership::members::Trait for Test {
+impl membership::Trait for Test {
     type Event = ();
     type MemberId = u32;
     type SubscriptionId = u32;
     type PaidTermId = u32;
     type ActorId = u32;
-    type InitialMembersBalance = InitialMembersBalance;
 }
 impl minting::Trait for Test {
     type Currency = Balances;
@@ -85,7 +84,6 @@ parameter_types! {
     pub const CreationFee: u32 = 0;
     pub const TransactionBaseFee: u32 = 1;
     pub const TransactionByteFee: u32 = 0;
-    pub const InitialMembersBalance: u32 = 0;
 }
 
 impl balances::Trait for Test {
@@ -118,7 +116,7 @@ pub fn initial_test_ext() -> runtime_io::TestExternalities {
         .build_storage::<Test>()
         .unwrap();
 
-    membership::members::GenesisConfig::<Test> {
+    membership::GenesisConfig::<Test> {
         default_paid_membership_fee: 0,
         members: vec![
             (1, "member1".into(), "".into(), "".into()),

+ 0 - 1
runtime-modules/hiring/src/mock.rs

@@ -58,7 +58,6 @@ parameter_types! {
     pub const CreationFee: u32 = 0;
     pub const TransactionBaseFee: u32 = 1;
     pub const TransactionByteFee: u32 = 0;
-    pub const InitialMembersBalance: u64 = 2000;
     pub const StakePoolId: [u8; 8] = *b"joystake";
 }
 

+ 1 - 1
runtime-modules/membership/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = 'substrate-membership-module'
-version = '1.0.1'
+version = '1.1.0'
 authors = ['Joystream contributors']
 edition = '2018'
 

+ 3 - 4
runtime-modules/membership/src/genesis.rs

@@ -2,9 +2,8 @@
 
 use common::currency::BalanceOf;
 use rstd::prelude::*;
-//pub use super::members::{GenesisConfig, Trait};
 
-use super::members::{self, Trait};
+use crate::{GenesisConfig, Trait};
 
 /// Builder fo membership module genesis configuration.
 pub struct GenesisConfigBuilder<T: Trait> {
@@ -34,8 +33,8 @@ impl<T: Trait> GenesisConfigBuilder<T> {
         self
     }
 
-    pub fn build(&self) -> members::GenesisConfig<T> {
-        members::GenesisConfig::<T> {
+    pub fn build(&self) -> GenesisConfig<T> {
+        GenesisConfig::<T> {
             default_paid_membership_fee: self.default_paid_membership_fee,
             members: self
                 .members

+ 647 - 3
runtime-modules/membership/src/lib.rs

@@ -1,9 +1,653 @@
 // Ensure we're `no_std` when compiling for Wasm.
 #![cfg_attr(not(feature = "std"), no_std)]
+// Clippy linter requirement.
+// Disable it because of the substrate lib design
+// Example:  pub PaidMembershipTermsById get(paid_membership_terms_by_id) build(|config: &GenesisConfig<T>| {}
+#![allow(clippy::redundant_closure_call)]
 
 pub mod genesis;
-pub mod members;
-pub mod role_types;
-
 pub(crate) mod mock;
 mod tests;
+
+use codec::{Codec, Decode, Encode};
+use rstd::borrow::ToOwned;
+use rstd::prelude::*;
+use sr_primitives::traits::{MaybeSerialize, Member, One, SimpleArithmetic};
+use srml_support::traits::Currency;
+use srml_support::{decl_event, decl_module, decl_storage, dispatch, ensure, Parameter};
+use system::{self, ensure_root, ensure_signed};
+
+use common::currency::{BalanceOf, GovernanceCurrency};
+
+pub trait Trait: system::Trait + GovernanceCurrency + timestamp::Trait {
+    type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
+
+    type MemberId: Parameter
+        + Member
+        + SimpleArithmetic
+        + Codec
+        + Default
+        + Copy
+        + MaybeSerialize
+        + PartialEq;
+
+    type PaidTermId: Parameter
+        + Member
+        + SimpleArithmetic
+        + Codec
+        + Default
+        + Copy
+        + MaybeSerialize
+        + PartialEq;
+
+    type SubscriptionId: Parameter
+        + Member
+        + SimpleArithmetic
+        + Codec
+        + Default
+        + Copy
+        + MaybeSerialize
+        + PartialEq;
+
+    /// Describes the common type for the working group members (workers).
+    type ActorId: Parameter
+        + Member
+        + SimpleArithmetic
+        + Codec
+        + Default
+        + Copy
+        + MaybeSerialize
+        + PartialEq
+        + Ord;
+}
+
+const FIRST_PAID_TERMS_ID: u32 = 1;
+
+// Default paid membership terms
+pub const DEFAULT_PAID_TERM_ID: u32 = 0;
+
+// Default user info constraints
+const DEFAULT_MIN_HANDLE_LENGTH: u32 = 5;
+const DEFAULT_MAX_HANDLE_LENGTH: u32 = 40;
+const DEFAULT_MAX_AVATAR_URI_LENGTH: u32 = 1024;
+const DEFAULT_MAX_ABOUT_TEXT_LENGTH: u32 = 2048;
+
+/// Public membership object alias.
+pub type Membership<T> = MembershipObject<
+    <T as system::Trait>::BlockNumber,
+    <T as timestamp::Trait>::Moment,
+    <T as Trait>::PaidTermId,
+    <T as Trait>::SubscriptionId,
+    <T as system::Trait>::AccountId,
+>;
+
+#[derive(Encode, Decode, Default)]
+/// Stored information about a registered user
+pub struct MembershipObject<BlockNumber, Moment, PaidTermId, SubscriptionId, AccountId> {
+    /// The unique handle chosen by member
+    pub handle: Vec<u8>,
+
+    /// A Url to member's Avatar image
+    pub avatar_uri: Vec<u8>,
+
+    /// Short text chosen by member to share information about themselves
+    pub about: Vec<u8>,
+
+    /// Block number when member was registered
+    pub registered_at_block: BlockNumber,
+
+    /// Timestamp when member was registered
+    pub registered_at_time: Moment,
+
+    /// How the member was registered
+    pub entry: EntryMethod<PaidTermId, AccountId>,
+
+    /// Whether the member is suspended or not.
+    pub suspended: bool,
+
+    /// The type of subscription the member has purchased if any.
+    pub subscription: Option<SubscriptionId>,
+
+    /// Member's root account id. Only the root account is permitted to set a new root account
+    /// and update the controller account. Other modules may only allow certain actions if
+    /// signed with root account. It is intended to be an account that can remain offline and
+    /// potentially hold a member's funds, and be a source for staking roles.
+    pub root_account: AccountId,
+
+    /// Member's controller account id. This account is intended to be used by
+    /// a member to act under their identity in other modules. It will usually be used more
+    /// online and will have less funds in its balance.
+    pub controller_account: AccountId,
+}
+
+// Contains valid or default user details
+struct ValidatedUserInfo {
+    handle: Vec<u8>,
+    avatar_uri: Vec<u8>,
+    about: Vec<u8>,
+}
+
+#[derive(Encode, Decode, Debug, PartialEq)]
+pub enum EntryMethod<PaidTermId, AccountId> {
+    Paid(PaidTermId),
+    Screening(AccountId),
+    Genesis,
+}
+
+/// Must be default constructible because it indirectly is a value in a storage map.
+/// ***SHOULD NEVER ACTUALLY GET CALLED, IS REQUIRED TO DUE BAD STORAGE MODEL IN SUBSTRATE***
+impl<PaidTermId, AccountId> Default for EntryMethod<PaidTermId, AccountId> {
+    fn default() -> Self {
+        Self::Genesis
+    }
+}
+
+#[derive(Encode, Decode, Eq, PartialEq, Default)]
+pub struct PaidMembershipTerms<Balance> {
+    /// Quantity of native tokens which must be provably burned
+    pub fee: Balance,
+    /// String of capped length describing human readable conditions which are being agreed upon
+    pub text: Vec<u8>,
+}
+
+decl_storage! {
+    trait Store for Module<T: Trait> as Membership {
+        /// MemberId to assign to next member that is added to the registry, and is also the
+        /// total number of members created. MemberIds start at Zero.
+        pub NextMemberId get(members_created) : T::MemberId;
+
+        /// Mapping of member's id to their membership profile
+        pub MembershipById get(membership) : map T::MemberId => Membership<T>;
+
+        /// Mapping of a root account id to vector of member ids it controls.
+        pub(crate) MemberIdsByRootAccountId : map T::AccountId => Vec<T::MemberId>;
+
+        /// Mapping of a controller account id to vector of member ids it controls
+        pub(crate) MemberIdsByControllerAccountId : map T::AccountId => Vec<T::MemberId>;
+
+        /// Registered unique handles and their mapping to their owner
+        pub MemberIdByHandle get(handles) : map Vec<u8> => T::MemberId;
+
+        /// Next paid membership terms id
+        pub NextPaidMembershipTermsId get(next_paid_membership_terms_id) : T::PaidTermId = T::PaidTermId::from(FIRST_PAID_TERMS_ID);
+
+        /// Paid membership terms record
+        // Remember to add _genesis_phantom_data: std::marker::PhantomData{} to membership
+        // genesis config if not providing config() or extra_genesis
+        pub PaidMembershipTermsById get(paid_membership_terms_by_id) build(|config: &GenesisConfig<T>| {
+            // This method only gets called when initializing storage, and is
+            // compiled as native code. (Will be called when building `raw` chainspec)
+            // So it can't be relied upon to initialize storage for runtimes updates.
+            // Initialization for updated runtime is done in run_migration()
+            let terms = PaidMembershipTerms {
+                fee:  config.default_paid_membership_fee,
+                text: Vec::default(),
+            };
+            vec![(T::PaidTermId::from(DEFAULT_PAID_TERM_ID), terms)]
+        }) : map T::PaidTermId => PaidMembershipTerms<BalanceOf<T>>;
+
+        /// Active Paid membership terms
+        pub ActivePaidMembershipTerms get(active_paid_membership_terms) : Vec<T::PaidTermId> = vec![T::PaidTermId::from(DEFAULT_PAID_TERM_ID)];
+
+        /// Is the platform is accepting new members or not
+        pub NewMembershipsAllowed get(new_memberships_allowed) : bool = true;
+
+        pub ScreeningAuthority get(screening_authority) : T::AccountId;
+
+        // User Input Validation parameters - do these really need to be state variables
+        // I don't see a need to adjust these in future?
+        pub MinHandleLength get(min_handle_length) : u32 = DEFAULT_MIN_HANDLE_LENGTH;
+        pub MaxHandleLength get(max_handle_length) : u32 = DEFAULT_MAX_HANDLE_LENGTH;
+        pub MaxAvatarUriLength get(max_avatar_uri_length) : u32 = DEFAULT_MAX_AVATAR_URI_LENGTH;
+        pub MaxAboutTextLength get(max_about_text_length) : u32 = DEFAULT_MAX_ABOUT_TEXT_LENGTH;
+
+    }
+    add_extra_genesis {
+        config(default_paid_membership_fee): BalanceOf<T>;
+        config(members) : Vec<(T::AccountId, String, String, String)>;
+        build(|config: &GenesisConfig<T>| {
+            for (who, handle, avatar_uri, about) in &config.members {
+                let user_info = ValidatedUserInfo {
+                    handle: handle.clone().into_bytes(),
+                    avatar_uri: avatar_uri.clone().into_bytes(),
+                    about: about.clone().into_bytes()
+                };
+
+                <Module<T>>::insert_member(&who, &user_info, EntryMethod::Genesis);
+            }
+        });
+    }
+}
+
+decl_event! {
+    pub enum Event<T> where
+      <T as system::Trait>::AccountId,
+      <T as Trait>::MemberId,
+    {
+        MemberRegistered(MemberId, AccountId),
+        MemberUpdatedAboutText(MemberId),
+        MemberUpdatedAvatar(MemberId),
+        MemberUpdatedHandle(MemberId),
+        MemberSetRootAccount(MemberId, AccountId),
+        MemberSetControllerAccount(MemberId, AccountId),
+    }
+}
+
+decl_module! {
+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
+        fn deposit_event() = default;
+
+        /// Non-members can buy membership
+        pub fn buy_membership(
+            origin,
+            paid_terms_id: T::PaidTermId,
+            handle: Option<Vec<u8>>,
+            avatar_uri: Option<Vec<u8>>,
+            about: Option<Vec<u8>>
+        ) {
+            let who = ensure_signed(origin)?;
+
+            // make sure we are accepting new memberships
+            ensure!(Self::new_memberships_allowed(), "new members not allowed");
+
+            // ensure paid_terms_id is active
+            let terms = Self::ensure_active_terms_id(paid_terms_id)?;
+
+            // ensure enough free balance to cover terms fees
+            ensure!(T::Currency::can_slash(&who, terms.fee), "not enough balance to buy membership");
+
+            let user_info = Self::check_user_registration_info(handle, avatar_uri, about)?;
+
+            // ensure handle is not already registered
+            Self::ensure_unique_handle(&user_info.handle)?;
+
+            let _ = T::Currency::slash(&who, terms.fee);
+            let member_id = Self::insert_member(&who, &user_info, EntryMethod::Paid(paid_terms_id));
+
+            Self::deposit_event(RawEvent::MemberRegistered(member_id, who));
+        }
+
+        /// Change member's about text
+        pub fn change_member_about_text(origin, member_id: T::MemberId, text: Vec<u8>) {
+            let sender = ensure_signed(origin)?;
+
+            let membership = Self::ensure_membership(member_id)?;
+
+            ensure!(membership.controller_account == sender, "only controller account can update member about text");
+
+            Self::_change_member_about_text(member_id, &text)?;
+        }
+
+        /// Change member's avatar
+        pub fn change_member_avatar(origin, member_id: T::MemberId, uri: Vec<u8>) {
+            let sender = ensure_signed(origin)?;
+
+            let membership = Self::ensure_membership(member_id)?;
+
+            ensure!(membership.controller_account == sender, "only controller account can update member avatar");
+
+            Self::_change_member_avatar(member_id, &uri)?;
+        }
+
+        /// Change member's handle. Will ensure new handle is unique and old one will be available
+        /// for other members to use.
+        pub fn change_member_handle(origin, member_id: T::MemberId, handle: Vec<u8>) {
+            let sender = ensure_signed(origin)?;
+
+            let membership = Self::ensure_membership(member_id)?;
+
+            ensure!(membership.controller_account == sender, "only controller account can update member handle");
+
+            Self::_change_member_handle(member_id, handle)?;
+        }
+
+        /// Update member's all or some of handle, avatar and about text.
+        pub fn update_membership(
+            origin,
+            member_id: T::MemberId,
+            handle: Option<Vec<u8>>,
+            avatar_uri: Option<Vec<u8>>,
+            about: Option<Vec<u8>>
+        ) {
+            let sender = ensure_signed(origin)?;
+
+            let membership = Self::ensure_membership(member_id)?;
+
+            ensure!(membership.controller_account == sender, "only controller account can update member info");
+
+            if let Some(uri) = avatar_uri {
+                Self::_change_member_avatar(member_id, &uri)?;
+            }
+            if let Some(about) = about {
+                Self::_change_member_about_text(member_id, &about)?;
+            }
+            if let Some(handle) = handle {
+                Self::_change_member_handle(member_id, handle)?;
+            }
+        }
+
+        pub fn set_controller_account(origin, member_id: T::MemberId, new_controller_account: T::AccountId) {
+            let sender = ensure_signed(origin)?;
+
+            let mut membership = Self::ensure_membership(member_id)?;
+
+            ensure!(membership.root_account == sender, "only root account can set new controller account");
+
+            // only update if new_controller_account is different than current one
+            if membership.controller_account != new_controller_account {
+                <MemberIdsByControllerAccountId<T>>::mutate(&membership.controller_account, |ids| {
+                    ids.retain(|id| *id != member_id);
+                });
+
+                <MemberIdsByControllerAccountId<T>>::mutate(&new_controller_account, |ids| {
+                    ids.push(member_id);
+                });
+
+                membership.controller_account = new_controller_account.clone();
+                <MembershipById<T>>::insert(member_id, membership);
+                Self::deposit_event(RawEvent::MemberSetControllerAccount(member_id, new_controller_account));
+            }
+        }
+
+        pub fn set_root_account(origin, member_id: T::MemberId, new_root_account: T::AccountId) {
+            let sender = ensure_signed(origin)?;
+
+            let mut membership = Self::ensure_membership(member_id)?;
+
+            ensure!(membership.root_account == sender, "only root account can set new root account");
+
+            // only update if new root account is different than current one
+            if membership.root_account != new_root_account {
+                <MemberIdsByRootAccountId<T>>::mutate(&membership.root_account, |ids| {
+                    ids.retain(|id| *id != member_id);
+                });
+
+                <MemberIdsByRootAccountId<T>>::mutate(&new_root_account, |ids| {
+                    ids.push(member_id);
+                });
+
+                membership.root_account = new_root_account.clone();
+                Self::deposit_event(RawEvent::MemberSetRootAccount(member_id, new_root_account));
+            }
+        }
+
+        pub fn add_screened_member(
+            origin,
+            new_member_account: T::AccountId,
+            handle: Option<Vec<u8>>,
+            avatar_uri: Option<Vec<u8>>,
+            about: Option<Vec<u8>>
+        ) {
+            // ensure sender is screening authority
+            let sender = ensure_signed(origin)?;
+
+            if <ScreeningAuthority<T>>::exists() {
+                ensure!(sender == Self::screening_authority(), "not screener");
+            } else {
+                // no screening authority defined. Cannot accept this request
+                return Err("no screening authority defined");
+            }
+
+            // make sure we are accepting new memberships
+            ensure!(Self::new_memberships_allowed(), "new members not allowed");
+
+            let user_info = Self::check_user_registration_info(handle, avatar_uri, about)?;
+
+            // ensure handle is not already registered
+            Self::ensure_unique_handle(&user_info.handle)?;
+
+            let member_id = Self::insert_member(&new_member_account, &user_info, EntryMethod::Screening(sender));
+
+            Self::deposit_event(RawEvent::MemberRegistered(member_id, new_member_account));
+        }
+
+        pub fn set_screening_authority(origin, authority: T::AccountId) {
+            ensure_root(origin)?;
+            <ScreeningAuthority<T>>::put(authority);
+        }
+    }
+}
+
+/// Reason why a given member id does not have a given account as the controller account.
+pub enum ControllerAccountForMemberCheckFailed {
+    NotMember,
+    NotControllerAccount,
+}
+
+pub enum MemberControllerAccountDidNotSign {
+    UnsignedOrigin,
+    MemberIdInvalid,
+    SignerControllerAccountMismatch,
+}
+
+pub enum MemberControllerAccountMismatch {
+    MemberIdInvalid,
+    SignerControllerAccountMismatch,
+}
+pub enum MemberRootAccountMismatch {
+    MemberIdInvalid,
+    SignerRootAccountMismatch,
+}
+
+impl<T: Trait> Module<T> {
+    /// Provided that the member_id exists return its membership. Returns error otherwise.
+    pub fn ensure_membership(id: T::MemberId) -> Result<Membership<T>, &'static str> {
+        if <MembershipById<T>>::exists(&id) {
+            Ok(Self::membership(&id))
+        } else {
+            Err("member profile not found")
+        }
+    }
+
+    /// Ensure that given member has given account as the controller account
+    pub fn ensure_is_controller_account_for_member(
+        member_id: &T::MemberId,
+        account: &T::AccountId,
+    ) -> Result<Membership<T>, ControllerAccountForMemberCheckFailed> {
+        if MembershipById::<T>::exists(member_id) {
+            let membership = MembershipById::<T>::get(member_id);
+
+            if membership.controller_account == *account {
+                Ok(membership)
+            } else {
+                Err(ControllerAccountForMemberCheckFailed::NotControllerAccount)
+            }
+        } else {
+            Err(ControllerAccountForMemberCheckFailed::NotMember)
+        }
+    }
+
+    /// Returns true if account is either a member's root or controller account
+    pub fn is_member_account(who: &T::AccountId) -> bool {
+        <MemberIdsByRootAccountId<T>>::exists(who)
+            || <MemberIdsByControllerAccountId<T>>::exists(who)
+    }
+
+    fn ensure_active_terms_id(
+        terms_id: T::PaidTermId,
+    ) -> Result<PaidMembershipTerms<BalanceOf<T>>, &'static str> {
+        let active_terms = Self::active_paid_membership_terms();
+        ensure!(
+            active_terms.iter().any(|&id| id == terms_id),
+            "paid terms id not active"
+        );
+
+        if <PaidMembershipTermsById<T>>::exists(terms_id) {
+            Ok(Self::paid_membership_terms_by_id(terms_id))
+        } else {
+            Err("paid membership term id does not exist")
+        }
+    }
+
+    #[allow(clippy::ptr_arg)] // cannot change to the "&[u8]" suggested by clippy
+    fn ensure_unique_handle(handle: &Vec<u8>) -> dispatch::Result {
+        ensure!(
+            !<MemberIdByHandle<T>>::exists(handle),
+            "handle already registered"
+        );
+        Ok(())
+    }
+
+    fn validate_handle(handle: &[u8]) -> dispatch::Result {
+        ensure!(
+            handle.len() >= Self::min_handle_length() as usize,
+            "handle too short"
+        );
+        ensure!(
+            handle.len() <= Self::max_handle_length() as usize,
+            "handle too long"
+        );
+        Ok(())
+    }
+
+    fn validate_text(text: &[u8]) -> Vec<u8> {
+        let mut text = text.to_owned();
+        text.truncate(Self::max_about_text_length() as usize);
+        text
+    }
+
+    fn validate_avatar(uri: &[u8]) -> dispatch::Result {
+        ensure!(
+            uri.len() <= Self::max_avatar_uri_length() as usize,
+            "avatar uri too long"
+        );
+        Ok(())
+    }
+
+    /// Basic user input validation
+    fn check_user_registration_info(
+        handle: Option<Vec<u8>>,
+        avatar_uri: Option<Vec<u8>>,
+        about: Option<Vec<u8>>,
+    ) -> Result<ValidatedUserInfo, &'static str> {
+        // Handle is required during registration
+        let handle = handle.ok_or("handle must be provided during registration")?;
+        Self::validate_handle(&handle)?;
+
+        let about = Self::validate_text(&about.unwrap_or_default());
+        let avatar_uri = avatar_uri.unwrap_or_default();
+        Self::validate_avatar(&avatar_uri)?;
+
+        Ok(ValidatedUserInfo {
+            handle,
+            avatar_uri,
+            about,
+        })
+    }
+
+    fn insert_member(
+        who: &T::AccountId,
+        user_info: &ValidatedUserInfo,
+        entry_method: EntryMethod<T::PaidTermId, T::AccountId>,
+    ) -> T::MemberId {
+        let new_member_id = Self::members_created();
+
+        let membership: Membership<T> = MembershipObject {
+            handle: user_info.handle.clone(),
+            avatar_uri: user_info.avatar_uri.clone(),
+            about: user_info.about.clone(),
+            registered_at_block: <system::Module<T>>::block_number(),
+            registered_at_time: <timestamp::Module<T>>::now(),
+            entry: entry_method,
+            suspended: false,
+            subscription: None,
+            root_account: who.clone(),
+            controller_account: who.clone(),
+        };
+
+        <MemberIdsByRootAccountId<T>>::mutate(who, |ids| {
+            ids.push(new_member_id);
+        });
+        <MemberIdsByControllerAccountId<T>>::mutate(who, |ids| {
+            ids.push(new_member_id);
+        });
+
+        <MembershipById<T>>::insert(new_member_id, membership);
+        <MemberIdByHandle<T>>::insert(user_info.handle.clone(), new_member_id);
+        <NextMemberId<T>>::put(new_member_id + One::one());
+
+        new_member_id
+    }
+
+    fn _change_member_about_text(id: T::MemberId, text: &[u8]) -> dispatch::Result {
+        let mut membership = Self::ensure_membership(id)?;
+        let text = Self::validate_text(text);
+        membership.about = text;
+        Self::deposit_event(RawEvent::MemberUpdatedAboutText(id));
+        <MembershipById<T>>::insert(id, membership);
+        Ok(())
+    }
+
+    fn _change_member_avatar(id: T::MemberId, uri: &[u8]) -> dispatch::Result {
+        let mut membership = Self::ensure_membership(id)?;
+        Self::validate_avatar(uri)?;
+        membership.avatar_uri = uri.to_owned();
+        Self::deposit_event(RawEvent::MemberUpdatedAvatar(id));
+        <MembershipById<T>>::insert(id, membership);
+        Ok(())
+    }
+
+    fn _change_member_handle(id: T::MemberId, handle: Vec<u8>) -> dispatch::Result {
+        let mut membership = Self::ensure_membership(id)?;
+        Self::validate_handle(&handle)?;
+        Self::ensure_unique_handle(&handle)?;
+        <MemberIdByHandle<T>>::remove(&membership.handle);
+        <MemberIdByHandle<T>>::insert(handle.clone(), id);
+        membership.handle = handle;
+        Self::deposit_event(RawEvent::MemberUpdatedHandle(id));
+        <MembershipById<T>>::insert(id, membership);
+        Ok(())
+    }
+
+    pub fn ensure_member_controller_account_signed(
+        origin: T::Origin,
+        member_id: &T::MemberId,
+    ) -> Result<T::AccountId, MemberControllerAccountDidNotSign> {
+        // Ensure transaction is signed.
+        let signer_account =
+            ensure_signed(origin).map_err(|_| MemberControllerAccountDidNotSign::UnsignedOrigin)?;
+
+        // Ensure member exists
+        let membership = Self::ensure_membership(*member_id)
+            .map_err(|_| MemberControllerAccountDidNotSign::MemberIdInvalid)?;
+
+        ensure!(
+            membership.controller_account == signer_account,
+            MemberControllerAccountDidNotSign::SignerControllerAccountMismatch
+        );
+
+        Ok(signer_account)
+    }
+
+    pub fn ensure_member_controller_account(
+        signer_account: &T::AccountId,
+        member_id: &T::MemberId,
+    ) -> Result<(), MemberControllerAccountMismatch> {
+        // Ensure member exists
+        let membership = Self::ensure_membership(*member_id)
+            .map_err(|_| MemberControllerAccountMismatch::MemberIdInvalid)?;
+
+        ensure!(
+            membership.controller_account == *signer_account,
+            MemberControllerAccountMismatch::SignerControllerAccountMismatch
+        );
+
+        Ok(())
+    }
+
+    pub fn ensure_member_root_account(
+        signer_account: &T::AccountId,
+        member_id: &T::MemberId,
+    ) -> Result<(), MemberRootAccountMismatch> {
+        // Ensure member exists
+        let membership = Self::ensure_membership(*member_id)
+            .map_err(|_| MemberRootAccountMismatch::MemberIdInvalid)?;
+
+        ensure!(
+            membership.root_account == *signer_account,
+            MemberRootAccountMismatch::SignerRootAccountMismatch
+        );
+
+        Ok(())
+    }
+}

+ 0 - 725
runtime-modules/membership/src/members.rs

@@ -1,725 +0,0 @@
-// Clippy linter requirement
-#![allow(clippy::redundant_closure_call)] // disable it because of the substrate lib design
-                                          // example:  pub PaidMembershipTermsById get(paid_membership_terms_by_id) build(|config: &GenesisConfig<T>| {}
-
-use codec::{Codec, Decode, Encode};
-use common::currency::{BalanceOf, GovernanceCurrency};
-
-use rstd::borrow::ToOwned;
-use rstd::prelude::*;
-use sr_primitives::traits::{MaybeSerialize, Member, One, SimpleArithmetic};
-use srml_support::traits::{Currency, Get};
-use srml_support::{decl_event, decl_module, decl_storage, dispatch, ensure, Parameter};
-
-use system::{self, ensure_root, ensure_signed};
-
-pub use super::role_types::*;
-
-pub trait Trait: system::Trait + GovernanceCurrency + timestamp::Trait {
-    type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
-
-    type MemberId: Parameter
-        + Member
-        + SimpleArithmetic
-        + Codec
-        + Default
-        + Copy
-        + MaybeSerialize
-        + PartialEq;
-
-    type PaidTermId: Parameter
-        + Member
-        + SimpleArithmetic
-        + Codec
-        + Default
-        + Copy
-        + MaybeSerialize
-        + PartialEq;
-
-    type SubscriptionId: Parameter
-        + Member
-        + SimpleArithmetic
-        + Codec
-        + Default
-        + Copy
-        + MaybeSerialize
-        + PartialEq;
-
-    type ActorId: Parameter
-        + Member
-        + SimpleArithmetic
-        + Codec
-        + Default
-        + Copy
-        + MaybeSerialize
-        + PartialEq
-        + Ord;
-
-    /// Initial balance of members created at genesis
-    type InitialMembersBalance: Get<BalanceOf<Self>>;
-}
-
-const FIRST_PAID_TERMS_ID: u32 = 1;
-
-// Default paid membership terms
-pub const DEFAULT_PAID_TERM_ID: u32 = 0;
-
-// Default user info constraints
-const DEFAULT_MIN_HANDLE_LENGTH: u32 = 5;
-const DEFAULT_MAX_HANDLE_LENGTH: u32 = 40;
-const DEFAULT_MAX_AVATAR_URI_LENGTH: u32 = 1024;
-const DEFAULT_MAX_ABOUT_TEXT_LENGTH: u32 = 2048;
-
-//#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
-#[derive(Encode, Decode)]
-/// Stored information about a registered user
-pub struct Profile<T: Trait> {
-    /// The unique handle chosen by member
-    pub handle: Vec<u8>,
-
-    /// A Url to member's Avatar image
-    pub avatar_uri: Vec<u8>,
-
-    /// Short text chosen by member to share information about themselves
-    pub about: Vec<u8>,
-
-    /// Blocknumber when member was registered
-    pub registered_at_block: T::BlockNumber,
-
-    /// Timestamp when member was registered
-    pub registered_at_time: T::Moment,
-
-    /// How the member was registered
-    pub entry: EntryMethod<T>,
-
-    /// Wether the member is suspended or not.
-    pub suspended: bool,
-
-    /// The type of subsction the member has purchased if any.
-    pub subscription: Option<T::SubscriptionId>,
-
-    /// Member's root account id. Only the root account is permitted to set a new root account
-    /// and update the controller account. Other modules may only allow certain actions if
-    /// signed with root account. It is intended to be an account that can remain offline and
-    /// potentially hold a member's funds, and be a source for staking roles.
-    pub root_account: T::AccountId,
-
-    /// Member's controller account id. This account is intended to be used by
-    /// a member to act under their identity in other modules. It will usually be used more
-    /// online and will have less funds in its balance.
-    pub controller_account: T::AccountId,
-
-    /// The set of registered roles the member has enrolled in.
-    pub roles: ActorInRoleSet<T::ActorId>,
-}
-
-#[derive(Clone, Debug, Encode, Decode, PartialEq)]
-/// A "Partial" struct used to batch user configurable profile information when registering or updating info
-pub struct UserInfo {
-    pub handle: Option<Vec<u8>>,
-    pub avatar_uri: Option<Vec<u8>>,
-    pub about: Option<Vec<u8>>,
-}
-
-struct CheckedUserInfo {
-    handle: Vec<u8>,
-    avatar_uri: Vec<u8>,
-    about: Vec<u8>,
-}
-
-//#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
-#[derive(Encode, Decode, Debug, PartialEq)]
-pub enum EntryMethod<T: Trait> {
-    Paid(T::PaidTermId),
-    Screening(T::AccountId),
-    Genesis,
-}
-
-//#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
-#[derive(Encode, Decode, Eq, PartialEq)]
-pub struct PaidMembershipTerms<T: Trait> {
-    /// Quantity of native tokens which must be provably burned
-    pub fee: BalanceOf<T>,
-    /// String of capped length describing human readable conditions which are being agreed upon
-    pub text: Vec<u8>,
-}
-
-decl_storage! {
-    trait Store for Module<T: Trait> as Membership {
-        /// MemberId to assign to next member that is added to the registry, and is also the
-        /// total number of members created. MemberIds start at Zero.
-        pub MembersCreated get(members_created) : T::MemberId;
-
-        /// Mapping of member's id to their membership profile
-        pub MemberProfile get(member_profile) : map T::MemberId => Option<Profile<T>>;
-
-        /// Mapping of a root account id to vector of member ids it controls
-        pub MemberIdsByRootAccountId get(member_ids_by_root_account_id) : map T::AccountId => Vec<T::MemberId>;
-
-        /// Mapping of a controller account id to vector of member ids it controls
-        pub MemberIdsByControllerAccountId get(member_ids_by_controller_account_id) : map T::AccountId => Vec<T::MemberId>;
-
-        /// Registered unique handles and their mapping to their owner
-        pub Handles get(handles) : map Vec<u8> => T::MemberId;
-
-        /// Next paid membership terms id
-        pub NextPaidMembershipTermsId get(next_paid_membership_terms_id) : T::PaidTermId = T::PaidTermId::from(FIRST_PAID_TERMS_ID);
-
-        /// Paid membership terms record
-        // Remember to add _genesis_phantom_data: std::marker::PhantomData{} to membership
-        // genesis config if not providing config() or extra_genesis
-        pub PaidMembershipTermsById get(paid_membership_terms_by_id) build(|config: &GenesisConfig<T>| {
-            // This method only gets called when initializing storage, and is
-            // compiled as native code. (Will be called when building `raw` chainspec)
-            // So it can't be relied upon to initialize storage for runtimes updates.
-            // Initialization for updated runtime is done in run_migration()
-            let terms = PaidMembershipTerms {
-                fee:  config.default_paid_membership_fee,
-                text: Vec::default(),
-            };
-            vec![(T::PaidTermId::from(DEFAULT_PAID_TERM_ID), terms)]
-        }) : map T::PaidTermId => Option<PaidMembershipTerms<T>>;
-
-        /// Active Paid membership terms
-        pub ActivePaidMembershipTerms get(active_paid_membership_terms) : Vec<T::PaidTermId> = vec![T::PaidTermId::from(DEFAULT_PAID_TERM_ID)];
-
-        /// Is the platform is accepting new members or not
-        pub NewMembershipsAllowed get(new_memberships_allowed) : bool = true;
-
-        pub ScreeningAuthority get(screening_authority) : Option<T::AccountId>;
-
-        // User Input Validation parameters - do these really need to be state variables
-        // I don't see a need to adjust these in future?
-        pub MinHandleLength get(min_handle_length) : u32 = DEFAULT_MIN_HANDLE_LENGTH;
-        pub MaxHandleLength get(max_handle_length) : u32 = DEFAULT_MAX_HANDLE_LENGTH;
-        pub MaxAvatarUriLength get(max_avatar_uri_length) : u32 = DEFAULT_MAX_AVATAR_URI_LENGTH;
-        pub MaxAboutTextLength get(max_about_text_length) : u32 = DEFAULT_MAX_ABOUT_TEXT_LENGTH;
-
-        pub MembershipIdByActorInRole get(membership_id_by_actor_in_role): map ActorInRole<T::ActorId> => T::MemberId;
-    }
-    add_extra_genesis {
-        config(default_paid_membership_fee): BalanceOf<T>;
-        config(members) : Vec<(T::AccountId, String, String, String)>;
-        build(|config: &GenesisConfig<T>| {
-            for (who, handle, avatar_uri, about) in &config.members {
-                let user_info = CheckedUserInfo {
-                    handle: handle.clone().into_bytes(), avatar_uri: avatar_uri.clone().into_bytes(), about: about.clone().into_bytes()
-                };
-
-                <Module<T>>::insert_member(&who, &user_info, EntryMethod::Genesis);
-
-                // Give member starting balance
-                T::Currency::deposit_creating(&who, T::InitialMembersBalance::get());
-            }
-        });
-    }
-}
-
-decl_event! {
-    pub enum Event<T> where
-      <T as system::Trait>::AccountId,
-      <T as Trait>::MemberId,
-      <T as Trait>::ActorId, {
-        MemberRegistered(MemberId, AccountId),
-        MemberUpdatedAboutText(MemberId),
-        MemberUpdatedAvatar(MemberId),
-        MemberUpdatedHandle(MemberId),
-        MemberSetRootAccount(MemberId, AccountId),
-        MemberSetControllerAccount(MemberId, AccountId),
-        MemberRegisteredRole(MemberId, ActorInRole<ActorId>),
-        MemberUnregisteredRole(MemberId, ActorInRole<ActorId>),
-    }
-}
-
-decl_module! {
-    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
-        fn deposit_event() = default;
-
-        /// Non-members can buy membership
-        pub fn buy_membership(origin, paid_terms_id: T::PaidTermId, user_info: UserInfo) {
-            let who = ensure_signed(origin)?;
-
-            // make sure we are accepting new memberships
-            ensure!(Self::new_memberships_allowed(), "new members not allowed");
-
-            // ensure paid_terms_id is active
-            let terms = Self::ensure_active_terms_id(paid_terms_id)?;
-
-            // ensure enough free balance to cover terms fees
-            ensure!(T::Currency::can_slash(&who, terms.fee), "not enough balance to buy membership");
-
-            let user_info = Self::check_user_registration_info(user_info)?;
-
-            // ensure handle is not already registered
-            Self::ensure_unique_handle(&user_info.handle)?;
-
-            let _ = T::Currency::slash(&who, terms.fee);
-            let member_id = Self::insert_member(&who, &user_info, EntryMethod::Paid(paid_terms_id));
-
-            Self::deposit_event(RawEvent::MemberRegistered(member_id, who));
-        }
-
-        /// Change member's about text
-        pub fn change_member_about_text(origin, member_id: T::MemberId, text: Vec<u8>) {
-            let sender = ensure_signed(origin)?;
-
-            let profile = Self::ensure_profile(member_id)?;
-
-            ensure!(profile.controller_account == sender, "only controller account can update member about text");
-
-            Self::_change_member_about_text(member_id, &text)?;
-        }
-
-        /// Change member's avatar
-        pub fn change_member_avatar(origin, member_id: T::MemberId, uri: Vec<u8>) {
-            let sender = ensure_signed(origin)?;
-
-            let profile = Self::ensure_profile(member_id)?;
-
-            ensure!(profile.controller_account == sender, "only controller account can update member avatar");
-
-            Self::_change_member_avatar(member_id, &uri)?;
-        }
-
-        /// Change member's handle. Will ensure new handle is unique and old one will be available
-        /// for other members to use.
-        pub fn change_member_handle(origin, member_id: T::MemberId, handle: Vec<u8>) {
-            let sender = ensure_signed(origin)?;
-
-            let profile = Self::ensure_profile(member_id)?;
-
-            ensure!(profile.controller_account == sender, "only controller account can update member handle");
-
-            Self::_change_member_handle(member_id, handle)?;
-        }
-
-        /// Update member's all or some of handle, avatar and about text.
-        pub fn update_profile(origin, member_id: T::MemberId, user_info: UserInfo) {
-            let sender = ensure_signed(origin)?;
-
-            let profile = Self::ensure_profile(member_id)?;
-
-            ensure!(profile.controller_account == sender, "only controller account can update member info");
-
-            if let Some(uri) = user_info.avatar_uri {
-                Self::_change_member_avatar(member_id, &uri)?;
-            }
-            if let Some(about) = user_info.about {
-                Self::_change_member_about_text(member_id, &about)?;
-            }
-            if let Some(handle) = user_info.handle {
-                Self::_change_member_handle(member_id, handle)?;
-            }
-        }
-
-        pub fn set_controller_account(origin, member_id: T::MemberId, new_controller_account: T::AccountId) {
-            let sender = ensure_signed(origin)?;
-
-            let mut profile = Self::ensure_profile(member_id)?;
-
-            ensure!(profile.root_account == sender, "only root account can set new controller account");
-
-            // only update if new_controller_account is different than current one
-            if profile.controller_account != new_controller_account {
-                <MemberIdsByControllerAccountId<T>>::mutate(&profile.controller_account, |ids| {
-                    ids.retain(|id| *id != member_id);
-                });
-
-                <MemberIdsByControllerAccountId<T>>::mutate(&new_controller_account, |ids| {
-                    ids.push(member_id);
-                });
-
-                profile.controller_account = new_controller_account.clone();
-                <MemberProfile<T>>::insert(member_id, profile);
-                Self::deposit_event(RawEvent::MemberSetControllerAccount(member_id, new_controller_account));
-            }
-        }
-
-        pub fn set_root_account(origin, member_id: T::MemberId, new_root_account: T::AccountId) {
-            let sender = ensure_signed(origin)?;
-
-            let mut profile = Self::ensure_profile(member_id)?;
-
-            ensure!(profile.root_account == sender, "only root account can set new root account");
-
-            // only update if new root account is different than current one
-            if profile.root_account != new_root_account {
-                <MemberIdsByRootAccountId<T>>::mutate(&profile.root_account, |ids| {
-                    ids.retain(|id| *id != member_id);
-                });
-
-                <MemberIdsByRootAccountId<T>>::mutate(&new_root_account, |ids| {
-                    ids.push(member_id);
-                });
-
-                profile.root_account = new_root_account.clone();
-                Self::deposit_event(RawEvent::MemberSetRootAccount(member_id, new_root_account));
-            }
-        }
-
-        pub fn add_screened_member(origin, new_member_account: T::AccountId, user_info: UserInfo) {
-            // ensure sender is screening authority
-            let sender = ensure_signed(origin)?;
-
-            if let Some(screening_authority) = Self::screening_authority() {
-                ensure!(sender == screening_authority, "not screener");
-            } else {
-                // no screening authority defined. Cannot accept this request
-                return Err("no screening authority defined");
-            }
-
-            // make sure we are accepting new memberships
-            ensure!(Self::new_memberships_allowed(), "new members not allowed");
-
-            let user_info = Self::check_user_registration_info(user_info)?;
-
-            // ensure handle is not already registered
-            Self::ensure_unique_handle(&user_info.handle)?;
-
-            let member_id = Self::insert_member(&new_member_account, &user_info, EntryMethod::Screening(sender));
-
-            Self::deposit_event(RawEvent::MemberRegistered(member_id, new_member_account));
-        }
-
-        pub fn set_screening_authority(origin, authority: T::AccountId) {
-            ensure_root(origin)?;
-            <ScreeningAuthority<T>>::put(authority);
-        }
-    }
-}
-
-/// Reason why a given member id does not have a given account as the controller account.
-pub enum ControllerAccountForMemberCheckFailed {
-    NotMember,
-    NotControllerAccount,
-}
-
-pub enum MemberControllerAccountDidNotSign {
-    UnsignedOrigin,
-    MemberIdInvalid,
-    SignerControllerAccountMismatch,
-}
-
-pub enum MemberControllerAccountMismatch {
-    MemberIdInvalid,
-    SignerControllerAccountMismatch,
-}
-pub enum MemberRootAccountMismatch {
-    MemberIdInvalid,
-    SignerRootAccountMismatch,
-}
-
-impl<T: Trait> Module<T> {
-    /// Provided that the memberid exists return its profile. Returns error otherwise.
-    pub fn ensure_profile(id: T::MemberId) -> Result<Profile<T>, &'static str> {
-        Self::member_profile(&id).ok_or("member profile not found")
-    }
-
-    /// Ensure that given member has given account as the controller account
-    pub fn ensure_is_controller_account_for_member(
-        member_id: &T::MemberId,
-        account: &T::AccountId,
-    ) -> Result<Profile<T>, ControllerAccountForMemberCheckFailed> {
-        if MemberProfile::<T>::exists(member_id) {
-            let profile = MemberProfile::<T>::get(member_id).unwrap();
-
-            if profile.controller_account == *account {
-                Ok(profile)
-            } else {
-                Err(ControllerAccountForMemberCheckFailed::NotControllerAccount)
-            }
-        } else {
-            Err(ControllerAccountForMemberCheckFailed::NotMember)
-        }
-    }
-
-    /// Returns true if account is either a member's root or controller account
-    pub fn is_member_account(who: &T::AccountId) -> bool {
-        <MemberIdsByRootAccountId<T>>::exists(who)
-            || <MemberIdsByControllerAccountId<T>>::exists(who)
-    }
-
-    fn ensure_active_terms_id(
-        terms_id: T::PaidTermId,
-    ) -> Result<PaidMembershipTerms<T>, &'static str> {
-        let active_terms = Self::active_paid_membership_terms();
-        ensure!(
-            active_terms.iter().any(|&id| id == terms_id),
-            "paid terms id not active"
-        );
-        let terms = Self::paid_membership_terms_by_id(terms_id)
-            .ok_or("paid membership term id does not exist")?;
-        Ok(terms)
-    }
-
-    #[allow(clippy::ptr_arg)] // cannot change to the "&[u8]" suggested by clippy
-    fn ensure_unique_handle(handle: &Vec<u8>) -> dispatch::Result {
-        ensure!(!<Handles<T>>::exists(handle), "handle already registered");
-        Ok(())
-    }
-
-    fn validate_handle(handle: &[u8]) -> dispatch::Result {
-        ensure!(
-            handle.len() >= Self::min_handle_length() as usize,
-            "handle too short"
-        );
-        ensure!(
-            handle.len() <= Self::max_handle_length() as usize,
-            "handle too long"
-        );
-        Ok(())
-    }
-
-    fn validate_text(text: &[u8]) -> Vec<u8> {
-        let mut text = text.to_owned();
-        text.truncate(Self::max_about_text_length() as usize);
-        text
-    }
-
-    fn validate_avatar(uri: &[u8]) -> dispatch::Result {
-        ensure!(
-            uri.len() <= Self::max_avatar_uri_length() as usize,
-            "avatar uri too long"
-        );
-        Ok(())
-    }
-
-    /// Basic user input validation
-    fn check_user_registration_info(user_info: UserInfo) -> Result<CheckedUserInfo, &'static str> {
-        // Handle is required during registration
-        let handle = user_info
-            .handle
-            .ok_or("handle must be provided during registration")?;
-        Self::validate_handle(&handle)?;
-
-        let about = Self::validate_text(&user_info.about.unwrap_or_default());
-        let avatar_uri = user_info.avatar_uri.unwrap_or_default();
-        Self::validate_avatar(&avatar_uri)?;
-
-        Ok(CheckedUserInfo {
-            handle,
-            avatar_uri,
-            about,
-        })
-    }
-
-    fn insert_member(
-        who: &T::AccountId,
-        user_info: &CheckedUserInfo,
-        entry_method: EntryMethod<T>,
-    ) -> T::MemberId {
-        let new_member_id = Self::members_created();
-
-        let profile: Profile<T> = Profile {
-            handle: user_info.handle.clone(),
-            avatar_uri: user_info.avatar_uri.clone(),
-            about: user_info.about.clone(),
-            registered_at_block: <system::Module<T>>::block_number(),
-            registered_at_time: <timestamp::Module<T>>::now(),
-            entry: entry_method,
-            suspended: false,
-            subscription: None,
-            root_account: who.clone(),
-            controller_account: who.clone(),
-            roles: ActorInRoleSet::new(),
-        };
-
-        <MemberIdsByRootAccountId<T>>::mutate(who, |ids| {
-            ids.push(new_member_id);
-        });
-        <MemberIdsByControllerAccountId<T>>::mutate(who, |ids| {
-            ids.push(new_member_id);
-        });
-
-        <MemberProfile<T>>::insert(new_member_id, profile);
-        <Handles<T>>::insert(user_info.handle.clone(), new_member_id);
-        <MembersCreated<T>>::put(new_member_id + One::one());
-
-        new_member_id
-    }
-
-    fn _change_member_about_text(id: T::MemberId, text: &[u8]) -> dispatch::Result {
-        let mut profile = Self::ensure_profile(id)?;
-        let text = Self::validate_text(text);
-        profile.about = text;
-        Self::deposit_event(RawEvent::MemberUpdatedAboutText(id));
-        <MemberProfile<T>>::insert(id, profile);
-        Ok(())
-    }
-
-    fn _change_member_avatar(id: T::MemberId, uri: &[u8]) -> dispatch::Result {
-        let mut profile = Self::ensure_profile(id)?;
-        Self::validate_avatar(uri)?;
-        profile.avatar_uri = uri.to_owned();
-        Self::deposit_event(RawEvent::MemberUpdatedAvatar(id));
-        <MemberProfile<T>>::insert(id, profile);
-        Ok(())
-    }
-
-    fn _change_member_handle(id: T::MemberId, handle: Vec<u8>) -> dispatch::Result {
-        let mut profile = Self::ensure_profile(id)?;
-        Self::validate_handle(&handle)?;
-        Self::ensure_unique_handle(&handle)?;
-        <Handles<T>>::remove(&profile.handle);
-        <Handles<T>>::insert(handle.clone(), id);
-        profile.handle = handle;
-        Self::deposit_event(RawEvent::MemberUpdatedHandle(id));
-        <MemberProfile<T>>::insert(id, profile);
-        Ok(())
-    }
-
-    /// Determines if the signing account is a controller account of a member that has the registered
-    /// actor_in_role.
-    pub fn key_can_sign_for_role(
-        signing_account: &T::AccountId,
-        actor_in_role: ActorInRole<T::ActorId>,
-    ) -> bool {
-        Self::member_ids_by_controller_account_id(signing_account)
-            .iter()
-            .any(|member_id| {
-                let profile = Self::member_profile(member_id).unwrap(); // must exist
-                profile.roles.has_registered_role(&actor_in_role)
-            })
-    }
-
-    /// Returns true if member identified by their member id occupies a Role at least once
-    pub fn member_is_in_role(member_id: T::MemberId, role: Role) -> bool {
-        Self::ensure_profile(member_id)
-            .ok()
-            .map_or(false, |profile| profile.roles.occupies_role(role))
-    }
-
-    pub fn ensure_member_controller_account_signed(
-        origin: T::Origin,
-        member_id: &T::MemberId,
-    ) -> Result<T::AccountId, MemberControllerAccountDidNotSign> {
-        // Ensure transaction is signed.
-        let signer_account =
-            ensure_signed(origin).map_err(|_| MemberControllerAccountDidNotSign::UnsignedOrigin)?;
-
-        // Ensure member exists
-        let profile = Self::ensure_profile(*member_id)
-            .map_err(|_| MemberControllerAccountDidNotSign::MemberIdInvalid)?;
-
-        ensure!(
-            profile.controller_account == signer_account,
-            MemberControllerAccountDidNotSign::SignerControllerAccountMismatch
-        );
-
-        Ok(signer_account)
-    }
-
-    pub fn ensure_member_controller_account(
-        signer_account: &T::AccountId,
-        member_id: &T::MemberId,
-    ) -> Result<(), MemberControllerAccountMismatch> {
-        // Ensure member exists
-        let profile = Self::ensure_profile(*member_id)
-            .map_err(|_| MemberControllerAccountMismatch::MemberIdInvalid)?;
-
-        ensure!(
-            profile.controller_account == *signer_account,
-            MemberControllerAccountMismatch::SignerControllerAccountMismatch
-        );
-
-        Ok(())
-    }
-
-    pub fn ensure_member_root_account(
-        signer_account: &T::AccountId,
-        member_id: &T::MemberId,
-    ) -> Result<(), MemberRootAccountMismatch> {
-        // Ensure member exists
-        let profile = Self::ensure_profile(*member_id)
-            .map_err(|_| MemberRootAccountMismatch::MemberIdInvalid)?;
-
-        ensure!(
-            profile.root_account == *signer_account,
-            MemberRootAccountMismatch::SignerRootAccountMismatch
-        );
-
-        Ok(())
-    }
-
-    // policy across all roles is:
-    // members can only occupy a role at most once at a time
-    // members can enter any role
-    // no limit on total number of roles a member can enter
-    // ** Note ** Role specific policies should be enforced by the client modules
-    // this method should handle higher level policies
-    pub fn can_register_role_on_member(
-        member_id: &T::MemberId,
-        actor_in_role: &ActorInRole<T::ActorId>,
-    ) -> Result<Profile<T>, &'static str> {
-        // Ensure member exists
-        let profile = Self::ensure_profile(*member_id)?;
-
-        // ensure is active member
-        ensure!(!profile.suspended, "SuspendedMemberCannotEnterRole");
-
-        // guard against duplicate ActorInRole
-        ensure!(
-            !<MembershipIdByActorInRole<T>>::exists(actor_in_role),
-            "ActorInRoleAlreadyExists"
-        );
-
-        /*
-        Disabling this temporarily for Rome, later we will drop all this
-        integration with Membership module anyway:
-        https://github.com/Joystream/substrate-runtime-joystream/issues/115
-        ensure!(
-            !profile.roles.occupies_role(actor_in_role.role),
-            "MemberAlreadyInRole"
-        );
-        */
-
-        // Other possible checks:
-        // How long the member has been registered
-        // Minimum balance
-        // EntryMethod
-
-        Ok(profile)
-    }
-
-    pub fn register_role_on_member(
-        member_id: T::MemberId,
-        actor_in_role: &ActorInRole<T::ActorId>,
-    ) -> Result<(), &'static str> {
-        // Policy check
-        let mut profile = Self::can_register_role_on_member(&member_id, actor_in_role)?;
-
-        assert!(profile.roles.register_role(actor_in_role));
-
-        <MemberProfile<T>>::insert(member_id, profile);
-        <MembershipIdByActorInRole<T>>::insert(actor_in_role, member_id);
-        Self::deposit_event(RawEvent::MemberRegisteredRole(member_id, *actor_in_role));
-        Ok(())
-    }
-
-    pub fn can_unregister_role(actor_in_role: ActorInRole<T::ActorId>) -> Result<(), &'static str> {
-        ensure!(
-            <MembershipIdByActorInRole<T>>::exists(&actor_in_role),
-            "ActorInRoleNotFound"
-        );
-
-        Ok(())
-    }
-
-    pub fn unregister_role(actor_in_role: ActorInRole<T::ActorId>) -> Result<(), &'static str> {
-        Self::can_unregister_role(actor_in_role)?;
-
-        let member_id = <MembershipIdByActorInRole<T>>::get(actor_in_role);
-
-        let mut profile = Self::ensure_profile(member_id)?; // .expect().. ?
-
-        assert!(profile.roles.unregister_role(&actor_in_role));
-
-        <MembershipIdByActorInRole<T>>::remove(actor_in_role);
-
-        <MemberProfile<T>>::insert(member_id, profile);
-
-        Self::deposit_event(RawEvent::MemberUnregisteredRole(member_id, actor_in_role));
-
-        Ok(())
-    }
-}

+ 6 - 8
runtime-modules/membership/src/mock.rs

@@ -1,6 +1,6 @@
 #![cfg(test)]
 
-pub use super::members::{self, Trait, DEFAULT_PAID_TERM_ID};
+pub use crate::{GenesisConfig, Trait, DEFAULT_PAID_TERM_ID};
 pub use common::currency::GovernanceCurrency;
 pub use srml_support::traits::Currency;
 pub use system;
@@ -60,7 +60,6 @@ parameter_types! {
     pub const CreationFee: u32 = 0;
     pub const TransactionBaseFee: u32 = 1;
     pub const TransactionByteFee: u32 = 0;
-    pub const InitialMembersBalance: u64 = 2000;
 }
 
 impl balances::Trait for Test {
@@ -84,18 +83,17 @@ impl GovernanceCurrency for Test {
     type Currency = balances::Module<Self>;
 }
 
-impl members::Trait for Test {
+impl Trait for Test {
     type Event = ();
     type MemberId = u32;
     type PaidTermId = u32;
     type SubscriptionId = u32;
     type ActorId = u32;
-    type InitialMembersBalance = InitialMembersBalance;
 }
 
 pub struct TestExternalitiesBuilder<T: Trait> {
     system_config: Option<system::GenesisConfig>,
-    membership_config: Option<members::GenesisConfig<T>>,
+    membership_config: Option<GenesisConfig<T>>,
 }
 
 impl<T: Trait> Default for TestExternalitiesBuilder<T> {
@@ -114,7 +112,7 @@ impl<T: Trait> TestExternalitiesBuilder<T> {
         self
     }
     */
-    pub fn set_membership_config(mut self, membership_config: members::GenesisConfig<T>) -> Self {
+    pub fn set_membership_config(mut self, membership_config: GenesisConfig<T>) -> Self {
         self.membership_config = Some(membership_config);
         self
     }
@@ -128,7 +126,7 @@ impl<T: Trait> TestExternalitiesBuilder<T> {
 
         // Add membership
         self.membership_config
-            .unwrap_or(members::GenesisConfig::default())
+            .unwrap_or(GenesisConfig::default())
             .assimilate_storage(&mut t)
             .unwrap();
 
@@ -137,4 +135,4 @@ impl<T: Trait> TestExternalitiesBuilder<T> {
 }
 
 pub type Balances = balances::Module<Test>;
-pub type Members = members::Module<Test>;
+pub type Members = crate::Module<Test>;

+ 0 - 64
runtime-modules/membership/src/role_types.rs

@@ -1,64 +0,0 @@
-#![allow(clippy::new_without_default)] // disable because Default for enums doesn't make sense
-
-use codec::{Decode, Encode};
-use rstd::collections::btree_set::BTreeSet;
-use rstd::prelude::*;
-
-#[cfg(feature = "std")]
-use serde::{Deserialize, Serialize};
-
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
-pub enum Role {
-    StorageProvider,
-    ChannelOwner,
-    CuratorLead,
-    Curator,
-}
-
-#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
-pub struct ActorInRole<ActorId> {
-    pub role: Role,
-    pub actor_id: ActorId,
-}
-
-impl<ActorId> ActorInRole<ActorId> {
-    pub fn new(role: Role, actor_id: ActorId) -> Self {
-        ActorInRole { role, actor_id }
-    }
-}
-
-#[derive(Encode, Decode, Eq, PartialEq, Ord, PartialOrd)]
-pub struct ActorInRoleSet<ActorId: Ord + Copy>(BTreeSet<ActorInRole<ActorId>>);
-
-impl<ActorId: Ord + Copy> ActorInRoleSet<ActorId> {
-    pub fn new() -> Self {
-        Self(BTreeSet::<ActorInRole<ActorId>>::new())
-    }
-
-    fn role_instance_count(&self, role: Role) -> usize {
-        self.0.iter().fold(0, |count, actor_in_role| {
-            if actor_in_role.role == role {
-                count + 1
-            } else {
-                count
-            }
-        })
-    }
-
-    pub fn occupies_role(&self, role: Role) -> bool {
-        self.role_instance_count(role) > 0
-    }
-
-    pub fn register_role(&mut self, actor_in_role: &ActorInRole<ActorId>) -> bool {
-        self.0.insert(*actor_in_role)
-    }
-
-    pub fn unregister_role(&mut self, actor_in_role: &ActorInRole<ActorId>) -> bool {
-        self.0.remove(actor_in_role)
-    }
-
-    pub fn has_registered_role(&self, actor_in_role: &ActorInRole<ActorId>) -> bool {
-        self.0.contains(actor_in_role)
-    }
-}

+ 55 - 135
runtime-modules/membership/src/tests.rs

@@ -5,16 +5,11 @@ use super::mock::*;
 
 use srml_support::*;
 
-fn assert_ok_unwrap<T>(value: Option<T>, err: &'static str) -> T {
-    match value {
-        None => {
-            assert!(false, err);
-            // although this code path is not reached, we need to return correct type
-            // in match arm. Using panic! would remove this need, but assert! gives us better error in
-            // console output
-            value.unwrap()
-        }
-        Some(v) => v,
+fn get_membership_by_id(member_id: u32) -> crate::Membership<Test> {
+    if <crate::MembershipById<Test>>::exists(member_id) {
+        Members::membership(member_id)
+    } else {
+        panic!("member profile not created");
     }
 }
 
@@ -24,8 +19,15 @@ fn assert_dispatch_error_message(result: Result<(), &'static str>, expected_mess
     assert_eq!(message, expected_message);
 }
 
-fn get_alice_info() -> members::UserInfo {
-    members::UserInfo {
+#[derive(Clone, Debug, PartialEq)]
+pub struct TestUserInfo {
+    pub handle: Option<Vec<u8>>,
+    pub avatar_uri: Option<Vec<u8>>,
+    pub about: Option<Vec<u8>>,
+}
+
+fn get_alice_info() -> TestUserInfo {
+    TestUserInfo {
         handle: Some(String::from("alice").as_bytes().to_vec()),
         avatar_uri: Some(
             String::from("http://avatar-url.com/alice")
@@ -36,8 +38,8 @@ fn get_alice_info() -> members::UserInfo {
     }
 }
 
-fn get_bob_info() -> members::UserInfo {
-    members::UserInfo {
+fn get_bob_info() -> TestUserInfo {
+    TestUserInfo {
         handle: Some(String::from("bobby").as_bytes().to_vec()),
         avatar_uri: Some(
             String::from("http://avatar-url.com/bob")
@@ -51,10 +53,13 @@ fn get_bob_info() -> members::UserInfo {
 const ALICE_ACCOUNT_ID: u64 = 1;
 
 fn buy_default_membership_as_alice() -> dispatch::Result {
+    let info = get_alice_info();
     Members::buy_membership(
         Origin::signed(ALICE_ACCOUNT_ID),
         DEFAULT_PAID_TERM_ID,
-        get_alice_info(),
+        info.handle,
+        info.avatar_uri,
+        info.about,
     )
 }
 
@@ -76,18 +81,14 @@ fn initial_state() {
         )
         .build()
         .execute_with(|| {
-            let default_terms = assert_ok_unwrap(
-                Members::paid_membership_terms_by_id(DEFAULT_PAID_TERM_ID),
-                "default terms not initialized",
-            );
+            let default_terms =
+                if <crate::PaidMembershipTermsById<Test>>::exists(DEFAULT_PAID_TERM_ID) {
+                    Members::paid_membership_terms_by_id(DEFAULT_PAID_TERM_ID)
+                } else {
+                    panic!("default terms not initialized");
+                };
 
             assert_eq!(default_terms.fee, DEFAULT_FEE);
-
-            // initial balance
-            assert_eq!(
-                Balances::free_balance(initial_members[0]),
-                <Test as members::Trait>::InitialMembersBalance::get()
-            );
         });
 }
 
@@ -111,13 +112,10 @@ fn buy_membership() {
 
             assert_ok!(buy_default_membership_as_alice());
 
-            let member_ids = Members::member_ids_by_root_account_id(&ALICE_ACCOUNT_ID);
+            let member_ids = vec![0];
             assert_eq!(member_ids, vec![next_member_id]);
 
-            let profile = assert_ok_unwrap(
-                Members::member_profile(&next_member_id),
-                "member profile not created",
-            );
+            let profile = get_membership_by_id(next_member_id);
 
             assert_eq!(Some(profile.handle), get_alice_info().handle);
             assert_eq!(Some(profile.avatar_uri), get_alice_info().avatar_uri);
@@ -128,7 +126,7 @@ fn buy_membership() {
             // controller account initially set to primary account
             assert_eq!(profile.controller_account, ALICE_ACCOUNT_ID);
             assert_eq!(
-                Members::member_ids_by_controller_account_id(ALICE_ACCOUNT_ID),
+                <crate::MemberIdsByControllerAccountId<Test>>::get(ALICE_ACCOUNT_ID),
                 vec![next_member_id]
             );
         });
@@ -171,7 +169,7 @@ fn new_memberships_allowed_flag() {
             let initial_balance = DEFAULT_FEE + 1;
             set_alice_free_balance(initial_balance);
 
-            members::NewMembershipsAllowed::put(false);
+            crate::NewMembershipsAllowed::put(false);
 
             assert_dispatch_error_message(
                 buy_default_membership_as_alice(),
@@ -197,7 +195,7 @@ fn unique_handles() {
             set_alice_free_balance(initial_balance);
 
             // alice's handle already taken
-            <members::Handles<Test>>::insert(get_alice_info().handle.unwrap(), 1);
+            <crate::MemberIdByHandle<Test>>::insert(get_alice_info().handle.unwrap(), 1);
 
             // should not be allowed to buy membership with that handle
             assert_dispatch_error_message(
@@ -226,17 +224,16 @@ fn update_profile() {
             let next_member_id = Members::members_created();
 
             assert_ok!(buy_default_membership_as_alice());
-
-            assert_ok!(Members::update_profile(
+            let info = get_bob_info();
+            assert_ok!(Members::update_membership(
                 Origin::signed(ALICE_ACCOUNT_ID),
                 next_member_id,
-                get_bob_info()
+                info.handle,
+                info.avatar_uri,
+                info.about,
             ));
 
-            let profile = assert_ok_unwrap(
-                Members::member_profile(&next_member_id),
-                "member profile not created",
-            );
+            let profile = get_membership_by_id(next_member_id);
 
             assert_eq!(Some(profile.handle), get_bob_info().handle);
             assert_eq!(Some(profile.avatar_uri), get_bob_info().avatar_uri);
@@ -251,26 +248,26 @@ fn add_screened_member() {
         .build()
         .execute_with(|| {
             let screening_authority = 5;
-            <members::ScreeningAuthority<Test>>::put(&screening_authority);
+            <crate::ScreeningAuthority<Test>>::put(&screening_authority);
 
             let next_member_id = Members::members_created();
 
+            let info = get_alice_info();
             assert_ok!(Members::add_screened_member(
                 Origin::signed(screening_authority),
                 ALICE_ACCOUNT_ID,
-                get_alice_info()
+                info.handle,
+                info.avatar_uri,
+                info.about
             ));
 
-            let profile = assert_ok_unwrap(
-                Members::member_profile(&next_member_id),
-                "member profile not created",
-            );
+            let profile = get_membership_by_id(next_member_id);
 
             assert_eq!(Some(profile.handle), get_alice_info().handle);
             assert_eq!(Some(profile.avatar_uri), get_alice_info().avatar_uri);
             assert_eq!(Some(profile.about), get_alice_info().about);
             assert_eq!(
-                members::EntryMethod::Screening(screening_authority),
+                crate::EntryMethod::Screening(screening_authority),
                 profile.entry
             );
         });
@@ -289,7 +286,7 @@ fn set_controller_key() {
         )
         .build()
         .execute_with(|| {
-            let member_id = Members::member_ids_by_root_account_id(&ALICE_ACCOUNT_ID)[0];
+            let member_id = 0;
 
             assert_ok!(Members::set_controller_account(
                 Origin::signed(ALICE_ACCOUNT_ID),
@@ -297,17 +294,16 @@ fn set_controller_key() {
                 ALICE_CONTROLLER_ID
             ));
 
-            let profile = assert_ok_unwrap(
-                Members::member_profile(&member_id),
-                "member profile not created",
-            );
+            let profile = get_membership_by_id(member_id);
 
             assert_eq!(profile.controller_account, ALICE_CONTROLLER_ID);
             assert_eq!(
-                Members::member_ids_by_controller_account_id(&ALICE_CONTROLLER_ID),
+                <crate::MemberIdsByControllerAccountId<Test>>::get(&ALICE_CONTROLLER_ID),
                 vec![member_id]
             );
-            assert!(Members::member_ids_by_controller_account_id(&ALICE_ACCOUNT_ID).is_empty());
+            assert!(
+                <crate::MemberIdsByControllerAccountId<Test>>::get(&ALICE_ACCOUNT_ID).is_empty()
+            );
         });
 }
 
@@ -324,94 +320,18 @@ fn set_root_account() {
         )
         .build()
         .execute_with(|| {
-            let member_id_1 = Members::member_ids_by_root_account_id(&ALICE_ACCOUNT_ID)[0];
+            let member_id = 0;
 
             assert_ok!(Members::set_root_account(
                 Origin::signed(ALICE_ACCOUNT_ID),
-                member_id_1,
+                member_id,
                 ALICE_NEW_ROOT_ACCOUNT
             ));
 
-            let member_id_2 = Members::member_ids_by_root_account_id(&ALICE_NEW_ROOT_ACCOUNT)[0];
-
-            assert_eq!(member_id_1, member_id_2);
+            let membership = Members::membership(member_id);
 
-            assert!(Members::member_ids_by_root_account_id(&ALICE_ACCOUNT_ID).is_empty());
-        });
-}
+            assert_eq!(ALICE_ACCOUNT_ID, membership.root_account);
 
-#[test]
-fn registering_and_unregistering_roles_on_member() {
-    let initial_members = [1, 2];
-
-    TestExternalitiesBuilder::<Test>::default()
-        .set_membership_config(
-            genesis::GenesisConfigBuilder::default()
-                .members(initial_members.to_vec())
-                .build(),
-        )
-        .build()
-        .execute_with(|| {
-            const DUMMY_ACTOR_ID: u32 = 100;
-            let member_id_1 = Members::member_ids_by_root_account_id(&1)[0];
-            let member_id_2 = Members::member_ids_by_root_account_id(&2)[0];
-
-            // no initial roles for member
-            assert!(!Members::member_is_in_role(
-                member_id_1,
-                members::Role::ChannelOwner
-            ));
-
-            // REGISTERING
-
-            // successful registration
-            assert_ok!(Members::register_role_on_member(
-                member_id_1,
-                &members::ActorInRole::new(members::Role::ChannelOwner, DUMMY_ACTOR_ID)
-            ));
-            assert!(Members::member_is_in_role(
-                member_id_1,
-                members::Role::ChannelOwner
-            ));
-
-            /*
-            Disabling this temporarily for Rome, later we will drop all this
-            integration with Membership module anyway:
-            https://github.com/Joystream/substrate-runtime-joystream/issues/115
-            assert_dispatch_error_message(
-                Members::register_role_on_member(
-                    member_id_1,
-                    &members::ActorInRole::new(members::Role::ChannelOwner, DUMMY_ACTOR_ID + 1),
-                ),
-                "MemberAlreadyInRole",
-            );
-            */
-
-            // registering another member in same role and actorid combination should fail
-            assert_dispatch_error_message(
-                Members::register_role_on_member(
-                    member_id_2,
-                    &members::ActorInRole::new(members::Role::ChannelOwner, DUMMY_ACTOR_ID),
-                ),
-                "ActorInRoleAlreadyExists",
-            );
-
-            // UNREGISTERING
-
-            // trying to unregister non existant actor role should fail
-            assert_dispatch_error_message(
-                Members::unregister_role(members::ActorInRole::new(members::Role::Curator, 222)),
-                "ActorInRoleNotFound",
-            );
-
-            // successfully unregister role
-            assert_ok!(Members::unregister_role(members::ActorInRole::new(
-                members::Role::ChannelOwner,
-                DUMMY_ACTOR_ID
-            )));
-            assert!(!Members::member_is_in_role(
-                member_id_1,
-                members::Role::ChannelOwner
-            ));
+            assert!(<crate::MemberIdsByRootAccountId<Test>>::get(&ALICE_ACCOUNT_ID).is_empty());
         });
 }

+ 2 - 2
runtime-modules/proposals/codex/src/lib.rs

@@ -143,7 +143,7 @@ pub trait Trait:
     system::Trait
     + proposal_engine::Trait
     + proposal_discussion::Trait
-    + membership::members::Trait
+    + membership::Trait
     + governance::election::Trait
     + content_working_group::Trait
     + staking::Trait
@@ -186,7 +186,7 @@ pub type BalanceOfMint<T> =
 pub type NegativeImbalance<T> =
     <<T as stake::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::NegativeImbalance;
 
-type MemberId<T> = <T as membership::members::Trait>::MemberId;
+type MemberId<T> = <T as membership::Trait>::MemberId;
 
 decl_error! {
     /// Codex module predefined errors

+ 1 - 2
runtime-modules/proposals/codex/src/tests/mock.rs

@@ -44,13 +44,12 @@ impl common::currency::GovernanceCurrency for Test {
     type Currency = balances::Module<Self>;
 }
 
-impl membership::members::Trait for Test {
+impl membership::Trait for Test {
     type Event = ();
     type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
     type ActorId = u64;
-    type InitialMembersBalance = ();
 }
 
 parameter_types! {

+ 3 - 3
runtime-modules/proposals/discussion/src/lib.rs

@@ -23,7 +23,7 @@
 //! use system::ensure_root;
 //! use substrate_proposals_discussion_module::{self as discussions};
 //!
-//! pub trait Trait: discussions::Trait + membership::members::Trait {}
+//! pub trait Trait: discussions::Trait + membership::Trait {}
 //!
 //! decl_module! {
 //!     pub struct Module<T: Trait> for enum Call where origin: T::Origin {
@@ -59,7 +59,7 @@ use types::{DiscussionPost, DiscussionThread, ThreadCounter};
 use common::origin::ActorOriginValidator;
 use srml_support::dispatch::DispatchResult;
 
-type MemberId<T> = <T as membership::members::Trait>::MemberId;
+type MemberId<T> = <T as membership::Trait>::MemberId;
 
 decl_event!(
     /// Proposals engine events
@@ -81,7 +81,7 @@ decl_event!(
 );
 
 /// 'Proposal discussion' substrate module Trait
-pub trait Trait: system::Trait + membership::members::Trait {
+pub trait Trait: system::Trait + membership::Trait {
     /// Discussion event type.
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 

+ 2 - 3
runtime-modules/proposals/discussion/src/tests/mock.rs

@@ -41,7 +41,7 @@ mod discussion {
 }
 
 mod membership_mod {
-    pub use membership::members::Event;
+    pub use membership::Event;
 }
 
 impl_outer_event! {
@@ -75,13 +75,12 @@ impl common::currency::GovernanceCurrency for Test {
     type Currency = balances::Module<Self>;
 }
 
-impl membership::members::Trait for Test {
+impl membership::Trait for Test {
     type Event = TestEvent;
     type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
     type ActorId = u64;
-    type InitialMembersBalance = ();
 }
 
 impl crate::Trait for Test {

+ 3 - 5
runtime-modules/proposals/engine/src/lib.rs

@@ -62,7 +62,7 @@
 //! use codec::Encode;
 //! use substrate_proposals_engine_module::{self as engine, ProposalParameters};
 //!
-//! pub trait Trait: engine::Trait + membership::members::Trait {}
+//! pub trait Trait: engine::Trait + membership::Trait {}
 //!
 //! decl_module! {
 //!     pub struct Module<T: Trait> for enum Call where origin: T::Origin {
@@ -138,12 +138,10 @@ use crate::types::ApprovedProposalData;
 use common::origin::ActorOriginValidator;
 use srml_support::dispatch::Dispatchable;
 
-type MemberId<T> = <T as membership::members::Trait>::MemberId;
+type MemberId<T> = <T as membership::Trait>::MemberId;
 
 /// Proposals engine trait.
-pub trait Trait:
-    system::Trait + timestamp::Trait + stake::Trait + membership::members::Trait
-{
+pub trait Trait: system::Trait + timestamp::Trait + stake::Trait + membership::Trait {
     /// Engine event type.
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 

+ 2 - 3
runtime-modules/proposals/engine/src/tests/mock/mod.rs

@@ -38,7 +38,7 @@ mod engine {
 }
 
 mod membership_mod {
-    pub use membership::members::Event;
+    pub use membership::Event;
 }
 
 impl_outer_event! {
@@ -94,13 +94,12 @@ parameter_types! {
     pub const MaxActiveProposalLimit: u32 = 100;
 }
 
-impl membership::members::Trait for Test {
+impl membership::Trait for Test {
     type Event = TestEvent;
     type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
     type ActorId = u64;
-    type InitialMembersBalance = ();
 }
 
 impl crate::Trait for Test {

+ 0 - 1
runtime-modules/recurring-reward/src/mock/mod.rs

@@ -56,7 +56,6 @@ parameter_types! {
     pub const CreationFee: u32 = 0;
     pub const TransactionBaseFee: u32 = 1;
     pub const TransactionByteFee: u32 = 0;
-    pub const InitialMembersBalance: u64 = 2000;
 }
 
 impl balances::Trait for Test {

+ 2 - 4
runtime-modules/service-discovery/src/mock.rs

@@ -21,7 +21,7 @@ mod working_group_mod {
 }
 
 mod membership_mod {
-    pub use membership::members::Event;
+    pub use membership::Event;
 }
 
 mod discovery {
@@ -50,7 +50,6 @@ parameter_types! {
     pub const MaximumBlockLength: u32 = 2 * 1024;
     pub const AvailableBlockRatio: Perbill = Perbill::one();
     pub const MinimumPeriod: u64 = 5;
-    pub const InitialMembersBalance: u64 = 2000;
     pub const StakePoolId: [u8; 8] = *b"joystake";
     pub const ExistentialDeposit: u32 = 0;
     pub const TransferFee: u32 = 0;
@@ -99,13 +98,12 @@ impl stake::Trait for Test {
     type SlashId = u64;
 }
 
-impl membership::members::Trait for Test {
+impl membership::Trait for Test {
     type Event = MetaEvent;
     type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
     type ActorId = u64;
-    type InitialMembersBalance = InitialMembersBalance;
 }
 
 impl common::currency::GovernanceCurrency for Test {

+ 1 - 1
runtime-modules/storage/src/data_directory.rs

@@ -41,7 +41,7 @@ pub trait Trait:
     timestamp::Trait
     + system::Trait
     + data_object_type_registry::Trait
-    + membership::members::Trait
+    + membership::Trait
     + working_group::Trait<StorageWorkingGroupInstance>
 {
     /// _Data directory_ event type.

+ 1 - 1
runtime-modules/storage/src/lib.rs

@@ -14,7 +14,7 @@ pub type StorageWorkingGroupInstance = working_group::Instance2;
 pub(crate) type StorageWorkingGroup<T> = working_group::Module<T, StorageWorkingGroupInstance>;
 
 // Alias for the member id.
-pub(crate) type MemberId<T> = <T as membership::members::Trait>::MemberId;
+pub(crate) type MemberId<T> = <T as membership::Trait>::MemberId;
 
 /// Storage provider is a worker from the working group module.
 pub type StorageProviderId<T> = working_group::WorkerId<T>;

+ 7 - 5
runtime-modules/storage/src/tests/mock.rs

@@ -2,7 +2,7 @@
 
 pub use crate::{data_directory, data_object_storage_registry, data_object_type_registry};
 pub use common::currency::GovernanceCurrency;
-use membership::members;
+use membership;
 pub use system;
 
 pub use primitives::{Blake2Hasher, H256};
@@ -23,6 +23,10 @@ mod working_group_mod {
     pub use working_group::Event;
 }
 
+mod members {
+    pub use membership::Event;
+}
+
 impl_outer_origin! {
     pub enum Origin for Test {}
 }
@@ -122,7 +126,6 @@ parameter_types! {
     pub const CreationFee: u32 = 0;
     pub const TransactionBaseFee: u32 = 1;
     pub const TransactionByteFee: u32 = 0;
-    pub const InitialMembersBalance: u32 = 2000;
     pub const StakePoolId: [u8; 8] = *b"joystake";
 }
 
@@ -190,13 +193,12 @@ impl data_object_storage_registry::Trait for Test {
     type ContentIdExists = MockContent;
 }
 
-impl members::Trait for Test {
+impl membership::Trait for Test {
     type Event = MetaEvent;
     type MemberId = u64;
     type SubscriptionId = u32;
     type PaidTermId = u32;
     type ActorId = u32;
-    type InitialMembersBalance = InitialMembersBalance;
 }
 
 impl stake::Trait for Test {
@@ -277,7 +279,7 @@ impl ExtBuilder {
         .assimilate_storage(&mut t)
         .unwrap();
 
-        membership::members::GenesisConfig::<Test> {
+        membership::GenesisConfig::<Test> {
             default_paid_membership_fee: 0,
             members: vec![(1, "alice".into(), "".into(), "".into())],
         }

+ 0 - 1
runtime-modules/token-minting/src/mock.rs

@@ -52,7 +52,6 @@ parameter_types! {
     pub const CreationFee: u32 = 0;
     pub const TransactionBaseFee: u32 = 1;
     pub const TransactionByteFee: u32 = 0;
-    pub const InitialMembersBalance: u64 = 2000;
 }
 
 impl balances::Trait for Test {

+ 5 - 7
runtime-modules/working-group/src/errors.rs

@@ -1,7 +1,5 @@
 use srml_support::decl_error;
 
-use membership::members;
-
 decl_error! {
     /// Discussion module predefined errors
     pub enum Error {
@@ -493,16 +491,16 @@ impl rstd::convert::From<WrappedError<hiring::AddApplicationError>> for Error {
     }
 }
 
-impl rstd::convert::From<WrappedError<members::MemberControllerAccountDidNotSign>> for Error {
-    fn from(wrapper: WrappedError<members::MemberControllerAccountDidNotSign>) -> Self {
+impl rstd::convert::From<WrappedError<membership::MemberControllerAccountDidNotSign>> for Error {
+    fn from(wrapper: WrappedError<membership::MemberControllerAccountDidNotSign>) -> Self {
         match wrapper.error {
-            members::MemberControllerAccountDidNotSign::UnsignedOrigin => {
+            membership::MemberControllerAccountDidNotSign::UnsignedOrigin => {
                 Error::MembershipUnsignedOrigin
             }
-            members::MemberControllerAccountDidNotSign::MemberIdInvalid => {
+            membership::MemberControllerAccountDidNotSign::MemberIdInvalid => {
                 Error::MembershipInvalidMemberId
             }
-            members::MemberControllerAccountDidNotSign::SignerControllerAccountMismatch => {
+            membership::MemberControllerAccountDidNotSign::SignerControllerAccountMismatch => {
                 Error::ApplyOnWorkerOpeningSignerNotControllerAccount
             }
         }

+ 16 - 17
runtime-modules/working-group/src/lib.rs

@@ -59,6 +59,7 @@ use rstd::vec::Vec;
 use sr_primitives::traits::{Bounded, One, Zero};
 use srml_support::traits::{Currency, ExistenceRequirement, Get, Imbalance, WithdrawReasons};
 use srml_support::{decl_event, decl_module, decl_storage, ensure, print, StorageValue};
+
 use system::{ensure_root, ensure_signed};
 
 use crate::types::ExitInitiationOrigin;
@@ -75,7 +76,7 @@ pub use types::{
 pub type StakeId<T> = <T as stake::Trait>::StakeId;
 
 /// Member identifier in membership::member module
-pub type MemberId<T> = <T as membership::members::Trait>::MemberId;
+pub type MemberId<T> = <T as membership::Trait>::MemberId;
 
 /// Workaround for BTreeSet type
 pub type ApplicationIdSet<T> = BTreeSet<ApplicationId<T>>;
@@ -105,7 +106,7 @@ pub type NegativeImbalance<T> =
 pub type ApplicationIdToWorkerIdMap<T> = BTreeMap<ApplicationId<T>, WorkerId<T>>;
 
 /// Type identifier for worker role, which must be same as membership actor identifier
-pub type WorkerId<T> = <T as membership::members::Trait>::ActorId;
+pub type WorkerId<T> = <T as membership::Trait>::ActorId;
 
 /// Alias for the application id from the hiring module.
 pub type HiringApplicationId<T> = <T as hiring::Trait>::ApplicationId;
@@ -149,7 +150,7 @@ type ApplicationOf<T> =
 /// The _Working group_ main _Trait_
 pub trait Trait<I: Instance>:
     system::Trait
-    + membership::members::Trait
+    + membership::Trait
     + hiring::Trait
     + minting::Trait
     + stake::Trait
@@ -167,7 +168,6 @@ decl_event!(
     pub enum Event<T, I>
     where
         WorkerId = WorkerId<T>,
-        <T as membership::members::Trait>::ActorId,
         <T as system::Trait>::AccountId,
         OpeningId = OpeningId<T>,
         ApplicationId = ApplicationId<T>,
@@ -205,20 +205,20 @@ decl_event!(
 
         /// Emits on updating the role account of the worker.
         /// Params:
-        /// - Member id of the worker.
+        /// - Id of the worker.
         /// - Role account id of the worker.
-        WorkerRoleAccountUpdated(ActorId, AccountId),
+        WorkerRoleAccountUpdated(WorkerId, AccountId),
 
         /// Emits on updating the reward account of the worker.
         /// Params:
         /// - Member id of the worker.
         /// - Reward account id of the worker.
-        WorkerRewardAccountUpdated(ActorId, AccountId),
+        WorkerRewardAccountUpdated(WorkerId, AccountId),
 
         /// Emits on updating the reward amount of the worker.
         /// Params:
-        /// - Member id of the worker.
-        WorkerRewardAmountUpdated(ActorId),
+        /// - Id of the worker.
+        WorkerRewardAmountUpdated(WorkerId),
 
         /// Emits on adding new worker opening.
         /// Params:
@@ -364,7 +364,7 @@ decl_module! {
 
             // Ensure that origin is signed by member with given id.
             ensure_on_wrapped_error!(
-                membership::members::Module::<T>::ensure_member_controller_account_signed(origin, &worker.member_id)
+                membership::Module::<T>::ensure_member_controller_account_signed(origin, &worker.member_id)
             )?;
 
             //
@@ -602,8 +602,8 @@ decl_module! {
             // and cannot specify another arbitrary account as the source account.
             // Ensure the source_account is either the controller or root account of member with given id
             ensure!(
-                membership::members::Module::<T>::ensure_member_controller_account(&source_account, &member_id).is_ok() ||
-                membership::members::Module::<T>::ensure_member_root_account(&source_account, &member_id).is_ok(),
+                membership::Module::<T>::ensure_member_controller_account(&source_account, &member_id).is_ok() ||
+                membership::Module::<T>::ensure_member_root_account(&source_account, &member_id).is_ok(),
                 Error::OriginIsNeitherMemberControllerOrRoot
             );
 
@@ -1337,7 +1337,8 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 
         let member_id = Module::<T, I>::member_id_by_hiring_application_id(hiring_application_id);
 
-        if let Some(member_profile) = membership::members::MemberProfile::<T>::get(member_id) {
+        if membership::MembershipById::<T>::exists(member_id) {
+            let member_profile = membership::MembershipById::<T>::get(member_id);
             let refunding_result = CurrencyOf::<T>::resolve_into_existing(
                 &member_profile.controller_account,
                 imbalance,
@@ -1517,10 +1518,8 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
                     let recipient = <recurringrewards::Module<T>>::add_recipient();
 
                     // Member must exist, since it was checked that it can enter the role.
-                    let member_profile = <membership::members::Module<T>>::member_profile(
-                        successful_application.member_id,
-                    )
-                    .unwrap();
+                    let member_profile =
+                        <membership::Module<T>>::membership(successful_application.member_id);
 
                     // Rewards are deposited in the member's root account.
                     let reward_destination_account = member_profile.root_account;

+ 3 - 6
runtime-modules/working-group/src/tests/fixtures.rs

@@ -464,11 +464,9 @@ pub fn setup_members(count: u8) {
         Membership::add_screened_member(
             RawOrigin::Signed(authority_account_id).into(),
             account_id,
-            membership::members::UserInfo {
-                handle: Some(handle.to_vec()),
-                avatar_uri: None,
-                about: None,
-            },
+            Some(handle.to_vec()),
+            None,
+            None,
         )
         .unwrap();
     }
@@ -775,7 +773,6 @@ impl EventFixture {
             u64,
             u64,
             u64,
-            u64,
             std::collections::BTreeMap<u64, u64>,
             Vec<u8>,
             u64,

+ 3 - 5
runtime-modules/working-group/src/tests/mock.rs

@@ -21,7 +21,7 @@ mod working_group {
 }
 
 mod membership_mod {
-    pub use membership::members::Event;
+    pub use membership::Event;
 }
 
 impl_outer_event! {
@@ -38,7 +38,6 @@ parameter_types! {
     pub const MaximumBlockLength: u32 = 2 * 1024;
     pub const AvailableBlockRatio: Perbill = Perbill::one();
     pub const MinimumPeriod: u64 = 5;
-    pub const InitialMembersBalance: u64 = 2000;
     pub const StakePoolId: [u8; 8] = *b"joystake";
     pub const ExistentialDeposit: u32 = 0;
     pub const TransferFee: u32 = 0;
@@ -87,13 +86,12 @@ impl stake::Trait for Test {
     type SlashId = u64;
 }
 
-impl membership::members::Trait for Test {
+impl membership::Trait for Test {
     type Event = TestEvent;
     type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
     type ActorId = u64;
-    type InitialMembersBalance = InitialMembersBalance;
 }
 
 impl common::currency::GovernanceCurrency for Test {
@@ -136,7 +134,7 @@ impl Trait<TestWorkingGroupInstance> for Test {
     type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
 }
 
-pub type Membership = membership::members::Module<Test>;
+pub type Membership = membership::Module<Test>;
 
 pub type TestWorkingGroupInstance = crate::Instance1;
 pub type TestWorkingGroup = Module<Test, TestWorkingGroupInstance>;

+ 1 - 1
runtime/src/integration/content_working_group.rs

@@ -107,7 +107,7 @@ impl stake::StakingEventsHandler<Runtime> for ContentWorkingGroupStakingEventHan
         let member_id = curator_application.member_id;
 
         // get member's profile
-        let member_profile = membership::members::MemberProfile::<Runtime>::get(member_id).unwrap();
+        let member_profile = membership::MembershipById::<Runtime>::get(member_id);
 
         // deposit funds to member's root_account
         // The application doesn't recorded the original source_account from which staked funds were

+ 11 - 18
runtime/src/integration/proposals/council_origin_validator.rs

@@ -13,7 +13,7 @@ pub struct CouncilManager<T> {
     marker: PhantomData<T>,
 }
 
-impl<T: governance::council::Trait + membership::members::Trait>
+impl<T: governance::council::Trait + membership::Trait>
     ActorOriginValidator<<T as system::Trait>::Origin, MemberId<T>, <T as system::Trait>::AccountId>
     for CouncilManager<T>
 {
@@ -45,7 +45,6 @@ mod tests {
     use super::CouncilManager;
     use crate::Runtime;
     use common::origin::ActorOriginValidator;
-    use membership::members::UserInfo;
     use proposals_engine::VotersParameters;
     use sr_primitives::AccountId32;
     use system::RawOrigin;
@@ -60,7 +59,7 @@ mod tests {
         t.into()
     }
 
-    type Membership = membership::members::Module<Runtime>;
+    type Membership = membership::Module<Runtime>;
 
     #[test]
     fn council_origin_validator_fails_with_unregistered_member() {
@@ -101,11 +100,9 @@ mod tests {
             Membership::add_screened_member(
                 RawOrigin::Signed(authority_account_id).into(),
                 account_id.clone(),
-                UserInfo {
-                    handle: Some(b"handle".to_vec()),
-                    avatar_uri: None,
-                    about: None,
-                },
+                Some(b"handle".to_vec()),
+                None,
+                None,
             )
             .unwrap();
             let member_id = 0; // newly created member_id
@@ -133,11 +130,9 @@ mod tests {
             Membership::add_screened_member(
                 RawOrigin::Signed(authority_account_id).into(),
                 account_id.clone(),
-                UserInfo {
-                    handle: Some(b"handle".to_vec()),
-                    avatar_uri: None,
-                    about: None,
-                },
+                Some(b"handle".to_vec()),
+                None,
+                None,
             )
             .unwrap();
             let member_id = 0; // newly created member_id
@@ -168,11 +163,9 @@ mod tests {
             Membership::add_screened_member(
                 RawOrigin::Signed(authority_account_id).into(),
                 account_id,
-                UserInfo {
-                    handle: Some(b"handle".to_vec()),
-                    avatar_uri: None,
-                    about: None,
-                },
+                Some(b"handle".to_vec()),
+                None,
+                None,
             )
             .unwrap();
             let member_id = 0; // newly created member_id

+ 10 - 15
runtime/src/integration/proposals/membership_origin_validator.rs

@@ -6,14 +6,14 @@ use common::origin::ActorOriginValidator;
 use system::ensure_signed;
 
 /// Member of the Joystream organization
-pub type MemberId<T> = <T as crate::members::Trait>::MemberId;
+pub type MemberId<T> = <T as membership::Trait>::MemberId;
 
 /// Default membership actor origin validator.
 pub struct MembershipOriginValidator<T> {
     marker: PhantomData<T>,
 }
 
-impl<T: crate::members::Trait>
+impl<T: membership::Trait>
     ActorOriginValidator<<T as system::Trait>::Origin, MemberId<T>, <T as system::Trait>::AccountId>
     for MembershipOriginValidator<T>
 {
@@ -27,7 +27,7 @@ impl<T: crate::members::Trait>
         let account_id = ensure_signed(origin)?;
 
         // check whether actor_id belongs to the registered member
-        let profile_result = <crate::members::Module<T>>::ensure_profile(actor_id);
+        let profile_result = <membership::Module<T>>::ensure_membership(actor_id);
 
         if let Ok(profile) = profile_result {
             // whether the account_id belongs to the actor
@@ -47,11 +47,10 @@ mod tests {
     use super::MembershipOriginValidator;
     use crate::Runtime;
     use common::origin::ActorOriginValidator;
-    use membership::members::UserInfo;
     use sr_primitives::AccountId32;
     use system::RawOrigin;
 
-    type Membership = crate::members::Module<Runtime>;
+    type Membership = membership::Module<Runtime>;
 
     fn initial_test_ext() -> runtime_io::TestExternalities {
         let t = system::GenesisConfig::default()
@@ -90,11 +89,9 @@ mod tests {
             Membership::add_screened_member(
                 RawOrigin::Signed(authority_account_id).into(),
                 account_id.clone(),
-                UserInfo {
-                    handle: Some(b"handle".to_vec()),
-                    avatar_uri: None,
-                    about: None,
-                },
+                Some(b"handle".to_vec()),
+                None,
+                None,
             )
             .unwrap();
             let member_id = 0; // newly created member_id
@@ -122,11 +119,9 @@ mod tests {
             Membership::add_screened_member(
                 RawOrigin::Signed(authority_account_id).into(),
                 account_id,
-                UserInfo {
-                    handle: Some(b"handle".to_vec()),
-                    avatar_uri: None,
-                    about: None,
-                },
+                Some(b"handle".to_vec()),
+                None,
+                None,
             )
             .unwrap();
             let member_id = 0; // newly created member_id

+ 3 - 5
runtime/src/lib.rs

@@ -68,7 +68,6 @@ pub use working_group;
 
 pub use governance::election_params::ElectionParameters;
 use governance::{council, election};
-use membership::members;
 use storage::{data_directory, data_object_storage_registry, data_object_type_registry};
 pub use versioned_store;
 
@@ -584,13 +583,12 @@ impl storage::data_object_storage_registry::Trait for Runtime {
     type ContentIdExists = DataDirectory;
 }
 
-impl members::Trait for Runtime {
+impl membership::Trait for Runtime {
     type Event = Event;
     type MemberId = u64;
     type PaidTermId = u64;
     type SubscriptionId = u64;
     type ActorId = ActorId;
-    type InitialMembersBalance = InitialMembersBalance;
 }
 
 /*
@@ -609,7 +607,7 @@ pub struct ShimMembershipRegistry {}
 
 impl forum::ForumUserRegistry<AccountId> for ShimMembershipRegistry {
     fn get_forum_user(id: &AccountId) -> Option<forum::ForumUser<AccountId>> {
-        if members::Module::<Runtime>::is_member_account(id) {
+        if membership::Module::<Runtime>::is_member_account(id) {
             // For now we don't retreive the members profile since it is not used for anything,
             // but in the future we may need it to read out more
             // information possibly required to construct a
@@ -735,7 +733,7 @@ construct_runtime!(
         CouncilElection: election::{Module, Call, Storage, Event<T>, Config<T>},
         Council: council::{Module, Call, Storage, Event<T>, Config<T>},
         Memo: memo::{Module, Call, Storage, Event<T>},
-        Members: members::{Module, Call, Storage, Event<T>, Config<T>},
+        Members: membership::{Module, Call, Storage, Event<T>, Config<T>},
         Forum: forum::{Module, Call, Storage, Event<T>, Config<T>},
         VersionedStore: versioned_store::{Module, Call, Storage, Event<T>, Config},
         VersionedStorePermissions: versioned_store_permissions::{Module, Call, Storage},

+ 5 - 7
runtime/src/tests/proposals_integration/mod.rs

@@ -6,7 +6,7 @@ mod working_group_proposals;
 
 use crate::{BlockNumber, ElectionParameters, ProposalCancellationFee, Runtime};
 use codec::Encode;
-use membership::members;
+use membership;
 use proposals_engine::{
     ActiveStake, ApprovedProposalStatus, BalanceOf, Error, FinalizationData, Proposal,
     ProposalDecisionStatus, ProposalParameters, ProposalStatus, VoteKind, VotersParameters,
@@ -25,7 +25,7 @@ use crate::CouncilManager;
 
 pub type Balances = balances::Module<Runtime>;
 pub type System = system::Module<Runtime>;
-pub type Membership = membership::members::Module<Runtime>;
+pub type Membership = membership::Module<Runtime>;
 pub type ProposalsEngine = proposals_engine::Module<Runtime>;
 pub type Council = governance::council::Module<Runtime>;
 pub type Election = governance::election::Module<Runtime>;
@@ -42,11 +42,9 @@ fn setup_members(count: u8) {
         Membership::add_screened_member(
             RawOrigin::Signed(authority_account_id.clone().into()).into(),
             account_id.clone().into(),
-            members::UserInfo {
-                handle: Some(account_id.to_vec()),
-                avatar_uri: None,
-                about: None,
-            },
+            Some(account_id.to_vec()),
+            None,
+            None,
         )
         .unwrap();
     }