1<?php 2 3/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */ 4 5include_once "Modules/Group/classes/class.ilGroupParticipants.php"; 6include_once "Modules/Course/classes/class.ilCourseParticipants.php"; 7include_once "Services/PersonalWorkspace/classes/class.ilWorkspaceAccessGUI.php"; 8 9/** 10 * Access handler for personal workspace 11 * 12 * @author Jörg Lützenkirchen <luetzenkirchen@leifos.com> 13 */ 14class ilWorkspaceAccessHandler 15{ 16 /** 17 * @var ilObjUser 18 */ 19 protected $user; 20 21 /** 22 * @var ilLanguage 23 */ 24 protected $lng; 25 26 /** 27 * @var ilRbacReview 28 */ 29 protected $rbacreview; 30 31 /** 32 * @var ilSetting 33 */ 34 protected $settings; 35 36 /** 37 * @var ilDB 38 */ 39 protected $db; 40 41 protected $tree; // [ilTree] 42 43 public function __construct(ilTree $a_tree = null) 44 { 45 global $DIC; 46 47 $this->user = $DIC->user(); 48 $this->lng = $DIC->language(); 49 $this->rbacreview = $DIC->rbac()->review(); 50 $this->settings = $DIC->settings(); 51 $this->db = $DIC->database(); 52 $ilUser = $DIC->user(); 53 $lng = $DIC->language(); 54 55 $lng->loadLanguageModule("wsp"); 56 57 if (!$a_tree) { 58 include_once "Services/PersonalWorkspace/classes/class.ilWorkspaceTree.php"; 59 $a_tree = new ilWorkspaceTree($ilUser->getId()); 60 } 61 $this->tree = $a_tree; 62 } 63 64 /** 65 * Get workspace tree 66 * 67 * @return ilWorkspaceTree 68 */ 69 public function getTree() 70 { 71 return $this->tree; 72 } 73 74 /** 75 * check access for an object 76 * 77 * @param string $a_permission 78 * @param string $a_cmd 79 * @param int $a_node_id 80 * @param string $a_type (optional) 81 * @return bool 82 */ 83 public function checkAccess($a_permission, $a_cmd, $a_node_id, $a_type = "") 84 { 85 $ilUser = $this->user; 86 87 return $this->checkAccessOfUser($this->tree, $ilUser->getId(), $a_permission, $a_cmd, $a_node_id, $a_type); 88 } 89 90 /** 91 * check access for an object 92 * 93 * @param ilTree $a_tree 94 * @param integer $a_user_id 95 * @param string $a_permission 96 * @param string $a_cmd 97 * @param int $a_node_id 98 * @param string $a_type (optional) 99 * @return bool 100 */ 101 public function checkAccessOfUser(ilTree $a_tree, $a_user_id, $a_permission, $a_cmd, $a_node_id, $a_type = "") 102 { 103 $rbacreview = $this->rbacreview; 104 $ilUser = $this->user; 105 $ilSetting = $this->settings; 106 107 // :TODO: create permission for parent node with type ?! 108 109 // #20310 110 if (!$ilSetting->get("enable_global_profiles") && $ilUser->getId() == ANONYMOUS_USER_ID) { 111 return false; 112 } 113 114 // tree root is read-only 115 if ($a_permission == "write") { 116 if ($a_tree->readRootId() == $a_node_id) { 117 return false; 118 } 119 } 120 121 // node owner has all rights 122 if ($a_tree->lookupOwner($a_node_id) == $a_user_id) { 123 return true; 124 } 125 126 // other users can only read 127 if ($a_permission == "read" || $a_permission == "visible") { 128 // get all objects with explicit permission 129 $objects = $this->getPermissions($a_node_id); 130 if ($objects) { 131 // check if given user is member of object or has role 132 foreach ($objects as $obj_id) { 133 switch ($obj_id) { 134 case ilWorkspaceAccessGUI::PERMISSION_ALL: 135 return true; 136 137 case ilWorkspaceAccessGUI::PERMISSION_ALL_PASSWORD: 138 // check against input kept in session 139 if (self::getSharedNodePassword($a_node_id) == self::getSharedSessionPassword($a_node_id) || 140 $a_permission == "visible") { 141 return true; 142 } 143 break; 144 145 case ilWorkspaceAccessGUI::PERMISSION_REGISTERED: 146 if ($ilUser->getId() != ANONYMOUS_USER_ID) { 147 return true; 148 } 149 break; 150 151 default: 152 switch (ilObject::_lookupType($obj_id)) { 153 case "grp": 154 // member of group? 155 if (ilGroupParticipants::_getInstanceByObjId($obj_id)->isAssigned($a_user_id)) { 156 return true; 157 } 158 break; 159 160 case "crs": 161 // member of course? 162 if (ilCourseParticipants::_getInstanceByObjId($obj_id)->isAssigned($a_user_id)) { 163 return true; 164 } 165 break; 166 167 case "role": 168 // has role? 169 if ($rbacreview->isAssigned($a_user_id, $obj_id)) { 170 return true; 171 } 172 break; 173 174 case "usr": 175 // direct assignment 176 if ($a_user_id == $obj_id) { 177 return true; 178 } 179 break; 180 } 181 break; 182 } 183 } 184 } 185 } 186 187 return false; 188 } 189 190 /** 191 * Set permissions after creating node/object 192 * 193 * @param int $a_parent_node_id 194 * @param int $a_node_id 195 */ 196 public function setPermissions($a_parent_node_id, $a_node_id) 197 { 198 // nothing to do as owner has irrefutable rights to any workspace object 199 } 200 201 /** 202 * Add permission to node for object 203 * 204 * @param int $a_node_id 205 * @param int $a_object_id 206 * @param string $a_extended_data 207 * @return bool 208 */ 209 public function addPermission($a_node_id, $a_object_id, $a_extended_data = null) 210 { 211 $ilDB = $this->db; 212 $ilUser = $this->user; 213 214 // tree owner must not be added 215 if ($this->tree->getTreeId() == $ilUser->getId() && 216 $a_object_id == $ilUser->getId()) { 217 return false; 218 } 219 220 $ilDB->manipulate("INSERT INTO acl_ws (node_id, object_id, extended_data, tstamp)" . 221 " VALUES (" . $ilDB->quote($a_node_id, "integer") . ", " . 222 $ilDB->quote($a_object_id, "integer") . "," . 223 $ilDB->quote($a_extended_data, "text") . "," . 224 $ilDB->quote(time(), "integer") . ")"); 225 return true; 226 } 227 228 /** 229 * Remove permission[s] (for object) to node 230 * 231 * @param int $a_node_id 232 * @param int $a_object_id 233 */ 234 public function removePermission($a_node_id, $a_object_id = null) 235 { 236 $ilDB = $this->db; 237 238 $query = "DELETE FROM acl_ws" . 239 " WHERE node_id = " . $ilDB->quote($a_node_id, "integer"); 240 241 if ($a_object_id) { 242 $query .= " AND object_id = " . $ilDB->quote($a_object_id, "integer"); 243 } 244 245 return $ilDB->manipulate($query); 246 } 247 248 /** 249 * Get all permissions to node 250 * 251 * @param int $a_node_id 252 * @return array 253 */ 254 public function getPermissions($a_node_id) 255 { 256 return self::_getPermissions($a_node_id); 257 } 258 259 /** 260 * Get all permissions to node 261 * 262 * @param int $a_node_id 263 * @return array 264 */ 265 public static function _getPermissions($a_node_id) 266 { 267 global $DIC; 268 269 $ilDB = $DIC->database(); 270 $ilSetting = $DIC->settings(); 271 272 $publish_enabled = $ilSetting->get("enable_global_profiles"); 273 $publish_perm = array(ilWorkspaceAccessGUI::PERMISSION_ALL, 274 ilWorkspaceAccessGUI::PERMISSION_ALL_PASSWORD); 275 276 $set = $ilDB->query("SELECT object_id FROM acl_ws" . 277 " WHERE node_id = " . $ilDB->quote($a_node_id, "integer")); 278 $res = array(); 279 while ($row = $ilDB->fetchAssoc($set)) { 280 if ($publish_enabled || !in_array($row["object_id"], $publish_perm)) { 281 $res[] = $row["object_id"]; 282 } 283 } 284 return $res; 285 } 286 287 public function hasRegisteredPermission($a_node_id) 288 { 289 $ilDB = $this->db; 290 291 $set = $ilDB->query("SELECT object_id FROM acl_ws" . 292 " WHERE node_id = " . $ilDB->quote($a_node_id, "integer") . 293 " AND object_id = " . $ilDB->quote(ilWorkspaceAccessGUI::PERMISSION_REGISTERED, "integer")); 294 return (bool) $ilDB->numRows($set); 295 } 296 297 public function hasGlobalPermission($a_node_id) 298 { 299 $ilDB = $this->db; 300 $ilSetting = $this->settings; 301 302 if (!$ilSetting->get("enable_global_profiles")) { 303 return false; 304 } 305 306 $set = $ilDB->query("SELECT object_id FROM acl_ws" . 307 " WHERE node_id = " . $ilDB->quote($a_node_id, "integer") . 308 " AND object_id = " . $ilDB->quote(ilWorkspaceAccessGUI::PERMISSION_ALL, "integer")); 309 return (bool) $ilDB->numRows($set); 310 } 311 312 public function hasGlobalPasswordPermission($a_node_id) 313 { 314 $ilDB = $this->db; 315 $ilSetting = $this->settings; 316 317 if (!$ilSetting->get("enable_global_profiles")) { 318 return false; 319 } 320 321 $set = $ilDB->query("SELECT object_id FROM acl_ws" . 322 " WHERE node_id = " . $ilDB->quote($a_node_id, "integer") . 323 " AND object_id = " . $ilDB->quote(ilWorkspaceAccessGUI::PERMISSION_ALL_PASSWORD, "integer")); 324 return (bool) $ilDB->numRows($set); 325 } 326 327 public static function getPossibleSharedTargets() 328 { 329 global $DIC; 330 331 $ilUser = $DIC->user(); 332 $ilSetting = $DIC->settings(); 333 334 include_once "Services/PersonalWorkspace/classes/class.ilWorkspaceAccessGUI.php"; 335 include_once "Services/Membership/classes/class.ilParticipants.php"; 336 $grp_ids = ilParticipants::_getMembershipByType($ilUser->getId(), "grp"); 337 $crs_ids = ilParticipants::_getMembershipByType($ilUser->getId(), "crs"); 338 339 $obj_ids = array_merge($grp_ids, $crs_ids); 340 $obj_ids[] = $ilUser->getId(); 341 $obj_ids[] = ilWorkspaceAccessGUI::PERMISSION_REGISTERED; 342 343 if ($ilSetting->get("enable_global_profiles")) { 344 $obj_ids[] = ilWorkspaceAccessGUI::PERMISSION_ALL; 345 $obj_ids[] = ilWorkspaceAccessGUI::PERMISSION_ALL_PASSWORD; 346 } 347 348 return $obj_ids; 349 } 350 351 public function getSharedOwners() 352 { 353 $ilUser = $this->user; 354 $ilDB = $this->db; 355 356 $obj_ids = $this->getPossibleSharedTargets(); 357 358 $user_ids = array(); 359 $set = $ilDB->query("SELECT DISTINCT(obj.owner), u.lastname, u.firstname, u.title" . 360 " FROM object_data obj" . 361 " JOIN object_reference_ws ref ON (obj.obj_id = ref.obj_id)" . 362 " JOIN tree_workspace tree ON (tree.child = ref.wsp_id)" . 363 " JOIN acl_ws acl ON (acl.node_id = tree.child)" . 364 " JOIN usr_data u on (u.usr_id = obj.owner)" . 365 " WHERE " . $ilDB->in("acl.object_id", $obj_ids, "", "integer") . 366 " AND obj.owner <> " . $ilDB->quote($ilUser->getId(), "integer") . 367 " ORDER BY u.lastname, u.firstname, u.title"); 368 while ($row = $ilDB->fetchAssoc($set)) { 369 $user_ids[$row["owner"]] = $row["lastname"] . ", " . $row["firstname"]; 370 if ($row["title"]) { 371 $user_ids[$row["owner"]] .= ", " . $row["title"]; 372 } 373 } 374 375 return $user_ids; 376 } 377 378 public function getSharedObjects($a_owner_id) 379 { 380 $ilDB = $this->db; 381 382 $obj_ids = $this->getPossibleSharedTargets(); 383 384 $res = array(); 385 $set = $ilDB->query("SELECT ref.wsp_id,obj.obj_id" . 386 " FROM object_data obj" . 387 " JOIN object_reference_ws ref ON (obj.obj_id = ref.obj_id)" . 388 " JOIN tree_workspace tree ON (tree.child = ref.wsp_id)" . 389 " JOIN acl_ws acl ON (acl.node_id = tree.child)" . 390 " WHERE " . $ilDB->in("acl.object_id", $obj_ids, "", "integer") . 391 " AND obj.owner = " . $ilDB->quote($a_owner_id, "integer")); 392 while ($row = $ilDB->fetchAssoc($set)) { 393 $res[$row["wsp_id"]] = $row["obj_id"]; 394 } 395 396 return $res; 397 } 398 399 public function findSharedObjects(array $a_filter = null, array $a_crs_ids = null, array $a_grp_ids = null) 400 { 401 $ilDB = $this->db; 402 $ilUser = $this->user; 403 404 if (!$a_filter["acl_type"]) { 405 $obj_ids = $this->getPossibleSharedTargets(); 406 } else { 407 include_once "Services/PersonalWorkspace/classes/class.ilWorkspaceAccessGUI.php"; 408 409 switch ($a_filter["acl_type"]) { 410 case "all": 411 $obj_ids = array(ilWorkspaceAccessGUI::PERMISSION_ALL); 412 break; 413 414 case "password": 415 $obj_ids = array(ilWorkspaceAccessGUI::PERMISSION_ALL_PASSWORD); 416 break; 417 418 case "registered": 419 $obj_ids = array(ilWorkspaceAccessGUI::PERMISSION_REGISTERED); 420 break; 421 422 case "course": 423 $obj_ids = $a_crs_ids; 424 break; 425 426 case "group": 427 $obj_ids = $a_grp_ids; 428 break; 429 430 case "user": 431 $obj_ids = array($ilUser->getId()); 432 break; 433 } 434 } 435 436 $res = array(); 437 438 $sql = "SELECT ref.wsp_id,obj.obj_id,obj.type,obj.title,obj.owner," . 439 "acl.object_id acl_type, acl.tstamp acl_date" . 440 " FROM object_data obj" . 441 " JOIN object_reference_ws ref ON (obj.obj_id = ref.obj_id)" . 442 " JOIN tree_workspace tree ON (tree.child = ref.wsp_id)" . 443 " JOIN acl_ws acl ON (acl.node_id = tree.child)" . 444 " WHERE " . $ilDB->in("acl.object_id", $obj_ids, "", "integer") . 445 " AND obj.owner <> " . $ilDB->quote($ilUser->getId(), "integer"); 446 447 if ($a_filter["obj_type"]) { 448 $sql .= " AND obj.type = " . $ilDB->quote($a_filter["obj_type"], "text"); 449 } 450 if ($a_filter["title"] && strlen($a_filter["title"]) >= 3) { 451 $sql .= " AND " . $ilDB->like("obj.title", "text", "%" . $a_filter["title"] . "%"); 452 } 453 if ($a_filter["user"] && strlen($a_filter["user"]) >= 3) { 454 $usr_ids = array(); 455 $set = $ilDB->query("SELECT usr_id FROM usr_data" . 456 " WHERE (" . $ilDB->like("login", "text", "%" . $a_filter["user"] . "%") . " " . 457 "OR " . $ilDB->like("firstname", "text", "%" . $a_filter["user"] . "%") . " " . 458 "OR " . $ilDB->like("lastname", "text", "%" . $a_filter["user"] . "%") . " " . 459 "OR " . $ilDB->like("email", "text", "%" . $a_filter["user"] . "%") . ")"); 460 while ($row = $ilDB->fetchAssoc($set)) { 461 $usr_ids[] = $row["usr_id"]; 462 } 463 if (!sizeof($usr_ids)) { 464 return; 465 } 466 $sql .= " AND " . $ilDB->in("obj.owner", $usr_ids, "", "integer"); 467 } 468 469 if ($a_filter["acl_date"]) { 470 $dt = $a_filter["acl_date"]->get(IL_CAL_DATE); 471 $dt = new ilDateTime($dt . " 00:00:00", IL_CAL_DATETIME); 472 $sql .= " AND acl.tstamp > " . $ilDB->quote($dt->get(IL_CAL_UNIX), "integer"); 473 } 474 475 if ($a_filter["crsgrp"]) { 476 include_once "Services/Membership/classes/class.ilParticipants.php"; 477 $part = ilParticipants::getInstanceByObjId($a_filter['crsgrp']); 478 $part = $part->getParticipants(); 479 if (!sizeof($part)) { 480 return; 481 } 482 $sql .= " AND " . $ilDB->in("obj.owner", $part, "", "integer"); 483 } 484 485 // we use the oldest share date 486 $sql .= " ORDER BY acl.tstamp"; 487 488 $set = $ilDB->query($sql); 489 while ($row = $ilDB->fetchAssoc($set)) { 490 if (!isset($res[$row["wsp_id"]])) { 491 $row["acl_type"] = array($row["acl_type"]); 492 $res[$row["wsp_id"]] = $row; 493 } else { 494 $res[$row["wsp_id"]]["acl_type"][] = $row["acl_type"]; 495 } 496 } 497 498 return $res; 499 } 500 501 public static function getSharedNodePassword($a_node_id) 502 { 503 global $DIC; 504 505 $ilDB = $DIC->database(); 506 507 include_once "Services/PersonalWorkspace/classes/class.ilWorkspaceAccessGUI.php"; 508 509 $set = $ilDB->query("SELECT * FROM acl_ws" . 510 " WHERE node_id = " . $ilDB->quote($a_node_id, "integer") . 511 " AND object_id = " . $ilDB->quote(ilWorkspaceAccessGUI::PERMISSION_ALL_PASSWORD, "integer")); 512 $res = $ilDB->fetchAssoc($set); 513 if ($res) { 514 return $res["extended_data"]; 515 } 516 } 517 518 public static function keepSharedSessionPassword($a_node_id, $a_password) 519 { 520 $_SESSION["ilshpw_" . $a_node_id] = $a_password; 521 } 522 523 public static function getSharedSessionPassword($a_node_id) 524 { 525 return $_SESSION["ilshpw_" . $a_node_id]; 526 } 527 528 public static function getGotoLink($a_node_id, $a_obj_id, $a_additional = null) 529 { 530 include_once('./Services/Link/classes/class.ilLink.php'); 531 return ilLink::_getStaticLink($a_node_id, ilObject::_lookupType($a_obj_id), true, $a_additional . "_wsp"); 532 } 533 534 public function getObjectsIShare() 535 { 536 $ilDB = $this->db; 537 $ilUser = $this->user; 538 539 $res = array(); 540 $set = $ilDB->query("SELECT ref.wsp_id,obj.obj_id" . 541 " FROM object_data obj" . 542 " JOIN object_reference_ws ref ON (obj.obj_id = ref.obj_id)" . 543 " JOIN tree_workspace tree ON (tree.child = ref.wsp_id)" . 544 " JOIN acl_ws acl ON (acl.node_id = tree.child)" . 545 " WHERE obj.owner = " . $ilDB->quote($ilUser->getId(), "integer")); 546 while ($row = $ilDB->fetchAssoc($set)) { 547 $res[$row["wsp_id"]] = $row["obj_id"]; 548 } 549 550 return $res; 551 } 552 553 public static function getObjectDataFromNode($a_node_id) 554 { 555 global $DIC; 556 557 $ilDB = $DIC->database(); 558 559 $set = $ilDB->query("SELECT obj.obj_id, obj.type, obj.title" . 560 " FROM object_reference_ws ref" . 561 " JOIN tree_workspace tree ON (tree.child = ref.wsp_id)" . 562 " JOIN object_data obj ON (ref.obj_id = obj.obj_id)" . 563 " WHERE ref.wsp_id = " . $ilDB->quote($a_node_id, "integer")); 564 return $ilDB->fetchAssoc($set); 565 } 566} 567