content_working_group.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. use crate::{AccountId, Credential, Runtime};
  2. use frame_support::traits::{Currency, Imbalance};
  3. use frame_support::{parameter_types, IterableStorageMap, 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>>::iter()
  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>>::iter()
  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. #[allow(dead_code)]
  71. pub struct ContentWorkingGroupStakingEventHandler {}
  72. impl stake::StakingEventsHandler<Runtime> for ContentWorkingGroupStakingEventHandler {
  73. fn unstaked(
  74. stake_id: &<Runtime as stake::Trait>::StakeId,
  75. _unstaked_amount: stake::BalanceOf<Runtime>,
  76. remaining_imbalance: stake::NegativeImbalance<Runtime>,
  77. ) -> stake::NegativeImbalance<Runtime> {
  78. if !hiring::ApplicationIdByStakingId::<Runtime>::contains_key(stake_id) {
  79. // Stake not related to a staked role managed by the hiring module
  80. return remaining_imbalance;
  81. }
  82. let application_id = hiring::ApplicationIdByStakingId::<Runtime>::get(stake_id);
  83. if !content_working_group::CuratorApplicationById::<Runtime>::contains_key(application_id) {
  84. // Stake not for a Curator
  85. return remaining_imbalance;
  86. }
  87. // Notify the Hiring module - is there a potential re-entrancy bug if
  88. // instant unstaking is occuring?
  89. hiring::Module::<Runtime>::unstaked(*stake_id);
  90. // Only notify working group module if non instantaneous unstaking occured
  91. if content_working_group::UnstakerByStakeId::<Runtime>::contains_key(stake_id) {
  92. content_working_group::Module::<Runtime>::unstaked(*stake_id);
  93. }
  94. // Determine member id of the curator
  95. let curator_application =
  96. content_working_group::CuratorApplicationById::<Runtime>::get(application_id);
  97. let member_id = curator_application.member_id;
  98. // get member's profile
  99. let member_profile = membership::MembershipById::<Runtime>::get(member_id);
  100. // deposit funds to member's root_account
  101. // The application doesn't recorded the original source_account from which staked funds were
  102. // provided, so we don't really have another option at the moment.
  103. <Runtime as stake::Trait>::Currency::resolve_creating(
  104. &member_profile.root_account,
  105. remaining_imbalance,
  106. );
  107. stake::NegativeImbalance::<Runtime>::zero()
  108. }
  109. // Handler for slashing event
  110. fn slashed(
  111. _id: &<Runtime as stake::Trait>::StakeId,
  112. _slash_id: Option<<Runtime as stake::Trait>::SlashId>,
  113. _slashed_amount: stake::BalanceOf<Runtime>,
  114. _remaining_stake: stake::BalanceOf<Runtime>,
  115. remaining_imbalance: stake::NegativeImbalance<Runtime>,
  116. ) -> stake::NegativeImbalance<Runtime> {
  117. // Check if the stake is associated with a hired curator or applicant
  118. // if their stake goes below minimum required for the role,
  119. // they should get deactivated.
  120. // Since we don't currently implement any slash initiation in working group,
  121. // there is nothing to do for now.
  122. // Not interested in transfering the slashed amount anywhere for now,
  123. // so return it to next handler.
  124. remaining_imbalance
  125. }
  126. }