Browse Source

content-directory: censoring channels

Mokhtar Naamani 4 years ago
parent
commit
e90634bec8

+ 5 - 0
runtime-modules/content/src/errors.rs

@@ -4,6 +4,8 @@ use frame_support::decl_error;
 decl_error! {
     /// Content directory errors
     pub enum Error for Module<T: Trait> {
+        /// Feature Not Implemented
+        FeatureNotImplemented,
 
         // Curator Management Errors
         // -------------------------
@@ -52,5 +54,8 @@ decl_error! {
 
         /// Channel Does Not Exist
         ChannelDoesNotExist,
+
+        /// Curators can only censore non curator group channels
+        CannotCensoreCuratorGroupOwnedChannels
     }
 }

+ 122 - 75
runtime-modules/content/src/lib.rs

@@ -847,23 +847,87 @@ decl_module! {
             Ok(())
         }
 
+        #[weight = 10_000_000] // TODO: adjust weight
+        pub fn censor_channel(
+            origin,
+            actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
+            channel_id: T::ChannelId,
+            rationale: Vec<u8>,
+        ) -> DispatchResult {
+            // check that channel exists
+            let channel = Self::ensure_channel_exists(&channel_id)?;
+
+            ensure_actor_authorized_to_censor::<T>(
+                origin,
+                &actor,
+                &channel.owner,
+            )?;
+
+            //
+            // == MUTATION SAFE ==
+            //
+
+            let mut channel = channel;
+
+            channel.is_censored = true;
+
+            // TODO: unset the reward account ? so no revenue can be earned for censored channels?
+
+            // Update the channel
+            ChannelById::<T>::insert(channel_id, channel.clone());
+
+            Self::deposit_event(RawEvent::ChannelCensored(channel_id, rationale));
+            Ok(())
+        }
+
+        #[weight = 10_000_000] // TODO: adjust weight
+        pub fn uncensor_channel(
+            origin,
+            actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
+            channel_id: T::ChannelId,
+            rationale: Vec<u8>,
+        ) -> DispatchResult {
+            // check that channel exists
+            let channel = Self::ensure_channel_exists(&channel_id)?;
+
+            ensure_actor_authorized_to_censor::<T>(
+                origin,
+                &actor,
+                &channel.owner,
+            )?;
+
+            //
+            // == MUTATION SAFE ==
+            //
+
+            let mut channel = channel;
+
+            channel.is_censored = false;
+
+            // Update the channel
+            ChannelById::<T>::insert(channel_id, channel.clone());
+
+            Self::deposit_event(RawEvent::ChannelUncensored(channel_id, rationale));
+            Ok(())
+        }
+
         #[weight = 10_000_000] // TODO: adjust weight
         pub fn request_channel_transfer(
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             request: ChannelOwnershipTransferRequest<T>,
-        ) -> DispatchResult {
+        ) {
             // requester must be new_owner
-            Ok(())
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
         pub fn cancel_channel_transfer_request(
             origin,
             request_id: T::ChannelOwnershipTransferRequestId,
-        ) -> DispatchResult {
+        ) {
             // origin must be original requester (ie. proposed new channel owner)
-            Ok(())
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -871,9 +935,9 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             request_id: T::ChannelOwnershipTransferRequestId,
-        ) -> DispatchResult {
+        ) {
             // only current owner of channel can approve
-            Ok(())
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -882,8 +946,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             channel_id: T::ChannelId,
             params: VideoCreationParameters<ContentParameters<T>>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -892,8 +956,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             video: T::VideoId,
             params: VideoUpdateParameters<ContentParameters<T>>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -901,8 +965,8 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             video: T::VideoId,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -911,8 +975,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             channel_id: T::ChannelId,
             params: PlaylistCreationParameters,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -921,8 +985,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             playlist: T::PlaylistId,
             params: PlaylistUpdateParameters,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -931,8 +995,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             channel_id: T::ChannelId,
             playlist: T::PlaylistId,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -940,9 +1004,10 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             list: Vec<T::VideoId>
-        ) -> DispatchResult {
+        ) {
             // can only be set by lead
-            Ok(())
+
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -950,8 +1015,8 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             params: VideoCategoryCreationParameters,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -960,8 +1025,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             category: T::VideoCategoryId,
             params: VideoCategoryUpdateParameters,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -969,8 +1034,8 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             category: T::VideoCategoryId,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -978,11 +1043,8 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             params: ChannelCategoryCreationParameters,
-        ) -> DispatchResult {
-            // check origin is curator in active curator group
-            // any curator can create a category
-            // create category and emit event
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -991,8 +1053,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             category: T::ChannelCategoryId,
             params: ChannelCategoryUpdateParameters,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1000,8 +1062,8 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             category: T::ChannelCategoryId,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1009,8 +1071,8 @@ decl_module! {
             origin,
             actor: PersonActor<T::MemberId, T::CuratorId>,
             params: PersonCreationParameters<ContentParameters<T>>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1019,8 +1081,8 @@ decl_module! {
             actor: PersonActor<T::MemberId, T::CuratorId>,
             person: T::PersonId,
             params: PersonUpdateParameters<ContentParameters<T>>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1028,8 +1090,8 @@ decl_module! {
             origin,
             actor: PersonActor<T::MemberId, T::CuratorId>,
             person: T::PersonId,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1038,8 +1100,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             video_id: T::VideoId,
             person: T::PersonId
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1047,8 +1109,8 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             video_id: T::VideoId
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1057,18 +1119,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             video_id: T::VideoId,
             rationale: Vec<u8>,
-        ) -> DispatchResult {
-            Ok(())
-        }
-
-        #[weight = 10_000_000] // TODO: adjust weight
-        pub fn censor_channel(
-            origin,
-            actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
-            channel_id: T::ChannelId,
-            rationale: Vec<u8>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1077,18 +1129,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             video_id: T::VideoId,
             rationale: Vec<u8>
-        ) -> DispatchResult {
-            Ok(())
-        }
-
-        #[weight = 10_000_000] // TODO: adjust weight
-        pub fn uncensor_channel(
-            origin,
-            actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
-            channel_id: T::ChannelId,
-            rationale: Vec<u8>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1097,8 +1139,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             channel_id: T::ChannelId,
             params: SeriesParameters<T::VideoId, ContentParameters<T>>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1107,8 +1149,8 @@ decl_module! {
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             channel_id: T::ChannelId,
             params: SeriesParameters<T::VideoId, ContentParameters<T>>,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
 
         #[weight = 10_000_000] // TODO: adjust weight
@@ -1116,8 +1158,8 @@ decl_module! {
             origin,
             actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
             series: T::SeriesId,
-        ) -> DispatchResult {
-            Ok(())
+        ) {
+            Self::not_implemented()?;
         }
     }
 }
@@ -1216,6 +1258,11 @@ impl<T: Trait> Module<T> {
             // ContentActor::Dao(id) => Ok(ChannelOwner::Dao(id)),
         }
     }
+
+    fn not_implemented() -> Result<(), Error<T>> {
+        ensure!(false, Error::<T>::FeatureNotImplemented);
+        Ok(())
+    }
 }
 
 // Some initial config for the module on runtime upgrade

+ 66 - 8
runtime-modules/content/src/permissions/mod.rs

@@ -93,7 +93,13 @@ pub fn ensure_actor_authorized_to_create_channel<T: Trait>(
 ) -> DispatchResult {
     match actor {
         // Lead should use their member or curator role to create or update channels.
-        ContentActor::Lead => Err(Error::<T>::ActorCannotOwnChannel),
+        ContentActor::Lead => {
+            ensure!(
+                false,
+                Error::<T>::ActorCannotOwnChannel
+            );
+            Ok(())
+        }
         ContentActor::Curator(curator_group_id, curator_id) => {
             let sender = ensure_signed(origin)?;
 
@@ -115,8 +121,7 @@ pub fn ensure_actor_authorized_to_create_channel<T: Trait>(
         }
         // TODO:
         // ContentActor::Dao(_daoId) => ...,
-    }?;
-    Ok(())
+    }
 }
 
 pub fn ensure_actor_authorized_to_update_or_delete_channel<T: Trait>(
@@ -124,10 +129,17 @@ pub fn ensure_actor_authorized_to_update_or_delete_channel<T: Trait>(
     actor: &ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
     owner: &ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
 ) -> DispatchResult {
-    // Authenticate actor against channel owner
-    // Only Owner of a channel can update and delete it.
+    // Only owner of a channel can update and delete it.
+    // Should we allow lead to also update and delete curator group owned channels,
+    // to avoid need for them to add themselves into the group?
     match actor {
-        ContentActor::Lead => Err(Error::<T>::ActorNotAuthorized),
+        ContentActor::Lead => {
+            ensure!(
+                false,
+                Error::<T>::ActorNotAuthorized
+            );
+            Ok(())
+        }
         ContentActor::Curator(curator_group_id, curator_id) => {
             let sender = ensure_signed(origin)?;
 
@@ -161,8 +173,54 @@ pub fn ensure_actor_authorized_to_update_or_delete_channel<T: Trait>(
         }
         // TODO:
         // ContentActor::Dao(_daoId) => ...,
-    }?;
-    Ok(())
+    }
+}
+
+pub fn ensure_actor_authorized_to_censor<T: Trait>(
+    origin: T::Origin,
+    actor: &ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
+    owner: &ChannelOwner<T::MemberId, T::CuratorGroupId, T::DAOId>,
+) -> DispatchResult {
+    // Only owner of a channel can update and delete it.
+    // Should we allow lead to also update and delete curator group owned channels,
+    // to avoid need for them to add themselves into the group?
+    match actor {
+        ContentActor::Lead => {
+            let sender = ensure_signed(origin)?;
+            ensure_lead_auth_success::<T>(&sender)?;
+            Ok(())
+        },
+        ContentActor::Curator(curator_group_id, curator_id) => {
+            let sender = ensure_signed(origin)?;
+
+            // Authorize curator, performing all checks to ensure curator can act
+            CuratorGroup::<T>::perform_curator_in_group_auth(
+                curator_id,
+                curator_group_id,
+                &sender,
+            )?;
+
+            // Curators cannot censor group channels
+            match owner {
+                ChannelOwner::CuratorGroup(_curator_group_id) => {
+                    Err(Error::<T>::CannotCensoreCuratorGroupOwnedChannels)
+                }
+                _ => Ok(())
+            }?;
+
+            Ok(())
+        }
+        ContentActor::Member(_member_id) => {
+            // Members cannot censore channels!
+            ensure!(
+                false,
+                Error::<T>::ActorNotAuthorized
+            );
+            Ok(())
+        }
+        // TODO:
+        // ContentActor::Dao(_daoId) => ...,
+    }
 }
 
 /// Enum, representing all possible `Actor`s