This repository has been archived by the owner on Sep 22, 2022. It is now read-only.
forked from substrate-developer-hub/substrate-node-template
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from F3Joule/f3-pallet-permissions
Loose coupling of pallets: Roles + Social
- Loading branch information
Showing
29 changed files
with
1,079 additions
and
4,075 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,164 @@ | ||
#![cfg_attr(not(feature = "std"), no_std)] | ||
|
||
use sp_std::prelude::*; | ||
use sp_std::collections::btree_set::BTreeSet; | ||
use sp_std::{ | ||
prelude::*, | ||
collections::btree_set::BTreeSet | ||
}; | ||
use codec::{Encode, Decode}; | ||
use frame_support::{decl_module, traits::Get}; | ||
use frame_support::{ | ||
decl_module, | ||
traits::Get | ||
}; | ||
use sp_runtime::RuntimeDebug; | ||
|
||
use pallet_utils::SpaceId; | ||
|
||
#[derive(Encode, Decode, Ord, PartialOrd, Clone, Eq, PartialEq, RuntimeDebug)] | ||
pub enum SpacePermission { | ||
/// Create, update, grant and revoke roles in this space. | ||
ManageRoles, | ||
/// Create, update own and delete any subspaces in this space. | ||
ManageSubspaces, | ||
/// Create, update own and delete any root posts in this space. | ||
ManagePosts, | ||
/// Create, update own and delete any comments in this space. | ||
ManageComments, | ||
|
||
/// Act on behalf of this space within this space. | ||
RepresentSpaceInternally, | ||
/// Act on behalf of this space outside of this space. | ||
RepresentSpaceExternally, | ||
|
||
UpdateSpace, | ||
BlockUsers, // or BlockUsers | ||
|
||
// TODO what about 'DeleteSpace'? (too dangerous) | ||
BlockUsers, | ||
|
||
// Related to subspaces in this space: | ||
CreateSubspaces, | ||
UpdateOwnSubspaces, | ||
UpdateAnySubspaces, | ||
DeleteOwnSubspaces, | ||
DeleteAnySubspaces, | ||
BlockSubspaces, | ||
|
||
// Related to posts in this space: | ||
CreatePosts, | ||
UpdateOwnPosts, | ||
UpdateAnyPosts, | ||
DeleteOwnPosts, | ||
DeleteAnyPosts, | ||
BlockPosts, | ||
|
||
// Related to comments in this space: | ||
CreateComments, | ||
UpdateOwnComments, | ||
DeleteOwnComments, | ||
DeleteAnyComments, | ||
BlockComments, | ||
|
||
/// Upvote on any post or comment in this space. | ||
Upvote, | ||
/// Upvote on any post or comment in this space. | ||
Downvote, | ||
/// Share any post or comment from this space to another outer space. | ||
Share, | ||
|
||
OverridePostPermissions, | ||
} | ||
|
||
#[derive(Encode, Decode, Ord, PartialOrd, Clone, Eq, PartialEq, RuntimeDebug)] | ||
pub enum PostPermission { | ||
// Related to comments on this post: | ||
CreateComments, | ||
UpdateOwnComments, | ||
DeleteOwnComments, | ||
pub type SpacePermissionSet = BTreeSet<SpacePermission>; | ||
|
||
// Related to this post and its comments: | ||
Upvote, | ||
Downvote, | ||
Share, | ||
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)] | ||
pub struct SpacePermissions { | ||
pub none: Option<SpacePermissionSet>, | ||
pub everyone: Option<SpacePermissionSet>, | ||
pub follower: Option<SpacePermissionSet>, | ||
pub space_owner: Option<SpacePermissionSet>, | ||
} | ||
|
||
impl Default for SpacePermissions { | ||
fn default() -> SpacePermissions { | ||
SpacePermissions { | ||
none: None, | ||
everyone: None, | ||
follower: None, | ||
space_owner: None, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)] | ||
pub struct SpacePermissionsContext { | ||
pub space_id: SpaceId, | ||
pub is_space_owner: bool, | ||
pub is_space_follower: bool, | ||
pub space_perms: Option<SpacePermissions> | ||
} | ||
|
||
/// The pallet's configuration trait. | ||
pub trait Trait: system::Trait { | ||
type DefaultEveryoneSpacePermissions: Get<BTreeSet<SpacePermission>>; | ||
|
||
type DefaultFollowerSpacePermissions: Get<BTreeSet<SpacePermission>>; | ||
type DefaultSpacePermissions: Get<SpacePermissions>; | ||
} | ||
|
||
decl_module! { | ||
pub struct Module<T: Trait> for enum Call where origin: T::Origin { | ||
const DefaultEveryoneSpacePermissions: BTreeSet<SpacePermission> = T::DefaultEveryoneSpacePermissions::get(); | ||
const DefaultSpacePermissions: SpacePermissions = T::DefaultSpacePermissions::get(); | ||
} | ||
} | ||
|
||
const DefaultFollowerSpacePermissions: BTreeSet<SpacePermission> = T::DefaultFollowerSpacePermissions::get(); | ||
impl SpacePermission { | ||
fn is_present_in_role(&self, perms_opt: Option<SpacePermissionSet>) -> bool { | ||
if let Some(perms) = perms_opt { | ||
if perms.contains(self) { | ||
return true | ||
} | ||
} | ||
false | ||
} | ||
} | ||
|
||
impl<T: Trait> Module<T> { | ||
|
||
fn get_overrides_or_defaults( | ||
overrides: Option<SpacePermissionSet>, | ||
defaults: Option<SpacePermissionSet> | ||
) -> Option<SpacePermissionSet> { | ||
|
||
return if overrides.is_some() { | ||
overrides | ||
} else { | ||
defaults | ||
} | ||
} | ||
|
||
fn resolve_space_perms( | ||
space_perms: Option<SpacePermissions>, | ||
) -> SpacePermissions { | ||
|
||
let defaults = T::DefaultSpacePermissions::get(); | ||
let overrides = space_perms.unwrap_or_default(); | ||
|
||
SpacePermissions { | ||
none: Self::get_overrides_or_defaults(overrides.none, defaults.none), | ||
everyone: Self::get_overrides_or_defaults(overrides.everyone, defaults.everyone), | ||
follower: Self::get_overrides_or_defaults(overrides.follower, defaults.follower), | ||
space_owner: Self::get_overrides_or_defaults(overrides.space_owner, defaults.space_owner) | ||
} | ||
} | ||
|
||
pub fn has_user_a_space_permission( | ||
ctx: SpacePermissionsContext, | ||
permission: SpacePermission, | ||
) -> Option<bool> { | ||
|
||
let perms_by_role = Self::resolve_space_perms(ctx.space_perms); | ||
|
||
// Check if this permission is forbidden: | ||
if permission.is_present_in_role(perms_by_role.none) { | ||
return Some(false) | ||
} | ||
|
||
let is_space_owner = ctx.is_space_owner; | ||
let is_follower = is_space_owner || ctx.is_space_follower; | ||
|
||
if | ||
permission.is_present_in_role(perms_by_role.everyone) || | ||
is_follower && permission.is_present_in_role(perms_by_role.follower) || | ||
is_space_owner && permission.is_present_in_role(perms_by_role.space_owner) | ||
{ | ||
return Some(true) | ||
} | ||
|
||
None | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,45 @@ | ||
{ | ||
"SpacePermission":{ | ||
"_enum":[ | ||
"SpacePermissionSet": "BTreeSet<SpacePermission>", | ||
|
||
"SpacePermission": { | ||
"_enum": [ | ||
"ManageRoles", | ||
"ManageSubspaces", | ||
"ManagePosts", | ||
"ManageComments", | ||
"RepresentSpaceInternally", | ||
"RepresentSpaceExternally", | ||
"UpdateSpace", | ||
"BlockUsers", | ||
"CreateSubspaces", | ||
"UpdateOwnSubspaces", | ||
"UpdateAnySubspaces", | ||
"DeleteOwnSubspaces", | ||
"DeleteAnySubspaces", | ||
"BlockSubspaces", | ||
"CreatePosts", | ||
"UpdateOwnPosts", | ||
"UpdateAnyPosts", | ||
"DeleteOwnPosts", | ||
"DeleteAnyPosts", | ||
"BlockPosts", | ||
"CreateComments", | ||
"UpdateOwnComments", | ||
"DeleteOwnComments", | ||
"DeleteAnyComments", | ||
"BlockComments", | ||
"Upvote", | ||
"Downvote", | ||
"Share" | ||
"Share", | ||
"OverridePostPermissions" | ||
] | ||
}, | ||
|
||
"PostPermission":{ | ||
"_enum":[ | ||
"CreateComments", | ||
"UpdateOwnComments", | ||
"DeleteOwnComments", | ||
"Upvote", | ||
"Downvote", | ||
"Share" | ||
] | ||
"SpacePermissions": { | ||
"none": "Option<SpacePermissionSet>", | ||
"everyone": "Option<SpacePermissionSet>", | ||
"follower": "Option<SpacePermissionSet>", | ||
"space_owner": "Option<SpacePermissionSet>" | ||
}, | ||
|
||
"SpacePermissionsContext": { | ||
"space_id": "SpaceId", | ||
"is_space_owner": "bool", | ||
"is_space_follower": "bool", | ||
"space_perms": "Option<SpacePermissionSet>" | ||
} | ||
} |
Oops, something went wrong.