[795] | 1 | <?php |
---|
| 2 | require_once(GALAXIA_LIBRARY.SEP.'src'.SEP.'common'.SEP.'Base.php'); |
---|
| 3 | |
---|
| 4 | /** |
---|
| 5 | * Handles most security issues in the engine |
---|
| 6 | * |
---|
| 7 | * @package Galaxia |
---|
| 8 | * @license http://www.gnu.org/copyleft/gpl.html GPL |
---|
| 9 | */ |
---|
| 10 | class WfSecurity extends Base { |
---|
| 11 | |
---|
| 12 | /** |
---|
| 13 | * @var array processes config values cached for this object life duration, init is done at first use for each process |
---|
| 14 | * @access public |
---|
| 15 | */ |
---|
| 16 | var $processesConfig= Array(); |
---|
| 17 | |
---|
| 18 | /** |
---|
| 19 | * Constructor |
---|
| 20 | * |
---|
| 21 | * @param object &$db ADOdb |
---|
| 22 | * @return object WfSecurity |
---|
| 23 | * @access public |
---|
| 24 | */ |
---|
| 25 | function WfSecurity(&$db) |
---|
| 26 | { |
---|
| 27 | $this->child_name = 'WfSecurity'; |
---|
| 28 | parent::Base($db); |
---|
| 29 | require_once(GALAXIA_LIBRARY.SEP.'src'.SEP.'API'.SEP.'Instance.php'); |
---|
| 30 | require_once(GALAXIA_LIBRARY.SEP.'src'.SEP.'API'.SEP.'Process.php'); |
---|
| 31 | require_once(GALAXIA_LIBRARY.SEP.'src'.SEP.'API'.SEP.'BaseActivity.php'); |
---|
| 32 | } |
---|
| 33 | |
---|
| 34 | /** |
---|
| 35 | * Loads config values for a given process. |
---|
| 36 | * Config values for a given process are cached while this WfSecurity object stay alive |
---|
| 37 | * |
---|
| 38 | * @param int $pId Process id |
---|
| 39 | * @access private |
---|
| 40 | * @return void |
---|
| 41 | */ |
---|
| 42 | function loadConfigValues($pId) |
---|
| 43 | { |
---|
| 44 | //check if we already have the config values for this processId |
---|
| 45 | if (!(isset($this->processesConfig[$pId]))) |
---|
| 46 | { |
---|
| 47 | //define conf values we need |
---|
| 48 | $arrayConf=array( |
---|
| 49 | 'ownership_give_abort_right' =>1, |
---|
| 50 | 'ownership_give_exception_right' =>1, |
---|
| 51 | 'ownership_give_release_right' =>1, |
---|
| 52 | 'role_give_abort_right' =>0, |
---|
| 53 | 'role_give_release_right' =>0, |
---|
| 54 | 'role_give_exception_right' =>0, |
---|
| 55 | 'disable_advanced_actions' =>0, |
---|
| 56 | 'iframe_view_height' =>-1, |
---|
| 57 | 'execute_activities_using_secure_connection' =>0 |
---|
| 58 | ); |
---|
| 59 | //check theses values for this process and store the result for this object life duration |
---|
| 60 | $myProcess = new Process($this->db); |
---|
| 61 | $myProcess->getProcess($pId); |
---|
| 62 | $this->processesConfig[$pId] = $myProcess->getConfigValues($arrayConf); |
---|
| 63 | unset($myProcess); |
---|
| 64 | } |
---|
| 65 | } |
---|
| 66 | |
---|
| 67 | /** |
---|
| 68 | * Checks if a user has a access to an activity, use it at runtime. |
---|
| 69 | * To do so it checks if the user is in the users having the roles associated with the activity |
---|
| 70 | * or if he is in the groups having roles associated with the activity |
---|
| 71 | * |
---|
| 72 | * @access public |
---|
| 73 | * @param int $user User id |
---|
| 74 | * @param int $activityId Activity id |
---|
| 75 | * @param bool $readonly False by default. If true we only check read-only access level for the user on this activity |
---|
| 76 | * @return bool True if access is granted false in other case. Errors are stored in the object |
---|
| 77 | */ |
---|
| 78 | function checkUserAccess($user, $activity_id, $readonly=false) |
---|
| 79 | { |
---|
| 80 | //group mapping, warning groups and user can have the same id |
---|
| 81 | if ($user[0] != 'p') |
---|
| 82 | $groups = galaxia_retrieve_user_groups($user); |
---|
| 83 | else |
---|
| 84 | $groups = false; |
---|
| 85 | |
---|
| 86 | $query = 'select count(*) from '.GALAXIA_TABLE_PREFIX.'activity_roles gar |
---|
| 87 | INNER JOIN '.GALAXIA_TABLE_PREFIX.'roles gr ON gar.wf_role_id=gr.wf_role_id |
---|
| 88 | INNER JOIN '.GALAXIA_TABLE_PREFIX.'user_roles gur ON gur.wf_role_id=gr.wf_role_id |
---|
| 89 | where gar.wf_activity_id=? |
---|
| 90 | and ( (gur.wf_user=? and gur.wf_account_type=?)'; |
---|
| 91 | if (is_array($groups)) |
---|
| 92 | { |
---|
| 93 | foreach ($groups as &$group) |
---|
| 94 | $group = "'{$group}'"; |
---|
| 95 | $query .= ' or (gur.wf_user in ('.implode(',',$groups).") and gur.wf_account_type='g')"; |
---|
| 96 | } |
---|
| 97 | |
---|
| 98 | $query .= " or ('p'||gur.wf_role_id = '$user')"; |
---|
| 99 | |
---|
| 100 | $query .= ')'; |
---|
| 101 | |
---|
| 102 | if (!($readonly)) |
---|
| 103 | { |
---|
| 104 | $query.= 'and NOT(gar.wf_readonly=1)'; |
---|
| 105 | } |
---|
| 106 | $result= $this->getOne($query ,array($activity_id, $user, 'u')); |
---|
| 107 | if ($result) |
---|
| 108 | { |
---|
| 109 | //echo "<br>Access granted for ".$user; |
---|
| 110 | return true; |
---|
| 111 | } |
---|
| 112 | else |
---|
| 113 | { |
---|
| 114 | $this->error[]= tra('Access denied for user %1 on activity %2, no role', $user, $activity_id); |
---|
| 115 | return false; |
---|
| 116 | } |
---|
| 117 | } |
---|
| 118 | |
---|
| 119 | /** |
---|
| 120 | * Checks at RUNTIME whether running user is authorized for a given action on some activity/instance. |
---|
| 121 | * This function will check the given action for the current running user, lock the table rows if necessary to ensure |
---|
| 122 | * nothing will move from another process between the check and the later action. |
---|
| 123 | * loacked tables can be instances and instance-activities. |
---|
| 124 | * NOTA BENE: there is no lock on activity/processes table, we assume the admin is not changing the activity data |
---|
| 125 | * on a running/production process, this is why there is versioning and activation on processes |
---|
| 126 | * Encapsulate this function call in a transaction, locks will be removed at the end of the transaction, whent COMMIT |
---|
| 127 | * or ROLLBACK will be launched |
---|
| 128 | * |
---|
| 129 | * @param int $activityId Activity id, it may be 0 |
---|
| 130 | * @param int $instanceId InstanceId, it may be 0 |
---|
| 131 | * @param string $action ONE action asked, it must be one of: 'grab', 'release', 'exception', 'resume', 'abort', 'run', 'send', 'view', 'viewrun', 'complete' (internal action before completing), 'restart' admin function, restarting a failed automatic activity |
---|
| 132 | * be carefull, View can be done in 2 ways: viewrun : by the view activity if the process has a view activity, and only by this way in such case, view: by a general view form with access to everybody if the process has no view activity |
---|
| 133 | * @return bool True if action access is granted false in other case. Errors are stored in the object |
---|
| 134 | * @access public |
---|
| 135 | */ |
---|
| 136 | function checkUserAction($activityId, $instanceId,$action) |
---|
| 137 | { |
---|
| 138 | //Warning: |
---|
| 139 | //start and standalone activities have no instances associated |
---|
| 140 | //aborted and completed instances have no activities associated |
---|
| 141 | |
---|
| 142 | //$this->error[] = 'DEBUG: action:'.$action; |
---|
| 143 | if ($action!='run' && $action!='send' && $action!='view' && $action!='viewrun' && $action!='complete' && $action!='grab' && $action!='release' && $action!='exception' && $action!='resume' && $action!='abort' && $action!='restart') |
---|
| 144 | { |
---|
| 145 | $this->error[] = tra('Security check: Cannot understand asked action'); |
---|
| 146 | return false; |
---|
| 147 | } |
---|
| 148 | |
---|
| 149 | $user = galaxia_retrieve_running_user(); |
---|
| 150 | //$this->error[] = 'DEBUG: running user:'.$user; |
---|
| 151 | if ( (!(isset($user))) || (empty($user)) ) |
---|
| 152 | { |
---|
| 153 | $this->error[] = tra('Cannot retrieve the user running the security check'); |
---|
| 154 | return false; |
---|
| 155 | } |
---|
| 156 | |
---|
| 157 | //0 - prepare RowLocks ---------------------------------------------------------- |
---|
| 158 | $lock_instance_activities = false; |
---|
| 159 | $lock_instances = false; |
---|
| 160 | switch($action) |
---|
| 161 | { |
---|
| 162 | case 'view': |
---|
| 163 | case 'viewrun': |
---|
| 164 | //no impact on write mode, no lock |
---|
| 165 | break; |
---|
| 166 | case 'grab': |
---|
| 167 | //impacted tables is instance_activities |
---|
| 168 | $lock_instance_activities = true; |
---|
| 169 | break; |
---|
| 170 | case 'release' : |
---|
| 171 | //impacted tables is instance_activities |
---|
| 172 | $lock_instance_activities = true; |
---|
| 173 | break; |
---|
| 174 | case 'exception': |
---|
| 175 | //impacted tables is instances |
---|
| 176 | $lock_instances = true; |
---|
| 177 | break; |
---|
| 178 | case 'resume': |
---|
| 179 | //impacted tables is instances |
---|
| 180 | $lock_instances = true; |
---|
| 181 | break; |
---|
| 182 | case 'abort': |
---|
| 183 | //impacted tables are instances and instance_activities (deleting rows) |
---|
| 184 | $lock_instance_activities = true; |
---|
| 185 | $lock_instances = true; |
---|
| 186 | break; |
---|
| 187 | case 'run': |
---|
| 188 | //impacted tables is instance_activities (new running user) |
---|
| 189 | $lock_instance_activities = true; |
---|
| 190 | break; |
---|
| 191 | case 'send': |
---|
| 192 | //impacted tables is instance_activities (deleting/adding row) |
---|
| 193 | $lock_instance_activities = true; |
---|
| 194 | break; |
---|
| 195 | case 'complete': |
---|
| 196 | //impacted tables are instances and instance_activities |
---|
| 197 | $lock_instance_activities = true; |
---|
| 198 | $lock_instances = true; |
---|
| 199 | break; |
---|
| 200 | case 'restart': |
---|
| 201 | //nothing to do, it will be done by the run part. |
---|
| 202 | break; |
---|
| 203 | } |
---|
| 204 | // no lock on instance_activities without a lock on instances |
---|
| 205 | // to avoid changing status of an instance or deletion of an instance while impacting instance_activities |
---|
| 206 | if ($lock_instance_activities) $lock_instances = true; |
---|
| 207 | |
---|
| 208 | //1 - load data ----------------------------------------------------------------- |
---|
| 209 | $_no_activity=false; |
---|
| 210 | $_no_instance=false; |
---|
| 211 | |
---|
| 212 | //retrieve some activity datas and process data |
---|
| 213 | if ($activityId==0) |
---|
| 214 | { |
---|
| 215 | $_no_activity = true; |
---|
| 216 | } |
---|
| 217 | else |
---|
| 218 | { |
---|
| 219 | $query = 'select ga.wf_activity_id, ga.wf_type, ga.wf_is_interactive, ga.wf_is_autorouted, |
---|
| 220 | gp.wf_name as wf_procname, gp.wf_is_active, gp.wf_version, gp.wf_p_id |
---|
| 221 | from '.GALAXIA_TABLE_PREFIX.'activities ga |
---|
| 222 | INNER JOIN '.GALAXIA_TABLE_PREFIX.'processes gp ON gp.wf_p_id=ga.wf_p_id |
---|
| 223 | where ga.wf_activity_id = ?'; |
---|
| 224 | $result = $this->query($query, array($activityId)); |
---|
| 225 | $resactivity = Array(); |
---|
| 226 | if (!!$result) |
---|
| 227 | { |
---|
| 228 | $resactivity = $result->fetchRow(); |
---|
| 229 | $pId = $resactivity['wf_p_id']; |
---|
| 230 | //DEBUG |
---|
| 231 | //$debugactivity = implode(",",$resactivity); |
---|
| 232 | //$this->error[] = 'DEBUG: '. date("[d/m/Y h:i:s]").'activity:'.$debugactivity; |
---|
| 233 | } |
---|
| 234 | if (count($resactivity)==0) |
---|
| 235 | { |
---|
| 236 | $_no_activity = true; |
---|
| 237 | } |
---|
| 238 | } |
---|
| 239 | |
---|
| 240 | //retrieve some instance and process data (need process data here as well if there is no activity) |
---|
| 241 | if ($instanceId==0) |
---|
| 242 | { |
---|
| 243 | $_no_instance = true; |
---|
| 244 | } |
---|
| 245 | else |
---|
| 246 | { |
---|
| 247 | if ($lock_instances) |
---|
| 248 | { |
---|
| 249 | //we need to make a row lock now, before any read action |
---|
| 250 | $where = 'wf_instance_id='.(int)$instanceId; |
---|
| 251 | //$this->error[]= '<br> Debug:locking instances '.$where; |
---|
| 252 | if (!($this->db->RowLock(GALAXIA_TABLE_PREFIX.'instances', $where))) |
---|
| 253 | { |
---|
| 254 | $this->error[] = tra('failed to obtain lock on %1 table', 'instances'); |
---|
| 255 | return false; |
---|
| 256 | } |
---|
| 257 | } |
---|
| 258 | $query = 'select gi.wf_instance_id, gi.wf_owner, gi.wf_status, |
---|
| 259 | gp.wf_name as wf_procname, gp.wf_is_active, gp.wf_version, gp.wf_p_id |
---|
| 260 | from '.GALAXIA_TABLE_PREFIX.'instances gi |
---|
| 261 | INNER JOIN '.GALAXIA_TABLE_PREFIX.'processes gp ON gp.wf_p_id=gi.wf_p_id |
---|
| 262 | where gi.wf_instance_id=?'; |
---|
| 263 | $result = $this->query($query,array($instanceId)); |
---|
| 264 | if (!!$result) |
---|
| 265 | { |
---|
| 266 | |
---|
| 267 | $resinstance = $result->fetchRow(); |
---|
| 268 | $pId = $resinstance['wf_p_id']; |
---|
| 269 | //DEBUG |
---|
| 270 | //$debuginstance = implode(",",$resinstance); |
---|
| 271 | //$this->error[] = 'DEBUG: '. date("[d/m/Y h:i:s]").'instance:'.$debuginstance; |
---|
| 272 | } |
---|
| 273 | if (count($resinstance)==0) |
---|
| 274 | { |
---|
| 275 | $_no_instance = true; |
---|
| 276 | } |
---|
| 277 | } |
---|
| 278 | |
---|
| 279 | if ($_no_activity && $_no_instance) |
---|
| 280 | { |
---|
| 281 | $this->error[] = tra('Action %1 is impossible if we have no activity and no instance designated for it!',$action); |
---|
| 282 | return false; |
---|
| 283 | } |
---|
| 284 | |
---|
| 285 | //retrieve some instance/activity data |
---|
| 286 | //if no_activity or no_instance we are with out-flow/without instances activities or with instances terminated |
---|
| 287 | //we would not obtain anything there |
---|
| 288 | if (!($_no_activity || $_no_instance)) |
---|
| 289 | { |
---|
| 290 | if ($lock_instance_activities) |
---|
| 291 | { |
---|
| 292 | //we need to lock this row now, before any read action |
---|
| 293 | $where = 'wf_instance_id='.(int)$instanceId.' and wf_activity_id='.(int)$activityId; |
---|
| 294 | //$this->error[] = '<br> Debug:locking instance_activities '.$where; |
---|
| 295 | if (!($this->db->RowLock(GALAXIA_TABLE_PREFIX.'instance_activities', $where))) |
---|
| 296 | { |
---|
| 297 | if ($this->db->getOne('SELECT 1 FROM ' . GALAXIA_TABLE_PREFIX . 'instance_activities WHERE ' . $where)) |
---|
| 298 | { |
---|
| 299 | $this->error[] = tra('failed to obtain lock on %1 table','instances_activities'); |
---|
| 300 | return false; |
---|
| 301 | } |
---|
| 302 | else |
---|
| 303 | { |
---|
| 304 | $this->error[] = tra("This instance doesn't exist in this activity. Probably, this instance has already been executed"); |
---|
| 305 | return false; |
---|
| 306 | } |
---|
| 307 | } |
---|
| 308 | } |
---|
| 309 | $query = 'select gia.wf_instance_id, gia.wf_user, gia.wf_status |
---|
| 310 | from '.GALAXIA_TABLE_PREFIX.'instance_activities gia |
---|
| 311 | where gia.wf_activity_id = ? and gia.wf_instance_id = ?'; |
---|
| 312 | $result = $this->query($query, array($activityId, $instanceId)); |
---|
| 313 | $res_inst_act = Array(); |
---|
| 314 | if (!!$result) |
---|
| 315 | { |
---|
| 316 | $res_inst_act = $result->fetchRow(); |
---|
| 317 | //DEBUG |
---|
| 318 | //$debuginstact = implode(",",$res_inst_act); |
---|
| 319 | //$this->error[] = 'DEBUG: '. date("[d/m/Y h:i:s]").'instance/activity:'.$debuginstact; |
---|
| 320 | |
---|
| 321 | } |
---|
| 322 | } |
---|
| 323 | |
---|
| 324 | //Now that we have the process we can load config values |
---|
| 325 | //$this->error[] = 'DEBUG: load config values for process:'.$pId; |
---|
| 326 | $this->loadConfigValues($pId); |
---|
| 327 | //$debuconfig = '';foreach ($this->processesConfig[$pId] as $label => $value){$debugconfig .= ':'.$label.'=>'.$value;} $this->error[] = 'DEBUG: config:'.$debugconfig; |
---|
| 328 | |
---|
| 329 | |
---|
| 330 | |
---|
| 331 | //2 - decide which tests must be done ------------------------------------------------ |
---|
| 332 | //init tests |
---|
| 333 | $_check_active_process = false; // is the process is valid? |
---|
| 334 | $_check_instance = false; //have we got an instance? |
---|
| 335 | $_check_instance_status = array(); //use to test some status between 'active','exception','aborted','completed' |
---|
| 336 | $_fail_on_exception = false; //no comment |
---|
| 337 | $_check_activity = false; //have we got an activity? |
---|
| 338 | //is there a relationship between instance and activity? this one can be decided already |
---|
| 339 | $_check_instance_activity = !(($_no_instance) || ($_no_activity)); |
---|
| 340 | $_bypass_user_role_if_owner = false; //if our user is the owner we ignore user tests |
---|
| 341 | $_bypass_user_on_non_interactive = false; //if activty is not interactive we do not perform user tests |
---|
| 342 | $_bypass_user_if_admin = false; //is our user a special rights user? |
---|
| 343 | $_bypass_instance_on_pseudo = false; //should we jump the instance check when in 'start' activity? |
---|
| 344 | $_check_is_user = false; //is the actual_user our user? |
---|
| 345 | $_check_is_not_star = false; //is the actual <>*? |
---|
| 346 | $_check_is_star = false; // is the actual user *? |
---|
| 347 | $_check_is_in_role = false; //is our user in associated roles with readonly=false? |
---|
| 348 | $_check_is_in_role_in_readonly = false; //is our user in associated roles? |
---|
| 349 | $_check_no_view_activity = false; //is the process having no view activities? |
---|
| 350 | $_check_is_admin_only = false; //is the action vaible only for admins? |
---|
| 351 | |
---|
| 352 | //first have a look at the action asked |
---|
| 353 | switch($action) |
---|
| 354 | { |
---|
| 355 | case 'restart': |
---|
| 356 | // we need an activity 'in_flow' ie: not start or standalone that means we need an instance |
---|
| 357 | // we need an instance not completed or aborted that means we need an activity |
---|
| 358 | // but if we have an instance it musn't be in 'exception' as well |
---|
| 359 | // authorization is given to admin only |
---|
| 360 | $_check_active_process = true; |
---|
| 361 | $_check_activity = true; |
---|
| 362 | $_check_instance = true; |
---|
| 363 | $_fail_on_exception = true; |
---|
| 364 | $_check_is_admin_only = true; |
---|
| 365 | break; |
---|
| 366 | case 'view': |
---|
| 367 | //process can be inactive |
---|
| 368 | //we need an existing instance |
---|
| 369 | //no activity needed |
---|
| 370 | $_check_instance = true; |
---|
| 371 | $_bypass_user_if_admin = true; |
---|
| 372 | //but be carefull the view function is forbidden on process having the viewrun action with activities |
---|
| 373 | $_check_no_view_activity = true; |
---|
| 374 | break; |
---|
| 375 | case 'viewrun': |
---|
| 376 | //process can be inactive |
---|
| 377 | //we need an existing instance |
---|
| 378 | //we need an activity |
---|
| 379 | //need a read-only role at least on this activity |
---|
| 380 | $_check_instance = true; |
---|
| 381 | $_bypass_user_if_admin = true; |
---|
| 382 | $_check_activity = true; |
---|
| 383 | $_check_is_in_role_in_readonly = true; |
---|
| 384 | //The view type is a special activity related to all instances |
---|
| 385 | $_check_instance_activity = false; |
---|
| 386 | break; |
---|
| 387 | case 'complete': |
---|
| 388 | // we need an activity 'in_flow' ie: not start or standalone that means we need an instance |
---|
| 389 | // (the 'view' activity is not 'in_flow' and has instance, but no relashionship, no need to |
---|
| 390 | // test it here or later for grab or others actions). |
---|
| 391 | // warning we can complete a start activity, in this case it is the contrary, we musn't have an instance |
---|
| 392 | // we need an instance not completed or aborted that means we need an activity |
---|
| 393 | // but if we have an instance it musn't be in 'exception' as well |
---|
| 394 | // authorization is given to currentuser only, |
---|
| 395 | // for interactive activities (except start), instance user need to be the actual user |
---|
| 396 | // 'view' cannot be completed |
---|
| 397 | $_check_active_process = true; |
---|
| 398 | $_check_instance = true; |
---|
| 399 | $_bypass_instance_on_pseudo = true; |
---|
| 400 | $_fail_on_exception = true; |
---|
| 401 | $_check_activity = true; |
---|
| 402 | $_bypass_user_on_non_interactive = true; |
---|
| 403 | $_check_is_user = true; |
---|
| 404 | $_check_is_not_star = true; |
---|
| 405 | break; |
---|
| 406 | case 'grab': |
---|
| 407 | // we need an activity 'in_flow' ie: not start or standalone that means we need an instance |
---|
| 408 | // we need an instance not completed or aborted that means we need an activity |
---|
| 409 | // authorization are given to currentuser, role, never owner actually |
---|
| 410 | // TODO: add conf setting to give grab access to owner (that mean run access as well maybe) |
---|
| 411 | // current user MUST be '*' or user (no matter to grab something we already have) |
---|
| 412 | // check is star is done after check_is_user which can be false |
---|
| 413 | $_check_active_process = true; |
---|
| 414 | $_check_activity = true; |
---|
| 415 | $_check_instance = true; |
---|
| 416 | $_check_is_user = true; |
---|
| 417 | $_check_is_star = true; |
---|
| 418 | $_bypass_user_if_admin = true; |
---|
| 419 | $_check_is_in_role = true; |
---|
| 420 | break; |
---|
| 421 | case 'release' : |
---|
| 422 | // we need an activity 'in_flow' ie: not start or standalone that means we need an instance |
---|
| 423 | // we need an instance not completed or aborted that means we need an activity |
---|
| 424 | // authorization are given to currentuser, maybe role, maybe owner, |
---|
| 425 | // current must not be '*' |
---|
| 426 | $_check_active_process = true; |
---|
| 427 | $_check_activity = true; |
---|
| 428 | $_check_instance = true; |
---|
| 429 | $_check_is_user = true; |
---|
| 430 | $_check_is_not_star = true; |
---|
| 431 | $_bypass_user_if_admin = true; |
---|
| 432 | if ($this->processesConfig[$pId]['role_give_release_right']) $_check_is_in_role = true; |
---|
| 433 | if ($this->processesConfig[$pId]['ownership_give_release_right']) $_bypass_user_role_if_owner = true; |
---|
| 434 | break; |
---|
| 435 | case 'exception': |
---|
| 436 | // we need an activity 'in_flow' ie: not start or standalone that means we need an instance |
---|
| 437 | // we need an instance not completed or aborted that means we need an activity |
---|
| 438 | // authorization are given to currentuser, maybe role, maybe owner, |
---|
| 439 | $_check_active_process = true; |
---|
| 440 | $_check_activity = true; |
---|
| 441 | $_check_instance = true; |
---|
| 442 | $_check_instance_status = array('active'); |
---|
| 443 | $_bypass_user_if_admin = true; |
---|
| 444 | $_check_is_user = true; |
---|
| 445 | if ($this->processesConfig[$pId]['role_give_exception_right']) $_check_is_in_role = true; |
---|
| 446 | if ($this->processesConfig[$pId]['ownership_give_exception_right']) $_bypass_user_role_if_owner = true; |
---|
| 447 | break; |
---|
| 448 | case 'resume': |
---|
| 449 | // like exception but inversed activity status |
---|
| 450 | $_check_active_process = true; |
---|
| 451 | $_check_activity = true; |
---|
| 452 | $_check_instance = true; |
---|
| 453 | $_check_instance_status = array('exception'); |
---|
| 454 | $_bypass_user_if_admin = true; |
---|
| 455 | $_check_is_user = true; |
---|
| 456 | if ($this->processesConfig[$pId]['role_give_exception_right']) $_check_is_in_role = true; |
---|
| 457 | if ($this->processesConfig[$pId]['ownership_give_exception_right']) $_bypass_user_role_if_owner = true; |
---|
| 458 | break; |
---|
| 459 | case 'abort': |
---|
| 460 | // process can be inactive |
---|
| 461 | // we do not need an activity |
---|
| 462 | // we need an instance |
---|
| 463 | // authorization are given to currentuser, maybe role, maybe owner, |
---|
| 464 | // TODO: add conf setting to refuse abort by user |
---|
| 465 | $_check_instance = true; |
---|
| 466 | $_check_instance_status = array('active','exception','completed'); |
---|
| 467 | $_bypass_user_if_admin = true; |
---|
| 468 | $_check_is_user = true; |
---|
| 469 | if ($this->processesConfig[$pId]['role_give_abort_right']) $_check_is_in_role = true; |
---|
| 470 | if ($this->processesConfig[$pId]['ownership_give_abort_right']) $_bypass_user_role_if_owner = true; |
---|
| 471 | break; |
---|
| 472 | case 'run': |
---|
| 473 | // the hell door: |
---|
| 474 | // all activities can be runned, even without instance, even if non interactive |
---|
| 475 | // if we have one we need an instance not completed or aborted that means we need an activity |
---|
| 476 | // but if we have an instance it musn't be in 'exception' as well |
---|
| 477 | // for interactive activities (except start and standalone), instance user need to be the actual user |
---|
| 478 | // run is ok if user is in role and actual user is '*', no rights for owner actually |
---|
| 479 | // no user bypassing on admin user, admin must grab (release if needed) the instance before |
---|
| 480 | $_check_active_process = true; |
---|
| 481 | $_check_activity = true; |
---|
| 482 | $_fail_on_exception = true; |
---|
| 483 | $_bypass_user_on_non_interactive = true; |
---|
| 484 | $_check_is_user = true; |
---|
| 485 | $_check_is_star = true; |
---|
| 486 | $_check_is_in_role = true; |
---|
| 487 | break; |
---|
| 488 | case 'send': |
---|
| 489 | // we need an instance not completed or aborted that means we need an activity |
---|
| 490 | // but if we have an instance it musn't be in 'exception' as well |
---|
| 491 | // authorization are given to currentuser, maybe role, no rights for owner actually |
---|
| 492 | // run is ok if user is in role and actual user is '*' |
---|
| 493 | // no user bypassing on admin user, admin must grab (release if needed) the instance before |
---|
| 494 | $_check_active_process = true; |
---|
| 495 | $_check_activity = true; |
---|
| 496 | $_fail_on_exception = true; |
---|
| 497 | $_bypass_user_if_admin = true; |
---|
| 498 | $_check_is_user = true; |
---|
| 499 | $_check_is_star = true; |
---|
| 500 | $_check_is_in_role = true; |
---|
| 501 | break; |
---|
| 502 | } |
---|
| 503 | |
---|
| 504 | //3- now perform asked tests --------------------------------------------------------------------- |
---|
| 505 | if ($_check_active_process) // require an active process? |
---|
| 506 | { |
---|
| 507 | //$this->error[] = 'DEBUG: check active process'; |
---|
| 508 | if ($_no_instance) //we need an instance or an activity to perfom the check |
---|
| 509 | { |
---|
| 510 | //we cannot be there without instance and without activity, we now we have one activity at least |
---|
| 511 | if (!($resactivity['wf_is_active']=='y')) |
---|
| 512 | { |
---|
| 513 | $this->error[] = tra('Process %1 %2 is not active, action %3 is impossible', $resactivity['wf_procname'], $resactivity['wf_version'], $action); |
---|
| 514 | return false; |
---|
| 515 | } |
---|
| 516 | } |
---|
| 517 | else |
---|
| 518 | { |
---|
| 519 | if (!($resinstance['wf_is_active']=='y')) |
---|
| 520 | { |
---|
| 521 | $this->error[] = tra('Process %1 %2 is not active, action %3 is impossible', $resinstance['wf_procname'], $resactivity['wf_version'], $action); |
---|
| 522 | return false; |
---|
| 523 | } |
---|
| 524 | } |
---|
| 525 | } |
---|
| 526 | |
---|
| 527 | if ($_check_instance) |
---|
| 528 | { |
---|
| 529 | //$this->error[] = 'DEBUG: check instance'; |
---|
| 530 | if ( (!($_bypass_instance_on_pseudo)) && ($_no_instance)) |
---|
| 531 | { |
---|
| 532 | $this->error[] = tra('Action %1 needs an instance and instance %2 does not exists', $action, $instanceId); |
---|
| 533 | return false; |
---|
| 534 | } |
---|
| 535 | } |
---|
| 536 | |
---|
| 537 | if ($_check_activity) |
---|
| 538 | { |
---|
| 539 | //$this->error[] = 'DEBUG: check activity'; |
---|
| 540 | if ($_no_activity) |
---|
| 541 | { |
---|
| 542 | $this->error[] = tra('Action %1 needs an activity and activity %2 does not exists', $action, $activityId); |
---|
| 543 | return false; |
---|
| 544 | } |
---|
| 545 | } |
---|
| 546 | |
---|
| 547 | if ($_check_instance_activity) //is there a realtionship between instance and activity |
---|
| 548 | { |
---|
| 549 | //$this->error[] = 'DEBUG: check activity-instance relationship'.count($res_inst_act); |
---|
| 550 | if ( (!isset($res_inst_act)) || empty($res_inst_act) || (count($res_inst_act)==0) ) |
---|
| 551 | { |
---|
| 552 | $this->error[] = tra('Instance %1 is not associated with activity %2, action %3 is impossible.', $instanceId, $activityId, $action); |
---|
| 553 | return false; |
---|
| 554 | } |
---|
| 555 | } |
---|
| 556 | |
---|
| 557 | if (!(count($_check_instance_status) == 0)) //use to test some status between 'active','exception','aborted','completed' |
---|
| 558 | { |
---|
| 559 | //DEBUG |
---|
| 560 | //$debug_status = implode(",",$_check_instance_status); |
---|
| 561 | //$this->error[] = 'DEBUG: check instance status, actually :'.$resinstance['wf_status'].' need:'.$debug_status; |
---|
| 562 | if (!(in_array($resinstance['wf_status'],$_check_instance_status))) |
---|
| 563 | { |
---|
| 564 | $this->error[] = tra('Instance %1 is in %2 state, action %3 is impossible.', $instanceId, $resinstance['wf_status'], $action); |
---|
| 565 | return false; |
---|
| 566 | } |
---|
| 567 | } |
---|
| 568 | if (($_fail_on_exception) && ($resinstance['wf_status']=='exception')) |
---|
| 569 | { |
---|
| 570 | $this->error[] = tra('Instance %1 is in exception, action %2 is not possible.', $instanceId, $action); |
---|
| 571 | return false; |
---|
| 572 | } |
---|
| 573 | |
---|
| 574 | // Test on the process to see if he has a view activity |
---|
| 575 | if ($_check_no_view_activity) |
---|
| 576 | { |
---|
| 577 | if (!(isset($this->pm))) |
---|
| 578 | { |
---|
| 579 | require_once(GALAXIA_LIBRARY.SEP.'src'.SEP.'ProcessManager'.SEP.'ProcessManager.php'); |
---|
| 580 | $this->pm = new ProcessManager($this->db); |
---|
| 581 | } |
---|
| 582 | //$this->error[] = 'DEBUG: checking to see if there is no view activities on process :'.$pId.':'.$this->pm->get_process_view_activity($pId); |
---|
| 583 | /** whithout this check we can see the instance data if any view activity exists */ |
---|
| 584 | /*if ($this->pm->get_process_view_activity($pId)) |
---|
| 585 | { |
---|
| 586 | $this->error[] = tra('This process has a view activity. Access in view mode is granted only for this view activty.'); |
---|
| 587 | return false; |
---|
| 588 | }*/ |
---|
| 589 | } |
---|
| 590 | |
---|
| 591 | // user tests --------------- |
---|
| 592 | $checks = true; |
---|
| 593 | //is our actual workflow user a special rights user? |
---|
| 594 | // TODO test actual workflow user diff of $user |
---|
| 595 | //$this->error[] = 'DEBUG: user can admin instance :'.galaxia_user_can_admin_instance().' bypass?:'.$_bypass_user_if_admin; |
---|
| 596 | $is_admin = galaxia_user_can_admin_instance(); |
---|
| 597 | if (! ( (($_bypass_user_if_admin) && ($is_admin)) || (($_check_is_admin_only) && ($is_admin))) ) |
---|
| 598 | { |
---|
| 599 | //if our user is the owner we ignore user tests |
---|
| 600 | //$this->error[] = 'DEBUG: user is owner :'.$resinstance['wf_owner'].' bypass?:'.$_bypass_user_role_if_owner; |
---|
| 601 | if (!( ($_bypass_user_role_if_owner) && ((int)$resinstance['wf_owner']==(int)$user) )) |
---|
| 602 | { |
---|
| 603 | //$this->error[] = 'DEBUG: no_activity:'.$_no_activity.' interactive? :'.$resactivity['wf_is_interactive'].' bypass?:'.$_bypass_user_on_non_interactive; |
---|
| 604 | //if activity is not interactive we do not perform user tests |
---|
| 605 | if (!( (!($_no_activity)) && ($_bypass_user_on_non_interactive) && ($resactivity['wf_is_interactive']=='n') )) |
---|
| 606 | { |
---|
| 607 | //$this->error[] = 'DEBUG: no bypassing done:'; |
---|
| 608 | //is the actual_user our user? |
---|
| 609 | if ( (!($_no_instance)) && $_check_is_user) |
---|
| 610 | { |
---|
| 611 | //$this->error[] = 'DEBUG: check user is actual instance user:'.$user.':'.$res_inst_act['wf_user']; |
---|
| 612 | if (!((int)$res_inst_act['wf_user']==(int)$user)) |
---|
| 613 | { |
---|
| 614 | //user test was false, but maybe we'll have better chance later |
---|
| 615 | $checks = false; |
---|
| 616 | } |
---|
| 617 | } |
---|
| 618 | // special '*' user |
---|
| 619 | if ($res_inst_act['wf_user']=='*') |
---|
| 620 | { |
---|
| 621 | //$this->error[] = 'DEBUG: we have the special * user:'; |
---|
| 622 | //is the actual *? |
---|
| 623 | if ($_check_is_star) |
---|
| 624 | { |
---|
| 625 | // redemption here |
---|
| 626 | //$this->error[] = 'DEBUG Ok, we have a star'; |
---|
| 627 | $checks = true; |
---|
| 628 | } |
---|
| 629 | |
---|
| 630 | //is the actual <>*? |
---|
| 631 | if ($_check_is_not_star) |
---|
| 632 | { |
---|
| 633 | //no redemption here |
---|
| 634 | $this->error[] = tra('Action %1 is impossible, there are no user assigned to this activity for this instance', $action); |
---|
| 635 | return false; |
---|
| 636 | } |
---|
| 637 | //perform the role test if actual user is '*' |
---|
| 638 | //$this->error[] = 'DEBUG: role checking?:'.$_check_is_in_role; |
---|
| 639 | if ($_check_is_in_role) |
---|
| 640 | { |
---|
| 641 | //$this->error[] = 'DEBUG: we have *, checking role of user:'.$user; |
---|
| 642 | $checks=$this->checkUserAccess($user, $activityId); |
---|
| 643 | } |
---|
| 644 | //$this->error[] = 'DEBUG: role checking in read-only at least?:'.$_check_is_in_role_in_readonly; |
---|
| 645 | if ($_check_is_in_role_in_readonly) |
---|
| 646 | { |
---|
| 647 | //$this->error[] = 'DEBUG: we have *, checking readonly role of user:'.$user; |
---|
| 648 | $checks=$this->checkUserAccess($user, $activityId, true); |
---|
| 649 | } |
---|
| 650 | } |
---|
| 651 | else |
---|
| 652 | { |
---|
| 653 | if (substr($res_inst_act['wf_user'], 0, 1) == 'p') |
---|
| 654 | { |
---|
| 655 | $role_id = substr($res_inst_act['wf_user'], 1); |
---|
| 656 | $groups = galaxia_retrieve_user_groups($user); |
---|
| 657 | $sql = "SELECT 1 "; |
---|
| 658 | $sql .= "FROM " . GALAXIA_TABLE_PREFIX . "user_roles WHERE ("; |
---|
| 659 | if (is_array($groups)) |
---|
| 660 | { |
---|
| 661 | foreach ($groups as &$group) |
---|
| 662 | $group = "'{$group}'"; |
---|
| 663 | $sql .= "(wf_user IN (" . implode(',',$groups) . ") AND wf_account_type = 'g') OR "; |
---|
| 664 | } |
---|
| 665 | $sql .= "(wf_user = '$user' AND wf_account_type = 'u')) AND "; |
---|
| 666 | $sql .= "(wf_role_id = $role_id)"; |
---|
| 667 | $result = $this->getOne($sql); |
---|
| 668 | |
---|
| 669 | if (is_null($result)) |
---|
| 670 | $checks = false; |
---|
| 671 | else |
---|
| 672 | $checks = true; |
---|
| 673 | |
---|
| 674 | } |
---|
| 675 | else |
---|
| 676 | { |
---|
| 677 | //we have not *, do we need * as the actual? (done only if check_is_user is false) |
---|
| 678 | //notice that if check_user was false and we have not the '*' user and if you do not want |
---|
| 679 | //the check_is_star it means the user can bypass the actual user if you have a check_is_in_role ok! |
---|
| 680 | if ( (!($checks)) && ($_check_is_star)) |
---|
| 681 | { |
---|
| 682 | // that was necessary |
---|
| 683 | $this->error[] = tra('Action %1 is impossible, another user is already in place', $action); |
---|
| 684 | return false; |
---|
| 685 | } |
---|
| 686 | //is our user in associated roles (done even if check_is_user was true) |
---|
| 687 | //$this->error[] = 'DEBUG: role checking?:'.$_check_is_in_role; |
---|
| 688 | if ($_check_is_in_role) |
---|
| 689 | { |
---|
| 690 | //$this->error[] = 'DEBUG: we have not *, checking role for user:'.$user; |
---|
| 691 | $checks=$this->checkUserAccess($user, $activityId); |
---|
| 692 | } |
---|
| 693 | //$this->error[] = 'DEBUG: role checking in read-only at least?:'.$_check_is_in_role_in_readonly; |
---|
| 694 | if ($_check_is_in_role_in_readonly) |
---|
| 695 | { |
---|
| 696 | //$this->error[] = 'DEBUG: we have not *, checking role in read-only for user:'.$user; |
---|
| 697 | $checks=$this->checkUserAccess($user, $activityId, true); |
---|
| 698 | } |
---|
| 699 | } |
---|
| 700 | } |
---|
| 701 | } |
---|
| 702 | } |
---|
| 703 | } |
---|
| 704 | //$this->error[] = 'DEBUG: final check:'.$checks; |
---|
| 705 | return $checks; |
---|
| 706 | } |
---|
| 707 | |
---|
| 708 | /** |
---|
| 709 | * Gets avaible actions for a given user on some activity and instance assuming he already have access to it. |
---|
| 710 | * To be able to decide this function needs all the parameters, use the GUI object equivalent function if you want less parameters. |
---|
| 711 | * |
---|
| 712 | * @access public |
---|
| 713 | * @param int $user User id |
---|
| 714 | * @param int $instanceId Instance id |
---|
| 715 | * @param int $activityId Activity id |
---|
| 716 | * @param bool $readonly It has to be true if the user has only read-only level access with his role mappings |
---|
| 717 | * @param int $pId Process id |
---|
| 718 | * @param string $actType Activity type |
---|
| 719 | * @param string $actInteractive 'y' or 'n' and is the activity interactivity |
---|
| 720 | * @param string $actAutorouted 'y' or 'n' and is the activity routage |
---|
| 721 | * @param string $actStatus Activity status ('running' or 'completed') |
---|
| 722 | * @param int $instanceOwner Instance owner id |
---|
| 723 | * @param string $instanceStatus Instance status ('running', 'completed', 'aborted' or 'exception') |
---|
| 724 | * @param mixed $currentUser Current instance/activity user id or '*'. |
---|
| 725 | * @param bool $viewactivity False if the process has no view activity, else it's the id of the view activity |
---|
| 726 | * @return array An array of this form: |
---|
| 727 | * array('action name' => 'action description') |
---|
| 728 | * 'actions names' are: 'grab', 'release', 'run', 'send', 'view', 'viewrun', 'exception', 'resume', 'monitor' |
---|
| 729 | * note that for the 'viewrun' key value is an array with a 'lang' key for the translation and a 'link' key for the view activity id |
---|
| 730 | * Some config values can change theses rules but basically here they are: |
---|
| 731 | * * 'grab' : be the user of this activity. User has access to it and instance status is ok. |
---|
| 732 | * * 'release' : let * be the user of this activity. Must be the actual user or the owner of the instance. |
---|
| 733 | * * 'run' : run an associated form. This activity is interactive, user has access, instance status is ok. |
---|
| 734 | * * 'send' : send this instance, activity was non-autorouted and he has access and status is ok. |
---|
| 735 | * * 'view' : view the instance, activity ok, always avaible if no view activity on the process except for start or standalone act. |
---|
| 736 | * * 'viewrun' : view the instance in a view activity, need role on view activity, always avaible except for start or standalone act. |
---|
| 737 | * * 'abort' : abort an instance, ok when we are the user |
---|
| 738 | * * 'exception' : set the instance status to exception, need to be the user |
---|
| 739 | * * 'resume' : back to running when instance status was exception, need to be the user |
---|
| 740 | * * 'monitor' : admin the instance, for special rights users |
---|
| 741 | * 'actions description' are translated explanations like 'release access to this activity' |
---|
| 742 | * This function will as well load process configuration which could have some impact on the rights. |
---|
| 743 | * Theses config data will be cached during the existence of this WfSecurity object. |
---|
| 744 | * WARNING: this is a snapshot, the engine give you a snaphsot of the rights a user have on an instance-activity |
---|
| 745 | * at a given time, this is not meaning theses rights will still be there when the user launch the action. |
---|
| 746 | * You should absolutely use the GUI Object or runtime to execute theses actions (except monitor) and they could be rejected. |
---|
| 747 | * WARNING: we do not check the user access rights. If you launch this function for a list of instances obtained via a |
---|
| 748 | * GUI object theses access rights are allready checked (for example we do not check your readonly parameter is true). |
---|
| 749 | * In fact this function is GUI oriented, it is not granting rights |
---|
| 750 | */ |
---|
| 751 | function getUserActions($user, $instanceId, $activityId, $readonly, $pId, $actType, $actInteractive, $actAutorouted, $actStatus, $instanceOwner, $instanceStatus, $currentUser, $view_activity) |
---|
| 752 | { |
---|
| 753 | $result= array();//returned array |
---|
| 754 | $stopflow=false;//true when the instance is in a state where the flow musn't advance |
---|
| 755 | //ie: we can't send or run it |
---|
| 756 | $deathflow=false;//true when the instance is in a state where the flow will never advance anymore |
---|
| 757 | //ie: we can't send, run, grab, release, exception or resume it |
---|
| 758 | $associated_instance=true;//false when no instance is associated with the activity |
---|
| 759 | // ie: we cannot send, grab, release, exception, resume or view the instance but we can run |
---|
| 760 | // it covers standalone activities and start activities not completed |
---|
| 761 | $_run = false; |
---|
| 762 | $_send = false; |
---|
| 763 | $_grab = false; |
---|
| 764 | $_release = false; |
---|
| 765 | $_abort = false; |
---|
| 766 | $_view = false; |
---|
| 767 | $_viewrun = false; |
---|
| 768 | $_resume = false; |
---|
| 769 | $_exception = false; |
---|
| 770 | // this can be decided right now, it depends only on user rights |
---|
| 771 | $_monitor = galaxia_user_can_admin_instance($user); |
---|
| 772 | |
---|
| 773 | $this->loadConfigValues($pId); |
---|
| 774 | |
---|
| 775 | // check the instance status |
---|
| 776 | // 'completed' => no action except 'view'/'viewrun' or 'abort' or 'monitor' |
---|
| 777 | // 'aborted' => no action except 'view'/'viewrun' or 'monitor' |
---|
| 778 | // 'active' => ok first add 'exception' |
---|
| 779 | // 'exception' => first add 'resume', no 'run' or 'send' after |
---|
| 780 | $_view = true; |
---|
| 781 | if ($view_activity) |
---|
| 782 | { |
---|
| 783 | //we should have a 'viewrun' instead of a 'view' action, but maybe we do not have access on this view activity |
---|
| 784 | //this access right will be checked by gui_get_process_view_activity |
---|
| 785 | $_viewrun = true; |
---|
| 786 | $_iframe_height = $this->processesConfig[$pId]['iframe_view_height']; |
---|
| 787 | } |
---|
| 788 | |
---|
| 789 | |
---|
| 790 | //on readonly mode things are simplier, no more rights |
---|
| 791 | if (!($readonly)) |
---|
| 792 | { |
---|
| 793 | if ($instanceStatus == 'aborted') |
---|
| 794 | { |
---|
| 795 | $deathflow=true; |
---|
| 796 | } |
---|
| 797 | else |
---|
| 798 | { |
---|
| 799 | // first check ABORT |
---|
| 800 | if ( ($user==$currentUser) || |
---|
| 801 | (($user==$instanceOwner)&&($this->processesConfig[$pId]['ownership_give_abort_right'])) || |
---|
| 802 | ($this->processesConfig[$pId]['role_give_abort_right'])) |
---|
| 803 | {// we are the assigned user |
---|
| 804 | //OR we are the owner and it gives rights |
---|
| 805 | //OR we have the role and it gives rights |
---|
| 806 | $_abort =true; |
---|
| 807 | } |
---|
| 808 | // now handle resume and exception but before detect completed instances |
---|
| 809 | if ($instanceStatus == 'completed') |
---|
| 810 | { |
---|
| 811 | $deathflow=true; |
---|
| 812 | } |
---|
| 813 | else |
---|
| 814 | { |
---|
| 815 | if ($instanceStatus == 'exception') |
---|
| 816 | { |
---|
| 817 | $stopflow = true; |
---|
| 818 | if ( ($user==$currentUser) || |
---|
| 819 | (($user==$instanceOwner)&&($this->processesConfig[$pId]['ownership_give_exception_right'])) || |
---|
| 820 | ($this->processesConfig[$pId]['role_give_exception_right'])) |
---|
| 821 | {// we are the assigned user OR we are the owner and it gives rights |
---|
| 822 | $_resume = true; |
---|
| 823 | } |
---|
| 824 | } |
---|
| 825 | elseif ($instanceStatus == 'active') |
---|
| 826 | { |
---|
| 827 | //handle rules about ownership |
---|
| 828 | if ( ($user==$currentUser) || |
---|
| 829 | (($user==$instanceOwner)&&($this->processesConfig[$pId]['ownership_give_exception_right'])) || |
---|
| 830 | ($this->processesConfig[$pId]['role_give_exception_right'])) |
---|
| 831 | {// we are the assigned user OR we are the owner and it gives rights |
---|
| 832 | $_exception = true; |
---|
| 833 | } |
---|
| 834 | } |
---|
| 835 | } |
---|
| 836 | } |
---|
| 837 | |
---|
| 838 | //now we check the activity |
---|
| 839 | // start (only uncompleted) and standalone activities have no instance associated. |
---|
| 840 | // If we are not in a 'stop' or 'death' flow we can check interactivity |
---|
| 841 | // interactive -> run |
---|
| 842 | // not interactive -> send (except for 'standalone') |
---|
| 843 | // if we are not in a 'death flow' we can add grab and release actions |
---|
| 844 | if ( ($actType=='standalone') || (($actType=='start') && (!($actStatus=='completed'))) ) |
---|
| 845 | { |
---|
| 846 | $associated_instance=false; |
---|
| 847 | // there's no instance to view in fact |
---|
| 848 | $_view = false; |
---|
| 849 | $_viewrun = false; |
---|
| 850 | } |
---|
| 851 | if (($actInteractive=='y') && (!($deathflow))) |
---|
| 852 | { |
---|
| 853 | if ($associated_instance) |
---|
| 854 | { |
---|
| 855 | if ($currentUser=='*') |
---|
| 856 | { |
---|
| 857 | $_grab = true; |
---|
| 858 | } |
---|
| 859 | else |
---|
| 860 | { |
---|
| 861 | if ( ($user==$currentUser) || |
---|
| 862 | (($user==$instanceOwner)&&($this->processesConfig[$pId]['ownership_give_release_right'])) || |
---|
| 863 | ($this->processesConfig[$pId]['role_give_release_right'])) |
---|
| 864 | {// we are the assigned user |
---|
| 865 | //OR we are the owner and it gives rights |
---|
| 866 | //OR we have the role and it gives rights |
---|
| 867 | $_release = true; |
---|
| 868 | } |
---|
| 869 | } |
---|
| 870 | } |
---|
| 871 | if (($actStatus=='running') && !($stopflow) && !($deathflow)) |
---|
| 872 | { |
---|
| 873 | if (($currentUser=='*') || ($currentUser==$user)) |
---|
| 874 | { |
---|
| 875 | $_run = true; |
---|
| 876 | } |
---|
| 877 | } |
---|
| 878 | } |
---|
| 879 | //for non autorouted activities we'll have to send, useless on standalone but usefull for start |
---|
| 880 | //activities which can be sended if completed and of course for all other activities |
---|
| 881 | if ($actAutorouted=='n') |
---|
| 882 | { |
---|
| 883 | if ($associated_instance) |
---|
| 884 | { |
---|
| 885 | if (($actStatus=='completed') && !($stopflow) && !($deathflow)) |
---|
| 886 | { |
---|
| 887 | $_send = true; |
---|
| 888 | } |
---|
| 889 | } |
---|
| 890 | } |
---|
| 891 | }//end if !$readonly |
---|
| 892 | |
---|
| 893 | //build final array |
---|
| 894 | if ($_run) $result['run']=tra('Execute this activity'); |
---|
| 895 | if ($_send) $result['send']=tra('Send this instance to the next activity'); |
---|
| 896 | if ($_grab) $result['grab']=tra('Assign me this activity'); |
---|
| 897 | if ($_release) $result['release']=tra('Release access to this activity'); |
---|
| 898 | if ($_abort) $result['abort']=tra('Abort this instance'); |
---|
| 899 | if ($_view) $result['view']=tra('View this instance'); |
---|
| 900 | if ($_viewrun) $result['viewrun']= array('lang' => tra('View this instance'), 'link' => $view_activity); |
---|
| 901 | if ($_iframe_height) $result['viewrun']['iframe_height'] = $_iframe_height; |
---|
| 902 | if ($_resume) $result['resume']=tra('Resume this exception instance'); |
---|
| 903 | if ($_exception) $result['exception']=tra('Exception this instance'); |
---|
| 904 | if ($_monitor) $result['monitor']=tra('Monitor this instance'); |
---|
| 905 | |
---|
| 906 | return $result; |
---|
| 907 | } |
---|
| 908 | |
---|
| 909 | |
---|
| 910 | } |
---|
| 911 | |
---|
| 912 | |
---|
| 913 | ?> |
---|