members.rs 25 KB

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