|
@@ -98,21 +98,11 @@ pub trait Trait:
|
|
|
|
|
|
/// The maximum number of curators per group constraint
|
|
|
type MaxNumberOfCuratorsPerGroup: Get<MaxNumber>;
|
|
|
-}
|
|
|
|
|
|
-/// Specifies how a new asset will be provided on creating and updating
|
|
|
-/// Channels, Videos, Series and Person
|
|
|
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
-#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub enum NewAssetsRecord<Balance> {
|
|
|
- /// Upload to the storage frame_system
|
|
|
- Upload(CreationUploadParameters<Balance>),
|
|
|
- /// Multiple url strings pointing at an asset
|
|
|
- Urls(Vec<AssetUrls>),
|
|
|
+ /// The storage type used
|
|
|
+ type DataObjectStorage: storage::DataObjectStorage<Self>;
|
|
|
}
|
|
|
|
|
|
-type NewAssets<T> = NewAssetsRecord<<T as balances::Trait>::Balance>;
|
|
|
-
|
|
|
/// The owner of a channel, is the authorized "actor" that can update
|
|
|
/// or delete or transfer a channel and its contents.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
@@ -179,8 +169,6 @@ pub struct ChannelRecord<MemberId, CuratorGroupId, AccountId> {
|
|
|
reward_account: Option<AccountId>,
|
|
|
/// Account for withdrawing deletion prize funds
|
|
|
deletion_prize_source_account_id: AccountId,
|
|
|
- /// Number of asset held in storage
|
|
|
- num_assets: u64,
|
|
|
}
|
|
|
|
|
|
// Channel alias type for simplification.
|
|
@@ -218,32 +206,37 @@ pub type ChannelOwnershipTransferRequest<T> = ChannelOwnershipTransferRequestRec
|
|
|
/// Information about channel being created.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct ChannelCreationParametersRecord<NewAssets, AccountId> {
|
|
|
+pub struct ChannelCreationParametersRecord<StorageAssets, AccountId> {
|
|
|
/// Asset collection for the channel, referenced by metadata
|
|
|
- assets: NewAssets,
|
|
|
+ assets: Option<StorageAssets>,
|
|
|
/// Metadata about the channel.
|
|
|
- meta: Vec<u8>,
|
|
|
+ meta: Option<Vec<u8>>,
|
|
|
/// optional reward account
|
|
|
reward_account: Option<AccountId>,
|
|
|
}
|
|
|
|
|
|
type ChannelCreationParameters<T> =
|
|
|
- ChannelCreationParametersRecord<NewAssets<T>, <T as frame_system::Trait>::AccountId>;
|
|
|
+ ChannelCreationParametersRecord<StorageAssets<T>, <T as frame_system::Trait>::AccountId>;
|
|
|
|
|
|
/// Information about channel being updated.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct ChannelUpdateParametersRecord<NewAssets, AccountId> {
|
|
|
+pub struct ChannelUpdateParametersRecord<StorageAssets, AccountId, DataObjectId: Ord> {
|
|
|
/// Asset collection for the channel, referenced by metadata
|
|
|
- assets: Option<NewAssets>,
|
|
|
+ assets_to_upload: Option<StorageAssets>,
|
|
|
/// If set, metadata update for the channel.
|
|
|
new_meta: Option<Vec<u8>>,
|
|
|
/// If set, updates the reward account of the channel
|
|
|
reward_account: Option<Option<AccountId>>,
|
|
|
+ /// assets to be removed from channel
|
|
|
+ assets_to_remove: BTreeSet<DataObjectId>,
|
|
|
}
|
|
|
|
|
|
-type ChannelUpdateParameters<T> =
|
|
|
- ChannelUpdateParametersRecord<NewAssets<T>, <T as frame_system::Trait>::AccountId>;
|
|
|
+type ChannelUpdateParameters<T> = ChannelUpdateParametersRecord<
|
|
|
+ StorageAssets<T>,
|
|
|
+ <T as frame_system::Trait>::AccountId,
|
|
|
+ DataObjectId<T>,
|
|
|
+>;
|
|
|
|
|
|
/// A category that videos can belong to.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
@@ -272,7 +265,7 @@ pub struct VideoCategoryUpdateParameters {
|
|
|
/// Information regarding the content being uploaded
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct CreationUploadParameters<Balance> {
|
|
|
+pub struct StorageAssetsRecord<Balance> {
|
|
|
/// Data object parameters.
|
|
|
pub object_creation_list: Vec<DataObjectCreationParameters>,
|
|
|
|
|
@@ -280,49 +273,47 @@ pub struct CreationUploadParameters<Balance> {
|
|
|
pub expected_data_size_fee: Balance,
|
|
|
}
|
|
|
|
|
|
+type StorageAssets<T> = StorageAssetsRecord<<T as balances::Trait>::Balance>;
|
|
|
+
|
|
|
/// Information about the video being created.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct VideoCreationParametersRecord<NewAssets> {
|
|
|
+pub struct VideoCreationParametersRecord<StorageAssets> {
|
|
|
/// Asset collection for the video
|
|
|
- assets: NewAssets,
|
|
|
+ assets: Option<StorageAssets>,
|
|
|
/// Metadata for the video.
|
|
|
- meta: Vec<u8>,
|
|
|
+ meta: Option<Vec<u8>>,
|
|
|
}
|
|
|
|
|
|
-type VideoCreationParameters<T> = VideoCreationParametersRecord<NewAssets<T>>;
|
|
|
+type VideoCreationParameters<T> = VideoCreationParametersRecord<StorageAssets<T>>;
|
|
|
|
|
|
/// Information about the video being updated
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct VideoUpdateParametersRecord<NewAssets> {
|
|
|
+pub struct VideoUpdateParametersRecord<StorageAssets, DataObjectId: Ord> {
|
|
|
/// Assets referenced by metadata
|
|
|
- assets: Option<NewAssets>,
|
|
|
+ assets_to_upload: Option<StorageAssets>,
|
|
|
/// If set, metadata update for the video.
|
|
|
new_meta: Option<Vec<u8>>,
|
|
|
+ /// video assets to be removed from channel
|
|
|
+ assets_to_remove: BTreeSet<DataObjectId>,
|
|
|
}
|
|
|
|
|
|
-type VideoUpdateParameters<T> = VideoUpdateParametersRecord<NewAssets<T>>;
|
|
|
+type VideoUpdateParameters<T> = VideoUpdateParametersRecord<StorageAssets<T>, DataObjectId<T>>;
|
|
|
|
|
|
/// A video which belongs to a channel. A video may be part of a series or playlist.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct VideoRecord<ChannelId, SeriesId, DataObjectId: Ord> {
|
|
|
+pub struct VideoRecord<ChannelId, SeriesId> {
|
|
|
pub in_channel: ChannelId,
|
|
|
// keep track of which season the video is in if it is an 'episode'
|
|
|
// - prevent removing a video if it is in a season (because order is important)
|
|
|
pub in_series: Option<SeriesId>,
|
|
|
/// Whether the curators have censored the video or not.
|
|
|
pub is_censored: bool,
|
|
|
- /// storage parameters used during deletion
|
|
|
- pub maybe_data_objects_id_set: Option<BTreeSet<DataObjectId>>,
|
|
|
}
|
|
|
|
|
|
-type Video<T> = VideoRecord<
|
|
|
- <T as storage::Trait>::ChannelId,
|
|
|
- <T as Trait>::SeriesId,
|
|
|
- <T as storage::Trait>::DataObjectId,
|
|
|
->;
|
|
|
+type Video<T> = VideoRecord<<T as storage::Trait>::ChannelId, <T as Trait>::SeriesId>;
|
|
|
|
|
|
/// Information about the plyalist being created.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
@@ -352,9 +343,9 @@ pub struct Playlist<ChannelId> {
|
|
|
/// Information about the episode being created or updated.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub enum EpisodeParameters<VideoId, NewAssets> {
|
|
|
+pub enum EpisodeParameters<VideoId, StorageAssets> {
|
|
|
/// A new video is being added as the episode.
|
|
|
- NewVideo(VideoCreationParametersRecord<NewAssets>),
|
|
|
+ NewVideo(VideoCreationParametersRecord<StorageAssets>),
|
|
|
/// An existing video is being made into an episode.
|
|
|
ExistingVideo(VideoId),
|
|
|
}
|
|
@@ -362,15 +353,15 @@ pub enum EpisodeParameters<VideoId, NewAssets> {
|
|
|
/// Information about the season being created or updated.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct SeasonParameters<VideoId, NewAssets> {
|
|
|
+pub struct SeasonParameters<VideoId, StorageAssets> {
|
|
|
/// Season assets referenced by metadata
|
|
|
- assets: Option<NewAssets>,
|
|
|
+ assets: Option<StorageAssets>,
|
|
|
// ?? It might just be more straighforward to always provide full list of episodes at cost of larger tx.
|
|
|
/// If set, updates the episodes of a season. Extends the number of episodes in a season
|
|
|
/// when length of new_episodes is greater than previously set. Last elements must all be
|
|
|
/// 'Some' in that case.
|
|
|
/// Will truncate existing season when length of new_episodes is less than previously set.
|
|
|
- episodes: Option<Vec<Option<EpisodeParameters<VideoId, NewAssets>>>>,
|
|
|
+ episodes: Option<Vec<Option<EpisodeParameters<VideoId, StorageAssets>>>>,
|
|
|
|
|
|
meta: Option<Vec<u8>>,
|
|
|
}
|
|
@@ -378,14 +369,14 @@ pub struct SeasonParameters<VideoId, NewAssets> {
|
|
|
/// Information about the series being created or updated.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct SeriesParameters<VideoId, NewAssets> {
|
|
|
+pub struct SeriesParameters<VideoId, StorageAssets> {
|
|
|
/// Series assets referenced by metadata
|
|
|
- assets: Option<NewAssets>,
|
|
|
+ assets: Option<StorageAssets>,
|
|
|
// ?? It might just be more straighforward to always provide full list of seasons at cost of larger tx.
|
|
|
/// If set, updates the seasons of a series. Extend a series when length of seasons is
|
|
|
/// greater than previoulsy set. Last elements must all be 'Some' in that case.
|
|
|
/// Will truncate existing series when length of seasons is less than previously set.
|
|
|
- seasons: Option<Vec<Option<SeasonParameters<VideoId, NewAssets>>>>,
|
|
|
+ seasons: Option<Vec<Option<SeasonParameters<VideoId, StorageAssets>>>>,
|
|
|
meta: Option<Vec<u8>>,
|
|
|
}
|
|
|
|
|
@@ -433,9 +424,9 @@ impl<MemberId: Default> Default for PersonController<MemberId> {
|
|
|
/// Information for Person being created.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct PersonCreationParameters<NewAssets> {
|
|
|
+pub struct PersonCreationParameters<StorageAssets> {
|
|
|
/// Assets referenced by metadata
|
|
|
- assets: NewAssets,
|
|
|
+ assets: StorageAssets,
|
|
|
/// Metadata for person.
|
|
|
meta: Vec<u8>,
|
|
|
}
|
|
@@ -443,9 +434,9 @@ pub struct PersonCreationParameters<NewAssets> {
|
|
|
/// Information for Persion being updated.
|
|
|
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
|
|
|
#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)]
|
|
|
-pub struct PersonUpdateParameters<NewAssets> {
|
|
|
+pub struct PersonUpdateParameters<StorageAssets> {
|
|
|
/// Assets referenced by metadata
|
|
|
- assets: Option<NewAssets>,
|
|
|
+ assets: Option<StorageAssets>,
|
|
|
/// Metadata to update person.
|
|
|
new_meta: Option<Vec<u8>>,
|
|
|
}
|
|
@@ -458,6 +449,8 @@ pub struct Person<MemberId> {
|
|
|
controlled_by: PersonController<MemberId>,
|
|
|
}
|
|
|
|
|
|
+type DataObjectId<T> = <T as storage::Trait>::DataObjectId;
|
|
|
+
|
|
|
decl_storage! {
|
|
|
trait Store for Module<T: Trait> as Content {
|
|
|
pub ChannelById get(fn channel_by_id): map hasher(blake2_128_concat) T::ChannelId => Channel<T>;
|
|
@@ -651,27 +644,17 @@ decl_module! {
|
|
|
// The channel owner will be..
|
|
|
let channel_owner = Self::actor_to_channel_owner(&actor)?;
|
|
|
|
|
|
-
|
|
|
// next channel id
|
|
|
let channel_id = NextChannelId::<T>::get();
|
|
|
|
|
|
- // get uploading parameters if assets have to be saved on storage
|
|
|
- let maybe_upload_parameters = Self::pick_upload_parameters_from_assets(
|
|
|
- ¶ms.assets,
|
|
|
- &channel_id,
|
|
|
- &sender,
|
|
|
- );
|
|
|
-
|
|
|
- // number of assets succesfully uploaded
|
|
|
- let num_assets = maybe_upload_parameters
|
|
|
- .map_or(Ok(0u64), |upload_parameters| {
|
|
|
- Storage::<T>::upload_data_objects(upload_parameters.clone())
|
|
|
- .map(|_| {
|
|
|
- upload_parameters
|
|
|
- .object_creation_list
|
|
|
- .len() as u64
|
|
|
- })
|
|
|
- })?;
|
|
|
+ // atomically upload to storage and return the # of uploaded assets
|
|
|
+ if let Some(upload_assets) = params.assets.as_ref() {
|
|
|
+ Self::upload_assets_to_storage(
|
|
|
+ upload_assets,
|
|
|
+ &channel_id,
|
|
|
+ &sender,
|
|
|
+ )?;
|
|
|
+ }
|
|
|
|
|
|
//
|
|
|
// == MUTATION SAFE ==
|
|
@@ -687,8 +670,6 @@ decl_module! {
|
|
|
num_videos: 0u64,
|
|
|
is_censored: false,
|
|
|
reward_account: params.reward_account.clone(),
|
|
|
- // number of assets uploaded
|
|
|
- num_assets,
|
|
|
// setting the channel owner account as the prize funds account
|
|
|
deletion_prize_source_account_id: sender,
|
|
|
};
|
|
@@ -707,8 +688,6 @@ decl_module! {
|
|
|
channel_id: T::ChannelId,
|
|
|
params: ChannelUpdateParameters<T>,
|
|
|
) {
|
|
|
- let sender = ensure_signed(origin.clone())?;
|
|
|
-
|
|
|
// check that channel exists
|
|
|
let channel = Self::ensure_channel_exists(&channel_id)?;
|
|
|
|
|
@@ -718,23 +697,17 @@ decl_module! {
|
|
|
&channel.owner,
|
|
|
)?;
|
|
|
|
|
|
- let maybe_upload_parameters = params.assets.clone()
|
|
|
- .and_then(|assets| {Self::pick_upload_parameters_from_assets(
|
|
|
- &assets,
|
|
|
+ Self::remove_assets_from_storage(¶ms.assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
|
|
|
+
|
|
|
+ // atomically upload to storage and return the # of uploaded assets
|
|
|
+ if let Some(upload_assets) = params.assets_to_upload.as_ref() {
|
|
|
+ Self::upload_assets_to_storage(
|
|
|
+ upload_assets,
|
|
|
&channel_id,
|
|
|
- &sender,
|
|
|
- )});
|
|
|
-
|
|
|
- // number of assets succesfully uploaded
|
|
|
- let maybe_num_assets = maybe_upload_parameters.as_ref()
|
|
|
- .map_or(
|
|
|
- Ok(Some(0u64)),
|
|
|
- |upload_parameters| {
|
|
|
- Storage::<T>::upload_data_objects(upload_parameters.clone())
|
|
|
- .map(|_| {
|
|
|
- Some(upload_parameters.object_creation_list.len() as u64)
|
|
|
- })
|
|
|
- })?;
|
|
|
+ &channel.deletion_prize_source_account_id
|
|
|
+ )?;
|
|
|
+ }
|
|
|
+
|
|
|
//
|
|
|
// == MUTATION SAFE ==
|
|
|
//
|
|
@@ -746,23 +719,19 @@ decl_module! {
|
|
|
channel.reward_account = reward_account.clone();
|
|
|
}
|
|
|
|
|
|
- // Maybe update asset num
|
|
|
- if let Some(num_assets) = maybe_num_assets {
|
|
|
- channel.num_assets = channel.num_assets.saturating_add(num_assets);
|
|
|
- }
|
|
|
-
|
|
|
// Update the channel
|
|
|
ChannelById::<T>::insert(channel_id, channel.clone());
|
|
|
|
|
|
Self::deposit_event(RawEvent::ChannelUpdated(actor, channel_id, channel, params));
|
|
|
}
|
|
|
|
|
|
- // extrinsics for channel deletion
|
|
|
+ // extrinsics for channel deletion
|
|
|
#[weight = 10_000_000] // TODO: adjust weight
|
|
|
pub fn delete_channel(
|
|
|
origin,
|
|
|
actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
|
|
|
channel_id: T::ChannelId,
|
|
|
+ num_objects_to_delete: u64,
|
|
|
) -> DispatchResult {
|
|
|
// check that channel exists
|
|
|
let channel = Self::ensure_channel_exists(&channel_id)?;
|
|
@@ -774,74 +743,49 @@ decl_module! {
|
|
|
&channel.owner,
|
|
|
)?;
|
|
|
|
|
|
- // check that channel assets are 0
|
|
|
- ensure!(channel.num_assets == 0, Error::<T>::ChannelContainsAssets);
|
|
|
-
|
|
|
// check that channel videos are 0
|
|
|
ensure!(channel.num_videos == 0, Error::<T>::ChannelContainsVideos);
|
|
|
|
|
|
- // delete channel dynamic bag
|
|
|
+ // get bag id for the channel
|
|
|
let dyn_bag = DynamicBagIdType::<T::MemberId, T::ChannelId>::Channel(channel_id);
|
|
|
- Storage::<T>::delete_dynamic_bag(
|
|
|
- channel.deletion_prize_source_account_id,
|
|
|
- dyn_bag
|
|
|
- )?;
|
|
|
-
|
|
|
- // remove channel from on chain state
|
|
|
- ChannelById::<T>::remove(channel_id);
|
|
|
-
|
|
|
- // deposit event
|
|
|
- Self::deposit_event(RawEvent::ChannelDeleted(actor, channel_id));
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- /// Remove assets of a channel from storage
|
|
|
- #[weight = 10_000_000] // TODO: adjust weight
|
|
|
- pub fn remove_channel_assets(
|
|
|
- origin,
|
|
|
- actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
|
|
|
- channel_id: T::ChannelId,
|
|
|
- assets: BTreeSet<<T as storage::Trait>::DataObjectId>,
|
|
|
- ) {
|
|
|
- // check that channel exists
|
|
|
- let channel = Self::ensure_channel_exists(&channel_id)?;
|
|
|
-
|
|
|
- ensure_actor_authorized_to_update_channel::<T>(
|
|
|
- origin,
|
|
|
- &actor,
|
|
|
- &channel.owner,
|
|
|
- )?;
|
|
|
-
|
|
|
- // ensure that the provided assets are not empty
|
|
|
- ensure!(!assets.is_empty(), Error::<T>::NoAssetsSpecified);
|
|
|
-
|
|
|
- let num_assets_to_remove = assets.len() as u64;
|
|
|
-
|
|
|
- // cannot remove more asset than those already present
|
|
|
- ensure!(
|
|
|
- num_assets_to_remove <= channel.num_assets,
|
|
|
- Error::<T>::InvalidAssetsProvided
|
|
|
- );
|
|
|
+ let bag_id = storage::BagIdType::from(dyn_bag.clone());
|
|
|
+
|
|
|
+ // channel has a dynamic bag associated to it -> remove assets from storage
|
|
|
+ if let Ok(bag) = T::DataObjectStorage::ensure_bag_exists(&bag_id) {
|
|
|
+ // ensure that bag size provided is valid
|
|
|
+ ensure!(
|
|
|
+ bag.objects_number == num_objects_to_delete,
|
|
|
+ Error::<T>::InvalidBagSizeSpecified
|
|
|
+ );
|
|
|
+
|
|
|
+ // construct collection of assets to be removed
|
|
|
+ let assets_to_remove = T::DataObjectStorage::get_data_objects_id(&bag_id);
|
|
|
+
|
|
|
+ // remove specified assets from storage
|
|
|
+ Self::remove_assets_from_storage(
|
|
|
+ &assets_to_remove,
|
|
|
+ &channel_id,
|
|
|
+ &channel.deletion_prize_source_account_id
|
|
|
+ )?;
|
|
|
|
|
|
- // remove assets from storage
|
|
|
- Storage::<T>::delete_data_objects(
|
|
|
- channel.deletion_prize_source_account_id.clone(),
|
|
|
- Self::bag_id_for_channel(&channel_id),
|
|
|
- assets.clone(),
|
|
|
- )?;
|
|
|
+ // delete channel dynamic bag
|
|
|
+ Storage::<T>::delete_dynamic_bag(
|
|
|
+ channel.deletion_prize_source_account_id,
|
|
|
+ dyn_bag
|
|
|
+ )?;
|
|
|
+ }
|
|
|
|
|
|
//
|
|
|
// == MUTATION SAFE ==
|
|
|
//
|
|
|
|
|
|
- // update onchain channel status
|
|
|
- let mut channel = channel;
|
|
|
- channel.num_assets = channel.num_assets.saturating_sub(num_assets_to_remove);
|
|
|
- ChannelById::<T>::insert(channel_id, channel.clone());
|
|
|
+ // remove channel from on chain state
|
|
|
+ ChannelById::<T>::remove(channel_id);
|
|
|
|
|
|
+ // deposit event
|
|
|
+ Self::deposit_event(RawEvent::ChannelDeleted(actor, channel_id));
|
|
|
|
|
|
- Self::deposit_event(RawEvent::ChannelAssetsRemoved(actor, channel_id, assets, channel));
|
|
|
+ Ok(())
|
|
|
}
|
|
|
|
|
|
#[weight = 10_000_000] // TODO: adjust weight
|
|
@@ -974,8 +918,6 @@ decl_module! {
|
|
|
params: VideoCreationParameters<T>,
|
|
|
) {
|
|
|
|
|
|
- let sender = ensure_signed(origin.clone())?;
|
|
|
-
|
|
|
// check that channel exists
|
|
|
let channel = Self::ensure_channel_exists(&channel_id)?;
|
|
|
|
|
@@ -988,26 +930,14 @@ decl_module! {
|
|
|
// next video id
|
|
|
let video_id = NextVideoId::<T>::get();
|
|
|
|
|
|
- // adding the content to storage node if uploading is needed
|
|
|
- let maybe_upload_parameters = Self::pick_upload_parameters_from_assets(
|
|
|
- ¶ms.assets,
|
|
|
- &channel_id,
|
|
|
- &sender,
|
|
|
- );
|
|
|
-
|
|
|
- // if storaged uploading is required save t he object id for the video
|
|
|
- let maybe_data_objects_ids = maybe_upload_parameters
|
|
|
- .map_or(
|
|
|
- Ok(None),
|
|
|
- |upload_parameters| {
|
|
|
- // beginning object id
|
|
|
- let beg = Storage::<T>::next_data_object_id();
|
|
|
-
|
|
|
- // upload objects and return their indexes
|
|
|
- Storage::<T>::upload_data_objects(upload_parameters)
|
|
|
- .map(|_| Storage::<T>::next_data_object_id()) // ending index
|
|
|
- .map(|end| Some((beg..end).collect::<BTreeSet<_>>())) // create collection
|
|
|
- })?;
|
|
|
+ // atomically upload to storage and return the # of uploaded assets
|
|
|
+ if let Some(upload_assets) = params.assets.as_ref() {
|
|
|
+ Self::upload_assets_to_storage(
|
|
|
+ upload_assets,
|
|
|
+ &channel_id,
|
|
|
+ &channel.deletion_prize_source_account_id
|
|
|
+ )?;
|
|
|
+ }
|
|
|
|
|
|
//
|
|
|
// == MUTATION SAFE ==
|
|
@@ -1021,8 +951,6 @@ decl_module! {
|
|
|
in_series: None,
|
|
|
/// Whether the curators have censored the video or not.
|
|
|
is_censored: false,
|
|
|
- /// storage parameters for later storage deletion
|
|
|
- maybe_data_objects_id_set: maybe_data_objects_ids,
|
|
|
};
|
|
|
|
|
|
// add it to the onchain state
|
|
@@ -1047,40 +975,34 @@ decl_module! {
|
|
|
video_id: T::VideoId,
|
|
|
params: VideoUpdateParameters<T>,
|
|
|
) {
|
|
|
- let sender = ensure_signed(origin.clone())?;
|
|
|
-
|
|
|
// check that video exists, retrieve corresponding channel id.
|
|
|
- let channel_id = Self::ensure_video_exists(&video_id)?.in_channel;
|
|
|
+ let video = Self::ensure_video_exists(&video_id)?;
|
|
|
+
|
|
|
+ let channel_id = video.in_channel;
|
|
|
+ let channel = ChannelById::<T>::get(&channel_id);
|
|
|
|
|
|
ensure_actor_authorized_to_update_channel::<T>(
|
|
|
origin,
|
|
|
&actor,
|
|
|
- &Self::channel_by_id(channel_id).owner,
|
|
|
+ &channel.owner,
|
|
|
)?;
|
|
|
|
|
|
- // Pick the assets to be uploaded to storage frame_system out
|
|
|
- if let Some(assets) = ¶ms.assets {
|
|
|
- // adding content to storage if needed
|
|
|
- let maybe_upload_parameters = Self::pick_upload_parameters_from_assets(
|
|
|
- assets,
|
|
|
- &channel_id,
|
|
|
- &sender,
|
|
|
- );
|
|
|
-
|
|
|
- if let Some(upload_parameters) = maybe_upload_parameters{
|
|
|
- Storage::<T>::upload_data_objects(upload_parameters)?;
|
|
|
- }
|
|
|
+ // remove specified assets from channel bag in storage
|
|
|
+ Self::remove_assets_from_storage(¶ms.assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
|
|
|
+
|
|
|
+ // atomically upload to storage and return the # of uploaded assets
|
|
|
+ if let Some(upload_assets) = params.assets_to_upload.as_ref() {
|
|
|
+ Self::upload_assets_to_storage(
|
|
|
+ upload_assets,
|
|
|
+ &channel_id,
|
|
|
+ &channel.deletion_prize_source_account_id
|
|
|
+ )?;
|
|
|
}
|
|
|
|
|
|
//
|
|
|
// == MUTATION SAFE ==
|
|
|
//
|
|
|
|
|
|
- // increase the number of video the selected channel by 1
|
|
|
- ChannelById::<T>::mutate(channel_id, |channel| {
|
|
|
- channel.num_videos = channel.num_videos.saturating_add(1);
|
|
|
- });
|
|
|
-
|
|
|
Self::deposit_event(RawEvent::VideoUpdated(actor, video_id, params));
|
|
|
}
|
|
|
|
|
@@ -1089,6 +1011,7 @@ decl_module! {
|
|
|
origin,
|
|
|
actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
|
|
|
video_id: T::VideoId,
|
|
|
+ assets_to_remove: BTreeSet<DataObjectId<T>>,
|
|
|
) {
|
|
|
|
|
|
// check that video exists
|
|
@@ -1106,16 +1029,11 @@ decl_module! {
|
|
|
&channel.owner,
|
|
|
)?;
|
|
|
|
|
|
+ // ensure video can be removed
|
|
|
Self::ensure_video_can_be_removed(&video)?;
|
|
|
|
|
|
- // If video is on storage, remove it
|
|
|
- if let Some(data_objects_id_set) = video.maybe_data_objects_id_set {
|
|
|
- Storage::<T>::delete_data_objects(
|
|
|
- channel.deletion_prize_source_account_id,
|
|
|
- Self::bag_id_for_channel(&channel_id),
|
|
|
- data_objects_id_set,
|
|
|
- )?;
|
|
|
- }
|
|
|
+ // remove specified assets from channel bag in storage
|
|
|
+ Self::remove_assets_from_storage(&assets_to_remove, &channel_id, &channel.deletion_prize_source_account_id)?;
|
|
|
|
|
|
//
|
|
|
// == MUTATION SAFE ==
|
|
@@ -1244,7 +1162,7 @@ decl_module! {
|
|
|
pub fn create_person(
|
|
|
_origin,
|
|
|
_actor: PersonActor<T::MemberId, T::CuratorId>,
|
|
|
- _params: PersonCreationParameters<NewAssets<T>>,
|
|
|
+ _params: PersonCreationParameters<StorageAssets<T>>,
|
|
|
) {
|
|
|
Self::not_implemented()?;
|
|
|
}
|
|
@@ -1254,7 +1172,7 @@ decl_module! {
|
|
|
_origin,
|
|
|
_actor: PersonActor<T::MemberId, T::CuratorId>,
|
|
|
_person: T::PersonId,
|
|
|
- _params: PersonUpdateParameters<NewAssets<T>>,
|
|
|
+ _params: PersonUpdateParameters<StorageAssets<T>>,
|
|
|
) {
|
|
|
Self::not_implemented()?;
|
|
|
}
|
|
@@ -1326,7 +1244,7 @@ decl_module! {
|
|
|
_origin,
|
|
|
_actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
|
|
|
_channel_id: T::ChannelId,
|
|
|
- _params: SeriesParameters<T::VideoId, NewAssets<T>>
|
|
|
+ _params: SeriesParameters<T::VideoId, StorageAssets<T>>
|
|
|
) {
|
|
|
Self::not_implemented()?;
|
|
|
}
|
|
@@ -1336,7 +1254,7 @@ decl_module! {
|
|
|
_origin,
|
|
|
_actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
|
|
|
_channel_id: T::ChannelId,
|
|
|
- _params: SeriesParameters<T::VideoId, NewAssets<T>>
|
|
|
+ _params: SeriesParameters<T::VideoId, StorageAssets<T>>
|
|
|
) {
|
|
|
Self::not_implemented()?;
|
|
|
}
|
|
@@ -1415,28 +1333,24 @@ impl<T: Trait> Module<T> {
|
|
|
}
|
|
|
|
|
|
fn pick_upload_parameters_from_assets(
|
|
|
- assets: &NewAssets<T>,
|
|
|
+ assets: &StorageAssets<T>,
|
|
|
channel_id: &T::ChannelId,
|
|
|
- sender: &T::AccountId,
|
|
|
- ) -> Option<UploadParameters<T>> {
|
|
|
+ prize_source_account: &T::AccountId,
|
|
|
+ ) -> UploadParameters<T> {
|
|
|
// dynamic bag for a media object
|
|
|
let dyn_bag = DynamicBagIdType::<T::MemberId, T::ChannelId>::Channel(*channel_id);
|
|
|
let bag_id = BagIdType::from(dyn_bag.clone());
|
|
|
|
|
|
- if !storage::Bags::<T>::contains_key(bag_id.clone()) {
|
|
|
+ if T::DataObjectStorage::ensure_bag_exists(&bag_id).is_err() {
|
|
|
// create_dynamic_bag checks automatically satifsfied with None as second parameter
|
|
|
Storage::<T>::create_dynamic_bag(dyn_bag, None).unwrap();
|
|
|
}
|
|
|
|
|
|
- if let NewAssets::<T>::Upload(creation_upload_params) = assets {
|
|
|
- Some(UploadParametersRecord {
|
|
|
- bag_id,
|
|
|
- object_creation_list: creation_upload_params.object_creation_list.clone(),
|
|
|
- deletion_prize_source_account_id: sender.clone(),
|
|
|
- expected_data_size_fee: creation_upload_params.expected_data_size_fee,
|
|
|
- })
|
|
|
- } else {
|
|
|
- None
|
|
|
+ UploadParametersRecord {
|
|
|
+ bag_id,
|
|
|
+ object_creation_list: assets.object_creation_list.clone(),
|
|
|
+ deletion_prize_source_account_id: prize_source_account.clone(),
|
|
|
+ expected_data_size_fee: assets.expected_data_size_fee,
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1462,6 +1376,37 @@ impl<T: Trait> Module<T> {
|
|
|
fn not_implemented() -> DispatchResult {
|
|
|
Err(Error::<T>::FeatureNotImplemented.into())
|
|
|
}
|
|
|
+
|
|
|
+ fn upload_assets_to_storage(
|
|
|
+ assets: &StorageAssets<T>,
|
|
|
+ channel_id: &T::ChannelId,
|
|
|
+ prize_source_account: &T::AccountId,
|
|
|
+ ) -> DispatchResult {
|
|
|
+ // construct upload params
|
|
|
+ let upload_params =
|
|
|
+ Self::pick_upload_parameters_from_assets(assets, channel_id, prize_source_account);
|
|
|
+
|
|
|
+ // attempt to upload objects att
|
|
|
+ Storage::<T>::upload_data_objects(upload_params.clone())?;
|
|
|
+
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
+
|
|
|
+ fn remove_assets_from_storage(
|
|
|
+ assets: &BTreeSet<DataObjectId<T>>,
|
|
|
+ channel_id: &T::ChannelId,
|
|
|
+ prize_source_account: &T::AccountId,
|
|
|
+ ) -> DispatchResult {
|
|
|
+ // remove assets if any
|
|
|
+ if !assets.is_empty() {
|
|
|
+ Storage::<T>::delete_data_objects(
|
|
|
+ prize_source_account.clone(),
|
|
|
+ Self::bag_id_for_channel(&channel_id),
|
|
|
+ assets.clone(),
|
|
|
+ )?;
|
|
|
+ }
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
decl_event!(
|
|
@@ -1485,13 +1430,13 @@ decl_event!(
|
|
|
ChannelOwnershipTransferRequest = ChannelOwnershipTransferRequest<T>,
|
|
|
Series = Series<<T as storage::Trait>::ChannelId, <T as Trait>::VideoId>,
|
|
|
Channel = Channel<T>,
|
|
|
- DataObjectId = <T as storage::Trait>::DataObjectId,
|
|
|
+ DataObjectId = DataObjectId<T>,
|
|
|
IsCensored = bool,
|
|
|
ChannelCreationParameters = ChannelCreationParameters<T>,
|
|
|
ChannelUpdateParameters = ChannelUpdateParameters<T>,
|
|
|
VideoCreationParameters = VideoCreationParameters<T>,
|
|
|
VideoUpdateParameters = VideoUpdateParameters<T>,
|
|
|
- NewAssets = NewAssets<T>,
|
|
|
+ StorageAssets = StorageAssets<T>,
|
|
|
{
|
|
|
// Curators
|
|
|
CuratorGroupCreated(CuratorGroupId),
|
|
@@ -1565,15 +1510,15 @@ decl_event!(
|
|
|
SeriesCreated(
|
|
|
ContentActor,
|
|
|
SeriesId,
|
|
|
- NewAssets,
|
|
|
- SeriesParameters<VideoId, NewAssets>,
|
|
|
+ StorageAssets,
|
|
|
+ SeriesParameters<VideoId, StorageAssets>,
|
|
|
Series,
|
|
|
),
|
|
|
SeriesUpdated(
|
|
|
ContentActor,
|
|
|
SeriesId,
|
|
|
- NewAssets,
|
|
|
- SeriesParameters<VideoId, NewAssets>,
|
|
|
+ StorageAssets,
|
|
|
+ SeriesParameters<VideoId, StorageAssets>,
|
|
|
Series,
|
|
|
),
|
|
|
SeriesDeleted(ContentActor, SeriesId),
|
|
@@ -1582,14 +1527,14 @@ decl_event!(
|
|
|
PersonCreated(
|
|
|
ContentActor,
|
|
|
PersonId,
|
|
|
- NewAssets,
|
|
|
- PersonCreationParameters<NewAssets>,
|
|
|
+ StorageAssets,
|
|
|
+ PersonCreationParameters<StorageAssets>,
|
|
|
),
|
|
|
PersonUpdated(
|
|
|
ContentActor,
|
|
|
PersonId,
|
|
|
- NewAssets,
|
|
|
- PersonUpdateParameters<NewAssets>,
|
|
|
+ StorageAssets,
|
|
|
+ PersonUpdateParameters<StorageAssets>,
|
|
|
),
|
|
|
PersonDeleted(ContentActor, PersonId),
|
|
|
ChannelDeleted(ContentActor, ChannelId),
|