Browse Source

Integrate discussion system (proposals) with membership crate

Shamil Gadelshin 5 years ago
parent
commit
7587e9fc69

+ 10 - 1
runtime-modules/proposals/codex/Cargo.toml

@@ -85,6 +85,10 @@ default_features = false
 package = 'substrate-stake-module'
 path = '../../stake'
 
+[dependencies.membership]
+default_features = false
+package = 'substrate-membership-module'
+path = '../../membership'
 
 [dependencies.proposal_engine]
 default_features = false
@@ -100,4 +104,9 @@ path = '../discussion'
 default_features = false
 git = 'https://github.com/paritytech/substrate.git'
 package = 'sr-io'
-rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
+[dev-dependencies.common]
+default_features = false
+package = 'substrate-common-module'
+path = '../../common'

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

@@ -28,7 +28,9 @@ use proposal_engine::*;
 pub use proposal_types::{ProposalType, RuntimeUpgradeProposalExecutable, TextProposalExecutable};
 
 /// 'Proposals codex' substrate module Trait
-pub trait Trait: system::Trait + proposal_engine::Trait + proposal_discussion::Trait {
+pub trait Trait:
+    system::Trait + proposal_engine::Trait + membership::members::Trait + proposal_discussion::Trait
+{
     /// Defines max allowed text proposal length.
     type TextProposalMaxLength: Get<u32>;
 
@@ -101,7 +103,7 @@ decl_module! {
 
             let discussion_thread_id = <proposal_discussion::Module<T>>::create_thread(
                 cloned_origin1,
-                T::ThreadAuthorId::one(), //TODO: temporary stub, provide implementation
+                T::MemberId::one(), //TODO: temporary stub, provide implementation
                 title.clone(),
             )?;
 
@@ -144,7 +146,7 @@ decl_module! {
 
             let discussion_thread_id = <proposal_discussion::Module<T>>::create_thread(
                 cloned_origin1,
-                T::ThreadAuthorId::one(), //TODO: temporary stub, provide implementation
+                T::MemberId::one(),  //TODO: temporary stub, provide implementation
                 title.clone(),
             )?;
 

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

@@ -36,6 +36,19 @@ impl_outer_dispatch! {
     }
 }
 
+impl common::currency::GovernanceCurrency for Test {
+    type Currency = balances::Module<Self>;
+}
+
+impl membership::members::Trait for Test {
+    type Event = ();
+    type MemberId = u64;
+    type PaidTermId = u64;
+    type SubscriptionId = u64;
+    type ActorId = u64;
+    type InitialMembersBalance = ();
+}
+
 parameter_types! {
     pub const ExistentialDeposit: u32 = 0;
     pub const TransferFee: u32 = 0;
@@ -124,7 +137,6 @@ impl proposal_discussion::Trait for Test {
     type PostAuthorOriginValidator = ();
     type ThreadId = u32;
     type PostId = u32;
-    type ThreadAuthorId = u64;
     type PostAuthorId = u64;
     type MaxPostEditionNumber = MaxPostEditionNumber;
     type ThreadTitleLengthLimit = ThreadTitleLengthLimit;

+ 16 - 0
runtime-modules/proposals/discussion/Cargo.toml

@@ -70,8 +70,24 @@ git = 'https://github.com/paritytech/substrate.git'
 package = 'srml-timestamp'
 rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
 
+[dependencies.membership]
+default_features = false
+package = 'substrate-membership-module'
+path = '../../membership'
+
 [dev-dependencies.runtime-io]
 default_features = false
 git = 'https://github.com/paritytech/substrate.git'
 package = 'sr-io'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
+[dev-dependencies.common]
+default_features = false
+package = 'substrate-common-module'
+path = '../../common'
+
+[dev-dependencies.balances]
+package = 'srml-balances'
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
 rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'

+ 11 - 15
runtime-modules/proposals/discussion/src/lib.rs

@@ -25,11 +25,12 @@ use rstd::prelude::*;
 use rstd::vec::Vec;
 use srml_support::{decl_event, decl_module, decl_storage, ensure, Parameter};
 
-use runtime_primitives::traits::SimpleArithmetic;
 use srml_support::traits::Get;
-pub use types::ActorOriginValidator;
+pub use types::{ActorOriginValidator, ThreadPostActorOriginValidator};
 use types::{Post, Thread, ThreadCounter};
 
+pub(crate) use types::MemberId;
+
 // TODO: move errors to decl_error macro (after substrate version upgrade)
 
 decl_event!(
@@ -37,12 +38,12 @@ decl_event!(
     pub enum Event<T>
     where
         <T as Trait>::ThreadId,
-        <T as Trait>::ThreadAuthorId,
+        MemberId = MemberId<T>,
         <T as Trait>::PostId,
         <T as Trait>::PostAuthorId,
     {
     	/// Emits on thread creation.
-        ThreadCreated(ThreadId, ThreadAuthorId),
+        ThreadCreated(ThreadId, MemberId),
 
     	/// Emits on post creation.
         PostCreated(PostId, PostAuthorId),
@@ -53,12 +54,12 @@ decl_event!(
 );
 
 /// 'Proposal discussion' substrate module Trait
-pub trait Trait: system::Trait {
+pub trait Trait: system::Trait + membership::members::Trait {
     /// Engine event type.
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 
     /// Validates thread author id and origin combination
-    type ThreadAuthorOriginValidator: ActorOriginValidator<Self::Origin, Self::ThreadAuthorId>;
+    type ThreadAuthorOriginValidator: ActorOriginValidator<Self::Origin, MemberId<Self>>;
 
     /// Validates post author id and origin combination
     type PostAuthorOriginValidator: ActorOriginValidator<Self::Origin, Self::PostAuthorId>;
@@ -69,9 +70,6 @@ pub trait Trait: system::Trait {
     /// Post Id type
     type PostId: From<u32> + Parameter + Default + Copy;
 
-    /// Type for the thread author id. Should be authenticated by account id.
-    type ThreadAuthorId: From<Self::AccountId> + Parameter + Default + SimpleArithmetic;
-
     /// Type for the post author id. Should be authenticated by account id.
     type PostAuthorId: From<Self::AccountId> + Parameter + Default;
 
@@ -93,7 +91,7 @@ decl_storage! {
     pub trait Store for Module<T: Trait> as ProposalDiscussion {
         /// Map thread identifier to corresponding thread.
         pub ThreadById get(thread_by_id): map T::ThreadId =>
-            Thread<T::ThreadAuthorId, T::BlockNumber>;
+            Thread<MemberId<T>, T::BlockNumber>;
 
         /// Count of all threads that have been created.
         pub ThreadCount get(fn thread_count): u32;
@@ -107,7 +105,7 @@ decl_storage! {
 
         /// Last author thread counter (part of the antispam mechanism)
         pub LastThreadAuthorCounter get(fn last_thread_author_counter):
-            Option<ThreadCounter<T::ThreadAuthorId>>;
+            Option<ThreadCounter<MemberId<T>>>;
     }
 }
 
@@ -210,7 +208,7 @@ impl<T: Trait> Module<T> {
     /// times in a row by the same author.
     pub fn create_thread(
         origin: T::Origin,
-        thread_author_id: T::ThreadAuthorId,
+        thread_author_id: MemberId<T>,
         title: Vec<u8>,
     ) -> Result<T::ThreadId, &'static str> {
         ensure!(
@@ -253,9 +251,7 @@ impl<T: Trait> Module<T> {
     }
 
     // returns incremented thread counter if last thread author equals with provided parameter
-    fn get_updated_thread_counter(
-        author_id: T::ThreadAuthorId,
-    ) -> ThreadCounter<T::ThreadAuthorId> {
+    fn get_updated_thread_counter(author_id: MemberId<T>) -> ThreadCounter<MemberId<T>> {
         // if thread counter exists
         if let Some(last_thread_author_counter) = Self::last_thread_author_counter() {
             // if last(previous) author is the same as current author

+ 42 - 1
runtime-modules/proposals/discussion/src/tests/mock.rs

@@ -40,19 +40,60 @@ mod discussion {
     pub use crate::Event;
 }
 
+mod membership_mod {
+    pub use membership::members::Event;
+}
+
 impl_outer_event! {
     pub enum TestEvent for Test {
         discussion<T>,
+        balances<T>,
+        membership_mod<T>,
     }
 }
 
+parameter_types! {
+    pub const ExistentialDeposit: u32 = 0;
+    pub const TransferFee: u32 = 0;
+    pub const CreationFee: u32 = 0;
+}
+
+impl balances::Trait for Test {
+    /// The type for recording an account's balance.
+    type Balance = u64;
+    /// What to do if an account's free balance gets zeroed.
+    type OnFreeBalanceZero = ();
+    /// What to do if a new account is created.
+    type OnNewAccount = ();
+
+    type Event = TestEvent;
+
+    type DustRemoval = ();
+    type TransferPayment = ();
+    type ExistentialDeposit = ExistentialDeposit;
+    type TransferFee = TransferFee;
+    type CreationFee = CreationFee;
+}
+
+impl common::currency::GovernanceCurrency for Test {
+    type Currency = balances::Module<Self>;
+}
+
+impl membership::members::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 {
     type Event = TestEvent;
     type ThreadAuthorOriginValidator = ();
     type PostAuthorOriginValidator = ();
     type ThreadId = u32;
     type PostId = u32;
-    type ThreadAuthorId = u64;
     type PostAuthorId = u64;
     type MaxPostEditionNumber = MaxPostEditionNumber;
     type ThreadTitleLengthLimit = ThreadTitleLengthLimit;

+ 50 - 2
runtime-modules/proposals/discussion/src/types.rs

@@ -1,8 +1,13 @@
-use rstd::prelude::*;
+use crate::Trait;
+
+use codec::{Decode, Encode};
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 
-use codec::{Decode, Encode};
+use rstd::marker::PhantomData;
+use rstd::prelude::*;
+
+use system::ensure_signed;
 
 /// Represents a discussion thread
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
@@ -75,3 +80,46 @@ pub trait ActorOriginValidator<Origin, ActorId> {
     /// Check for valid combination of origin and actor_id
     fn validate_actor_origin(origin: Origin, actor_id: ActorId) -> bool;
 }
+
+// Member of the Joystream organization
+pub(crate) type MemberId<T> = <T as membership::members::Trait>::MemberId;
+
+/// Default discussion system actor origin validator. Valid for both thread and post authors.
+pub struct ThreadPostActorOriginValidator<T> {
+    marker: PhantomData<T>,
+}
+
+impl<T> ThreadPostActorOriginValidator<T> {
+    /// Create ThreadPostActorOriginValidator instance
+    pub fn new() -> Self {
+        ThreadPostActorOriginValidator {
+            marker: PhantomData,
+        }
+    }
+}
+
+impl<T: Trait> ActorOriginValidator<<T as system::Trait>::Origin, MemberId<T>>
+    for ThreadPostActorOriginValidator<T>
+{
+    /// Check for valid combination of origin and actor_id. Actor_id should be valid member_id of
+    /// the membership module
+    fn validate_actor_origin(origin: <T as system::Trait>::Origin, actor_id: MemberId<T>) -> bool {
+        let account_id_result = ensure_signed(origin);
+
+        //todo : modify to Result and rename to ensure
+
+        // check valid signed account_id
+        if let Ok(account_id) = account_id_result {
+            // check whether actor_id belongs to the registered member
+            let profile_result = <membership::members::Module<T>>::ensure_profile(actor_id);
+
+            if let Ok(profile) = profile_result {
+                // whether the account_id belongs to the actor
+                return profile.root_account == account_id
+                    || profile.controller_account == account_id;
+            }
+        }
+
+        false
+    }
+}

+ 0 - 2
runtime/src/lib.rs

@@ -3,7 +3,6 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
 #![recursion_limit = "256"]
-
 // srml_staking_reward_curve::build! - substrate macro produces a warning.
 // TODO: remove after post-Rome substrate upgrade
 #![allow(array_into_iter)]
@@ -332,7 +331,6 @@ impl session::historical::Trait for Runtime {
     type FullIdentificationOf = staking::ExposureOf<Runtime>;
 }
 
-
 srml_staking_reward_curve::build! {
     const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
         min_inflation: 0_025_000,