members.rs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. // Clippy linter requirement
  2. #![allow(clippy::redundant_closure_call)] // disable it because of the substrate lib design
  3. // example: pub PaidMembershipTermsById get(paid_membership_terms_by_id) build(|config: &GenesisConfig<T>| {}
  4. use codec::{Codec, Decode, Encode};
  5. use common::currency::{BalanceOf, GovernanceCurrency};
  6. use rstd::prelude::*;
  7. use rstd::borrow::ToOwned;
  8. use sr_primitives::traits::{MaybeSerialize, Member, One, SimpleArithmetic};
  9. use srml_support::traits::{Currency, Get};
  10. use srml_support::{decl_event, decl_module, decl_storage, dispatch, ensure, Parameter};
  11. use system::{self, ensure_root, ensure_signed};
  12. use timestamp;
  13. pub use super::role_types::*;
  14. pub trait Trait: system::Trait + GovernanceCurrency + timestamp::Trait {
  15. type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
  16. type MemberId: Parameter
  17. + Member
  18. + SimpleArithmetic
  19. + Codec
  20. + Default
  21. + Copy
  22. + MaybeSerialize
  23. + PartialEq;
  24. type PaidTermId: Parameter
  25. + Member
  26. + SimpleArithmetic
  27. + Codec
  28. + Default
  29. + Copy
  30. + MaybeSerialize
  31. + PartialEq;
  32. type SubscriptionId: Parameter
  33. + Member
  34. + SimpleArithmetic
  35. + Codec
  36. + Default
  37. + Copy
  38. + MaybeSerialize
  39. + PartialEq;
  40. type ActorId: Parameter
  41. + Member
  42. + SimpleArithmetic
  43. + Codec
  44. + Default
  45. + Copy
  46. + MaybeSerialize
  47. + PartialEq
  48. + Ord;
  49. /// Initial balance of members created at genesis
  50. type InitialMembersBalance: Get<BalanceOf<Self>>;
  51. }
  52. const FIRST_PAID_TERMS_ID: u32 = 1;
  53. // Default paid membership terms
  54. pub const DEFAULT_PAID_TERM_ID: u32 = 0;
  55. // Default user info constraints
  56. const DEFAULT_MIN_HANDLE_LENGTH: u32 = 5;
  57. const DEFAULT_MAX_HANDLE_LENGTH: u32 = 40;
  58. const DEFAULT_MAX_AVATAR_URI_LENGTH: u32 = 1024;
  59. const DEFAULT_MAX_ABOUT_TEXT_LENGTH: u32 = 2048;
  60. //#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
  61. #[derive(Encode, Decode)]
  62. /// Stored information about a registered user
  63. pub struct Profile<T: Trait> {
  64. /// The unique handle chosen by member
  65. pub handle: Vec<u8>,
  66. /// A Url to member's Avatar image
  67. pub avatar_uri: Vec<u8>,
  68. /// Short text chosen by member to share information about themselves
  69. pub about: Vec<u8>,
  70. /// Blocknumber when member was registered
  71. pub registered_at_block: T::BlockNumber,
  72. /// Timestamp when member was registered
  73. pub registered_at_time: T::Moment,
  74. /// How the member was registered
  75. pub entry: EntryMethod<T>,
  76. /// Wether the member is suspended or not.
  77. pub suspended: bool,
  78. /// The type of subsction the member has purchased if any.
  79. pub subscription: Option<T::SubscriptionId>,
  80. /// Member's root account id. Only the root account is permitted to set a new root account
  81. /// and update the controller account. Other modules may only allow certain actions if
  82. /// signed with root account. It is intended to be an account that can remain offline and
  83. /// potentially hold a member's funds, and be a source for staking roles.
  84. pub root_account: T::AccountId,
  85. /// Member's controller account id. This account is intended to be used by
  86. /// a member to act under their identity in other modules. It will usually be used more
  87. /// online and will have less funds in its balance.
  88. pub controller_account: T::AccountId,
  89. /// The set of registered roles the member has enrolled in.
  90. pub roles: ActorInRoleSet<T::ActorId>,
  91. }
  92. #[derive(Clone, Debug, Encode, Decode, PartialEq)]
  93. /// A "Partial" struct used to batch user configurable profile information when registering or updating info
  94. pub struct UserInfo {
  95. pub handle: Option<Vec<u8>>,
  96. pub avatar_uri: Option<Vec<u8>>,
  97. pub about: Option<Vec<u8>>,
  98. }
  99. struct CheckedUserInfo {
  100. handle: Vec<u8>,
  101. avatar_uri: Vec<u8>,
  102. about: Vec<u8>,
  103. }
  104. //#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
  105. #[derive(Encode, Decode, Debug, PartialEq)]
  106. pub enum EntryMethod<T: Trait> {
  107. Paid(T::PaidTermId),
  108. Screening(T::AccountId),
  109. Genesis,
  110. }
  111. //#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
  112. #[derive(Encode, Decode, Eq, PartialEq)]
  113. pub struct PaidMembershipTerms<T: Trait> {
  114. /// Quantity of native tokens which must be provably burned
  115. pub fee: BalanceOf<T>,
  116. /// String of capped length describing human readable conditions which are being agreed upon
  117. pub text: Vec<u8>,
  118. }
  119. decl_storage! {
  120. trait Store for Module<T: Trait> as Membership {
  121. /// MemberId to assign to next member that is added to the registry, and is also the
  122. /// total number of members created. MemberIds start at Zero.
  123. pub MembersCreated get(members_created) : T::MemberId;
  124. /// Mapping of member's id to their membership profile
  125. pub MemberProfile get(member_profile) : map T::MemberId => Option<Profile<T>>;
  126. /// Mapping of a root account id to vector of member ids it controls
  127. pub MemberIdsByRootAccountId get(member_ids_by_root_account_id) : map T::AccountId => Vec<T::MemberId>;
  128. /// Mapping of a controller account id to vector of member ids it controls
  129. pub MemberIdsByControllerAccountId get(member_ids_by_controller_account_id) : map T::AccountId => Vec<T::MemberId>;
  130. /// Registered unique handles and their mapping to their owner
  131. pub Handles get(handles) : map Vec<u8> => T::MemberId;
  132. /// Next paid membership terms id
  133. pub NextPaidMembershipTermsId get(next_paid_membership_terms_id) : T::PaidTermId = T::PaidTermId::from(FIRST_PAID_TERMS_ID);
  134. /// Paid membership terms record
  135. // Remember to add _genesis_phantom_data: std::marker::PhantomData{} to membership
  136. // genesis config if not providing config() or extra_genesis
  137. pub PaidMembershipTermsById get(paid_membership_terms_by_id) build(|config: &GenesisConfig<T>| {
  138. // This method only gets called when initializing storage, and is
  139. // compiled as native code. (Will be called when building `raw` chainspec)
  140. // So it can't be relied upon to initialize storage for runtimes updates.
  141. // Initialization for updated runtime is done in run_migration()
  142. let terms = PaidMembershipTerms {
  143. fee: config.default_paid_membership_fee,
  144. text: Vec::default(),
  145. };
  146. vec![(T::PaidTermId::from(DEFAULT_PAID_TERM_ID), terms)]
  147. }) : map T::PaidTermId => Option<PaidMembershipTerms<T>>;
  148. /// Active Paid membership terms
  149. pub ActivePaidMembershipTerms get(active_paid_membership_terms) : Vec<T::PaidTermId> = vec![T::PaidTermId::from(DEFAULT_PAID_TERM_ID)];
  150. /// Is the platform is accepting new members or not
  151. pub NewMembershipsAllowed get(new_memberships_allowed) : bool = true;
  152. pub ScreeningAuthority get(screening_authority) : Option<T::AccountId>;
  153. // User Input Validation parameters - do these really need to be state variables
  154. // I don't see a need to adjust these in future?
  155. pub MinHandleLength get(min_handle_length) : u32 = DEFAULT_MIN_HANDLE_LENGTH;
  156. pub MaxHandleLength get(max_handle_length) : u32 = DEFAULT_MAX_HANDLE_LENGTH;
  157. pub MaxAvatarUriLength get(max_avatar_uri_length) : u32 = DEFAULT_MAX_AVATAR_URI_LENGTH;
  158. pub MaxAboutTextLength get(max_about_text_length) : u32 = DEFAULT_MAX_ABOUT_TEXT_LENGTH;
  159. pub MembershipIdByActorInRole get(membership_id_by_actor_in_role): map ActorInRole<T::ActorId> => T::MemberId;
  160. }
  161. add_extra_genesis {
  162. config(default_paid_membership_fee): BalanceOf<T>;
  163. config(members) : Vec<(T::AccountId, String, String, String)>;
  164. build(|config: &GenesisConfig<T>| {
  165. for (who, handle, avatar_uri, about) in &config.members {
  166. let user_info = CheckedUserInfo {
  167. handle: handle.clone().into_bytes(), avatar_uri: avatar_uri.clone().into_bytes(), about: about.clone().into_bytes()
  168. };
  169. <Module<T>>::insert_member(&who, &user_info, EntryMethod::Genesis);
  170. // Give member starting balance
  171. T::Currency::deposit_creating(&who, T::InitialMembersBalance::get());
  172. }
  173. });
  174. }
  175. }
  176. decl_event! {
  177. pub enum Event<T> where
  178. <T as system::Trait>::AccountId,
  179. <T as Trait>::MemberId,
  180. <T as Trait>::ActorId, {
  181. MemberRegistered(MemberId, AccountId),
  182. MemberUpdatedAboutText(MemberId),
  183. MemberUpdatedAvatar(MemberId),
  184. MemberUpdatedHandle(MemberId),
  185. MemberSetRootAccount(MemberId, AccountId),
  186. MemberSetControllerAccount(MemberId, AccountId),
  187. MemberRegisteredRole(MemberId, ActorInRole<ActorId>),
  188. MemberUnregisteredRole(MemberId, ActorInRole<ActorId>),
  189. }
  190. }
  191. decl_module! {
  192. pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  193. fn deposit_event() = default;
  194. /// Non-members can buy membership
  195. pub fn buy_membership(origin, paid_terms_id: T::PaidTermId, user_info: UserInfo) {
  196. let who = ensure_signed(origin)?;
  197. // make sure we are accepting new memberships
  198. ensure!(Self::new_memberships_allowed(), "new members not allowed");
  199. // ensure paid_terms_id is active
  200. let terms = Self::ensure_active_terms_id(paid_terms_id)?;
  201. // ensure enough free balance to cover terms fees
  202. ensure!(T::Currency::can_slash(&who, terms.fee), "not enough balance to buy membership");
  203. let user_info = Self::check_user_registration_info(user_info)?;
  204. // ensure handle is not already registered
  205. Self::ensure_unique_handle(&user_info.handle)?;
  206. let _ = T::Currency::slash(&who, terms.fee);
  207. let member_id = Self::insert_member(&who, &user_info, EntryMethod::Paid(paid_terms_id));
  208. Self::deposit_event(RawEvent::MemberRegistered(member_id, who));
  209. }
  210. /// Change member's about text
  211. pub fn change_member_about_text(origin, member_id: T::MemberId, text: Vec<u8>) {
  212. let sender = ensure_signed(origin)?;
  213. let profile = Self::ensure_profile(member_id)?;
  214. ensure!(profile.controller_account == sender, "only controller account can update member about text");
  215. Self::_change_member_about_text(member_id, &text)?;
  216. }
  217. /// Change member's avatar
  218. pub fn change_member_avatar(origin, member_id: T::MemberId, uri: Vec<u8>) {
  219. let sender = ensure_signed(origin)?;
  220. let profile = Self::ensure_profile(member_id)?;
  221. ensure!(profile.controller_account == sender, "only controller account can update member avatar");
  222. Self::_change_member_avatar(member_id, &uri)?;
  223. }
  224. /// Change member's handle. Will ensure new handle is unique and old one will be available
  225. /// for other members to use.
  226. pub fn change_member_handle(origin, member_id: T::MemberId, handle: Vec<u8>) {
  227. let sender = ensure_signed(origin)?;
  228. let profile = Self::ensure_profile(member_id)?;
  229. ensure!(profile.controller_account == sender, "only controller account can update member handle");
  230. Self::_change_member_handle(member_id, handle)?;
  231. }
  232. /// Update member's all or some of handle, avatar and about text.
  233. pub fn update_profile(origin, member_id: T::MemberId, user_info: UserInfo) {
  234. let sender = ensure_signed(origin)?;
  235. let profile = Self::ensure_profile(member_id)?;
  236. ensure!(profile.controller_account == sender, "only controller account can update member info");
  237. if let Some(uri) = user_info.avatar_uri {
  238. Self::_change_member_avatar(member_id, &uri)?;
  239. }
  240. if let Some(about) = user_info.about {
  241. Self::_change_member_about_text(member_id, &about)?;
  242. }
  243. if let Some(handle) = user_info.handle {
  244. Self::_change_member_handle(member_id, handle)?;
  245. }
  246. }
  247. pub fn set_controller_account(origin, member_id: T::MemberId, new_controller_account: T::AccountId) {
  248. let sender = ensure_signed(origin)?;
  249. let mut profile = Self::ensure_profile(member_id)?;
  250. ensure!(profile.root_account == sender, "only root account can set new controller account");
  251. // only update if new_controller_account is different than current one
  252. if profile.controller_account != new_controller_account {
  253. <MemberIdsByControllerAccountId<T>>::mutate(&profile.controller_account, |ids| {
  254. ids.retain(|id| *id != member_id);
  255. });
  256. <MemberIdsByControllerAccountId<T>>::mutate(&new_controller_account, |ids| {
  257. ids.push(member_id);
  258. });
  259. profile.controller_account = new_controller_account.clone();
  260. <MemberProfile<T>>::insert(member_id, profile);
  261. Self::deposit_event(RawEvent::MemberSetControllerAccount(member_id, new_controller_account));
  262. }
  263. }
  264. pub fn set_root_account(origin, member_id: T::MemberId, new_root_account: T::AccountId) {
  265. let sender = ensure_signed(origin)?;
  266. let mut profile = Self::ensure_profile(member_id)?;
  267. ensure!(profile.root_account == sender, "only root account can set new root account");
  268. // only update if new root account is different than current one
  269. if profile.root_account != new_root_account {
  270. <MemberIdsByRootAccountId<T>>::mutate(&profile.root_account, |ids| {
  271. ids.retain(|id| *id != member_id);
  272. });
  273. <MemberIdsByRootAccountId<T>>::mutate(&new_root_account, |ids| {
  274. ids.push(member_id);
  275. });
  276. profile.root_account = new_root_account.clone();
  277. Self::deposit_event(RawEvent::MemberSetRootAccount(member_id, new_root_account));
  278. }
  279. }
  280. pub fn add_screened_member(origin, new_member_account: T::AccountId, user_info: UserInfo) {
  281. // ensure sender is screening authority
  282. let sender = ensure_signed(origin)?;
  283. if let Some(screening_authority) = Self::screening_authority() {
  284. ensure!(sender == screening_authority, "not screener");
  285. } else {
  286. // no screening authority defined. Cannot accept this request
  287. return Err("no screening authority defined");
  288. }
  289. // make sure we are accepting new memberships
  290. ensure!(Self::new_memberships_allowed(), "new members not allowed");
  291. let user_info = Self::check_user_registration_info(user_info)?;
  292. // ensure handle is not already registered
  293. Self::ensure_unique_handle(&user_info.handle)?;
  294. let member_id = Self::insert_member(&new_member_account, &user_info, EntryMethod::Screening(sender));
  295. Self::deposit_event(RawEvent::MemberRegistered(member_id, new_member_account));
  296. }
  297. pub fn set_screening_authority(origin, authority: T::AccountId) {
  298. ensure_root(origin)?;
  299. <ScreeningAuthority<T>>::put(authority);
  300. }
  301. }
  302. }
  303. /// Reason why a given member id does not have a given account as the controller account.
  304. pub enum ControllerAccountForMemberCheckFailed {
  305. NotMember,
  306. NotControllerAccount,
  307. }
  308. pub enum MemberControllerAccountDidNotSign {
  309. UnsignedOrigin,
  310. MemberIdInvalid,
  311. SignerControllerAccountMismatch,
  312. }
  313. pub enum MemberControllerAccountMismatch {
  314. MemberIdInvalid,
  315. SignerControllerAccountMismatch,
  316. }
  317. pub enum MemberRootAccountMismatch {
  318. MemberIdInvalid,
  319. SignerRootAccountMismatch,
  320. }
  321. impl<T: Trait> Module<T> {
  322. /// Provided that the memberid exists return its profile. Returns error otherwise.
  323. pub fn ensure_profile(id: T::MemberId) -> Result<Profile<T>, &'static str> {
  324. Self::member_profile(&id).ok_or("member profile not found")
  325. }
  326. /// Ensure that given member has given account as the controller account
  327. pub fn ensure_is_controller_account_for_member(
  328. member_id: &T::MemberId,
  329. account: &T::AccountId,
  330. ) -> Result<Profile<T>, ControllerAccountForMemberCheckFailed> {
  331. if MemberProfile::<T>::exists(member_id) {
  332. let profile = MemberProfile::<T>::get(member_id).unwrap();
  333. if profile.controller_account == *account {
  334. Ok(profile)
  335. } else {
  336. Err(ControllerAccountForMemberCheckFailed::NotControllerAccount)
  337. }
  338. } else {
  339. Err(ControllerAccountForMemberCheckFailed::NotMember)
  340. }
  341. }
  342. /// Returns true if account is either a member's root or controller account
  343. pub fn is_member_account(who: &T::AccountId) -> bool {
  344. <MemberIdsByRootAccountId<T>>::exists(who)
  345. || <MemberIdsByControllerAccountId<T>>::exists(who)
  346. }
  347. fn ensure_active_terms_id(
  348. terms_id: T::PaidTermId,
  349. ) -> Result<PaidMembershipTerms<T>, &'static str> {
  350. let active_terms = Self::active_paid_membership_terms();
  351. ensure!(
  352. active_terms.iter().any(|&id| id == terms_id),
  353. "paid terms id not active"
  354. );
  355. let terms = Self::paid_membership_terms_by_id(terms_id)
  356. .ok_or("paid membership term id does not exist")?;
  357. Ok(terms)
  358. }
  359. #[allow(clippy::ptr_arg)] // cannot change to the "&[u8]" suggested by clippy
  360. fn ensure_unique_handle(handle: &Vec<u8>) -> dispatch::Result {
  361. ensure!(!<Handles<T>>::exists(handle), "handle already registered");
  362. Ok(())
  363. }
  364. fn validate_handle(handle: &[u8]) -> dispatch::Result {
  365. ensure!(
  366. handle.len() >= Self::min_handle_length() as usize,
  367. "handle too short"
  368. );
  369. ensure!(
  370. handle.len() <= Self::max_handle_length() as usize,
  371. "handle too long"
  372. );
  373. Ok(())
  374. }
  375. fn validate_text(text: &[u8]) -> Vec<u8> {
  376. let mut text = text.to_owned();
  377. text.truncate(Self::max_about_text_length() as usize);
  378. text
  379. }
  380. fn validate_avatar(uri: &[u8]) -> dispatch::Result {
  381. ensure!(
  382. uri.len() <= Self::max_avatar_uri_length() as usize,
  383. "avatar uri too long"
  384. );
  385. Ok(())
  386. }
  387. /// Basic user input validation
  388. fn check_user_registration_info(user_info: UserInfo) -> Result<CheckedUserInfo, &'static str> {
  389. // Handle is required during registration
  390. let handle = user_info
  391. .handle
  392. .ok_or("handle must be provided during registration")?;
  393. Self::validate_handle(&handle)?;
  394. let about = Self::validate_text(&user_info.about.unwrap_or_default());
  395. let avatar_uri = user_info.avatar_uri.unwrap_or_default();
  396. Self::validate_avatar(&avatar_uri)?;
  397. Ok(CheckedUserInfo {
  398. handle,
  399. avatar_uri,
  400. about,
  401. })
  402. }
  403. fn insert_member(
  404. who: &T::AccountId,
  405. user_info: &CheckedUserInfo,
  406. entry_method: EntryMethod<T>,
  407. ) -> T::MemberId {
  408. let new_member_id = Self::members_created();
  409. let profile: Profile<T> = Profile {
  410. handle: user_info.handle.clone(),
  411. avatar_uri: user_info.avatar_uri.clone(),
  412. about: user_info.about.clone(),
  413. registered_at_block: <system::Module<T>>::block_number(),
  414. registered_at_time: <timestamp::Module<T>>::now(),
  415. entry: entry_method,
  416. suspended: false,
  417. subscription: None,
  418. root_account: who.clone(),
  419. controller_account: who.clone(),
  420. roles: ActorInRoleSet::new(),
  421. };
  422. <MemberIdsByRootAccountId<T>>::mutate(who, |ids| {
  423. ids.push(new_member_id);
  424. });
  425. <MemberIdsByControllerAccountId<T>>::mutate(who, |ids| {
  426. ids.push(new_member_id);
  427. });
  428. <MemberProfile<T>>::insert(new_member_id, profile);
  429. <Handles<T>>::insert(user_info.handle.clone(), new_member_id);
  430. <MembersCreated<T>>::put(new_member_id + One::one());
  431. new_member_id
  432. }
  433. fn _change_member_about_text(id: T::MemberId, text: &[u8]) -> dispatch::Result {
  434. let mut profile = Self::ensure_profile(id)?;
  435. let text = Self::validate_text(text);
  436. profile.about = text;
  437. Self::deposit_event(RawEvent::MemberUpdatedAboutText(id));
  438. <MemberProfile<T>>::insert(id, profile);
  439. Ok(())
  440. }
  441. fn _change_member_avatar(id: T::MemberId, uri: &[u8]) -> dispatch::Result {
  442. let mut profile = Self::ensure_profile(id)?;
  443. Self::validate_avatar(uri)?;
  444. profile.avatar_uri = uri.to_owned();
  445. Self::deposit_event(RawEvent::MemberUpdatedAvatar(id));
  446. <MemberProfile<T>>::insert(id, profile);
  447. Ok(())
  448. }
  449. fn _change_member_handle(id: T::MemberId, handle: Vec<u8>) -> dispatch::Result {
  450. let mut profile = Self::ensure_profile(id)?;
  451. Self::validate_handle(&handle)?;
  452. Self::ensure_unique_handle(&handle)?;
  453. <Handles<T>>::remove(&profile.handle);
  454. <Handles<T>>::insert(handle.clone(), id);
  455. profile.handle = handle;
  456. Self::deposit_event(RawEvent::MemberUpdatedHandle(id));
  457. <MemberProfile<T>>::insert(id, profile);
  458. Ok(())
  459. }
  460. /// Determines if the signing account is a controller account of a member that has the registered
  461. /// actor_in_role.
  462. pub fn key_can_sign_for_role(
  463. signing_account: &T::AccountId,
  464. actor_in_role: ActorInRole<T::ActorId>,
  465. ) -> bool {
  466. Self::member_ids_by_controller_account_id(signing_account)
  467. .iter()
  468. .any(|member_id| {
  469. let profile = Self::member_profile(member_id).unwrap(); // must exist
  470. profile.roles.has_registered_role(&actor_in_role)
  471. })
  472. }
  473. /// Returns true if member identified by their member id occupies a Role at least once
  474. pub fn member_is_in_role(member_id: T::MemberId, role: Role) -> bool {
  475. Self::ensure_profile(member_id)
  476. .ok()
  477. .map_or(false, |profile| profile.roles.occupies_role(role))
  478. }
  479. pub fn ensure_member_controller_account_signed(
  480. origin: T::Origin,
  481. member_id: &T::MemberId,
  482. ) -> Result<T::AccountId, MemberControllerAccountDidNotSign> {
  483. // Ensure transaction is signed.
  484. let signer_account =
  485. ensure_signed(origin).map_err(|_| MemberControllerAccountDidNotSign::UnsignedOrigin)?;
  486. // Ensure member exists
  487. let profile = Self::ensure_profile(*member_id)
  488. .map_err(|_| MemberControllerAccountDidNotSign::MemberIdInvalid)?;
  489. ensure!(
  490. profile.controller_account == signer_account,
  491. MemberControllerAccountDidNotSign::SignerControllerAccountMismatch
  492. );
  493. Ok(signer_account)
  494. }
  495. pub fn ensure_member_controller_account(
  496. signer_account: &T::AccountId,
  497. member_id: &T::MemberId,
  498. ) -> Result<(), MemberControllerAccountMismatch> {
  499. // Ensure member exists
  500. let profile = Self::ensure_profile(*member_id)
  501. .map_err(|_| MemberControllerAccountMismatch::MemberIdInvalid)?;
  502. ensure!(
  503. profile.controller_account == *signer_account,
  504. MemberControllerAccountMismatch::SignerControllerAccountMismatch
  505. );
  506. Ok(())
  507. }
  508. pub fn ensure_member_root_account(
  509. signer_account: &T::AccountId,
  510. member_id: &T::MemberId,
  511. ) -> Result<(), MemberRootAccountMismatch> {
  512. // Ensure member exists
  513. let profile = Self::ensure_profile(*member_id)
  514. .map_err(|_| MemberRootAccountMismatch::MemberIdInvalid)?;
  515. ensure!(
  516. profile.root_account == *signer_account,
  517. MemberRootAccountMismatch::SignerRootAccountMismatch
  518. );
  519. Ok(())
  520. }
  521. // policy across all roles is:
  522. // members can only occupy a role at most once at a time
  523. // members can enter any role
  524. // no limit on total number of roles a member can enter
  525. // ** Note ** Role specific policies should be enforced by the client modules
  526. // this method should handle higher level policies
  527. pub fn can_register_role_on_member(
  528. member_id: &T::MemberId,
  529. actor_in_role: &ActorInRole<T::ActorId>,
  530. ) -> Result<Profile<T>, &'static str> {
  531. // Ensure member exists
  532. let profile = Self::ensure_profile(*member_id)?;
  533. // ensure is active member
  534. ensure!(!profile.suspended, "SuspendedMemberCannotEnterRole");
  535. // guard against duplicate ActorInRole
  536. ensure!(
  537. !<MembershipIdByActorInRole<T>>::exists(actor_in_role),
  538. "ActorInRoleAlreadyExists"
  539. );
  540. /*
  541. Disabling this temporarily for Rome, later we will drop all this
  542. integration with Membership module anyway:
  543. https://github.com/Joystream/substrate-runtime-joystream/issues/115
  544. ensure!(
  545. !profile.roles.occupies_role(actor_in_role.role),
  546. "MemberAlreadyInRole"
  547. );
  548. */
  549. // Other possible checks:
  550. // How long the member has been registered
  551. // Minimum balance
  552. // EntryMethod
  553. Ok(profile)
  554. }
  555. pub fn register_role_on_member(
  556. member_id: T::MemberId,
  557. actor_in_role: &ActorInRole<T::ActorId>,
  558. ) -> Result<(), &'static str> {
  559. // Policy check
  560. let mut profile = Self::can_register_role_on_member(&member_id, actor_in_role)?;
  561. assert!(profile.roles.register_role(actor_in_role));
  562. <MemberProfile<T>>::insert(member_id, profile);
  563. <MembershipIdByActorInRole<T>>::insert(actor_in_role, member_id);
  564. Self::deposit_event(RawEvent::MemberRegisteredRole(member_id, *actor_in_role));
  565. Ok(())
  566. }
  567. pub fn can_unregister_role(actor_in_role: ActorInRole<T::ActorId>) -> Result<(), &'static str> {
  568. ensure!(
  569. <MembershipIdByActorInRole<T>>::exists(&actor_in_role),
  570. "ActorInRoleNotFound"
  571. );
  572. Ok(())
  573. }
  574. pub fn unregister_role(actor_in_role: ActorInRole<T::ActorId>) -> Result<(), &'static str> {
  575. Self::can_unregister_role(actor_in_role)?;
  576. let member_id = <MembershipIdByActorInRole<T>>::get(actor_in_role);
  577. let mut profile = Self::ensure_profile(member_id)?; // .expect().. ?
  578. assert!(profile.roles.unregister_role(&actor_in_role));
  579. <MembershipIdByActorInRole<T>>::remove(actor_in_role);
  580. <MemberProfile<T>>::insert(member_id, profile);
  581. Self::deposit_event(RawEvent::MemberUnregisteredRole(member_id, actor_in_role));
  582. Ok(())
  583. }
  584. }