@@ -309,9 +309,8 @@ impl<T: Config> Pallet<T> {
309309
310310 pub fn do_assign_user (
311311 admin : T :: AccountId ,
312- user : T :: AccountId ,
313312 project_id : [ u8 ; 32 ] ,
314- role : ProxyRole ,
313+ users : BoundedVec < ( T :: AccountId , ProxyRole ) , T :: MaxResgistrationsAtTime > ,
315314 ) -> DispatchResult {
316315 //ensure admin permissions
317316 Self :: is_superuser ( admin. clone ( ) , & Self :: get_global_scope ( ) , ProxyRole :: Administrator . id ( ) ) ?;
@@ -322,43 +321,38 @@ impl<T: Config> Pallet<T> {
322321 // Ensure project is not completed
323322 Self :: is_project_completed ( project_id) ?;
324323
325- //Ensure user is registered
326- ensure ! ( <UsersInfo <T >>:: contains_key( user. clone( ) ) , Error :: <T >:: UserNotRegistered ) ;
324+ for user in users{
325+ // Basic validations prior to assign user
326+ Self :: check_user_role ( user. 0 . clone ( ) , user. 1 ) ?;
327327
328- //Ensure user is not already assigned to the project
329- ensure ! ( !<UsersByProject <T >>:: get( project_id) . contains( & user. clone ( ) ) , Error :: <T >:: UserAlreadyAssignedToProject ) ;
330- ensure ! ( !<ProjectsByUser <T >>:: get( user. clone( ) ) . contains( & project_id) , Error :: <T >:: UserAlreadyAssignedToProject ) ;
328+ //Ensure user is not already assigned to the project
329+ ensure ! ( !<UsersByProject <T >>:: get( project_id) . contains( & user. 0 ) , Error :: <T >:: UserAlreadyAssignedToProject ) ;
330+ ensure ! ( !<ProjectsByUser <T >>:: get( user. 0 . clone( ) ) . contains( & project_id) , Error :: <T >:: UserAlreadyAssignedToProject ) ;
331331
332- // Ensure user is not assigened to the selected scope (project_id) with the selected role
333- ensure ! ( !T :: Rbac :: has_role( user. clone( ) , Self :: pallet_id( ) , & project_id, [ role . id( ) ] . to_vec( ) ) . is_ok( ) , Error :: <T >:: UserAlreadyHasRole ) ;
332+ // Ensure user is not assigened to the selected scope (project_id) with the selected role
333+ ensure ! ( !T :: Rbac :: has_role( user. 0 . clone( ) , Self :: pallet_id( ) , & project_id, [ user . 1 . id( ) ] . to_vec( ) ) . is_ok( ) , Error :: <T >:: UserAlreadyAssignedToProject ) ;
334334
335- // Update project data depending on the role assigned
336- Self :: add_project_role ( project_id, user. clone ( ) , role ) ?;
335+ // Update project data depending on the role assigned
336+ Self :: add_project_role ( project_id, user. 0 . clone ( ) , user . 1 ) ?;
337337
338-
339- //HERE
340- //Update user data depending on the role assigned
341- //Self::add_user_role(user.clone(), role)?;
342-
343- //TOREVIEW: this storage map will be removed?
344- // Insert project to ProjectsByUser storagemap
345- <ProjectsByUser < T > >:: try_mutate :: < _ , _ , DispatchError , _ > ( user. clone ( ) , |projects| {
346- projects. try_push ( project_id) . map_err ( |_| Error :: < T > :: MaxProjectsPerUserReached ) ?;
347- Ok ( ( ) )
348- } ) ?;
338+ // Insert project to ProjectsByUser storagemap
339+ <ProjectsByUser < T > >:: try_mutate :: < _ , _ , DispatchError , _ > ( user. 0 . clone ( ) , |projects| {
340+ projects. try_push ( project_id) . map_err ( |_| Error :: < T > :: MaxProjectsPerUserReached ) ?;
341+ Ok ( ( ) )
342+ } ) ?;
349343
350- //TOREVIEW: this storage map will be removed?
351- // Insert user to UsersByProject storagemap
352- <UsersByProject < T > >:: try_mutate :: < _ , _ , DispatchError , _ > ( project_id, |users| {
353- users. try_push ( user. clone ( ) ) . map_err ( |_| Error :: < T > :: MaxUsersPerProjectReached ) ?;
354- Ok ( ( ) )
355- } ) ?;
344+ // Insert user to UsersByProject storagemap
345+ <UsersByProject < T > >:: try_mutate :: < _ , _ , DispatchError , _ > ( project_id, |users| {
346+ users. try_push ( user. 0 . clone ( ) ) . map_err ( |_| Error :: < T > :: MaxUsersPerProjectReached ) ?;
347+ Ok ( ( ) )
348+ } ) ?;
356349
357- // Insert user into scope rbac pallet
358- T :: Rbac :: assign_role_to_user ( user. clone ( ) , Self :: pallet_id ( ) , & project_id, role. id ( ) ) ?;
350+ // Insert user into scope rbac pallet
351+ T :: Rbac :: assign_role_to_user ( user. 0 . clone ( ) , Self :: pallet_id ( ) , & project_id, user. 1 . id ( ) ) ?;
352+ }
359353
360354 //Event
361- Self :: deposit_event ( Event :: UserAssignedToProject ( user , project_id ) ) ;
355+ Self :: deposit_event ( Event :: UserAssignedToProject ) ;
362356 Ok ( ( ) )
363357 }
364358
@@ -499,6 +493,19 @@ impl<T: Config> Pallet<T> {
499493
500494 // B U D G E T E X P E N D I T U R E
501495 // --------------------------------------------------------------------------------------------
496+ /// Create a new budget expenditure
497+ ///
498+ /// # Arguments
499+ ///
500+ /// * `admin` - The admin user that creates the budget expenditure
501+ /// * `project_id` - The project id where the budget expenditure will be created
502+ ///
503+ /// Then we add the budget expenditure data
504+ /// * `name` - The name of the budget expenditure
505+ /// * `type` - The type of the budget expenditure
506+ /// * `budget amount` - The amount of the budget expenditure
507+ /// * `naics code` - The naics code of the budget expenditure
508+ /// * `jobs_multiplier` - The jobs multiplier of the budget expenditure
502509 pub fn do_create_expenditure (
503510 admin : T :: AccountId ,
504511 project_id : [ u8 ; 32 ] ,
@@ -579,9 +586,8 @@ impl<T: Config> Pallet<T> {
579586 } ,
580587 None => {
581588 Self :: do_create_budget ( admin. clone ( ) , expenditure_id, 0 , project_id) ?;
582- } ,
583- }
584-
589+ } ,
590+ }
585591 }
586592
587593 Self :: deposit_event ( Event :: ExpenditureCreated ) ;
@@ -1304,43 +1310,30 @@ impl<T: Config> Pallet<T> {
13041310 }
13051311
13061312
1307- //HERE
1308- // fn add_user_role(
1309- // user: T::AccountId,
1310- // role: ProxyRole,
1311- // ) -> DispatchResult {
1312- // // Get user account data
1313- // let user_data = UsersInfo::<T>::get(user.clone()).ok_or(Error::<T>::UserNotRegistered)?;
1313+ /// This functions performs the following checks:
1314+ ///
1315+ /// 1. Checks if the user is registered in the system
1316+ /// 2. Checks if the user has the required role from UsersInfo storage
1317+ /// 3. Checks if the user is trying to assign an admin role
1318+ fn check_user_role (
1319+ user : T :: AccountId ,
1320+ role : ProxyRole ,
1321+ ) -> DispatchResult {
1322+ // Ensure user is registered & get user data
1323+ let user_data = UsersInfo :: < T > :: get ( user. clone ( ) ) . ok_or ( Error :: < T > :: UserNotRegistered ) ?;
13141324
1315- // // Check if user already has a role
1316- // match user_data.role {
1317- // Some(user_role) => {
1318- // //TODO: Ccheck what role is the user trying to add
1319- // if user_role == role {
1320- // return Ok(())
1321- // } else {
1322- // return Err(Error::<T>::UserCannotHaveMoreThanOneRole.into());
1323- // }
1324- // },
1325- // None => {
1326- // match role {
1327- // ProxyRole::Administrator => {
1328- // return Err(Error::<T>::CannotAddAdminRole.into());
1329- // },
1330- // _ => {
1331- // // Update user data
1332- // <UsersInfo<T>>::try_mutate::<_,_,DispatchError,_>(user.clone(), |user_data| {
1333- // let user_data = user_data.as_mut().ok_or(Error::<T>::UserNotRegistered)?;
1334- // user_data.role = Some(role);
1335- // Ok(())
1336- // })?;
1337- // //TOREVIEW: Remove ? operator and final Ok(())
1338- // Ok(())
1339- // },
1340- // }
1341- // }
1342- // }
1343- // }
1325+ // Check if the user role trying to be assigned matchs the actual user role from UsersInfo storage
1326+ if user_data. role != role {
1327+ return Err ( Error :: < T > :: UserCannotHaveMoreThanOneRole . into ( ) ) ;
1328+ }
1329+
1330+ // Can't assign an admin to a project, admins exists globally
1331+ if role == ProxyRole :: Administrator {
1332+ return Err ( Error :: < T > :: CannotAddAdminRole . into ( ) ) ;
1333+ }
1334+
1335+ Ok ( ( ) )
1336+ }
13441337
13451338
13461339 //HERE
0 commit comments