From fe49792fc050eaca026eb85a346e12620d8124e9 Mon Sep 17 00:00:00 2001 From: Andrea Adamczyk Date: Tue, 8 Sep 2020 16:20:28 -0400 Subject: [PATCH] PMCORE-561 --- gulliver/system/class.rbac.php | 1 + .../engine/methods/users/Users_AjaxTest.php | 147 ++++++++++++++++++ .../src/ProcessMaker/Model/ProcessTest.php | 59 +++++++ .../ProcessMaker/Services/Api/ProjectTest.php | 49 ++++++ workflow/engine/classes/model/Process.php | 3 + .../translations/english/processmaker.en.po | 6 + workflow/engine/data/mysql/insert.sql | 1 + workflow/engine/methods/users/users_Ajax.php | 10 ++ .../engine/src/ProcessMaker/Model/Process.php | 33 ++++ .../src/ProcessMaker/Services/Api/Project.php | 26 ++-- workflow/engine/templates/users/usersList.js | 33 +++- 11 files changed, 355 insertions(+), 13 deletions(-) create mode 100644 tests/unit/workflow/engine/methods/users/Users_AjaxTest.php diff --git a/gulliver/system/class.rbac.php b/gulliver/system/class.rbac.php index d211e625f..49d49e7bd 100644 --- a/gulliver/system/class.rbac.php +++ b/gulliver/system/class.rbac.php @@ -57,6 +57,7 @@ class RBAC 'ofToAssign' => ['PM_FACTORY'], 'usersGroup' => ['PM_FACTORY'], 'canDeleteUser' => ['PM_USERS'], + 'privateProcesses' => ['PM_USERS'], 'deleteUser' => ['PM_USERS'], 'changeUserStatus' => ['PM_USERS'], 'availableGroups' => ['PM_USERS'], diff --git a/tests/unit/workflow/engine/methods/users/Users_AjaxTest.php b/tests/unit/workflow/engine/methods/users/Users_AjaxTest.php new file mode 100644 index 000000000..d5796adab --- /dev/null +++ b/tests/unit/workflow/engine/methods/users/Users_AjaxTest.php @@ -0,0 +1,147 @@ +create(); + $usrUid = $user['USR_UID']; + factory(Process::class)->create([ + 'PRO_CREATE_USER' => $usrUid, + 'PRO_STATUS' => 'ACTIVE', + 'PRO_TYPE_PROCESS' => 'PRIVATE', + ]); + + //Creates the configuration factory + factory(Configuration::class)->create([ + 'CFG_UID' => 'USER_PREFERENCES', + 'OBJ_UID' => '', + 'CFG_VALUE' => 'a:3:{s:12:"DEFAULT_LANG";s:0:"";s:12:"DEFAULT_MENU";s:8:"PM_SETUP";s:18:"DEFAULT_CASES_MENU";s:0:"";}', + 'PRO_UID' => '', + 'USR_UID' => $usrUid, + 'APP_UID' => '', + ]); + + //Sets the needed variables + $_SESSION['USER_LOGGED'] = '00000000000000000000000000000001'; + $_POST['action'] = 'privateProcesses'; + $_POST['USR_UID'] = $usrUid; + $_REQUEST['function'] = 'privateProcesses'; + $_GET['function'] = 'privateProcesses'; + $RBAC = RBAC::getSingleton(PATH_DATA, session_id()); + $RBAC->initRBAC(); + $RBAC->loadUserRolePermission('PROCESSMAKER', $_SESSION['USER_LOGGED']); + + //Turn on output buffering + ob_start(); + + //Call the tested file + require_once PATH_TRUNK . 'workflow/engine/methods/users/users_Ajax.php'; + + //Return the contents of the output buffer + $outputBuffer = ob_get_contents(); + + //Clean the output buffer and turn off output buffering + ob_end_clean(); + + //Removing the BOM (Byte Order Mark) + if (0 === strpos(bin2hex($outputBuffer), 'efbbbf')) { + //Decode the JSON string + $res = json_decode(substr($outputBuffer, 3)); + } else { + //Decode the JSON string + $res = json_decode($outputBuffer); + } + + //Assert the response contains a row + $this->assertNotEmpty($res); + } + + /** + * Tests the users_ajax file with the deleteUser action + * @test + */ + public function it_tests_the_users_ajax_file_delete_user_action() + { + //Declare the global variable + global $RBAC; + + //Creates the user factory + $user = factory(User::class)->create(); + factory(RbacUsers::class)->create([ + 'USR_UID' => $user['USR_UID'], + 'USR_USERNAME' => $user->USR_USERNAME, + 'USR_FIRSTNAME' => $user->USR_FIRSTNAME, + 'USR_LASTNAME' => $user->USR_LASTNAME + ]); + $usrUid = $user['USR_UID']; + + $process = factory(Process::class)->create([ + 'PRO_CREATE_USER' => $usrUid, + 'PRO_STATUS' => 'ACTIVE', + 'PRO_TYPE_PROCESS' => 'PRIVATE', + ]); + + //Sets the needed variables + $_SESSION['USER_LOGGED'] = '00000000000000000000000000000001'; + $_POST['action'] = 'userData'; + $_POST['USR_UID'] = $usrUid; + $_REQUEST['function'] = 'deleteUser'; + $_GET['function'] = 'deleteUser'; + $_POST['private_processes'] = Process::where('PRO_ID', $process->PRO_ID)->get(); + $RBAC = RBAC::getSingleton(PATH_DATA, session_id()); + $RBAC->initRBAC(); + $RBAC->loadUserRolePermission('PROCESSMAKER', $_SESSION['USER_LOGGED']); + + //Turn on output buffering + ob_start(); + + //Call the tested file + require_once PATH_TRUNK . 'workflow/engine/methods/users/users_Ajax.php'; + + //Return the contents of the output buffer + $outputBuffer = ob_get_contents(); + + //Clean the output buffer and turn off output buffering + ob_end_clean(); + + //Removing the BOM (Byte Order Mark) + if (0 === strpos(bin2hex($outputBuffer), 'efbbbf')) { + //Decode the JSON string + $res = json_decode(substr($outputBuffer, 3)); + } else { + //Decode the JSON string + $res = json_decode($outputBuffer); + } + + //Asserts the result is null + $this->assertNull($res); + } +} \ No newline at end of file diff --git a/tests/unit/workflow/engine/src/ProcessMaker/Model/ProcessTest.php b/tests/unit/workflow/engine/src/ProcessMaker/Model/ProcessTest.php index 9168176e5..97c61c96f 100644 --- a/tests/unit/workflow/engine/src/ProcessMaker/Model/ProcessTest.php +++ b/tests/unit/workflow/engine/src/ProcessMaker/Model/ProcessTest.php @@ -183,4 +183,63 @@ class ProcessTest extends TestCase $this->assertNotEquals($process2['PRO_UID'], $res[0]['PRO_UID']); $this->assertNotEquals($process3['PRO_UID'], $res[0]['PRO_UID']); } + + /** + * It tests the getProcessPrivateListByUser method + * + * @covers \ProcessMaker\Model\Process::getProcessPrivateListByUser() + * @test + */ + public function it_should_test_the_get_process_private_list_by_user_method() + { + //Create user + $user = factory(User::class)->create(); + + //Create process + factory(Process::class)->create([ + 'PRO_CREATE_USER' => $user['USR_UID'], + 'PRO_STATUS' => 'ACTIVE', + 'PRO_TYPE_PROCESS' => 'PRIVATE', + ]); + + //Create a Process object + $process = new Process(); + + //Call the getProcessPrivateListByUser() method + $res = $process->getProcessPrivateListByUser($user['USR_UID']); + + // This asserts the result contains one row + $this->assertCount(1, $res); + } + + /** + * It tests the convertPrivateProcessesToPublic method + * + * @covers \ProcessMaker\Model\Process::convertPrivateProcessesToPublic() + * @test + */ + public function it_should_test_the_convert_private_processes_to_public_method() + { + //Create user + $user = factory(User::class)->create(); + + //Create process + $pro = factory(Process::class)->create([ + 'PRO_CREATE_USER' => $user['USR_UID'], + 'PRO_STATUS' => 'ACTIVE', + 'PRO_TYPE_PROCESS' => 'PRIVATE', + ]); + + $p = Process::where('PRO_UID', $pro->PRO_UID)->get()->values()->toArray(); + //Create a Process object + $process = new Process(); + + //Call the convertPrivateProcessesToPublic() method + $process->convertPrivateProcessesToPublic($p); + + $p = Process::where('PRO_UID', $pro->PRO_UID)->get()->values(); + + // This asserts the process was converted from private to public + $this->assertEquals('PUBLIC', $p[0]->PRO_TYPE_PROCESS); + } } \ No newline at end of file diff --git a/tests/unit/workflow/engine/src/ProcessMaker/Services/Api/ProjectTest.php b/tests/unit/workflow/engine/src/ProcessMaker/Services/Api/ProjectTest.php index 21a9d30d0..1dcc46773 100644 --- a/tests/unit/workflow/engine/src/ProcessMaker/Services/Api/ProjectTest.php +++ b/tests/unit/workflow/engine/src/ProcessMaker/Services/Api/ProjectTest.php @@ -5,6 +5,7 @@ namespace Tests\unit\workflow\engine\src\ProcessMaker\Services\Api; use Faker\Factory; use ProcessMaker\Model\Process; use ProcessMaker\Model\User; +use ProcessMaker\Model\RbacUsers; use ProcessMaker\Importer\XmlImporter; use ProcessMaker\Services\Api\Project; use Tests\TestCase; @@ -40,4 +41,52 @@ class ProjectTest extends TestCase $this->assertNotEmpty($result); } + + /** + * Tests the doGetProcess method + * + * @test + * @covers \ProcessMaker\Services\Api\Project::doGetProcess() + */ + public function it_should_test_the_do_get_process_method() + { + //Create user + $user = factory(User::class)->create(); + factory(RbacUsers::class)->create([ + 'USR_UID' => $user->USR_UID, + 'USR_USERNAME' => $user->USR_USERNAME, + 'USR_FIRSTNAME' => $user->USR_FIRSTNAME, + 'USR_LASTNAME' => $user->USR_LASTNAME + ]); + + //Create process + $process = factory(Process::class)->create([ + 'PRO_CREATE_USER' => $user->USR_UID, + 'PRO_STATUS' => 'ACTIVE', + 'PRO_TYPE_PROCESS' => 'PRIVATE', + ]); + + $project = new Project(); + $res = $project->doGetProcess($process->PRO_UID); + + //Asserts the response has the user information + $this->assertArrayHasKey('pro_create_username', $res); + $this->assertArrayHasKey('pro_create_firstname', $res); + $this->assertArrayHasKey('pro_create_lastname', $res); + } + + /** + * Tests the doGetProcess with exception + * + * @test + * @covers \ProcessMaker\Services\Api\Project::doGetProcess() + */ + public function it_should_test_the_do_get_process_method_with_exception() + { + $project = new Project(); + + //This asserts the expected exception + $this->expectExceptionMessage("**ID_PROJECT_DOES_NOT_EXIST**"); + $project->doGetProcess(''); + } } diff --git a/workflow/engine/classes/model/Process.php b/workflow/engine/classes/model/Process.php index 304ba1cdb..17ea8a301 100644 --- a/workflow/engine/classes/model/Process.php +++ b/workflow/engine/classes/model/Process.php @@ -323,6 +323,9 @@ class Process extends BaseProcess if (isset($aData['PRO_DESCRIPTION'])) { $oPro->setProDescriptionContent($aData['PRO_DESCRIPTION']); } + if (isset($aData['PRO_PROCESS_OWNER'])) { + $oPro->setProCreateUser($aData['PRO_PROCESS_OWNER']); + } $res = $oPro->save(); $con->commit(); diff --git a/workflow/engine/content/translations/english/processmaker.en.po b/workflow/engine/content/translations/english/processmaker.en.po index d9223fbaa..44432e8e2 100755 --- a/workflow/engine/content/translations/english/processmaker.en.po +++ b/workflow/engine/content/translations/english/processmaker.en.po @@ -19253,6 +19253,12 @@ msgstr "Do you want to delete this user ?" msgid "The user can not be deleted while assigned as a supervisor. Do you want to delete it anyway?" msgstr "The user can not be deleted while assigned as a supervisor. Do you want to delete it anyway?" +# TRANSLATION +# LABEL/ID_MSG_CONFIRM_DELETE_USER_PRIVATE_PROCESSES +#: LABEL/ID_MSG_CONFIRM_DELETE_USER_PRIVATE_PROCESSES +msgid "This user has private processes, if you continue all the user's private processes will become public processes. Do you want to continue?" +msgstr "This user has private processes, if you continue all the user's private processes will become public processes. Do you want to continue?" + # TRANSLATION # LABEL/ID_MSG_CONFIRM_DELETE_WEBBOT #: LABEL/ID_MSG_CONFIRM_DELETE_WEBBOT diff --git a/workflow/engine/data/mysql/insert.sql b/workflow/engine/data/mysql/insert.sql index 5507779b8..99f86af6b 100755 --- a/workflow/engine/data/mysql/insert.sql +++ b/workflow/engine/data/mysql/insert.sql @@ -60092,6 +60092,7 @@ INSERT INTO TRANSLATION (TRN_CATEGORY,TRN_ID,TRN_LANG,TRN_VALUE,TRN_UPDATE_DATE ( 'LABEL','ID_MSG_CONFIRM_DELETE_TRIGGER','en','Do you want to delete this trigger?','2014-01-15') , ( 'LABEL','ID_MSG_CONFIRM_DELETE_USER','en','Do you want to delete this user ?','2014-01-15') , ( 'LABEL','ID_MSG_CONFIRM_DELETE_USER_ASSINGED_SUPERVISOR','en','The user can not be deleted while assigned as a supervisor. Do you want to delete it anyway?','2014-10-21') , +( 'LABEL','ID_MSG_CONFIRM_DELETE_USER_PRIVATE_PROCESSES','en',"This user has private processes, if you continue all the user's private processes will become public processes. Do you want to continue?",'2020-09-02') , ( 'LABEL','ID_MSG_CONFIRM_DELETE_WEBBOT','en','Are you sure you want to delete this webbot?','2014-01-15') , ( 'LABEL','ID_MSG_CONFIRM_REMOVE_LANGUAGE','en','Are you sure you want to remove this language?','2014-01-15') , ( 'LABEL','ID_MSG_CONFIRM_REMOVE_TRIGGER','en','Are you sure you want to remove this trigger?','2014-01-15') , diff --git a/workflow/engine/methods/users/users_Ajax.php b/workflow/engine/methods/users/users_Ajax.php index ff4aef854..bd089d394 100644 --- a/workflow/engine/methods/users/users_Ajax.php +++ b/workflow/engine/methods/users/users_Ajax.php @@ -1,5 +1,7 @@ userCanAccess('PM_LOGIN')) { @@ -107,7 +109,15 @@ try { $response .= '}'; echo $response; break; + case 'privateProcesses': + $usrUid = $_POST['USR_UID']; + //Check if the user has private processes + $r = Process::getProcessPrivateListByUser($usrUid); + $response = json_encode(['success'=>true, 'publicProcesses'=>$r]); + echo $response; + break; case 'deleteUser': + Process::convertPrivateProcessesToPublic(json_decode($_POST['private_processes'])); $usrUid = $_POST['USR_UID']; //Check if the user was defined in a process permissions $oObjectPermission = new ObjectPermission(); diff --git a/workflow/engine/src/ProcessMaker/Model/Process.php b/workflow/engine/src/ProcessMaker/Model/Process.php index 0c46cb8db..ab0086363 100644 --- a/workflow/engine/src/ProcessMaker/Model/Process.php +++ b/workflow/engine/src/ProcessMaker/Model/Process.php @@ -3,6 +3,8 @@ namespace ProcessMaker\Model; use Illuminate\Database\Eloquent\Model; +use RbacUsers; +use RBAC; /** * Class Process @@ -57,4 +59,35 @@ class Process extends Model return ($query->get()->values()->toArray()); } + + /** + * Obtains the list of private processes assigned to the user + * + * @param string $userUid + * @return array + */ + public static function getProcessPrivateListByUser($userUid) + { + $query = Process::query() + ->select() + ->where('PRO_CREATE_USER', $userUid) + ->where('PRO_TYPE_PROCESS', 'PRIVATE'); + + return ($query->get()->values()->toArray()); + } + + /** + * Converts the private processes to public + * + * @param array $privateProcesses + * @return void + */ + public static function convertPrivateProcessesToPublic($privateProcesses) + { + $admin = RBAC::ADMIN_USER_UID; + + $processes = array_column($privateProcesses, 'PRO_ID'); + Process::whereIn('PRO_ID', $processes) + ->update(['PRO_TYPE_PROCESS' => 'PUBLIC', 'PRO_CREATE_USER' => $admin]); + } } diff --git a/workflow/engine/src/ProcessMaker/Services/Api/Project.php b/workflow/engine/src/ProcessMaker/Services/Api/Project.php index 81f48f798..ffa1c3dbe 100644 --- a/workflow/engine/src/ProcessMaker/Services/Api/Project.php +++ b/workflow/engine/src/ProcessMaker/Services/Api/Project.php @@ -1,19 +1,19 @@ getProcess($prj_uid); + $rbacUser = new RbacUsers(); + $res = $rbacUser->load($response['pro_create_user']); + if (!empty($res)) { + $response['pro_create_username'] = $res['USR_USERNAME']; + $response['pro_create_firstname'] = $res['USR_FIRSTNAME']; + $response['pro_create_lastname'] = $res['USR_LASTNAME']; + } + return DateTime::convertUtcToIso8601($response, $this->arrayFieldIso8601); } catch (Exception $e) { diff --git a/workflow/engine/templates/users/usersList.js b/workflow/engine/templates/users/usersList.js index 47ff73075..b71ce3452 100644 --- a/workflow/engine/templates/users/usersList.js +++ b/workflow/engine/templates/users/usersList.js @@ -525,7 +525,7 @@ DeleteUserAction = function(){ if (response.hashistory){ Ext.Msg.confirm(_('ID_CONFIRM'), _('ID_USERS_DELETE_WITH_HISTORY'), function(btn){ - if (btn=='yes') DeleteUser(uid.data.USR_UID); + if (btn=='yes') hasPrivateProcesses(uid.data.USR_UID); } ); }else{ @@ -533,7 +533,7 @@ DeleteUserAction = function(){ Ext.Msg.confirm(_('ID_CONFIRM'), msgConfirm, function(btn){ - if (btn=='yes') DeleteUser(uid.data.USR_UID); + if (btn=='yes') hasPrivateProcesses(uid.data.USR_UID); } ); } @@ -631,10 +631,10 @@ DoSearch = function(){ }; //Delete User Function -DeleteUser = function(uid){ +DeleteUser = function(uid, privateProcesses){ Ext.Ajax.request({ url: 'users_Ajax', - params: {'function': 'deleteUser', USR_UID: uid}, + params: {'function': 'deleteUser', USR_UID: uid, private_processes: privateProcesses}, success: function(res, opt){ var response = Ext.util.JSON.decode(res.responseText); if (response.status === 'ERROR') { @@ -648,6 +648,31 @@ DeleteUser = function(uid){ }); }; +/** + * Show a message in case the user to be deleted has private processes + * + * @param {string} uid + */ +hasPrivateProcesses = function (uid) { + Ext.Ajax.request({ + url: 'users_Ajax', + params: { 'function': 'privateProcesses', USR_UID: uid }, + success: function (res, opt) { + var response = Ext.util.JSON.decode(res.responseText); + if (!(response.publicProcesses === undefined || response.publicProcesses.length == 0)) { + Ext.Msg.confirm(_('ID_CONFIRM'), _("ID_MSG_CONFIRM_DELETE_USER_PRIVATE_PROCESSES"), + function(btn){ + if (btn == 'yes') DeleteUser(uid, Ext.util.JSON.encode(response.publicProcesses)); + } + ); + } else { + DeleteUser(uid, Ext.util.JSON.encode(response.publicProcesses)); + } + }, + failure: DoNothing + }); +}; + //Update Page Size Configuration UpdatePageConfig = function(pageSize){ Ext.Ajax.request({