content_working_group.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. use crate::{AccountId, Credential, Runtime};
  2. use srml_support::traits::{Currency, Imbalance};
  3. use srml_support::{parameter_types, StorageLinkedMap, StorageMap};
  4. parameter_types! {
  5. pub const CurrentLeadCredential: Credential = 0;
  6. pub const AnyActiveCuratorCredential: Credential = 1;
  7. pub const AnyActiveChannelOwnerCredential: Credential = 2;
  8. pub const PrincipalIdMappingStartsAtCredential: Credential = 1000;
  9. }
  10. pub struct ContentWorkingGroupCredentials {}
  11. impl versioned_store_permissions::CredentialChecker<Runtime> for ContentWorkingGroupCredentials {
  12. fn account_has_credential(
  13. account: &AccountId,
  14. credential: <Runtime as versioned_store_permissions::Trait>::Credential,
  15. ) -> bool {
  16. match credential {
  17. // Credentials from 0..999 represents groups or more complex requirements
  18. // Current Lead if set
  19. credential if credential == CurrentLeadCredential::get() => {
  20. match <content_working_group::Module<Runtime>>::ensure_lead_is_set() {
  21. Ok((_, lead)) => lead.role_account == *account,
  22. _ => false,
  23. }
  24. }
  25. // Any Active Curator
  26. credential if credential == AnyActiveCuratorCredential::get() => {
  27. // Look for a Curator with a matching role account
  28. for (_principal_id, principal) in
  29. <content_working_group::PrincipalById<Runtime>>::enumerate()
  30. {
  31. if let content_working_group::Principal::Curator(curator_id) = principal {
  32. let curator =
  33. <content_working_group::CuratorById<Runtime>>::get(curator_id);
  34. if curator.role_account == *account
  35. && curator.stage == content_working_group::CuratorRoleStage::Active
  36. {
  37. return true;
  38. }
  39. }
  40. }
  41. false
  42. }
  43. // Any Active Channel Owner
  44. credential if credential == AnyActiveChannelOwnerCredential::get() => {
  45. // Look for a ChannelOwner with a matching role account
  46. for (_principal_id, principal) in
  47. <content_working_group::PrincipalById<Runtime>>::enumerate()
  48. {
  49. if let content_working_group::Principal::ChannelOwner(channel_id) = principal {
  50. let channel =
  51. <content_working_group::ChannelById<Runtime>>::get(channel_id);
  52. if channel.role_account == *account {
  53. return true; // should we also take publishing_status/curation_status into account ?
  54. }
  55. }
  56. }
  57. false
  58. }
  59. // mapping to working group principal id
  60. n if n >= PrincipalIdMappingStartsAtCredential::get() => {
  61. <content_working_group::Module<Runtime>>::account_has_credential(
  62. account,
  63. n - PrincipalIdMappingStartsAtCredential::get(),
  64. )
  65. }
  66. _ => false,
  67. }
  68. }
  69. }
  70. pub struct ContentWorkingGroupStakingEventHandler {}
  71. impl stake::StakingEventsHandler<Runtime> for ContentWorkingGroupStakingEventHandler {
  72. fn unstaked(
  73. stake_id: &<Runtime as stake::Trait>::StakeId,
  74. _unstaked_amount: stake::BalanceOf<Runtime>,
  75. remaining_imbalance: stake::NegativeImbalance<Runtime>,
  76. ) -> stake::NegativeImbalance<Runtime> {
  77. if !hiring::ApplicationIdByStakingId::<Runtime>::exists(stake_id) {
  78. // Stake not related to a staked role managed by the hiring module
  79. return remaining_imbalance;
  80. }
  81. let application_id = hiring::ApplicationIdByStakingId::<Runtime>::get(stake_id);
  82. if !content_working_group::CuratorApplicationById::<Runtime>::exists(application_id) {
  83. // Stake not for a Curator
  84. return remaining_imbalance;
  85. }
  86. // Notify the Hiring module - is there a potential re-entrancy bug if
  87. // instant unstaking is occuring?
  88. hiring::Module::<Runtime>::unstaked(*stake_id);
  89. // Only notify working group module if non instantaneous unstaking occured
  90. if content_working_group::UnstakerByStakeId::<Runtime>::exists(stake_id) {
  91. content_working_group::Module::<Runtime>::unstaked(*stake_id);
  92. }
  93. // Determine member id of the curator
  94. let curator_application =
  95. content_working_group::CuratorApplicationById::<Runtime>::get(application_id);
  96. let member_id = curator_application.member_id;
  97. // get member's profile
  98. let member_profile = membership::members::MemberProfile::<Runtime>::get(member_id).unwrap();
  99. // deposit funds to member's root_account
  100. // The application doesn't recorded the original source_account from which staked funds were
  101. // provided, so we don't really have another option at the moment.
  102. <Runtime as stake::Trait>::Currency::resolve_creating(
  103. &member_profile.root_account,
  104. remaining_imbalance,
  105. );
  106. stake::NegativeImbalance::<Runtime>::zero()
  107. }
  108. // Handler for slashing event
  109. fn slashed(
  110. _id: &<Runtime as stake::Trait>::StakeId,
  111. _slash_id: Option<<Runtime as stake::Trait>::SlashId>,
  112. _slashed_amount: stake::BalanceOf<Runtime>,
  113. _remaining_stake: stake::BalanceOf<Runtime>,
  114. remaining_imbalance: stake::NegativeImbalance<Runtime>,
  115. ) -> stake::NegativeImbalance<Runtime> {
  116. // Check if the stake is associated with a hired curator or applicant
  117. // if their stake goes below minimum required for the role,
  118. // they should get deactivated.
  119. // Since we don't currently implement any slash initiation in working group,
  120. // there is nothing to do for now.
  121. // Not interested in transfering the slashed amount anywhere for now,
  122. // so return it to next handler.
  123. remaining_imbalance
  124. }
  125. }