members.rs 23 KB

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