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