Kaynağa Gözat

runtime: proposals: Introduce max author white-list size.

Shamil Gadelshin 4 yıl önce
ebeveyn
işleme
2f1a0f3178

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

@@ -812,10 +812,16 @@ impl<T: Trait> Module<T> {
             params.exact_execution_block,
         )?;
 
-        <proposals_discussion::Module<T>>::ensure_can_create_thread(params.member_id)?;
+        let initial_thread_mode = ThreadMode::Open;
+        <proposals_discussion::Module<T>>::ensure_can_create_thread(
+            params.member_id,
+            &initial_thread_mode,
+        )?;
 
-        let discussion_thread_id =
-            <proposals_discussion::Module<T>>::create_thread(params.member_id, ThreadMode::Open)?;
+        let discussion_thread_id = <proposals_discussion::Module<T>>::create_thread(
+            params.member_id,
+            initial_thread_mode,
+        )?;
 
         let proposal_creation_params = ProposalCreationParameters {
             account_id,

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

@@ -127,6 +127,7 @@ parameter_types! {
     pub const MaxThreadInARowNumber: u32 = 3;
     pub const ThreadTitleLengthLimit: u32 = 200;
     pub const PostLengthLimit: u32 = 2000;
+    pub const MaxWhiteListSize: u32 = 20;
 }
 
 impl proposals_discussion::Trait for Test {
@@ -137,6 +138,7 @@ impl proposals_discussion::Trait for Test {
     type PostId = u64;
     type MaxPostEditionNumber = MaxPostEditionNumber;
     type MaxThreadInARowNumber = MaxThreadInARowNumber;
+    type MaxWhiteListSize = MaxWhiteListSize;
 }
 
 pub struct MockVotersParameters;

+ 32 - 5
runtime-modules/proposals/discussion/src/lib.rs

@@ -30,8 +30,9 @@
 //!         #[weight = 10_000_000]
 //!         pub fn create_discussion(origin, title: Vec<u8>, author_id : T::MemberId) {
 //!             ensure_root(origin)?;
-//!             <discussions::Module<T>>::ensure_can_create_thread(author_id)?;
-//!             <discussions::Module<T>>::create_thread(author_id, ThreadMode::Open)?;
+//!             let thread_mode = ThreadMode::Open;
+//!             <discussions::Module<T>>::ensure_can_create_thread(author_id, &thread_mode)?;
+//!             <discussions::Module<T>>::create_thread(author_id, thread_mode)?;
 //!         }
 //!     }
 //! }
@@ -49,6 +50,7 @@ mod tests;
 mod types;
 
 use frame_support::dispatch::{DispatchError, DispatchResult};
+use frame_support::sp_runtime::SaturatedConversion;
 use frame_support::traits::Get;
 use frame_support::{decl_error, decl_event, decl_module, decl_storage, ensure, Parameter};
 use sp_std::clone::Clone;
@@ -111,6 +113,9 @@ pub trait Trait: system::Trait + membership::Trait {
 
     /// Defines max thread by same author in a row number limit.
     type MaxThreadInARowNumber: Get<u32>;
+
+    /// Defines author list size limit for the Closed discussion.
+    type MaxWhiteListSize: Get<u32>;
 }
 
 decl_error! {
@@ -139,6 +144,9 @@ decl_error! {
 
         /// Should be thread author or councilor.
         NotAuthorOrCouncilor,
+
+        /// Max allowed authors list limit exceeded.
+        MaxWhiteListSizeExceeded,
     }
 }
 
@@ -260,6 +268,13 @@ decl_module! {
 
             ensure!(<ThreadById<T>>::contains_key(thread_id), Error::<T>::ThreadDoesntExist);
 
+            if let ThreadMode::Closed(ref list) = mode{
+                ensure!(
+                    list.len() <= (T::MaxWhiteListSize::get()).saturated_into(),
+                    Error::<T>::MaxWhiteListSizeExceeded
+                );
+            }
+
             let thread = Self::thread_by_id(&thread_id);
 
             let is_councilor =
@@ -286,7 +301,7 @@ impl<T: Trait> Module<T> {
         thread_author_id: MemberId<T>,
         mode: ThreadMode<MemberId<T>>,
     ) -> Result<T::ThreadId, DispatchError> {
-        Self::ensure_can_create_thread(thread_author_id)?;
+        Self::ensure_can_create_thread(thread_author_id, &mode)?;
 
         let next_thread_count_value = Self::thread_count() + 1;
         let new_thread_id = next_thread_count_value;
@@ -312,8 +327,20 @@ impl<T: Trait> Module<T> {
     }
 
     /// Ensures thread can be created.
-    /// Checks max thread in a row by the same author
-    pub fn ensure_can_create_thread(thread_author_id: MemberId<T>) -> DispatchResult {
+    /// Checks:
+    /// - max thread in a row by the same author
+    /// - max allowed authors for the Closed thread mode
+    pub fn ensure_can_create_thread(
+        thread_author_id: MemberId<T>,
+        mode: &ThreadMode<MemberId<T>>,
+    ) -> DispatchResult {
+        if let ThreadMode::Closed(list) = mode {
+            ensure!(
+                list.len() <= (T::MaxWhiteListSize::get()).saturated_into(),
+                Error::<T>::MaxWhiteListSizeExceeded
+            );
+        }
+
         // get new 'threads in a row' counter for the author
         let current_thread_counter = Self::get_updated_thread_counter(thread_author_id);
 

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

@@ -57,6 +57,7 @@ parameter_types! {
     pub const ExistentialDeposit: u32 = 0;
     pub const TransferFee: u32 = 0;
     pub const CreationFee: u32 = 0;
+    pub const MaxWhiteListSize: u32 = 4;
 }
 
 impl balances::Trait for Test {
@@ -87,6 +88,7 @@ impl crate::Trait for Test {
     type PostId = u64;
     type MaxPostEditionNumber = MaxPostEditionNumber;
     type MaxThreadInARowNumber = MaxThreadInARowNumber;
+    type MaxWhiteListSize = MaxWhiteListSize;
 }
 
 impl ActorOriginValidator<Origin, u64, u64> for () {

+ 27 - 0
runtime-modules/proposals/discussion/src/tests/mod.rs

@@ -596,3 +596,30 @@ fn thread_counter_new_works() {
 
     assert_eq!(expected, ThreadCounter::new(56));
 }
+
+#[test]
+fn change_thread_mode_fails_with_exceeded_max_author_list_size() {
+    initial_test_ext().execute_with(|| {
+        let discussion_fixture = DiscussionFixture::default();
+
+        let thread_id = discussion_fixture
+            .create_discussion_and_assert(Ok(1))
+            .unwrap();
+
+        let change_thread_mode_fixture = ChangeThreadModeFixture::default_for_thread_id(thread_id)
+            .with_mode(ThreadMode::Closed(vec![2, 3, 4, 5, 6]));
+        change_thread_mode_fixture
+            .call_and_assert(Err(Error::<Test>::MaxWhiteListSizeExceeded.into()));
+    });
+}
+
+#[test]
+fn create_discussion_call_fails_with_exceeded_max_author_list_size() {
+    initial_test_ext().execute_with(|| {
+        let discussion_fixture =
+            DiscussionFixture::default().with_mode(ThreadMode::Closed(vec![2, 3, 4, 5, 6]));
+
+        discussion_fixture
+            .create_discussion_and_assert(Err(Error::<Test>::MaxWhiteListSizeExceeded.into()));
+    });
+}

+ 1 - 1
runtime-modules/proposals/engine/src/tests/mod.rs

@@ -2259,7 +2259,7 @@ fn proposal_exact_execution_block_not_reached() {
 }
 
 #[test]
-fn proposal_status_resolution_is_approval_achievable_works_correctly() {
+fn proposal_status_resolution_approval_achievable_works_correctly() {
     let approval_threshold_proposal: Proposal<u64, u64, u64, u64> = Proposal {
         parameters: ProposalParameters {
             slashing_threshold_percentage: 50,

+ 2 - 2
runtime/src/lib.rs

@@ -579,8 +579,7 @@ impl Default for Call {
 parameter_types! {
     pub const ProposalMaxPostEditionNumber: u32 = 0; // post update is disabled
     pub const ProposalMaxThreadInARowNumber: u32 = 100_000; // will not be used
-    pub const ProposalThreadTitleLengthLimit: u32 = 40;
-    pub const ProposalPostLengthLimit: u32 = 1000;
+    pub const MaxWhiteListSize: u32 = 20;
 }
 
 impl proposals_discussion::Trait for Runtime {
@@ -591,6 +590,7 @@ impl proposals_discussion::Trait for Runtime {
     type PostId = PostId;
     type MaxPostEditionNumber = ProposalMaxPostEditionNumber;
     type MaxThreadInARowNumber = ProposalMaxThreadInARowNumber;
+    type MaxWhiteListSize = MaxWhiteListSize;
 }
 
 parameter_types! {