diff --git a/pallets/fruniques/src/functions.rs b/pallets/fruniques/src/functions.rs index 07f30c09..40a0040d 100644 --- a/pallets/fruniques/src/functions.rs +++ b/pallets/fruniques/src/functions.rs @@ -145,7 +145,7 @@ impl Pallet { pub fn do_create_collection( origin: OriginFor, class_id: T::CollectionId, - metadata: Option>, + metadata: Option>, admin: ::Source, ) -> DispatchResult { pallet_uniques::Pallet::::create( diff --git a/pallets/fruniques/src/lib.rs b/pallets/fruniques/src/lib.rs index 453876fc..5943d87a 100644 --- a/pallets/fruniques/src/lib.rs +++ b/pallets/fruniques/src/lib.rs @@ -76,6 +76,10 @@ pub mod pallet { ParentNotFound, // The frunique doesn't exist FruniqueNotFound, + // Collection already exists + CollectionAlreadyExists, + // Frunique already exists + FruniqueAlreadyExists, } #[pallet::storage] @@ -142,10 +146,17 @@ pub mod pallet { Ok(()) } + /// # Creation of a collection + /// This function creates a collection and an asset class. + /// The collection is a unique identifier for a set of fruniques. + /// + /// ## Parameters + /// - `origin`: The origin of the transaction. + /// - `Metadata`: The title of the collection. #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] pub fn create_collection( origin: OriginFor, - metadata: Option>, + metadata: Option>, ) -> DispatchResult { let admin: T::AccountId = ensure_signed(origin.clone())?; @@ -182,14 +193,10 @@ pub mod pallet { } /// ## Set multiple attributes to a frunique. - /// `origin` must be signed by the owner of the frunique. + /// - `origin` must be signed by the owner of the frunique. /// - `class_id` must be a valid class of the asset class. /// - `instance_id` must be a valid instance of the asset class. /// - `attributes` must be a list of pairs of `key` and `value`. - /// `key` must be a valid key for the asset class. - /// `value` must be a valid value for the asset class. - /// `attributes` must not be empty. - #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] pub fn set_attributes( origin: OriginFor, @@ -218,22 +225,12 @@ pub mod pallet { Ok(()) } - /// ## NFT Division - /// - /// PD: the Key/value length limits are inherited from the uniques pallet, - /// so they're not explicitly declared on this pallet - /// - /// - /// ### Boilerplate parameters: - /// - /// - `admin`: The admin of this class of assets. The admin is the initial address of each - /// member of the asset class's admin team. - /// - /// ### Parameters needed in order to divide a unique: - /// - `class_id`: The type of NFT that the function will create, categorized by numbers. - /// - `parent_info`: Information of the parent NFT and a flag to indicate the child would inherit their attributes. - /// - `attributes`: Generates a list of attributes for the new NFT. - /// + /// ## NFT creation + /// ### Parameters: + /// - `origin` must be signed by the owner of the frunique. + /// - `class_id` must be a valid class of the asset class. + /// - `parent_info` Optional value needed for the NFT division. + /// - `attributes` An array of attributes (key, value) to be added to the NFT. #[pallet::weight(10_000 + T::DbWeight::get().writes(4))] pub fn spawn( origin: OriginFor, @@ -279,6 +276,61 @@ pub mod pallet { Ok(()) } + /// ## Force set counter + /// ### Parameters: + /// `origin` must be signed by the Root origin. + /// - `class_id` must be a valid class of the asset class. + /// - `instance_id` must be a valid instance of the asset class. + /// + /// ### Considerations: + /// This function is only used for testing purposes. Or in case someone calls uniques pallet directly. + /// This function it's not expected to be used in production as it can lead to unexpected results. + #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] + pub fn force_set_counter( + origin: OriginFor, + class_id: T::CollectionId, + instance_id: Option, + ) -> DispatchResult { + T::RemoveOrigin::ensure_origin(origin.clone())?; + + if let Some(instance_id) = instance_id { + ensure!(!Self::item_exists(&class_id, &instance_id), >::FruniqueAlreadyExists); + >::insert(class_id, instance_id); + } else { + ensure!(!Self::collection_exists(&class_id), >::CollectionAlreadyExists); + >::set(class_id); + } + + Ok(()) + } + + /// ## Force destroy collection + /// ### Parameters: + /// - `origin` must be signed by the Root origin. + /// - `class_id` must be a valid class of the asset class. + /// - `witness` the witness data to destroy the collection. This is used to prevent accidental destruction of the collection. The witness data is retrieved from the `class` storage. + /// - `maybe_check_owner` Optional value to check if the owner of the collection is the same as the signer. + /// ### Considerations: + /// This function is only used for testing purposes. Or in case someone calls uniques pallet directly. + /// This function it's not expected to be used in production as it can lead to unexpected results. + #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] + pub fn force_destroy_collection( + origin: OriginFor, + class_id: T::CollectionId, + witness: pallet_uniques::DestroyWitness, + maybe_check_owner: Option, + ) -> DispatchResult { + T::RemoveOrigin::ensure_origin(origin.clone())?; + + ensure!(Self::collection_exists(&class_id), >::CollectionNotFound); + pallet_uniques::Pallet::::do_destroy_collection( + class_id, + witness, + maybe_check_owner, + )?; + Ok(()) + } + /// Kill all the stored data. /// /// This function is used to kill ALL the stored data. diff --git a/pallets/fruniques/src/types.rs b/pallets/fruniques/src/types.rs index d25ae138..0c9d7754 100644 --- a/pallets/fruniques/src/types.rs +++ b/pallets/fruniques/src/types.rs @@ -10,13 +10,14 @@ pub type AttributeKey = BoundedVec::KeyLimi pub type AttributeValue = BoundedVec::ValueLimit>; pub type Attributes = Vec<(AttributeKey, AttributeValue)>; -pub type CollectionDescription = [u8; 32]; +// pub type CollectionDescription = [u8; 32]; pub type StringLimit = BoundedVec::StringLimit>; pub type CollectionId = u32; pub type ItemId = u32; -// (ParentId, Heirarchical) +pub type CollectionDescription = BoundedVec::StringLimit>; +// (ParentId, Hierarchical, Percentage) pub type HierarchicalInfo = (ItemId, bool, u8); #[derive(CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen)] diff --git a/pallets/proxy-financial/src/functions.rs b/pallets/proxy-financial/src/functions.rs index 4978dd98..290f8b9e 100644 --- a/pallets/proxy-financial/src/functions.rs +++ b/pallets/proxy-financial/src/functions.rs @@ -16,32 +16,31 @@ impl Pallet { // -------------------------------------------------------------------------------------------- pub fn do_initial_setup() -> DispatchResult{ + // Create a global scope for the administrator role let pallet_id = Self::pallet_id(); let global_scope = pallet_id.using_encoded(blake2_256); >::put(global_scope); + T::Rbac::create_scope(Self::pallet_id(), global_scope)?; //Admin rol & permissions let administrator_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::Administrator.to_vec()].to_vec())?; T::Rbac::create_and_set_permissions(pallet_id.clone(), administrator_role_id[0], ProxyPermission::administrator_permissions())?; - //Developer rol & permissions - let _developer_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::Developer.to_vec()].to_vec())?; - //T::Rbac::create_and_set_permissions(pallet_id.clone(), developer_role_id[0], ProxyPermission::developer_permissions())?; + //Builder rol & permissions + let builder_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::Builder.to_vec()].to_vec())?; + T::Rbac::create_and_set_permissions(pallet_id.clone(), builder_role_id[0], ProxyPermission::builder_permissions())?; // Investor rol & permissions - let _investor_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::Investor.to_vec()].to_vec())?; - //T::Rbac::create_and_set_permissions(pallet_id.clone(), investor_role_id[0], ProxyPermission::investor_permissions())?; + let investor_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::Investor.to_vec()].to_vec())?; + T::Rbac::create_and_set_permissions(pallet_id.clone(), investor_role_id[0], ProxyPermission::investor_permissions())?; // Issuer rol & permissions - let _issuer_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::Issuer.to_vec()].to_vec())?; - //T::Rbac::create_and_set_permissions(pallet_id.clone(), issuer_role_id[0], ProxyPermission::issuer_permissions())?; + let issuer_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::Issuer.to_vec()].to_vec())?; + T::Rbac::create_and_set_permissions(pallet_id.clone(), issuer_role_id[0], ProxyPermission::issuer_permissions())?; // Regional center rol & permissions - let _regional_center_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::RegionalCenter.to_vec()].to_vec())?; - //T::Rbac::create_and_set_permissions(pallet_id.clone(), regional_center_role_id[0], ProxyPermission::regional_center_permissions())?; - - // Create a global scope for the administrator role - T::Rbac::create_scope(Self::pallet_id(), global_scope)?; + let regional_center_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [ProxyRole::RegionalCenter.to_vec()].to_vec())?; + T::Rbac::create_and_set_permissions(pallet_id.clone(), regional_center_role_id[0], ProxyPermission::regional_center_permissions())?; Self::deposit_event(Event::ProxySetupCompleted); Ok(()) @@ -51,16 +50,7 @@ impl Pallet { admin: T::AccountId, name: FieldName, ) -> DispatchResult{ - let pallet_id = Self::pallet_id(); - let global_scope = >::try_get().map_err(|_| Error::::GlobalScopeNotSet)?; - - T::Rbac::assign_role_to_user( - admin.clone(), - pallet_id.clone(), - &global_scope, - ProxyRole::Administrator.id())?; - - // create a administrator user account + // create a administrator user account & register it in the rbac pallet Self::sudo_register_admin(admin.clone(), name)?; Self::deposit_event(Event::AdministratorAssigned(admin)); @@ -70,16 +60,7 @@ impl Pallet { pub fn do_sudo_remove_administrator( admin: T::AccountId, ) -> DispatchResult{ - let pallet_id = Self::pallet_id(); - let global_scope = >::try_get().map_err(|_| Error::::GlobalScopeNotSet)?; - - T::Rbac::remove_role_from_user( - admin.clone(), - pallet_id.clone(), - &global_scope, - ProxyRole::Administrator.id())?; - - // remove administrator user account + // remove administrator user account & remove it from the rbac pallet Self::sudo_delete_admin(admin.clone())?; Self::deposit_event(Event::AdministratorRemoved(admin)); @@ -118,7 +99,7 @@ impl Pallet { ), T::MaxRegistrationsAtTime>>, ) -> DispatchResult { // Ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::CreateProject)?; //Add timestamp let timestamp = Self::get_timestamp_in_milliseconds().ok_or(Error::::TimestampError)?; @@ -132,7 +113,7 @@ impl Pallet { //Create project data let project_data = ProjectData:: { - developer: Some(BoundedVec::::default()), + builder: Some(BoundedVec::::default()), investor: Some(BoundedVec::::default()), issuer: Some(BoundedVec::::default()), regional_center: Some(BoundedVec::::default()), @@ -183,8 +164,8 @@ impl Pallet { creation_date: Option, completion_date: Option, ) -> DispatchResult { - //ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::EditProject)?; //Ensure project exists ensure!(ProjectsInfo::::contains_key(project_id), Error::::ProjectNotFound); @@ -241,8 +222,8 @@ impl Pallet { admin: T::AccountId, project_id: [u8;32], ) -> DispatchResult { - //ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::DeleteProject)?; //Ensure project exists & get project data let project_data = ProjectsInfo::::get(project_id).ok_or(Error::::ProjectNotFound)?; @@ -283,8 +264,8 @@ impl Pallet { AssignAction, ), T::MaxRegistrationsAtTime>, ) -> DispatchResult { - //ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::AssignUser)?; //Ensure project exists ensure!(ProjectsInfo::::contains_key(project_id), Error::::ProjectNotFound); @@ -395,8 +376,8 @@ impl Pallet { CUDAction, // 3:action ), T::MaxRegistrationsAtTime>, ) -> DispatchResult { - //ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::RegisterUser)?; for user in users{ match user.3 { @@ -591,8 +572,8 @@ impl Pallet { Option<[u8;32]>, // 6: expenditure_id ), T::MaxRegistrationsAtTime>, ) -> DispatchResult { - // Ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::Expenditures)?; // Ensure project exists ensure!(>::contains_key(project_id), Error::::ProjectNotFound); @@ -769,7 +750,6 @@ impl Pallet { // D R A W D O W N S // -------------------------------------------------------------------------------------------- // For now drawdowns functions are private, but in the future they may be public - fn do_create_drawdown( project_id: [u8;32], drawdown_type: DrawdownType, @@ -820,8 +800,8 @@ impl Pallet { admin: T::AccountId, project_id: [u8;32], ) -> DispatchResult { - // Ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::Expenditures)?; // Ensure project exists ensure!(ProjectsInfo::::contains_key(project_id), Error::::ProjectNotFound); @@ -839,12 +819,9 @@ impl Pallet { } pub fn do_submit_drawdown( - _user: T::AccountId, //TODO: remove underscore when user permissions are implemented project_id: [u8;32], drawdown_id: [u8;32], ) -> DispatchResult { - //TODO: Ensure builder & admin permissions - // Ensure project exists & is not completed Self::is_project_completed(project_id)?; @@ -891,9 +868,9 @@ impl Pallet { project_id: [u8;32], drawdown_id: [u8;32], ) -> DispatchResult { - //ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; - + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::Expenditures)?; + // Get drawdown data & ensure drawdown exists let drawdown_data = DrawdownsInfo::::get(drawdown_id).ok_or(Error::::DrawdownNotFound)?; @@ -949,8 +926,8 @@ impl Pallet { transactions_feedback: Option>, drawdown_feedback: Option>, ) -> DispatchResult { - //ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::Expenditures)?; // Get drawdown data & ensure drawdown exists let drawdown_data = DrawdownsInfo::::get(drawdown_id).ok_or(Error::::DrawdownNotFound)?; @@ -1029,7 +1006,6 @@ impl Pallet { // -------------------------------------------------------------------------------------------- // For now transactions functions are private, but in the future they may be public pub fn do_execute_transactions( - _user: T::AccountId, //TODO: remove underscore when permissions are implemented project_id: [u8;32], drawdown_id: [u8;32], transactions: BoundedVec<( @@ -1040,8 +1016,6 @@ impl Pallet { Option<[u8;32]>, // transaction_id ), T::MaxRegistrationsAtTime>, ) -> DispatchResult { - // Check permissions here so helper private functions doesn't need to check it - // TODO: Ensure admin & builder permissions // Ensure project exists & is not completed so helper private functions doesn't need to check it Self::is_project_completed(project_id)?; @@ -1220,14 +1194,15 @@ impl Pallet { // B U L K U P L O A D T R A N S A C T I O N S pub fn do_up_bulk_upload( - _user: T::AccountId, //TODO: Remove underscore when permissions are implemented + user: T::AccountId, //TODO: Remove underscore when permissions are implemented project_id: [u8;32], drawdown_id: [u8;32], description: FieldDescription, total_amount: u64, documents: Documents, ) -> DispatchResult { - // TODO: Ensure builder permissions + // Ensure builder permissions + Self::is_authorized(user, &project_id, ProxyPermission::UpBulkupload)?; // Ensure project is not completed Self::is_project_completed(project_id)?; @@ -1267,8 +1242,8 @@ impl Pallet { admin: T::AccountId, projects: BoundedVec<([u8;32], Option, CUDAction), T::MaxRegistrationsAtTime>, ) -> DispatchResult { - // Ensure admin permissions - Self::is_superuser(admin.clone(), &Self::get_global_scope(), ProxyRole::Administrator.id())?; + // Ensure admin permissions + Self::is_authorized(admin.clone(), &Self::get_global_scope(), ProxyPermission::Expenditures)?; // Ensure projects is not empty ensure!(!projects.is_empty(), Error::::ProjectsIsEmpty); @@ -1374,21 +1349,21 @@ impl Pallet { ProxyRole::Administrator => { return Err(Error::::CannotRegisterAdminRole.into()); }, - ProxyRole::Developer => { + ProxyRole::Builder => { //TODO: Fix internal validations //TODO: move logic to a helper function to avoid boilerplate //Mutate project data >::try_mutate::<_,_,DispatchError,_>(project_id, |project| { let project = project.as_mut().ok_or(Error::::ProjectNotFound)?; - match project.developer.as_mut() { - Some(developer) => { - //developer.iter().find(|&u| *u != user).ok_or(Error::::UserAlreadyAssignedToProject)?; - developer.try_push(user.clone()).map_err(|_| Error::::MaxDevelopersPerProjectReached)?; + match project.builder.as_mut() { + Some(builder) => { + //builder.iter().find(|&u| *u != user).ok_or(Error::::UserAlreadyAssignedToProject)?; + builder.try_push(user.clone()).map_err(|_| Error::::MaxBuildersPerProjectReached)?; }, None => { - let devs = project.developer.get_or_insert(BoundedVec::::default()); - devs.try_push(user.clone()).map_err(|_| Error::::MaxDevelopersPerProjectReached)?; + let devs = project.builder.get_or_insert(BoundedVec::::default()); + devs.try_push(user.clone()).map_err(|_| Error::::MaxBuildersPerProjectReached)?; } } Ok(()) @@ -1460,16 +1435,16 @@ impl Pallet { ProxyRole::Administrator => { return Err(Error::::CannotRemoveAdminRole.into()); }, - ProxyRole::Developer => { + ProxyRole::Builder => { //TODO: Fix internal validations //TODO: move logic to a helper function to avoid boilerplate //Mutate project data >::try_mutate::<_,_,DispatchError,_>(project_id, |project| { let project = project.as_mut().ok_or(Error::::ProjectNotFound)?; - match project.developer.as_mut() { - Some(developer) => { - //developer.clone().iter().find(|&u| *u == user).ok_or(Error::::UserNotAssignedToProject)?; - developer.retain(|u| *u != user); + match project.builder.as_mut() { + Some(builder) => { + //builder.clone().iter().find(|&u| *u == user).ok_or(Error::::UserNotAssignedToProject)?; + builder.retain(|u| *u != user); }, None => { return Err(Error::::UserNotAssignedToProject.into()); @@ -1606,7 +1581,6 @@ impl Pallet { } } - #[allow(dead_code)] fn is_transaction_editable( transaction_id: [u8;32], ) -> DispatchResult { @@ -1625,9 +1599,8 @@ impl Pallet { } } - //TODO: remove macro when used - #[allow(dead_code)] - fn is_authorized( authority: T::AccountId, project_id: &[u8;32], permission: ProxyPermission ) -> DispatchResult{ + + pub fn is_authorized( authority: T::AccountId, project_id: &[u8;32], permission: ProxyPermission ) -> DispatchResult{ T::Rbac::is_authorized( authority, Self::pallet_id(), @@ -1636,6 +1609,7 @@ impl Pallet { ) } + #[allow(dead_code)] fn is_superuser( authority: T::AccountId, scope_global: &[u8;32], rol_id: RoleId ) -> DispatchResult{ T::Rbac::has_role( authority, @@ -1666,6 +1640,15 @@ impl Pallet { //Insert user data >::insert(admin.clone(), user_data); + + // Add administrator to rbac pallet + T::Rbac::assign_role_to_user( + admin.clone(), + Self::pallet_id(), + &Self::get_global_scope(), + ProxyRole::Administrator.id() + )?; + Ok(()) } @@ -1676,6 +1659,14 @@ impl Pallet { //Remove user from UsersInfo storage map >::remove(admin.clone()); + // Remove administrator to rbac pallet + T::Rbac::remove_role_from_user( + admin.clone(), + Self::pallet_id(), + &Self::get_global_scope(), + ProxyRole::Administrator.id() + )?; + Ok(()) } diff --git a/pallets/proxy-financial/src/lib.rs b/pallets/proxy-financial/src/lib.rs index a5e38b67..8a9922a6 100644 --- a/pallets/proxy-financial/src/lib.rs +++ b/pallets/proxy-financial/src/lib.rs @@ -55,10 +55,6 @@ pub mod pallet { type RemoveOrigin: EnsureOrigin; - //TODO: Update pallet errors related to bounded vecs bounds - //ie: BoundedVec - // -> MaxDevelopersPerProjectReached - #[pallet::constant] type ProjectNameMaxLen: Get; @@ -81,7 +77,7 @@ pub mod pallet { type CIDMaxLen: Get; #[pallet::constant] - type MaxDevelopersPerProject: Get; + type MaxBuildersPerProject: Get; #[pallet::constant] type MaxInvestorsPerProject: Get; @@ -327,8 +323,8 @@ pub mod pallet { UserNotAssignedToProject, /// Can not register administator role CannotRegisterAdminRole, - /// Max number of developers per project reached - MaxDevelopersPerProjectReached, + /// Max number of builders per project reached + MaxBuildersPerProjectReached, /// Max number of investors per project reached MaxInvestorsPerProjectReached, /// Max number of issuers per project reached @@ -661,12 +657,13 @@ pub mod pallet { submit: bool, ) -> DispatchResult { let who = ensure_signed(origin)?; // origin need to be an admin - + // Ensure builder permissions + Self::is_authorized(who, &project_id, ProxyPermission::SubmitDrawdown)?; + match submit{ false => { // Do execute transactions Self::do_execute_transactions( - who, project_id, drawdown_id, transactions.ok_or(Error::::EmptyTransactions)?, @@ -677,7 +674,6 @@ pub mod pallet { if let Some(transactions) = transactions { // Do execute transactions Self::do_execute_transactions( - who.clone(), project_id, drawdown_id, transactions, @@ -685,7 +681,7 @@ pub mod pallet { } // Do submit drawdown - Self::do_submit_drawdown(who, project_id, drawdown_id) + Self::do_submit_drawdown(project_id, drawdown_id) }, } @@ -721,14 +717,13 @@ pub mod pallet { false => { // 1. Do execute transactions Self::do_execute_transactions( - who.clone(), project_id, drawdown_id, transactions.ok_or(Error::::EmptyTransactions)?, )?; // 2. Do submit drawdown - Self::do_submit_drawdown(who, project_id, drawdown_id) + Self::do_submit_drawdown(project_id, drawdown_id) }, true => { @@ -736,14 +731,13 @@ pub mod pallet { if let Some(transactions) = transactions { // Do execute transactions Self::do_execute_transactions( - who.clone(), project_id, drawdown_id, transactions, )?; // 2. Submit drawdown - Self::do_submit_drawdown(who.clone(), project_id, drawdown_id)?; + Self::do_submit_drawdown(project_id, drawdown_id)?; } // 3. Approve drawdown diff --git a/pallets/proxy-financial/src/mock.rs b/pallets/proxy-financial/src/mock.rs index 76615d11..f6f0be0c 100644 --- a/pallets/proxy-financial/src/mock.rs +++ b/pallets/proxy-financial/src/mock.rs @@ -66,7 +66,7 @@ parameter_types! { pub const MaxProjectsPerUser:u32 = 10; pub const CIDMaxLen:u32 = 100; pub const MaxUserPerProject:u32 = 50; - pub const MaxDevelopersPerProject:u32 = 1; + pub const MaxBuildersPerProject:u32 = 1; pub const MaxInvestorsPerProject:u32 = 50; pub const MaxIssuersPerProject:u32 = 1; pub const MaxRegionalCenterPerProject:u32 = 1; @@ -89,7 +89,7 @@ impl pallet_proxy_financial::Config for Test { type MaxProjectsPerUser = MaxProjectsPerUser; type CIDMaxLen = CIDMaxLen; type MaxUserPerProject = MaxUserPerProject; - type MaxDevelopersPerProject = MaxDevelopersPerProject; + type MaxBuildersPerProject = MaxBuildersPerProject; type MaxInvestorsPerProject = MaxInvestorsPerProject; type MaxIssuersPerProject = MaxIssuersPerProject; type MaxRegionalCenterPerProject = MaxRegionalCenterPerProject; diff --git a/pallets/proxy-financial/src/types.rs b/pallets/proxy-financial/src/types.rs index 1b00fe2e..412a8a90 100644 --- a/pallets/proxy-financial/src/types.rs +++ b/pallets/proxy-financial/src/types.rs @@ -14,7 +14,7 @@ pub type Documents = BoundedVec<(FieldName,CID), ::MaxDocuments> #[scale_info(skip_type_params(T))] #[codec(mel_bound())] pub struct ProjectData { - pub developer: Option>, + pub builder: Option>, pub investor: Option>, pub issuer: Option>, pub regional_center: Option>, @@ -57,7 +57,7 @@ pub struct UserData { #[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebugNoBound, MaxEncodedLen, TypeInfo, Copy)] pub enum ProxyRole { Administrator, - Developer, + Builder, Investor, Issuer, RegionalCenter, @@ -190,7 +190,7 @@ impl ProxyRole { //TOREVIEW: optimization (?) //Self::Administrator => b"Administrator".to_vec(), Self::Administrator => "Administrator".as_bytes().to_vec(), - Self::Developer => "Developer".as_bytes().to_vec(), + Self::Builder => "Builder".as_bytes().to_vec(), Self::Investor => "Investor".as_bytes().to_vec(), Self::Issuer => "Issuer".as_bytes().to_vec(), Self::RegionalCenter => "RegionalCenter".as_bytes().to_vec(), @@ -203,7 +203,7 @@ impl ProxyRole { pub fn enum_to_vec() -> Vec>{ use crate::types::ProxyRole::*; - [Administrator.to_vec(), Developer.to_vec(), Investor.to_vec(), Issuer.to_vec(), RegionalCenter.to_vec()].to_vec() + [Administrator.to_vec(), Builder.to_vec(), Investor.to_vec(), Issuer.to_vec(), RegionalCenter.to_vec()].to_vec() } } @@ -213,28 +213,35 @@ impl ProxyRole { /// Extrinsics which require previous authorization to call them #[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebugNoBound, MaxEncodedLen, TypeInfo, Copy)] pub enum ProxyPermission { - RegisterUser, // users_register_user - UpdateUser, // users_update_user - DeleteUser, // users_delete_user + RegisterUser, // users + EditUser, // users_edit_user CreateProject, // projects_create_project EditProject, // projects_edit_project DeleteProject, // projects_delete_project AssignUser, // projects_assign_user - UnassignUser, // projects_unassign_user + Expenditures, // expenditures + SubmitDrawdown, // submit_drawdown + ApproveDrawdown, // approve_drawdown + RejectDrawdown, // reject_drawdown + UpBulkupload, // up_bulkupload + Inflation, // inflation } impl ProxyPermission { pub fn to_vec(self) -> Vec{ match self{ Self::RegisterUser => "RegisterUser".as_bytes().to_vec(), - Self::UpdateUser => "UpdateUser".as_bytes().to_vec(), - Self::DeleteUser => "DeleteUser".as_bytes().to_vec(), + Self::EditUser => "EditUser".as_bytes().to_vec(), Self::CreateProject => "CreateProject".as_bytes().to_vec(), Self::EditProject => "EditProject".as_bytes().to_vec(), Self::DeleteProject => "DeleteProject".as_bytes().to_vec(), Self::AssignUser => "AssignUser".as_bytes().to_vec(), - Self::UnassignUser => "UnassignUser".as_bytes().to_vec(), - + Self::Expenditures => "Expenditures".as_bytes().to_vec(), + Self::SubmitDrawdown => "SubmitDrawdown".as_bytes().to_vec(), + Self::ApproveDrawdown => "ApproveDrawdown".as_bytes().to_vec(), + Self::RejectDrawdown => "RejectDrawdown".as_bytes().to_vec(), + Self::UpBulkupload => "UpBulkupload".as_bytes().to_vec(), + Self::Inflation => "Inflation".as_bytes().to_vec(), } } @@ -244,26 +251,46 @@ impl ProxyPermission { pub fn administrator_permissions() -> Vec>{ use crate::types::ProxyPermission::*; - //TODO: change it to mut when add new roles let administrator_permissions = [ RegisterUser.to_vec(), - UpdateUser.to_vec(), - DeleteUser.to_vec(), + EditUser.to_vec(), CreateProject.to_vec(), EditProject.to_vec(), DeleteProject.to_vec(), AssignUser.to_vec(), - UnassignUser.to_vec(), + Expenditures.to_vec(), + SubmitDrawdown.to_vec(), + ApproveDrawdown.to_vec(), + RejectDrawdown.to_vec(), + UpBulkupload.to_vec(), + Inflation.to_vec(), ].to_vec(); administrator_permissions } - // pub fn developer_permissions() -> Vec>{ - // //use crate::types::ProxyPermission::*; - // let developer_permissions = [ - // ].to_vec(); - // developer_permissions - // } + pub fn builder_permissions() -> Vec>{ + use crate::types::ProxyPermission::*; + [ + EditUser.to_vec(), + SubmitDrawdown.to_vec(), + UpBulkupload.to_vec(), + ].to_vec() + } + + pub fn investor_permissions() -> Vec>{ + use crate::types::ProxyPermission::*; + [EditUser.to_vec(),].to_vec() + } + + pub fn issuer_permissions() -> Vec>{ + use crate::types::ProxyPermission::*; + [EditUser.to_vec(),].to_vec() + } + + pub fn regional_center_permissions() -> Vec>{ + use crate::types::ProxyPermission::*; + [EditUser.to_vec(),].to_vec() + } } \ No newline at end of file diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 29d87870..2611885d 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -106,7 +106,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 121, + spec_version: 122, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -562,7 +562,7 @@ parameter_types! { pub const MaxProjectsPerUser:u32 = 10; pub const CIDMaxLen:u32 = 100; pub const MaxUserPerProject:u32 = 50; - pub const MaxDevelopersPerProject:u32 = 1; + pub const MaxBuildersPerProject:u32 = 1; pub const MaxInvestorsPerProject:u32 = 50; pub const MaxIssuersPerProject:u32 = 1; pub const MaxRegionalCenterPerProject:u32 = 1; @@ -592,7 +592,7 @@ impl pallet_proxy_financial::Config for Runtime { type MaxProjectsPerUser = MaxProjectsPerUser; type CIDMaxLen = CIDMaxLen; type MaxUserPerProject = MaxUserPerProject; - type MaxDevelopersPerProject = MaxDevelopersPerProject; + type MaxBuildersPerProject = MaxBuildersPerProject; type MaxInvestorsPerProject = MaxInvestorsPerProject; type MaxIssuersPerProject = MaxIssuersPerProject; type MaxRegionalCenterPerProject = MaxRegionalCenterPerProject;