Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subscriptions pallet #147

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
26 changes: 24 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions integration-tests/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ impl pallet_posts::Config for TestRuntime {
impl pallet_profiles::Config for TestRuntime {
type Event = Event;
type SpacePermissionsProvider = Spaces;
type SpaceInterface = Spaces;
}

impl pallet_reactions::Config for TestRuntime {
Expand Down
6 changes: 3 additions & 3 deletions integration-tests/src/utils/spaces_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,23 @@ pub(crate) fn space_update(
}
}

pub(crate) fn _create_default_space() -> DispatchResultWithPostInfo {
pub(crate) fn _create_default_space() -> DispatchResult {
_create_space(None, None, None)
}

pub(crate) fn _create_space(
origin: Option<Origin>,
content: Option<Content>,
permissions: Option<Option<SpacePermissions>>
) -> DispatchResultWithPostInfo {
) -> DispatchResult {
Spaces::create_space(
origin.unwrap_or_else(|| Origin::signed(ACCOUNT1)),
content.unwrap_or_else(space_content_ipfs),
permissions.unwrap_or_default()
)
}

pub(crate) fn _create_space_with_content(content: Content) -> DispatchResultWithPostInfo {
pub(crate) fn _create_space_with_content(content: Content) -> DispatchResult {
_create_space(None, Some(content), None)
}

Expand Down
22 changes: 20 additions & 2 deletions pallets/profiles/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ pub mod pallet {

use pallet_permissions::SpacePermissions;
use subsocial_support::{
traits::{ProfileManager, SpacePermissionsProvider},
SpaceId, SpacePermissionsInfo,
traits::{ProfileManager, SpacePermissionsProvider, SpacesInterface},
Content, SpaceId, SpacePermissionsInfo,
};

type SpacePermissionsInfoOf<T> =
Expand All @@ -27,6 +27,8 @@ pub mod pallet {
Self::AccountId,
SpacePermissionsInfoOf<Self>,
>;

type SpaceInterface: SpacesInterface<Self::AccountId, SpaceId>;
}

#[pallet::pallet]
Expand Down Expand Up @@ -85,6 +87,22 @@ pub mod pallet {
Ok(())
}

#[pallet::weight(10_250_000 + T::DbWeight::get().reads_writes(3, 4))]
pub fn create_space_as_profile(origin: OriginFor<T>, content: Content) -> DispatchResult {
let sender = ensure_signed(origin)?;

let space_id = T::SpaceInterface::create_space(&sender, content)?;

Self::do_set_profile(&sender, space_id)?;

Self::deposit_event(Event::ProfileUpdated {
account: sender,
space_id: Some(space_id),
});

Ok(())
}

#[pallet::weight((
10_000 + T::DbWeight::get().writes(1),
DispatchClass::Operational,
Expand Down
97 changes: 95 additions & 2 deletions pallets/roles/src/functions.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use super::*;

use frame_support::dispatch::DispatchError;

use pallet_permissions::SpacePermissionsContext;
use subsocial_support::traits::RolesInterface;

use super::*;

impl<T: Config> Pallet<T> {
/// Check that there is a `Role` with such `role_id` in the storage
Expand Down Expand Up @@ -109,6 +111,74 @@ impl<T: Config> Pallet<T> {

Err(error)
}

pub fn do_create_role(
space_owner: &T::AccountId,
space_id: SpaceId,
time_to_live: Option<T::BlockNumber>,
content: Content,
permissions: Vec<SpacePermission>,
) -> Result<RoleId, DispatchError> {
ensure!(!permissions.is_empty(), Error::<T>::NoPermissionsProvided);

ensure_content_is_valid(content.clone())?;
ensure!(
T::IsContentBlocked::is_allowed_content(content.clone(), space_id),
ModerationError::ContentIsBlocked,
);

Self::ensure_role_manager(space_owner.clone(), space_id)?;

let permissions_set = permissions.into_iter().collect();
let new_role =
Role::<T>::new(space_owner.clone(), space_id, time_to_live, content, permissions_set)?;

// TODO review strange code:
let next_role_id = new_role.id.checked_add(1).ok_or(Error::<T>::RoleIdOverflow)?;
NextRoleId::<T>::put(next_role_id);

RoleById::<T>::insert(new_role.id, new_role.clone());
RoleIdsBySpaceId::<T>::mutate(space_id, |role_ids| role_ids.push(new_role.id));

Ok(new_role.id)
}

pub fn do_grant_role(
manager: Option<T::AccountId>,
role_id: RoleId,
users: Vec<User<T::AccountId>>,
) -> DispatchResult {
let users_set: BTreeSet<User<T::AccountId>> = convert_users_vec_to_btree_set(users)?;

let role = Self::require_role(role_id)?;

if let Some(who) = manager.clone() {
Self::ensure_role_manager(who, role.space_id)?;
}

for user in users_set.iter() {
if !Self::users_by_role_id(role_id).contains(user) {
<UsersByRoleId<T>>::mutate(role_id, |users| {
users.push(user.clone());
});
}
if !Self::role_ids_by_user_in_space(user.clone(), role.space_id).contains(&role_id) {
<RoleIdsByUserInSpace<T>>::mutate(user.clone(), role.space_id, |roles| {
roles.push(role_id);
})
}
}

Self::deposit_event(Event::RoleGranted {
account: manager.unwrap_or_else(|| {
T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap()
}),
role_id,
users: users_set.iter().cloned().collect(),
});

Ok(())
}
}

impl<T: Config> Role<T> {
Expand Down Expand Up @@ -185,3 +255,26 @@ impl<T: Config> PermissionChecker for Pallet<T> {
Self::ensure_user_has_space_permission(user, ctx, permission, error)
}
}

impl<T: Config> RolesInterface<RoleId, SpaceId, T::AccountId, SpacePermission, T::BlockNumber>
for Pallet<T>
{
fn get_role_space(role_id: RoleId) -> Result<SpaceId, DispatchError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn get_role_space(role_id: RoleId) -> Result<SpaceId, DispatchError> {
fn get_role_space_id(role_id: RoleId) -> Result<SpaceId, DispatchError> {

let role = Pallet::<T>::require_role(role_id)?;
Ok(role.space_id)
}

fn grant_role(account_id: T::AccountId, role_id: RoleId) -> DispatchResult {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We always use just account or a descriptive name for a specific account.

Suggested change
fn grant_role(account_id: T::AccountId, role_id: RoleId) -> DispatchResult {
fn grant_role(account: T::AccountId, role_id: RoleId) -> DispatchResult {

Pallet::<T>::do_grant_role(None, role_id, vec![User::Account(account_id)])
}

fn create_role(
space_owner: &T::AccountId,
space_id: SpaceId,
time_to_live: Option<T::BlockNumber>,
content: Content,
permissions: Vec<SpacePermission>,
) -> Result<RoleId, DispatchError> {
Pallet::<T>::do_create_role(space_owner, space_id, time_to_live, content, permissions)
}
}
64 changes: 11 additions & 53 deletions pallets/roles/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
#![cfg_attr(not(feature = "std"), no_std)]

use codec::{Decode, Encode};
use frame_support::{dispatch::DispatchResult, ensure, traits::Get};
use frame_system::{self as system, ensure_signed};
use frame_support::{dispatch::DispatchResult, ensure};
use frame_system as system;
use scale_info::TypeInfo;
use sp_runtime::RuntimeDebug;
use sp_std::{collections::btree_set::BTreeSet, prelude::*};

pub use pallet::*;
use pallet_permissions::{
Pallet as Permissions, PermissionChecker, SpacePermission, SpacePermissionSet,
};
Expand All @@ -25,12 +26,11 @@ use subsocial_support::{
traits::{IsAccountBlocked, IsContentBlocked, SpaceFollowsProvider, SpacePermissionsProvider},
Content, ModerationError, SpaceId, User, WhoAndWhenOf,
};
pub use types::*;

pub use pallet::*;
pub mod functions;

pub mod types;
pub use types::*;
// pub mod rpc;

#[cfg(test)]
Expand All @@ -41,12 +41,14 @@ mod tests;

#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

use pallet_permissions::SpacePermissionsInfoOf;
use subsocial_support::{remove_from_vec, WhoAndWhen};

use super::*;

#[pallet::config]
pub trait Config:
frame_system::Config + pallet_permissions::Config + pallet_timestamp::Config
Expand Down Expand Up @@ -180,32 +182,10 @@ pub mod pallet {
) -> DispatchResult {
let who = ensure_signed(origin)?;

ensure!(!permissions.is_empty(), Error::<T>::NoPermissionsProvided);

ensure_content_is_valid(content.clone())?;
ensure!(
T::IsContentBlocked::is_allowed_content(content.clone(), space_id),
ModerationError::ContentIsBlocked,
);

Self::ensure_role_manager(who.clone(), space_id)?;

let permissions_set = permissions.into_iter().collect();
let new_role =
Role::<T>::new(who.clone(), space_id, time_to_live, content, permissions_set)?;

// TODO review strange code:
let next_role_id = new_role.id.checked_add(1).ok_or(Error::<T>::RoleIdOverflow)?;
NextRoleId::<T>::put(next_role_id);
let role_id =
Pallet::<T>::do_create_role(&who, space_id, time_to_live, content, permissions)?;

RoleById::<T>::insert(new_role.id, new_role.clone());
RoleIdsBySpaceId::<T>::mutate(space_id, |role_ids| role_ids.push(new_role.id));

Self::deposit_event(Event::RoleCreated {
account: who,
space_id,
role_id: new_role.id,
});
Self::deposit_event(Event::RoleCreated { account: who, space_id, role_id });
Ok(())
}

Expand Down Expand Up @@ -313,31 +293,9 @@ pub mod pallet {
let who = ensure_signed(origin)?;

ensure!(!users.is_empty(), Error::<T>::NoUsersProvided);
let users_set: BTreeSet<User<T::AccountId>> = convert_users_vec_to_btree_set(users)?;

let role = Self::require_role(role_id)?;

Self::ensure_role_manager(who.clone(), role.space_id)?;

for user in users_set.iter() {
if !Self::users_by_role_id(role_id).contains(user) {
<UsersByRoleId<T>>::mutate(role_id, |users| {
users.push(user.clone());
});
}
if !Self::role_ids_by_user_in_space(user.clone(), role.space_id).contains(&role_id)
{
<RoleIdsByUserInSpace<T>>::mutate(user.clone(), role.space_id, |roles| {
roles.push(role_id);
})
}
}
Pallet::<T>::do_grant_role(Some(who), role_id, users)?;

Self::deposit_event(Event::RoleGranted {
account: who,
role_id,
users: users_set.iter().cloned().collect(),
});
Ok(())
}

Expand Down
Loading