Procházet zdrojové kódy

Drop security/configuration constraints from runtime storage, make them configurable through runtime trait

iorveth před 4 roky
rodič
revize
48888d538e

+ 24 - 19
runtime-modules/content-directory/src/lib.rs

@@ -5,7 +5,7 @@ use codec::{Codec, Encode, Decode};
 use rstd::collections::{btree_map::BTreeMap, btree_set::BTreeSet};
 use rstd::prelude::*;
 use runtime_primitives::traits::{MaybeSerialize, Member, SimpleArithmetic};
-use srml_support::{decl_module, decl_storage, dispatch, ensure, Parameter};
+use srml_support::{decl_module, traits::Get, decl_storage, dispatch, ensure, Parameter};
 use system;
 
 #[cfg(feature = "std")]
@@ -42,6 +42,16 @@ pub trait Trait: system::Trait {
         + Eq
         + PartialEq
         + Ord;
+    
+    /// Security/configuration constraints
+
+    type PropertyNameConstraint: Get<InputValidationLengthConstraint>;
+
+    type PropertyDescriptionConstraint: Get<InputValidationLengthConstraint>;
+
+    type ClassNameConstraint: Get<InputValidationLengthConstraint>;
+
+    type ClassDescriptionConstraint: Get<InputValidationLengthConstraint>;
 
     /// External type for checking if an account has specified credential.
     type CredentialChecker: CredentialChecker<Self>;
@@ -86,7 +96,7 @@ impl<T: Trait> CreateClassPermissionsChecker<T> for () {
 
 /// Length constraint for input validation
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
+#[derive(Encode, Decode, Default, Clone, Copy, PartialEq, Eq, Debug)]
 pub struct InputValidationLengthConstraint {
     /// Minimum length
     pub min: u16,
@@ -99,6 +109,13 @@ pub struct InputValidationLengthConstraint {
 }
 
 impl InputValidationLengthConstraint {
+    pub fn new(min: u16, max_min_diff: u16) -> Self {
+        Self {
+            min,
+            max_min_diff
+        }
+    }
+
     /// Helper for computing max
     pub fn max(&self) -> u16 {
         self.min + self.max_min_diff
@@ -343,19 +360,7 @@ decl_storage! {
         pub NextClassId get(next_class_id) config(): ClassId;
 
         pub NextEntityId get(next_entity_id) config(): EntityId;
-
-        pub PropertyNameConstraint get(property_name_constraint)
-            config(): InputValidationLengthConstraint;
-
-        pub PropertyDescriptionConstraint get(property_description_constraint)
-            config(): InputValidationLengthConstraint;
-
-        pub ClassNameConstraint get(class_name_constraint)
-            config(): InputValidationLengthConstraint;
-
-        pub ClassDescriptionConstraint get(class_description_constraint)
-            config(): InputValidationLengthConstraint;
-        }
+    }
 }
 
 decl_module! {
@@ -1411,7 +1416,7 @@ impl<T: Trait> Module<T> {
         }
     
         pub fn ensure_property_name_is_valid(text: &Vec<u8>) -> dispatch::Result {
-            PropertyNameConstraint::get().ensure_valid(
+            T::PropertyNameConstraint::get().ensure_valid(
                 text.len(),
                 ERROR_PROPERTY_NAME_TOO_SHORT,
                 ERROR_PROPERTY_NAME_TOO_LONG,
@@ -1419,7 +1424,7 @@ impl<T: Trait> Module<T> {
         }
     
         pub fn ensure_property_description_is_valid(text: &Vec<u8>) -> dispatch::Result {
-            PropertyDescriptionConstraint::get().ensure_valid(
+            T::PropertyDescriptionConstraint::get().ensure_valid(
                 text.len(),
                 ERROR_PROPERTY_DESCRIPTION_TOO_SHORT,
                 ERROR_PROPERTY_DESCRIPTION_TOO_LONG,
@@ -1427,7 +1432,7 @@ impl<T: Trait> Module<T> {
         }
     
         pub fn ensure_class_name_is_valid(text: &Vec<u8>) -> dispatch::Result {
-            ClassNameConstraint::get().ensure_valid(
+            T::ClassNameConstraint::get().ensure_valid(
                 text.len(),
                 ERROR_CLASS_NAME_TOO_SHORT,
                 ERROR_CLASS_NAME_TOO_LONG,
@@ -1435,7 +1440,7 @@ impl<T: Trait> Module<T> {
         }
     
         pub fn ensure_class_description_is_valid(text: &Vec<u8>) -> dispatch::Result {
-            ClassDescriptionConstraint::get().ensure_valid(
+            T::ClassDescriptionConstraint::get().ensure_valid(
                 text.len(),
                 ERROR_CLASS_DESCRIPTION_TOO_SHORT,
                 ERROR_CLASS_DESCRIPTION_TOO_LONG,

+ 99 - 29
runtime-modules/content-directory/src/mock.rs

@@ -10,6 +10,7 @@ use runtime_primitives::{
     Perbill,
 };
 use srml_support::{assert_err, assert_ok, impl_outer_origin, parameter_types};
+use std::cell::RefCell;
 
 pub const MEMBER_ONE_WITH_CREDENTIAL_ZERO: u64 = 100;
 pub const MEMBER_TWO_WITH_CREDENTIAL_ZERO: u64 = 101;
@@ -85,10 +86,49 @@ impl timestamp::Trait for Runtime {
     type MinimumPeriod = MinimumPeriod;
 }
 
+thread_local! {
+    static PROPERTY_NAME_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
+    static PROPERTY_DESCRIPTION_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
+    static CLASS_NAME_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
+    static CLASS_DESCRIPTION_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
+}
+
+pub struct PropertyNameConstraint;
+impl Get<InputValidationLengthConstraint> for PropertyNameConstraint {
+    fn get() -> InputValidationLengthConstraint {
+        PROPERTY_NAME_CONSTRAINT.with(|v| *v.borrow())
+    }
+}
+
+pub struct PropertyDescriptionConstraint;
+impl Get<InputValidationLengthConstraint> for PropertyDescriptionConstraint {
+    fn get() -> InputValidationLengthConstraint {
+        PROPERTY_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow())
+    }
+}
+
+pub struct ClassNameConstraint;
+impl Get<InputValidationLengthConstraint> for ClassNameConstraint {
+    fn get() -> InputValidationLengthConstraint {
+        CLASS_NAME_CONSTRAINT.with(|v| *v.borrow())
+    }
+}
+
+pub struct ClassDescriptionConstraint;
+impl Get<InputValidationLengthConstraint> for ClassDescriptionConstraint {
+    fn get() -> InputValidationLengthConstraint {
+        CLASS_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow())
+    }
+}
+
 impl Trait for Runtime {
     type Credential = u64;
     type CredentialChecker = MockCredentialChecker;
     type CreateClassPermissionsChecker = MockCreateClassPermissionsChecker;
+    type PropertyNameConstraint = PropertyNameConstraint;
+    type PropertyDescriptionConstraint = PropertyDescriptionConstraint;
+    type ClassNameConstraint = ClassNameConstraint;
+    type ClassDescriptionConstraint  = ClassDescriptionConstraint;
 }
 
 pub struct MockCredentialChecker {}
@@ -120,47 +160,77 @@ impl CreateClassPermissionsChecker<Runtime> for MockCreateClassPermissionsChecke
     }
 }
 
+pub struct ExtBuilder {
+    property_name_constraint: InputValidationLengthConstraint,
+    property_description_constraint: InputValidationLengthConstraint,
+    class_name_constraint: InputValidationLengthConstraint,
+    class_description_constraint: InputValidationLengthConstraint,
+}
+
+impl Default for ExtBuilder {
+    fn default() -> Self {
+        Self {
+            property_name_constraint: InputValidationLengthConstraint::new(1, 49),
+            property_description_constraint: InputValidationLengthConstraint::new(0, 500),
+            class_name_constraint: InputValidationLengthConstraint::new(1, 49),
+            class_description_constraint: InputValidationLengthConstraint::new(0, 500),
+        }
+    }
+}
+
+impl ExtBuilder {
+    pub fn post_title_max_length(mut self, property_name_constraint: InputValidationLengthConstraint) -> Self {
+        self.property_name_constraint = property_name_constraint;
+        self
+    }
+
+    pub fn post_body_max_length(mut self, property_description_constraint: InputValidationLengthConstraint) -> Self {
+        self.property_description_constraint = property_description_constraint;
+        self
+    }
+
+    pub fn reply_max_length(mut self, class_name_constraint: InputValidationLengthConstraint) -> Self {
+        self.class_name_constraint = class_name_constraint;
+        self
+    }
+
+    pub fn posts_max_number(mut self, class_description_constraint: InputValidationLengthConstraint) -> Self {
+        self.class_description_constraint = class_description_constraint;
+        self
+    }
+
+    pub fn set_associated_consts(&self) {
+        PROPERTY_NAME_CONSTRAINT.with(|v| *v.borrow_mut() = self.property_name_constraint);
+        PROPERTY_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow_mut() = self.property_description_constraint);
+        CLASS_NAME_CONSTRAINT.with(|v| *v.borrow_mut() = self.class_name_constraint);
+        CLASS_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow_mut() = self.class_description_constraint);
+    }
+
+    pub fn build(self, config: GenesisConfig<Runtime>) -> runtime_io::TestExternalities {
+        self.set_associated_consts();
+        let mut t = system::GenesisConfig::default()
+            .build_storage::<Runtime>()
+            .unwrap();
+        config.assimilate_storage(&mut t).unwrap();
+        t.into()
+    }
+}
+
 // This function basically just builds a genesis storage key/value store according to
 // our desired mockup.
 
-fn default_versioned_store_genesis_config() -> GenesisConfig<Runtime> {
+fn default_content_directory_genesis_config() -> GenesisConfig<Runtime> {
     GenesisConfig {
         class_by_id: vec![],
         entity_by_id: vec![],
         next_class_id: 1,
         next_entity_id: 1,
-        property_name_constraint: InputValidationLengthConstraint {
-            min: 1,
-            max_min_diff: 49,
-        },
-        property_description_constraint: InputValidationLengthConstraint {
-            min: 0,
-            max_min_diff: 500,
-        },
-        class_name_constraint: InputValidationLengthConstraint {
-            min: 1,
-            max_min_diff: 49,
-        },
-        class_description_constraint: InputValidationLengthConstraint {
-            min: 0,
-            max_min_diff: 500,
-        },
     }
 }
 
-fn build_test_externalities(config: GenesisConfig<Runtime>) -> runtime_io::TestExternalities {
-    let mut t = system::GenesisConfig::default()
-        .build_storage::<Runtime>()
-        .unwrap();
-
-    config.assimilate_storage(&mut t).unwrap();
-
-    t.into()
-}
-
 pub fn with_test_externalities<R, F: FnOnce() -> R>(f: F) -> R {
-    let versioned_store_config = default_versioned_store_genesis_config();
-    build_test_externalities(versioned_store_config).execute_with(f)
+    let default_genesis_config = default_content_directory_genesis_config();
+    ExtBuilder::default().build(default_genesis_config).execute_with(f)
 }
 
 impl Property {