*/ require_once ("domframework/dblayer.php"); /** All the needed functions to authorize or deny access to an authenticated user by its groups membership */ class authzgroups { public $tableprefix = ""; private $dbObject = null; private $dbGroup = null; private $dbGroupMember = null; private $dbRight = null; public $debug = 0; ///////////////////// // USER RIGHTS // ///////////////////// /** Return an array with all the rights of the user in the module. Cache this information to be quicker with next requests Remove the entries where path is not at least readable */ public function userrightsget ($module, $user) { // if (isset ($_SESSION["domframework"]["authzgroups"][$module][$user])) // return $_SESSION["domframework"]["authzgroups"][$module][$user]; if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); // Do the SQL request in hard to be more performant on jointures $req = "SELECT o.object,MAX(r.right) AS right FROM ".$this->tableprefix."authzright AS r, ".$this->tableprefix."authzobject AS o, ".$this->tableprefix."authzgroup AS g, ".$this->tableprefix."authzgroupmember AS gm WHERE r.idgroup=g.idgroup AND r.idobject=o.idobject AND gm.idgroup=g.idgroup AND gm.user=:user AND g.module=:module GROUP BY o.object ORDER BY o.object"; if ($this->debug) echo "$req\n"; try { $st = $this->dbObject->db->prepare ($req); } catch (Exception $e) { if ($this->dbObject->debug) echo "DEBUG : PREPARE ERROR ! Return FALSE". $e->getMessage()."\n"; throw new Exception ($e->getMessage(), 500); } $st->bindValue (":user", $user); $st->bindValue (":module", $module); $rc = $st->execute (); if ($rc === false) { if ($this->dbObject->debug) echo "DEBUG : EXECUTE ERROR ! Return FALSE\n"; } $res = array (); while ($d = $st->fetch (PDO::FETCH_ASSOC)) $res[$d["object"]] = $d["right"]; // Transform the numerical rights to RO/RW foreach ($res as $k=>$r) { switch ($r) { case "2": $res[$k] = "RW"; break; case "1": $res[$k] = "RO"; break; default: throw new Exception (dgettext ("domframework", "Unknown right stored"), 500); } } if (isset ($_SESSION)) $_SESSION["domframework"]["authzgroups"][$module][$user] = $res; return $res; } /** Return the right defined for this user in the module for one object */ public function allow ($module, $user, $object) { $ressource = $this->userrightsget ($module, $user); // The complete tree should not be readable for the user : it can have // access to a card, but not to all the cards (group -> reject, // group/XXX->allow) /*// Limit to allowed trees : if a member of the path is not recorded (is // unreadable), return NO. // Can be the last entry (the complete object) too $path = explode ("/", $object); $completePath = "/"; foreach ($path as $k=>$p) { if ($k>1) $completePath .= "/"; $completePath .= "$p"; if (! isset ($ressource[$completePath])) { if ($this->debug) echo "DEBUG allow : REJECT because $completePath is not found\n"; return "NO"; } }*/ if (! isset ($ressource[$object])) return "NO"; return $ressource[$object]; } ///////////////////////// // DATABASE STORAGE // ///////////////////////// /** Connect to the database before using it */ public function connect ($dsn, $username=null, $password=null, $driver_options=null) { $this->dbObject = new dblayer ($dsn, $username, $password, $driver_options); $this->dbObject->debug = $this->debug; $this->dbObject->table = "authzobject"; $this->dbObject->prefix = $this->tableprefix; $this->dbObject->fields = array ( "idobject"=>array ("integer", "not null", "autoincrement"), "module"=> array ("varchar", "255", "not null"), "object"=> array ("varchar", "255", "not null"), "comment"=> array ("varchar", "255")); $this->dbObject->primary = "idobject"; $this->dbObject->unique = array ("idobject", array ("object", "module")); $this->dbObject->titles = array ("idobject"=>_("idobject"), "module"=>_("Module"), "object"=>_("Object"), "comment"=>_("Comment")); $this->dbGroup = new dblayer ($dsn, $username, $password, $driver_options); $this->dbGroup->debug = $this->debug; $this->dbGroup->table = "authzgroup"; $this->dbGroup->prefix = $this->tableprefix; $this->dbGroup->fields = array ( "idgroup"=>array ("integer", "not null", "autoincrement"), "module"=> array ("varchar", "255", "not null"), "group"=> array ("varchar", "255", "not null"), "comment"=>array ("varchar", "255")); $this->dbGroup->primary = "idgroup"; $this->dbGroup->unique = array ("idgroup", array ("module","group")); $this->dbGroup->titles = array ("idgroup"=>_("idgroup"), "module"=>_("Module"), "group"=>_("Group"), "comment"=>_("Comment")); $this->dbGroupMember = new dblayer ($dsn, $username, $password, $driver_options); $this->dbGroupMember->debug = $this->debug; $this->dbGroupMember->table = "authzgroupmember"; $this->dbGroupMember->prefix = $this->tableprefix; $this->dbGroupMember->fields = array ( "idgroupmember"=>array ("integer", "not null", "autoincrement"), "user"=> array ("varchar", "255", "not null"), "idgroup"=> array ("integer", "not null"), "comment"=> array ("varchar", "255")); $this->dbGroupMember->primary = "idgroupmember"; $this->dbGroupMember->unique = array ("idgroupmember", array ("user","idgroup")); $this->dbGroupMember->foreign = array ( "idgroup"=>array ("authzgroup", "idgroup", "ON UPDATE CASCADE ON DELETE CASCADE")); $this->dbRight = new dblayer ($dsn, $username, $password, $driver_options); $this->dbRight->debug = $this->debug; $this->dbRight->table = "authzright"; $this->dbRight->prefix = $this->tableprefix; $this->dbRight->fields = array ( "idright"=> array ("integer", "not null", "autoincrement"), "idgroup"=> array ("integer", "not null"), "idobject"=>array ("integer", "not null"), "right"=> array ("integer", "not null"), // 1=RO,2=RW "comment"=> array ("varchar", "255")); $this->dbRight->primary = "idright"; $this->dbRight->unique = array ("idright", array ("idgroup","idobject")); $this->dbRight->foreign = array ( "idgroup"=> array ("authzgroup", "idgroup", "ON UPDATE CASCADE ON DELETE CASCADE"), "idobject"=>array ("authzobject", "idobject", "ON UPDATE CASCADE ON DELETE CASCADE"), ); return TRUE; } /** Create the tables in the database to store the datas */ public function createTables () { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); if ($this->dbGroupMember == null) throw new Exception (dgettext ("domframework", "DB for GroupMember is not connected"), 500); if ($this->dbRight == null) throw new Exception (dgettext ("domframework", "DB for Right is not connected"), 500); $tables = array ("Object", "Group", "GroupMember", "Right"); foreach ($tables as $table) { try { $class= "db$table"; $this->$class->createTable (); } catch (Exception $e) { echo $e->getMessage()."\n"; } } return TRUE; } ///////////////// // OBJECTS // ///////////////// /** Add a new object to object list Return the idobject created */ public function objectAdd ($module, $object, $comment="") { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); // TODO : Check parameters before saving them return $this->dbObject->insert (array ("module"=>$module, "object"=>$object, "comment"=>$comment)); } /** Remove an object from database and all the rights using it */ public function objectDel ($module, $object) { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); $idobjects = $this->objectRead ($module, $object); if (! isset ($idobjects[0]["idobject"])) throw new Exception (dgettext ("domframework", "Wanted object not found"), 404); return $this->dbObject->delete ($idobjects[0]["idobject"]); } /** Remove an object from database and all the rights using it */ public function objectDelByID ($module, $idobject) { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); $idobjects = $this->objectReadByID ($module, $idobject); if (! isset ($idobjects[0]["idobject"])) throw new Exception (dgettext ("domframework", "Wanted object not found"), 404); return $this->dbObject->delete ($idobjects[0]["idobject"]); } /** Update an object in the database */ public function objectUpdate ($module, $object, $newobject, $newcomment="") { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); $idobjects = $this->objectRead ($module, $object); if (! isset ($idobjects[0]["idobject"])) throw new Exception (dgettext ("domframework", "Wanted object not found"), 404); return $this->dbObject->update ($idobjects[0]["idobject"], array ("object"=>$newobject, "comment"=>$newcomment)); } /** Update an object in the database */ public function objectUpdateByID ($module, $idobject, $newobject, $newcomment="") { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); $idobjects = $this->objectReadByID ($module, $idobject); if (! isset ($idobjects[0]["idobject"])) throw new Exception (dgettext ("domframework", "Wanted object not found"), 404); return $this->dbObject->update ($idobjects[0]["idobject"], array ("object"=>$newobject, "comment"=>$newcomment)); } /** Return an array with all the available objects in the module, or only one object if $object is provided */ public function objectRead ($module, $object=null) { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); $select[] = array ("module", $module); if ($object !== null) $select[] = array ("object", $object); return $this->dbObject->read ($select); } /** Return an array with all the available objects in the module, or only one object if $object is provided */ public function objectReadByID ($module, $idobject=null) { if ($this->dbObject == null) throw new Exception (dgettext ("domframework", "DB for Object is not connected"), 500); $select[] = array ("module", $module); if ($idobject !== null) $select[] = array ("idobject", $idobject); return $this->dbObject->read ($select); } /** Return an array containing the titles of the table translating in the user language */ public function objectTitles () { return $this->dbObject->titles; } /** Check if the provided datas are compilant with the object specification @return array The errors found in the datas */ public function objectVerify ($datas, $idobject=false) { return $this->dbObject->verify ($datas, $idobject); } //////////////// // GROUPS // //////////////// /** Add a new group to group list Return the idgroup created */ public function groupAdd ($module, $group, $comment="") { if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); // TODO : Check parameters before saving them return $this->dbGroup->insert (array ("module"=>$module, "group"=>$group, "comment"=>$comment)); } /** Remove an group from database and all the rights using it */ public function groupDel ($module, $group) { if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); $idgroups = $this->groupRead ($module, $group); if (! isset ($idgroups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); return $this->dbGroup->delete ($idgroups[0]["idgroup"]); } /** Remove an group from database and all the rights using it */ public function groupDelByID ($module, $idgroup) { if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); $idgroups = $this->groupReadByID ($module, $idgroup); if (! isset ($idgroups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); return $this->dbGroup->delete ($idgroups[0]["idgroup"]); } /** Update an group in the database */ public function groupUpdate ($module, $group, $newgroup, $comment="") { if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); $idgroups = $this->groupRead ($module, $group); if (! isset ($idgroups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); return $this->dbGroup->update ($idgroups[0]["idgroup"], array ("group"=>$newgroup, "comment"=>$comment)); } /** Update an group in the database */ public function groupUpdateByID ($module, $idgroup, $newgroup, $comment="") { if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); $idgroups = $this->groupReadByID ($module, $idgroup); if (! isset ($idgroups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); return $this->dbGroup->update ($idgroups[0]["idgroup"], array ("group"=>$newgroup, "comment"=>$comment)); } /** Return an array with all the available groups in the module */ public function groupRead ($module, $group=null) { if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); $select[] = array ("module", $module); if ($group !== null) $select[] = array ("group", $group); return $this->dbGroup->read ($select); } public function groupReadByID ($module, $idgroup) { if ($this->dbGroup == null) throw new Exception (dgettext ("domframework", "DB for Group is not connected"), 500); $select[] = array ("module", $module); $select[] = array ("idgroup", $idgroup); return $this->dbGroup->read ($select); } /** Return an array containing the titles of the table translating in the user language */ public function groupTitles () { return $this->dbGroup->titles; } /** Check if the provided datas are compilant with the group specification @return array The errors found in the datas */ public function groupVerify ($datas, $idgroup=false) { return $this->dbGroup->verify ($datas, $idgroup); } ////////////////////// // GROUP MEMBER // ////////////////////// /** Add a new groupmember to groupmember list Return the idgroupmember created */ public function groupmemberAdd ($module, $group, $user, $comment="") { if ($this->dbGroupMember == null) throw new Exception (dgettext ("domframework", "DB for GroupMember is not connected"), 500); $groups = $this->groupRead ($module, $group); if (! isset ($groups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); return $this->dbGroupMember->insert (array ( "user"=>$user, "idgroup"=>$groups[0]["idgroup"], "comment"=>$comment)); } /** Remove an groupmember from database and all the rights using it */ public function groupmemberDel ($module, $group, $user) { if ($this->dbGroupMember == null) throw new Exception (dgettext ("domframework", "DB for GroupMember is not connected"), 500); $groups = $this->groupRead ($module, $group); if (! isset ($groups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); $groupsMembers = $this->dbGroupMember->read (array ( array ("user",$user), array ("idgroup",$groups[0]["idgroup"]))); if (! isset ($groupsMembers[0]["idgroupmember"])) throw new Exception (dgettext ("domframework", "Wanted GroupMember not found"), 404); return $this->dbGroupMember->delete ($groupsMembers[0]["idgroupmember"]); } /** Update an groupmember in the database */ public function groupmemberUpdate ($module, $group, $user, $comment="") { die ("This function is not available : contact us if you need it\n"); } /** Return an array with all the groups where the user is in and in the module */ public function groupmemberReadUser ($module, $user) { if ($this->dbGroupMember == null) throw new Exception (dgettext ("domframework", "DB for GroupMember is not connected"), 500); $idgrouptmps = $this->groupRead ($module); // Create an array with idgroup=>group $idgroups = array (); foreach ($idgrouptmps as $val) $idgroups[$val["idgroup"]] = $val["group"]; $select = array (); $select[] = array ("user", $user); $idgroupmembers = $this->dbGroupMember->read ($select); $res = array (); foreach ($idgroupmembers as $idmembers) { $res[$idmembers["idgroup"]] = $idgroups[$idmembers["idgroup"]]; } return $res; } /** Return an array with all the available users in the group and in the module */ public function groupmemberReadGroup ($module, $group) { if ($this->dbGroupMember == null) throw new Exception (dgettext ("domframework", "DB for GroupMember is not connected"), 500); $groups = $this->groupRead ($module, $group); if (! isset ($groups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); $select[] = array ("idgroup", $groups[0]["idgroup"]); return $this->dbGroupMember->read ($select, array ("user")); } //////////////// // RIGHTS // //////////////// /** Add a new right to right list Return the idright created */ public function rightAdd ($module, $group, $object, $right, $comment="") { if ($this->dbRight == null) throw new Exception (dgettext ("domframework", "DB for Right is not connected"), 500); switch ($right) { case "RW": $right=2;break; case "RO": $right=1;break; default: throw new Exception (dgettext ("domframework", "Unknown right provided (RO/RW only)"), 500); } $groups = $this->groupRead ($module, $group); if (! isset ($groups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); $objects = $this->objectRead ($module, $object); if (! isset ($objects[0]["idobject"])) throw new Exception (dgettext ("domframework", "Wanted object not found"), 404); return $this->dbRight->insert (array ("idgroup"=>$groups[0]["idgroup"], "idobject"=>$objects[0]["idobject"], "right"=>$right, "comment"=>$comment)); } /** Remove an right from database and all the rights using it */ public function rightDel ($module, $group, $object) { if ($this->dbRight == null) throw new Exception (dgettext ("domframework", "DB for Right is not connected"), 500); $idrights = $this->rightRead ($module, $group, $object); if (!isset ($idrights[0]["idright"])) throw new Exception (dgettext ("domframework", "Wanted right not found"), 404); return $this->dbRight->delete ($idrights[0]["idright"]); } /** Update an right in the database */ public function rightUpdate ($module, $group, $object, $newright, $newcomment="") { if ($this->dbRight == null) throw new Exception (dgettext ("domframework", "DB for Right is not connected"), 500); switch ($newright) { case "RW": $newright=2;break; case "RO": $newright=1;break; default: throw new Exception (dgettext ("domframework", "Unknown right provided (RO/RW only)"), 500); } $idrights = $this->rightRead ($module, $group, $object); if (!isset ($idrights[0]["idright"])) throw new Exception (dgettext ("domframework", "Wanted right not found"), 404); return $this->dbRight->update ($idrights[0]["idright"], array ("right"=>$newright, "comment"=>$newcomment)); } /** Return an array with all the available rights in the module, or the right if provided */ public function rightRead ($module, $group, $object) { if ($this->dbRight == null) throw new Exception (dgettext ("domframework", "DB for Right is not connected"), 500); $groups = $this->groupRead ($module, $group); if (! isset ($groups[0]["idgroup"])) throw new Exception (dgettext ("domframework", "Wanted group not found"), 404); $objects = $this->objectRead ($module, $object); if (! isset ($objects[0]["idobject"])) throw new Exception (dgettext ("domframework", "Wanted object not found"), 404); $select[] = array ("idgroup",$groups[0]["idgroup"]); $select[] = array ("idobject",$objects[0]["idobject"]); return $this->dbRight->read ($select); } }