diff --git a/README.md b/README.md index fc83d200f..1c612271d 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ ProcessMaker "Michelangelo" Overview -------- -ProcessMaker is an open source, workflow management software suite, which +ProcessMaker is an open source, workflow management software suite, which includes tools to automate your workflow, design forms, create documents, assign roles and users, create routing rules, and map an individual process quickly and easily. It's relatively lightweight and doesn't require any kind of installation -on the client computer. This file describes the requirements and installation +on the client computer. This file describes the requirements and installation steps for the server. License @@ -32,3 +32,4 @@ http://www.affero.org/oagpl.html For further information visit: http://www.processmaker.com/ + diff --git a/Rakefile b/Rakefile index fc26987ef..9d6e94a57 100644 --- a/Rakefile +++ b/Rakefile @@ -192,7 +192,7 @@ def getVersion(path) version = `rake version` end - return version.strip + return /([0-9\.]{5}+)/.match(version) end diff --git a/features/backend/application_cases/case_task/main_tests_case_tasks.feature b/features/backend/application_cases/case_task/main_tests_case_tasks.feature new file mode 100644 index 000000000..42241cef6 --- /dev/null +++ b/features/backend/application_cases/case_task/main_tests_case_tasks.feature @@ -0,0 +1,107 @@ +@ProcessMakerMichelangelo @RestAPI +Feature: Case Tasks Main Tests +Requirements: + a workspace with the case 383652497533b1492846753088523464 "case #174" and 587530805533b0d5031bd35011041644 "case #146" of the process ("Test Case Variables and Derivation rules-selection") already loaded + +Background: + Given that I have a valid access_token + + +Scenario: Get list case tasks of case 174 + Given I request "cases/383652497533b1492846753088523464/tasks" + Then the response status code should be 200 + And the response charset is "UTF-8" + And the content type is "application/json" + And the type is "array" + And that "tas_uid" is set to "63847491053347e25555c29086425576" + And that "tas_type" is set to "NORMAL" + And that "tas_title" is set to "Task 1" + And that "rou_type" is set to "0" + And that "rou_next_task" is set to "93695356653347e2702ab38033892652" + And that "rou_condition" is set to "" + And that "rou_to_last_user" is set to "FALSE" + And that "rou_optional" is set to "FALSE" + And that "usr_uid" is set to "Administrator" + And that "usr_firstname" is set to "Administrator" + And that "usr_lastname" is set to "" + And that "del_init_date" is set to "2014-04-01 15:33:38" + And that "del_task_due_date" is set to "2014-04-02 15:33:38" + And that "del_finish_date" is set to "2014-04-01 15:33:47" + And that "duration" is set to "0 Hours 0 Minutes 9 Seconds" + And that "color" is set to "#006633" + And that "tas_uid" is set to "93695356653347e2702ab38033892652" + And that "tas_type" is set to "NORMAL" + And that "tas_title" is set to "Task 2" + And that "rou_type" is set to "0" + And that "rou_next_task" is set to "-1" + And that "rou_condition" is set to "" + And that "rou_to_last_user" is set to "FALSE" + And that "rou_optional" is set to "FALSE" + And that "usr_uid" is set to "Administrator" + And that "usr_firstname" is set to "Administrator" + And that "usr_lastname" is set to "" + And that "del_init_date" is set to "Case not started yet" + And that "del_task_due_date" is set to "2014-04-02 15:33:47" + And that "del_finish_date" is set to "Not finished" + And that "duration" is set to "Not finished" + And that "color" is set to "#FF0000" + +Scenario: Get list case tasks of case 146 + Given I request "cases/587530805533b0d5031bd35011041644/tasks" + Then the response status code should be 200 + And the response charset is "UTF-8" + And the content type is "application/json" + And the type is "array" + And that "tas_uid" is set to "17300415050ec6a1687f439060824658" + And that "tas_type" is set to "NORMAL" + And that "tas_title" is set to "Self Service" + And that "rou_type" is set to "" + And that "color" is set to "#939598" + + And that "tas_uid" is set to "18637084950ec669487b1b3034500214" + And that "tas_type" is set to "NORMAL" + And that "tas_title" is set to "Cyclical" + And that "rou_type" is set to "" + And that "color" is set to "#939598" + + And that "tas_uid" is set to "56900024450ec668e4a9243080698854" + And that "tas_type" is set to "NORMAL" + And that "tas_title" is set to "Init" + And that "rou_type" is set to "1" + + And that "rou_next_task" is set to "-1" + And that "rou_condition" is set to "" + And that "rou_to_last_user" is set to "FALSE" + And that "rou_optional" is set to "FALSE" + And that "usr_uid" is set to "Administrator" + And that "usr_firstname" is set to "Administrator" + And that "usr_lastname" is set to "" + And that "del_init_date" is set to "2014-04-01 15:02:40" + And that "del_task_due_date" is set to "2014-04-01 15:02:40" + And that "del_finish_date" is set to "2014-04-01 15:02:51" + And that "duration" is set to "0 Hours 0 Minutes 11 Seconds" + + And that "rou_next_task" is set to "18637084950ec669487b1b3034500214" + And that "rou_condition" is set to "" + And that "rou_to_last_user" is set to "FALSE" + And that "rou_optional" is set to "FALSE" + And that "usr_uid" is set to "Administrator" + And that "usr_firstname" is set to "Administrator" + And that "usr_lastname" is set to "" + And that "del_init_date" is set to "2014-04-01 15:02:40" + And that "del_task_due_date" is set to "2014-04-02 15:02:40" + And that "del_finish_date" is set to "2014-04-01 15:02:51" + And that "duration" is set to "0 Hours 0 Minutes 11 Seconds" + And that "color" is set to "#006633" + + And that "tas_uid" is set to "79440307650ec67a8ba3969022801548" + And that "tas_type" is set to "NORMAL" + And that "tas_title" is set to "Reports to" + And that "rou_type" is set to "" + And that "color" is set to "#939598" + + And that "tas_uid" is set to "82464599650ec679055e040061009891" + And that "tas_type" is set to "NORMAL" + And that "tas_title" is set to "Manual" + And that "rou_type" is set to "" + And that "color" is set to "#939598" \ No newline at end of file diff --git a/features/backend/application_cases/case_task/negative_tests_case_tasks.feature b/features/backend/application_cases/case_task/negative_tests_case_tasks.feature new file mode 100644 index 000000000..64379c2df --- /dev/null +++ b/features/backend/application_cases/case_task/negative_tests_case_tasks.feature @@ -0,0 +1,18 @@ +@ProcessMakerMichelangelo @RestAPI +Feature: Case Tasks Negative Tests +Requirements: + a workspace with the case 383652497533b1492846753088523464 "case #174" and 587530805533b0d5031bd35011041644 "case #146" of the process ("Test Case Variables and Derivation rules-selection") already loaded + +Background: + Given that I have a valid access_token + +Scenario: Get list case tasks of case 174 + Given I request "cases/38365249000000000046753088523464/tasks" + Then the response status code should be 400 + And the response status message should have the following text "doesn't exist" + + +Scenario: Get list case tasks of case 174 + Given I request "cases//tasks" + Then the response status code should be 400 + And the response status message should have the following text "app_uid" \ No newline at end of file diff --git a/gulliver/system/class.publisher.php b/gulliver/system/class.publisher.php index 0000e8c93..40b7fc20e 100755 --- a/gulliver/system/class.publisher.php +++ b/gulliver/system/class.publisher.php @@ -293,15 +293,13 @@ class Publisher $oFieldCondition = new FieldCondition(); //This dynaform has show/hide field conditions - $dynUid = ''; if (isset($_SESSION['CURRENT_DYN_UID']) && $_SESSION['CURRENT_DYN_UID'] != '') { - $dynUid = $_SESSION['CURRENT_DYN_UID']; + $ConditionalShowHideRoutines = $oFieldCondition->getConditionScript($_SESSION["CURRENT_DYN_UID"]); //lsl } else { if (isset($_SESSION['CONDITION_DYN_UID']) && $_SESSION['CONDITION_DYN_UID'] != '') { - $dynUid = $_SESSION['CONDITION_DYN_UID']; + $ConditionalShowHideRoutines = $oFieldCondition->getConditionScript($_SESSION["CONDITION_DYN_UID"]); //lsl } } - $ConditionalShowHideRoutines = $oFieldCondition->getConditionScript($dynUid); } } diff --git a/gulliver/system/class.xmlform.php b/gulliver/system/class.xmlform.php index aa8c38a31..b8dc6db09 100755 --- a/gulliver/system/class.xmlform.php +++ b/gulliver/system/class.xmlform.php @@ -3178,17 +3178,12 @@ class XmlForm_Field_Checkbox extends XmlForm_Field $checked = (isset( $value ) && ($value == $this->value)) ? 'checked' : ''; if ($this->labelOnRight) { $html = ''; - $html = "NSFieldType() . " name='form[" . $this->name . "]' type='checkbox' $checked $readOnly disabled > + $html = "NSFieldType() . " type='checkbox' $checked $readOnly disabled /> " . $this->label . ''; } else { - $html = "NSFieldType() . " name='form[" . $this->name . "]' type='checkbox' $checked $readOnly disabled/>"; + $html = "NSFieldType() . " type='checkbox' $checked $readOnly disabled />"; } $html .= ""; - // if($this->hint){ - // $html .= ' - // - // '; - // } return $html; } } @@ -3360,11 +3355,6 @@ class XmlForm_Field_Submit extends XmlForm_Field $sLinkNextStep = 'window.location=("casesSaveDataView?UID=' . $_SESSION['CURRENT_DYN_UID'] . '");'; $html = 'NSFieldType() . ' name="form[' . $this->name . ']" type="button" value="' . G::LoadTranslation( 'ID_CONTINUE' ) . '" onclick="' . htmlentities( $sLinkNextStep, ENT_COMPAT, 'utf-8' ) . '" />'; } - - $html .= 'name . ']" '; - $html .= 'name="form[' . $this->name . ']" '; - $html .= 'type="hidden" value="' . $this->htmlentities( $this->label, ENT_QUOTES, 'utf-8' ) . '" />'; return $html; } else { return $this->htmlentities( $value, ENT_COMPAT, 'utf-8' ); @@ -3616,7 +3606,7 @@ class XmlForm_Field_Dropdown extends XmlForm_Field $html = $html . ""; } - if ($value !== $findValue) { + if ($value !== $findValue && $this->renderMode == 'view') { $html .= ""; } diff --git a/gulliver/thirdparty/propel-generator/classes/propel/engine/builder/om/php5/PHP5BasicObjectBuilder.php b/gulliver/thirdparty/propel-generator/classes/propel/engine/builder/om/php5/PHP5BasicObjectBuilder.php index 7a656ac87..a448320c8 100755 --- a/gulliver/thirdparty/propel-generator/classes/propel/engine/builder/om/php5/PHP5BasicObjectBuilder.php +++ b/gulliver/thirdparty/propel-generator/classes/propel/engine/builder/om/php5/PHP5BasicObjectBuilder.php @@ -588,7 +588,15 @@ abstract class ".$this->getClassname()." extends ".ClassTools::classname($this-> $script .= " if (\$v !== null && !is_int(\$v)) { - \$ts = strtotime(\$v); + \$ts = strtotime(\$v);"; + if ($col->getPhpDefaultValue() != 1) { + $script .= " + //Date/time accepts null values + if (\$v == '') { + \$ts = null; + }"; + } + $script .=" if (\$ts === -1 || \$ts === false) { throw new PropelException(\"Unable to parse date/time value for [$clo] from input: \" . var_export(\$v, true)); diff --git a/workflow/engine/classes/class.pmFunctions.php b/workflow/engine/classes/class.pmFunctions.php index 1c769798a..b7d3c486d 100755 --- a/workflow/engine/classes/class.pmFunctions.php +++ b/workflow/engine/classes/class.pmFunctions.php @@ -2843,8 +2843,9 @@ function PMFAddAttachmentToArray($arrayData, $index, $value, $suffix = " Copy({i * * It delete the mask a field. * - * @name PMFAddAttachmentToArray - * + * @name PMFRemoveMask + * @label PMF Remove Mask + * * @param string | $field | Value the field * @param string | $separator | Separator of thousands (, or .) * @param string | $currency | symbol of currency @@ -2852,7 +2853,7 @@ function PMFAddAttachmentToArray($arrayData, $index, $value, $suffix = " Copy({i * */ -function PMRemoveMask ($field, $separator = '.', $currency = '') +function PMFRemoveMask ($field, $separator = '.', $currency = '') { $sep = array(); if ( trim($currency) != '') { diff --git a/workflow/engine/classes/class.wsBase.php b/workflow/engine/classes/class.wsBase.php index f3f7732db..667c5a878 100755 --- a/workflow/engine/classes/class.wsBase.php +++ b/workflow/engine/classes/class.wsBase.php @@ -3125,7 +3125,6 @@ class wsBase return $result; } - if (empty( $userUid )) { $result = new wsResponse( 100, G::LoadTranslation( "ID_REQUIRED_FIELD" ) . " userUid" ); @@ -3133,8 +3132,7 @@ class wsBase return $result; } - - if (! empty( $unpauseDate )) { + if( strlen($unpauseDate) >=10 ){ if (! preg_match( "/^\d{4}-\d{2}-\d{2}| \d{2}:\d{2}:\d{2}$/", $unpauseDate )) { $result = new wsResponse( 100, G::LoadTranslation( "ID_INVALID_DATA" ) . " $unpauseDate" ); @@ -3142,8 +3140,9 @@ class wsBase return $result; } + } else { + $unpauseDate = null; } - $case = new Cases(); $case->pauseCase( $caseUid, $delIndex, $userUid, $unpauseDate ); @@ -3154,7 +3153,6 @@ class wsBase ); $g->sessionVarRestore(); - return $result; } catch (Exception $e) { $result = new wsResponse(100, $e->getMessage()); diff --git a/workflow/engine/methods/appFolder/appFolderAjax.php b/workflow/engine/methods/appFolder/appFolderAjax.php index 9f07313e3..6ee91744a 100755 --- a/workflow/engine/methods/appFolder/appFolderAjax.php +++ b/workflow/engine/methods/appFolder/appFolderAjax.php @@ -20,12 +20,6 @@ if (! isset ($_REQUEST ['action'])) { print G::json_encode ($res); die (); } -if (! function_exists ($_REQUEST['action']) || !G::isUserFunction($_REQUEST['action'])) { - $res ['success'] = false; - $res ['message'] = 'The requested action does not exist'; - print G::json_encode ($res); - die (); -} if (($_REQUEST['action']) != 'rename') { $functionName = $_REQUEST ['action']; @@ -48,6 +42,12 @@ if (($_REQUEST['action']) != 'rename') { renameFolder ($oldname, $newname, $uid); } +if (! function_exists ($_REQUEST['action']) || !G::isUserFunction($_REQUEST['action'])) { + $res ['success'] = false; + $res ['message'] = 'The requested action does not exist'; + print G::json_encode ($res); + die (); +} ///////////////////////////////////////////// function renameFolder($oldname, $newname, $uid) diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php index 988cb3cb5..9b1be0c9f 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php @@ -1540,6 +1540,15 @@ class Cases $oCriteria->addSelectColumn(\ContentPeer::CON_VALUE); $oCriteria->addSelectColumn(\TaskPeer::TAS_START); $oCriteria->addSelectColumn(\TaskPeer::TAS_TYPE); + + $oCriteria->addSelectColumn(\TaskPeer::TAS_ASSIGN_TYPE); + $oCriteria->addSelectColumn(\TaskPeer::TAS_ASSIGN_LOCATION); + $oCriteria->addSelectColumn(\TaskPeer::TAS_ASSIGN_LOCATION_ADHOC); + $oCriteria->addSelectColumn(\TaskPeer::TAS_LAST_ASSIGNED); + $oCriteria->addSelectColumn(\TaskPeer::TAS_START); + $oCriteria->addSelectColumn(\TaskPeer::TAS_TO_LAST_USER); + $oCriteria->addSelectColumn(\TaskPeer::TAS_DERIVATION); + $aConditions = array(); $aConditions[] = array(0 => \TaskPeer::TAS_UID, 1 => \ContentPeer::CON_ID); $aConditions[] = array(0 => \ContentPeer::CON_CATEGORY, 1 => \DBAdapter::getStringDelimiter() . 'TAS_TITLE' . \DBAdapter::getStringDelimiter() ); @@ -1584,6 +1593,15 @@ class Cases $oTask->tas_title = htmlentities($aRow1['CON_VALUE'], ENT_QUOTES, 'UTF-8'); } } + + $oTask->tas_assign_type = $aRow1['TAS_ASSIGN_TYPE']; + $oTask->tas_assign_location = $aRow1['TAS_ASSIGN_LOCATION']; + $oTask->tas_assign_location_adhoc = $aRow1['TAS_ASSIGN_LOCATION_ADHOC']; + $oTask->tas_last_assigned = $aRow1['TAS_LAST_ASSIGNED']; + $oTask->tas_start = $aRow1['TAS_START']; + $oTask->tas_to_last_user = $aRow1['TAS_TO_LAST_USER']; + $oTask->tas_derivation = $aRow1['TAS_DERIVATION']; + $oTask->routing = new \StdClass(); $oTask->routing->rou_type = ''; $oTask->routing->to = array(); @@ -1609,30 +1627,8 @@ class Cases $oDataset2 = \AppDelegationPeer::doSelectRS($oCriteria); $oDataset2->setFetchmode(\ResultSet::FETCHMODE_ASSOC); $oDataset2->next(); + while ($aRow2 = $oDataset2->getRow()) { - switch ($aRow2['ROU_TYPE']) { - case 'SEQUENTIAL': - $aRow2['ROU_TYPE'] = 0; - break; - case 'SELECT': - $aRow2['ROU_TYPE'] = 1; - break; - case 'EVALUATE': - $aRow2['ROU_TYPE'] = 2; - break; - case 'PARALLEL': - $aRow2['ROU_TYPE'] = 3; - break; - case 'PARALLEL-BY-EVALUATION': - $aRow2['ROU_TYPE'] = 4; - break; - case 'SEC-JOIN': - $aRow2['ROU_TYPE'] = 5; - break; - case 'DISCRIMINATOR': - $aRow2['ROU_TYPE'] = 8; - break; - } $iDiff = strtotime($aRow2['DEL_FINISH_DATE']) - strtotime($aRow2['DEL_INIT_DATE']); $oTo = new \StdClass(); $oTo->rou_next_task = $aRow2['ROU_NEXT_TASK']; @@ -1673,22 +1669,22 @@ class Cases $aRow2['FINISH'] = ''; } if (empty($aRow2["FINISH"]) && $aRow1["TAS_UID"] == $sTask) { - $oTask->color = "#FF0000"; //Red + $oTask->status = G::LoadTranslation( 'ID_TASK_IN_PROGRESS' ); } else { if (!empty($aRow2["FINISH"])) { - $oTask->color = "#006633"; //Green + $oTask->status = G::LoadTranslation( 'ID_COMPLETED_TASK' ); } else { - if ($oTask->routing->rou_type != 5) { + if ($oTask->routing->rou_type != 'SEC-JOIN') { if ($aRow2["CANT"] != 0) { - $oTask->color = "#FF0000"; //Red + $oTask->status = G::LoadTranslation( 'ID_TASK_IN_PROGRESS' ); } else { - $oTask->color = "#939598"; //Gray + $oTask->status = G::LoadTranslation( 'ID_PENDING_TASK' ); } } else { if ($aRow3) { - $oTask->color = "#FF0000"; //Red + $oTask->status = G::LoadTranslation( 'ID_TASK_IN_PROGRESS' ); } else { - $oTask->color = "#939598"; //Gray + $oTask->status = G::LoadTranslation( 'ID_PENDING_TASK' ); } } } @@ -1717,19 +1713,19 @@ class Cases $aRow2['FINISH'] = ''; } if (empty($aRow2["FINISH"]) && $aRow1["TAS_UID"] == $sTask) { - $oTask->color = "#FF0000"; //Red + $oTask->status = G::LoadTranslation( 'ID_TASK_IN_PROGRESS' ); } else { if (!empty($aRow2["FINISH"])) { - $oTask->color = "#006633"; //Green + $oTask->status = G::LoadTranslation( 'ID_COMPLETED_TASK' ); } else { - if ($oTask->routing->rou_type != 5) { + if ($oTask->routing->rou_type != 'SEC-JOIN') { if ($aRow2["CANT"] != 0) { - $oTask->color = "#FF0000"; //Red + $oTask->status = G::LoadTranslation( 'ID_TASK_IN_PROGRESS' ); } else { - $oTask->color = "#939598"; //Gray + $oTask->status = G::LoadTranslation( 'ID_PENDING_TASK' ); } } else { - $oTask->color = "#FF9900"; //Yellow + $oTask->status = G::LoadTranslation( 'ID_PARALLEL_TASK' ); } } } @@ -1743,4 +1739,4 @@ class Cases throw $e; } } -} \ No newline at end of file +} diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Process.php b/workflow/engine/src/ProcessMaker/BusinessModel/Process.php index c030f24b2..53ff54710 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Process.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Process.php @@ -483,6 +483,27 @@ class Process } } + /** + * Verify if does not exist the Permission in table PERMISSIONS (Database RBAC) + * + * @param string $permissionUid Unique id of Permission + * @param string $fieldNameForException Field name for the exception + * + * return void Throw exception if does not exist the Permission in table PERMISSIONS + */ + public function throwExceptionIfNotExistsPermission($permissionUid, $fieldNameForException) + { + try { + $obj = \PermissionsPeer::retrieveByPK($permissionUid); + + if (is_null($obj)) { + throw new \Exception(\G::LoadTranslation("ID_PERMISSION_DOES_NOT_EXIST", array($fieldNameForException, $permissionUid))); + } + } catch (\Exception $e) { + throw $e; + } + } + /** * Update Process * diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Role.php b/workflow/engine/src/ProcessMaker/BusinessModel/Role.php index c888829a5..4928b1400 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Role.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Role.php @@ -355,6 +355,10 @@ class Role //Verify data $this->throwExceptionIfNotExistsRole($roleUid, $this->arrayFieldNameForException["roleUid"]); + if ($roleUid == "00000000000000000000000000000002") { + throw new \Exception(\G::LoadTranslation("ID_ROLES_MSG")); + } + $this->throwExceptionIfDataIsInvalid($roleUid, $arrayData); //Update diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Role/Permission.php b/workflow/engine/src/ProcessMaker/BusinessModel/Role/Permission.php new file mode 100644 index 000000000..2e7fd3c0a --- /dev/null +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Role/Permission.php @@ -0,0 +1,405 @@ + array("type" => "string", "required" => false, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "roleUid"), + "PER_UID" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "permissionUid") + ); + + private $formatFieldNameInUppercase = true; + + private $arrayFieldNameForException = array( + "filter" => "FILTER", + "start" => "START", + "limit" => "LIMIT" + ); + + /** + * Constructor of the class + * + * return void + */ + public function __construct() + { + try { + foreach ($this->arrayFieldDefinition as $key => $value) { + $this->arrayFieldNameForException[$value["fieldNameAux"]] = $key; + } + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Set the format of the fields name (uppercase, lowercase) + * + * @param bool $flag Value that set the format + * + * return void + */ + public function setFormatFieldNameInUppercase($flag) + { + try { + $this->formatFieldNameInUppercase = $flag; + + $this->setArrayFieldNameForException($this->arrayFieldNameForException); + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Set exception messages for fields + * + * @param array $arrayData Data with the fields + * + * return void + */ + public function setArrayFieldNameForException(array $arrayData) + { + try { + foreach ($arrayData as $key => $value) { + $this->arrayFieldNameForException[$key] = $this->getFieldNameByFormatFieldName($value); + } + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Get the name of the field according to the format + * + * @param string $fieldName Field name + * + * return string Return the field name according the format + */ + public function getFieldNameByFormatFieldName($fieldName) + { + try { + return ($this->formatFieldNameInUppercase)? strtoupper($fieldName) : strtolower($fieldName); + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Verify if it's assigned the Permission to Role + * + * @param string $roleUid Unique id of Role + * @param string $permissionUid Unique id of Permission + * @param string $fieldNameForException Field name for the exception + * + * return void Throw exception if it's assigned the Permission to Role + */ + public function throwExceptionIfItsAssignedPermissionToRole($roleUid, $permissionUid, $fieldNameForException) + { + try { + $obj = \RolesPermissionsPeer::retrieveByPK($roleUid, $permissionUid); + + if (!is_null($obj)) { + throw new \Exception(\G::LoadTranslation("ID_ROLE_PERMISSION_IS_ALREADY_ASSIGNED", array($fieldNameForException, $permissionUid))); + } + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Verify if not it's assigned the Permission to Role + * + * @param string $roleUid Unique id of Role + * @param string $permissionUid Unique id of Permission + * @param string $fieldNameForException Field name for the exception + * + * return void Throw exception if not it's assigned the Permission to Role + */ + public function throwExceptionIfNotItsAssignedPermissionToRole($roleUid, $permissionUid, $fieldNameForException) + { + try { + $obj = \RolesPermissionsPeer::retrieveByPK($roleUid, $permissionUid); + + if (is_null($obj)) { + throw new \Exception(\G::LoadTranslation("ID_ROLE_PERMISSION_IS_NOT_ASSIGNED", array($fieldNameForException, $permissionUid))); + } + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Assign Permission to Role + * + * @param string $roleUid Unique id of Role + * @param array $arrayData Data + * + * return array Return data of the Permission assigned to Role + */ + public function create($roleUid, array $arrayData) + { + try { + //Verify data + $process = new \ProcessMaker\BusinessModel\Process(); + $validator = new \ProcessMaker\BusinessModel\Validator(); + + $validator->throwExceptionIfDataIsNotArray($arrayData, "\$arrayData"); + $validator->throwExceptionIfDataIsEmpty($arrayData, "\$arrayData"); + + //Set data + $arrayData = array_change_key_case($arrayData, CASE_UPPER); + + unset($arrayData["ROL_UID"]); + + //Verify data + $role = new \ProcessMaker\BusinessModel\Role(); + + $role->throwExceptionIfNotExistsRole($roleUid, $this->arrayFieldNameForException["roleUid"]); + + $process->throwExceptionIfDataNotMetFieldDefinition($arrayData, $this->arrayFieldDefinition, $this->arrayFieldNameForException, true); + + $process->throwExceptionIfNotExistsPermission($arrayData["PER_UID"], $this->arrayFieldNameForException["permissionUid"]); + + $this->throwExceptionIfItsAssignedPermissionToRole($roleUid, $arrayData["PER_UID"], $this->arrayFieldNameForException["permissionUid"]); + + if ($roleUid == "00000000000000000000000000000002") { + throw new \Exception(\G::LoadTranslation("ID_ROLE_PERMISSION_ROLE_PERMISSIONS_CAN_NOT_BE_CHANGED", array("PROCESSMAKER_ADMIN"))); + } + + //Create + $role = new \Roles(); + + $arrayData = array_merge(array("ROL_UID" => $roleUid), $arrayData); + + $role->assignPermissionRole($arrayData); + + //Return + if (!$this->formatFieldNameInUppercase) { + $arrayData = array_change_key_case($arrayData, CASE_LOWER); + } + + return $arrayData; + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Unassign Permission of the Role + * + * @param string $roleUid Unique id of Role + * @param string $permissionUid Unique id of Permission + * + * return void + */ + public function delete($roleUid, $permissionUid) + { + try { + //Verify data + $process = new \ProcessMaker\BusinessModel\Process(); + $role = new \ProcessMaker\BusinessModel\Role(); + + $role->throwExceptionIfNotExistsRole($roleUid, $this->arrayFieldNameForException["roleUid"]); + + $process->throwExceptionIfNotExistsPermission($permissionUid, $this->arrayFieldNameForException["permissionUid"]); + + $this->throwExceptionIfNotItsAssignedPermissionToRole($roleUid, $permissionUid, $this->arrayFieldNameForException["permissionUid"]); + + if ($roleUid == "00000000000000000000000000000002") { + throw new \Exception(\G::LoadTranslation("ID_ROLE_PERMISSION_ROLE_PERMISSIONS_CAN_NOT_BE_CHANGED", array("PROCESSMAKER_ADMIN"))); + } + + //Delete + $role = new \Roles(); + + $role->deletePermissionRole($roleUid, $permissionUid); + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Get criteria for Permission + * + * @param string $roleUid Unique id of Role + * @param array $arrayPermissionUidExclude Unique id of Permissions to exclude + * + * return object + */ + public function getPermissionCriteria($roleUid, array $arrayPermissionUidExclude = null) + { + try { + $criteria = new \Criteria("rbac"); + + $criteria->addSelectColumn(\PermissionsPeer::PER_UID); + $criteria->addSelectColumn(\PermissionsPeer::PER_CODE); + + if ($roleUid != "") { + $criteria->addJoin(\RolesPermissionsPeer::PER_UID, \PermissionsPeer::PER_UID, \Criteria::LEFT_JOIN); + $criteria->add(\RolesPermissionsPeer::ROL_UID, $roleUid, \Criteria::EQUAL); + } + + $criteria->add(\PermissionsPeer::PER_STATUS, 1, \Criteria::EQUAL); + + if (!is_null($arrayPermissionUidExclude) && is_array($arrayPermissionUidExclude)) { + $criteria->add(\PermissionsPeer::PER_UID, $arrayPermissionUidExclude, \Criteria::NOT_IN); + } + + return $criteria; + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Get data of a Permission from a record + * + * @param array $record Record + * + * return array Return an array with data Permission + */ + public function getPermissionDataFromRecord(array $record) + { + try { + return array( + $this->getFieldNameByFormatFieldName("PER_UID") => $record["PER_UID"], + $this->getFieldNameByFormatFieldName("PER_CODE") => $record["PER_CODE"], + $this->getFieldNameByFormatFieldName("PER_NAME") => $record["PER_NAME"] + ); + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Get all Permissions of a Role + * + * @param string $roleUid Unique id of Role + * @param string $option Option (PERMISSIONS, AVAILABLE-PERMISSIONS) + * @param array $arrayFilterData Data of the filters + * @param string $sortField Field name to sort + * @param string $sortDir Direction of sorting (ASC, DESC) + * @param int $start Start + * @param int $limit Limit + * + * return array Return an array with all Permissions of a Role + */ + public function getPermissions($roleUid, $option, array $arrayFilterData = null, $sortField = null, $sortDir = null, $start = null, $limit = null) + { + try { + $arrayPermission = array(); + + //Verify data + $process = new \ProcessMaker\BusinessModel\Process(); + $role = new \ProcessMaker\BusinessModel\Role(); + + $role->throwExceptionIfNotExistsRole($roleUid, $this->arrayFieldNameForException["roleUid"]); + + $process->throwExceptionIfDataNotMetFieldDefinition( + array("OPTION" => $option), + array("OPTION" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array("PERMISSIONS", "AVAILABLE-PERMISSIONS"), "fieldNameAux" => "option")), + array("option" => "\$option"), + true + ); + + $process->throwExceptionIfDataNotMetPagerVarDefinition(array("start" => $start, "limit" => $limit), $this->arrayFieldNameForException); + + //Get data + if (!is_null($limit) && $limit . "" == "0") { + return $arrayPermission; + } + + //Set variables + $rolePermission = new \RolesPermissions(); + + //SQL + switch ($option) { + case "PERMISSIONS": + //Criteria + $criteria = $this->getPermissionCriteria($roleUid); + break; + case "AVAILABLE-PERMISSIONS": + //Get Uids + $arrayUid = array(); + + $criteria = $this->getPermissionCriteria($roleUid); + + $rsCriteria = \PermissionsPeer::doSelectRS($criteria); + $rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + + while ($rsCriteria->next()) { + $row = $rsCriteria->getRow(); + + $arrayUid[] = $row["PER_UID"]; + } + + //Criteria + $criteria = $this->getPermissionCriteria("", $arrayUid); + break; + } + + if (!is_null($arrayFilterData) && is_array($arrayFilterData) && isset($arrayFilterData["filter"]) && trim($arrayFilterData["filter"]) != "") { + $criteria->add(\PermissionsPeer::PER_CODE, "%" . $arrayFilterData["filter"] . "%", \Criteria::LIKE); + } + + //Number records total + $criteriaCount = clone $criteria; + + $criteriaCount->clearSelectColumns(); + $criteriaCount->addAsColumn("NUM_REC", "COUNT(" . \PermissionsPeer::PER_UID . ")"); + + $rsCriteriaCount = \PermissionsPeer::doSelectRS($criteriaCount); + $rsCriteriaCount->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + + $rsCriteriaCount->next(); + $row = $rsCriteriaCount->getRow(); + + $numRecTotal = $row["NUM_REC"]; + + //SQL + if (!is_null($sortField) && trim($sortField) != "") { + $sortField = strtoupper($sortField); + + if (in_array($sortField, array("PER_UID", "PER_CODE"))) { + $sortField = \PermissionsPeer::TABLE_NAME . "." . $sortField; + } else { + $sortField = \PermissionsPeer::PER_CODE; + } + } else { + $sortField = \PermissionsPeer::PER_CODE; + } + + if (!is_null($sortDir) && trim($sortDir) != "" && strtoupper($sortDir) == "DESC") { + $criteria->addDescendingOrderByColumn($sortField); + } else { + $criteria->addAscendingOrderByColumn($sortField); + } + + if (!is_null($start)) { + $criteria->setOffset((int)($start)); + } + + if (!is_null($limit)) { + $criteria->setLimit((int)($limit)); + } + + $rsCriteria = \PermissionsPeer::doSelectRS($criteria); + $rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + + while ($rsCriteria->next()) { + $row = $rsCriteria->getRow(); + + $rolePermission->setPerUid($row["PER_UID"]); + $row["PER_NAME"] = $rolePermission->getPermissionName(); + + $arrayPermission[] = $this->getPermissionDataFromRecord($row); + } + + //Return + return $arrayPermission; + } catch (\Exception $e) { + throw $e; + } + } +} + diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Role/User.php b/workflow/engine/src/ProcessMaker/BusinessModel/Role/User.php index c7c377478..0f5cfb701 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Role/User.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Role/User.php @@ -187,8 +187,8 @@ class User /** * Unassign User of the Role * - * @param string $roleUid Unique id of Role - * @param string $userUid Unique id of User + * @param string $roleUid Unique id of Role + * @param string $userUid Unique id of User * * return void */ @@ -205,7 +205,7 @@ class User $this->throwExceptionIfNotItsAssignedUserToRole($roleUid, $userUid, $this->arrayFieldNameForException["userUid"]); - if ($roleUid == "00000000000000000000000000000002" && $userUid == "00000000000000000000000000000001") { + if ($userUid == "00000000000000000000000000000001") { throw new \Exception(\G::LoadTranslation("ID_ADMINISTRATOR_ROLE_CANT_CHANGED")); } diff --git a/workflow/engine/src/ProcessMaker/Services/Api/Role/Permission.php b/workflow/engine/src/ProcessMaker/Services/Api/Role/Permission.php new file mode 100644 index 000000000..8d32016c1 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Services/Api/Role/Permission.php @@ -0,0 +1,81 @@ +rolePermission = new \ProcessMaker\BusinessModel\Role\Permission(); + + $this->rolePermission->setFormatFieldNameInUppercase(false); + } catch (\Exception $e) { + throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()); + } + } + + /** + * @url GET /:rol_uid/permissions + * @url GET /:rol_uid/available-permissions + * + * @param string $rol_uid {@min 32}{@max 32} + */ + public function doGetPermissions($rol_uid, $filter = null, $start = null, $limit = null) + { + try { + $response = $this->rolePermission->getPermissions($rol_uid, (preg_match("/^.*\/permissions$/", $this->restler->url))? "PERMISSIONS" : "AVAILABLE-PERMISSIONS", array("filter" => $filter), null, null, $start, $limit); + + return $response; + } catch (\Exception $e) { + throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()); + } + } + + /** + * @url POST /:rol_uid/permission + * + * @param string $rol_uid {@min 32}{@max 32} + * @param array $request_data + * + * @status 201 + */ + public function doPostPermission($rol_uid, array $request_data) + { + try { + $arrayData = $this->rolePermission->create($rol_uid, $request_data); + } catch (\Exception $e) { + throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()); + } + } + + /** + * @url DELETE /:rol_uid/permission/:per_uid + * + * @param string $rol_uid {@min 32}{@max 32} + * @param string $per_uid {@min 32}{@max 32} + */ + public function doDeletePermission($rol_uid, $per_uid) + { + try { + $this->rolePermission->delete($rol_uid, $per_uid); + } catch (\Exception $e) { + throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()); + } + } +} + diff --git a/workflow/engine/templates/cases/casesDocuments.js b/workflow/engine/templates/cases/casesDocuments.js index a5be99239..72ea9ff29 100755 --- a/workflow/engine/templates/cases/casesDocuments.js +++ b/workflow/engine/templates/cases/casesDocuments.js @@ -34,6 +34,7 @@ catch(z){ itemSelected = ""; lastDir = ""; var conn = new Ext.data.Connection(); +var showDirs = 'noFolders'; streamFilefromPM=function(fileStream) { Ext.Ajax.request({ @@ -605,6 +606,9 @@ function getRequestParams() { } else { sOptiondir='documents'; + if (selectedRows[0].data.owner == '') { + sOptiondir='directory'; + } selitems = Array(selectedRows.length); if( selectedRows.length > 0 ) { @@ -1128,18 +1132,10 @@ var gridtb = new Ext.Toolbar( handler : function(btn, e) { if (btn.pressed) { datastore.sendWhat = 'both'; - loadDir(); } else { datastore.sendWhat = 'files'; - loadDir(); - } - if (showDirs) { - Ext.getCmp("showOrHiDirs").setText(_('ID_SHOW_DIRS')); - showDirs = false; - } else { - Ext.getCmp("showOrHiDirs").setText(_('ID_HIDE_DIRS')); - showDirs = true; } + loadDir(); } }), '-', new Ext.form.TextField({ name : "filterValue", @@ -1321,11 +1317,15 @@ rowExpander, { header: _("ID_SIZE"), dataIndex: "size", width: 50, + sortable: false, + hideable: false, hidden: true }, { header: _("ID_PERMISSIONS"), dataIndex: "perms", width: 100, + sortable: false, + hideable: false, hidden: true }, { dataIndex: "is_deletable", @@ -1373,28 +1373,34 @@ rowExpander, { cm.defaultSortable = true; function handleRowClick(sm, rowIndex) {//alert(rowIndex); - // console.log("Row Clicked: "+rowIndex); - var selections = sm.getSelections(); - tb = ext_itemgrid.getTopToolbar(); - if (selections.length > 1) { -// tb.items.get('tb_delete').enable(); - tb.items.get('tb_delete')[permitodelete==1 ? 'enable': 'disable'](); - tb.items.get('tb_rename').disable(); - tb.items.get('tb_download').hide(); - //tb.items.get('tb_download').disable(); - } else if (selections.length == 1) { - -// tb.items.get('tb_delete')[selections[0].get('is_deletable') ? 'enable': 'disable'](); - tb.items.get('tb_delete')[permitodelete==1 ? 'enable': 'disable'](); - tb.items.get('tb_rename')[selections[0].get('is_deletable') ? 'disable': 'disable'](); - tb.items.get('tb_download')[selections[0].get('is_readable') - && selections[0].get('is_file') ? 'show' : 'hide'](); - } else { - tb.items.get('tb_delete').disable(); - tb.items.get('tb_rename').disable(); - tb.items.get('tb_download').hide(); - } - return true; + //console.log("Row Clicked: ", rowIndex); + var selections = sm.getSelections(); + tb = ext_itemgrid.getTopToolbar(); + if (selections.length > 1) { + //tb.items.get('tb_delete').enable(); + tb.items.get('tb_delete')[permitodelete==1 ? 'enable': 'disable'](); + tb.items.get('tb_rename').disable(); + tb.items.get('tb_download').hide(); + //tb.items.get('tb_download').disable(); + } else if (selections.length == 1) { + //tb.items.get('tb_delete')[selections[0].get('is_deletable') ? 'enable': 'disable'](); + tb.items.get('tb_delete')[permitodelete==1 ? 'enable': 'disable'](); + tb.items.get('tb_rename')[selections[0].get('is_deletable') ? 'disable': 'disable'](); + tb.items.get('tb_download')[selections[0].get('is_readable') + && selections[0].get('is_file') ? 'show' : 'hide'](); + if (showDirs == 'folders') { + Ext.getCmp("showOrHiDirs").setText(_('ID_SHOW_DIRS')); + showDirs = 'noFolders'; + } else { + Ext.getCmp("showOrHiDirs").setText(_('ID_HIDE_DIRS')); + showDirs = 'folders'; + } + } else { + tb.items.get('tb_delete').disable(); + tb.items.get('tb_rename').disable(); + tb.items.get('tb_download').hide(); + } + return true; } @@ -1402,18 +1408,23 @@ function handleRowClick(sm, rowIndex) {//alert(rowIndex); function loadDir() { // console.info("loadDir"); // console.trace(); - itemSelected = "loadDir"; - datastore.load({ - params : { - start: 0, - limit: 100, - dir : datastore.directory, - node : datastore.directory, - option : 'gridDocuments', - action : 'expandNode', - sendWhat : datastore.sendWhat + itemSelected = "loadDir"; + datastore.load({ + params : { + start: 0, + limit: 100, + dir : datastore.directory, + node : datastore.directory, + option : 'gridDocuments', + action : 'expandNode', + sendWhat : datastore.sendWhat + } + }); + if (datastore.sendWhat == 'files') { + Ext.getCmp("showOrHiDirs").setText(_('ID_SHOW_DIRS')); + } else { + Ext.getCmp("showOrHiDirs").setText(_('ID_HIDE_DIRS')); } - }); } function rowContextMenu(grid, rowIndex, e, f) { @@ -1438,6 +1449,14 @@ function rowContextMenu(grid, rowIndex, e, f) { gridCtxMenu.items.get('gc_rename')[selections[0].get('is_deletable') ? 'disable': 'disable'](); gridCtxMenu.items.get('gc_download')[selections[0].get('is_readable') && selections[0].get('is_file') ? 'enable' : 'disable'](); + if (showDirs == 'folders') { + Ext.getCmp("showOrHiDirs").setText(_('ID_SHOW_DIRS')); + showDirs = 'noFolders'; + } else { + Ext.getCmp("showOrHiDirs").setText(_('ID_HIDE_DIRS')); + showDirs = 'folders'; + } + } gridCtxMenu.show(e.getTarget(), 'tr-br?'); diff --git a/workflow/engine/templates/dashboard/dashletsList.js b/workflow/engine/templates/dashboard/dashletsList.js index 6a2107b51..f4b11e8d2 100644 --- a/workflow/engine/templates/dashboard/dashletsList.js +++ b/workflow/engine/templates/dashboard/dashletsList.js @@ -399,11 +399,9 @@ statusDashletInstance = function(){ var data = { DAS_INS_UID: rows[i].data.DAS_INS_UID, DAS_INS_TITLE: rows[i].data.DAS_INS_TITLE, - DAS_UID: rows[i].data.DAS_INS_UID, - DAS_INS_STATUS: status, - DAS_STATUS: status + DAS_INS_STATUS: status }; - + Ext.Ajax.request({ url: 'saveDashletInstance', method: 'POST', diff --git a/workflow/engine/xmlform/tracker/tracker_Configuration.xml b/workflow/engine/xmlform/tracker/tracker_Configuration.xml index 2df2d08a4..c721b4c93 100755 --- a/workflow/engine/xmlform/tracker/tracker_Configuration.xml +++ b/workflow/engine/xmlform/tracker/tracker_Configuration.xml @@ -64,9 +64,9 @@ var editStagesMap = function(sProcessUID) { oPanel.events = { remove: function() { delete(oPanel); - if(menu_edit.maked === true){ + if(typeof menu_edit != "undefined" && menu_edit.maked === true){ menu_edit.remove(); - } else if (menu_add.maked === true) { + } else if (typeof menu_add != "undefined" && menu_add.maked === true) { menu_add.remove(); } }.extend(this)