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