diff --git a/lib/permissions/permission.inc.php b/lib/permissions/permission.inc.php new file mode 100644 index 0000000..416432b --- /dev/null +++ b/lib/permissions/permission.inc.php @@ -0,0 +1,60 @@ + "id", + "sName" => "name", + "sHumanName" => "human_name", + "bBuiltIn" => "built_in", + ); + + var $_bUsePearError = true; + + function getID() { return $this->iId; } + function getName() { return $this->sName; } + function getHumanName() { return $this->sHumanName; } + function getBuiltIn() { return $this->bBuiltIn; } + function setID($iId) { $this->iId = $iId; } + function setName($sName) { $this->sName = $sName; } + function setHumanName($sHumanName) { $this->sHumanName = $sHumanName; } + function setBuiltIn($sBuiltIn) { $this->sBuiltIn = $sBuiltIn; } + + function _table () { + global $default; + return $default->permissions_table; + } + + // STATIC + function &get($iId) { + return KTEntityUtil::get('KTPermission', $iId); + } + + // STATIC + function &createFromArray($aOptions) { + return KTEntityUtil::createFromArray('KTPermission', $aOptions); + } + + // STATIC + function &getList($sWhereClause = null) { + global $default; + return KTEntityUtil::getList($default->permissions_table, 'KTPermission', $sWhereClause); + } + + // STATIC + function &getByName($sName) { + return KTEntityUtil::getBy('KTPermission', 'name', $sName); + } +} + +?> diff --git a/lib/permissions/permissionassignment.inc.php b/lib/permissions/permissionassignment.inc.php new file mode 100644 index 0000000..63749aa --- /dev/null +++ b/lib/permissions/permissionassignment.inc.php @@ -0,0 +1,66 @@ + "id", + "iPermissionID" => "permission_id", + "iPermissionObjectID" => "permission_object_id", + "iPermissionDescriptorID" => "permission_descriptor_id", + ); + + var $_bUsePearError = true; + + function getID() { return $this->iId; } + function setID($iId) { $this->iId = $iId; } + function getPermissionID() { return $this->iPermissionID; } + function setPermissionID($iPermissionID) { $this->iPermissionID = $iPermissionID; } + function getPermissionObjectID() { return $this->iPermissionObjectID; } + function setPermissionObjectID($iPermissionObjectID) { $this->iPermissionObjectID = $iPermissionObjectID; } + function getPermissionDescriptorID() { return $this->iPermissionDescriptorID; } + function setPermissionDescriptorID($iPermissionDescriptorID) { $this->iPermissionDescriptorID = $iPermissionDescriptorID; } + + function _table () { + global $default; + return $default->permission_assignments_table; + } + + // STATIC + function &get($iId) { + return KTEntityUtil::get('KTPermissionAssignment', $iId); + } + + // STATIC + function &createFromArray($aOptions) { + return KTEntityUtil::createFromArray('KTPermissionAssignment', $aOptions); + } + + // STATIC + function &getList($sWhereClause = null) { + global $default; + return KTEntityUtil::getList($default->permission_assignments_table, 'KTPermissionAssignment', $sWhereClause); + } + + function &getByPermissionAndObject($oPermission, $oObject) { + return KTEntityUtil::getByDict('KTPermissionAssignment', array( + 'permission_id' => $oPermission->getId(), + 'permission_object_id' => $oObject->getId(), + )); + } + + function &getByObjectMulti($oObject) { + return KTEntityUtil::getByDict('KTPermissionAssignment', array( + 'permission_object_id' => $oObject->getId(), + ), array('multi' => true)); + } +} + +?> diff --git a/lib/permissions/permissiondescriptor.inc.php b/lib/permissions/permissiondescriptor.inc.php new file mode 100644 index 0000000..d19d809 --- /dev/null +++ b/lib/permissions/permissiondescriptor.inc.php @@ -0,0 +1,149 @@ + "id", + "sDescriptor" => "descriptor", + "sDescriptorText" => "descriptor_text", + ); + + var $_bUsePearError = true; + + function getID() { return $this->iId; } + function setID($iId) { $this->iId = $iId; } + function getDescriptor() { return $this->sDescriptor; } + function setDescriptor($sDescriptor) { $this->sDescriptor = $sDescriptor; } + function getDescriptorText() { return $this->sDescriptorText; } + function setDescriptorText($sDescriptorText) { $this->sDescriptorText = $sDescriptorText; } + + function _table () { + global $default; + return $default->permission_descriptors_table; + } + + function create() { + if (empty($this->sDescriptor)) { + $this->sDescriptor = md5($this->sDescriptorText); + } + return parent::create(); + } + + function update() { + if (empty($this->sDescriptor)) { + $this->sDescriptor = md5($this->sDescriptorText); + } + return parent::update(); + } + + // STATIC + function &get($iId) { + return KTEntityUtil::get('KTPermissionDescriptor', $iId); + } + + // STATIC + function &createFromArray($aOptions) { + return KTEntityUtil::createFromArray('KTPermissionDescriptor', $aOptions); + } + + // STATIC + function &getList($sWhereClause = null) { + global $default; + return KTEntityUtil::getList($default->permission_objects_table, 'KTPermissionDescriptor', $sWhereClause); + } + + // STATIC + function &getByDescriptor($sDescriptor) { + return KTEntityUtil::getBy('KTPermissionDescriptor', 'descriptor', $sDescriptor); + } + + function saveAllowed($aAllowed) { + foreach ($aAllowed as $k => $aIDs) { + if ($k === "group") { + $this->_clearGroups(); + foreach ($aIDs as $iID) { + $this->_addGroup($iID); + } + } + } + } + + function _clearGroups() { + global $default; + $sQuery = "DELETE FROM $default->permission_descriptor_groups_table WHERE descriptor_id = ?"; + $aParams = array($this->getID()); + $res = DBUtil::runQuery(array($sQuery, $aParams)); + return $res; + } + + function _addGroup($iID) { + global $default; + $sQuery = "INSERT INTO $default->permission_descriptor_groups_table (descriptor_id, group_id) VALUES (?, ?)"; + $aParams = array($this->getID(), $iID); + $res = DBUtil::runQuery(array($sQuery, $aParams)); + return $res; + } + + function hasGroups($aGroups) { + global $default; + $aGroupIDs = array(); + foreach ($aGroups as $oGroup) { + $aGroupIDs[] = $oGroup->getID(); + } + $sGroupIDs = DBUtil::paramArray($aGroupIDs); + $sQuery = "SELECT COUNT(group_id) AS num FROM $default->permission_descriptor_groups_table + WHERE descriptor_id = ? AND group_id IN ($sGroupIDs)"; + $aParams = array($this->getID()); + $aParams = array_merge($aParams, $aGroupIDs); + $res = DBUtil::getOneResultKey(array($sQuery, $aParams), 'num'); + if (PEAR::isError($res)) { + return $res; + } + if ((int)$res === 0) { + return false; + } + return true; + } + + function getGroups() { + global $default; + $sQuery = "SELECT group_id FROM $default->permission_descriptor_groups_table WHERE descriptor_id = ?"; + $aParams = array($this->getID()); + return DBUtil::getResultArrayKey(array($sQuery, $aParams), 'group_id'); + } + + function &getByGroup($oGroup) { + global $default; + $sQuery = "SELECT descriptor_id FROM $default->permission_descriptor_groups_table WHERE group_id = ?"; + $aParams = array($oGroup->getID()); + $aIDs = DBUtil::getResultArrayKey(array($sQuery, $aParams), 'descriptor_id'); + $aRet = array(); + foreach ($aIDs as $iID) { + $aRet[] =& KTPermissionDescriptor::get($iID); + } + return $aRet; + } + + function &getByGroups($aGroups) { + global $default; + $aGroupIDs = array(); + foreach ($aGroups as $oGroup) { + $aGroupIDs[] = $oGroup->getID(); + } + $sGroupIDs = DBUtil::paramArray($aGroupIDs); + $sQuery = "SELECT DISTINCT descriptor_id FROM $default->permission_descriptor_groups_table WHERE group_id IN ( $sGroupIDs )"; + $aParams = $aGroupIDs; + $aIDs = DBUtil::getResultArrayKey(array($sQuery, $aParams), 'descriptor_id'); + $aRet = array(); + foreach ($aIDs as $iID) { + $aRet[] =& KTPermissionDescriptor::get($iID); + } + return $aRet; + } +} + +?> diff --git a/lib/permissions/permissionlookup.inc.php b/lib/permissions/permissionlookup.inc.php new file mode 100644 index 0000000..91f697a --- /dev/null +++ b/lib/permissions/permissionlookup.inc.php @@ -0,0 +1,40 @@ + "id", + ); + + var $_bUsePearError = true; + + function getID() { return $this->iId; } + function setID($iId) { $this->iId = $iId; } + + function _table () { + global $default; + return $default->permission_lookups_table; + } + + // STATIC + function &get($iId) { + return KTEntityUtil::get('KTPermissionLookup', $iId); + } + + // STATIC + function &createFromArray($aOptions) { + return KTEntityUtil::createFromArray('KTPermissionLookup', $aOptions); + } + + // STATIC + function &getList($sWhereClause = null) { + global $default; + return KTEntityUtil::getList($default->permission_lookups_table, 'KTPermissionLookup', $sWhereClause); + } +} + +?> diff --git a/lib/permissions/permissionlookupassignment.inc.php b/lib/permissions/permissionlookupassignment.inc.php new file mode 100644 index 0000000..92ed54b --- /dev/null +++ b/lib/permissions/permissionlookupassignment.inc.php @@ -0,0 +1,103 @@ + "id", + "iPermissionID" => "permission_id", + "iPermissionLookupID" => "permission_lookup_id", + "iPermissionDescriptorID" => "permission_descriptor_id", + ); + + var $_bUsePearError = true; + + function getID() { return $this->iId; } + function setID($iId) { $this->iId = $iId; } + function getPermissionID() { return $this->iPermissionID; } + function setPermissionID($iPermissionID) { $this->iPermissionID = $iPermissionID; } + function getPermissionLookupID() { return $this->iPermissionLookupID; } + function setPermissionLookupID($iPermissionLookupID) { $this->iPermissionLookupID = $iPermissionLookupID; } + function getPermissionDescriptorID() { return $this->iPermissionDescriptorID; } + function setPermissionDescriptorID($iPermissionDescriptorID) { $this->iPermissionDescriptorID = $iPermissionDescriptorID; } + + function _table () { + global $default; + return $default->permission_lookup_assignments_table; + } + + // STATIC + function &get($iId) { + return KTEntityUtil::get('KTPermissionLookupAssignment', $iId); + } + + // STATIC + function &createFromArray($aOptions) { + return KTEntityUtil::createFromArray('KTPermissionLookupAssignment', $aOptions); + } + + // STATIC + function &getList($sWhereClause = null) { + global $default; + return KTEntityUtil::getList2('KTPermissionLookupAssignment', $sWhereClause); + } + + function &getByPermissionAndDescriptor($oPermission, $oDescriptor) { + return KTEntityUtil::getByDict('KTPermissionLookupAssignment', array( + 'permission_id' => $oPermission->getId(), + 'permission_descriptor_id' => $oDescriptor->getId(), + ), array('multi' => true)); + } + + function &getByPermissionAndLookup($oPermission, $oLookup) { + return KTEntityUtil::getByDict('KTPermissionLookupAssignment', array( + 'permission_id' => $oPermission->getId(), + 'permission_lookup_id' => $oLookup->getId(), + )); + } + + function &_getLookupIDsByPermissionIDAndDescriptorID($iPermissionID, $iDescriptorID) { + return KTEntityUtil::getByDict('KTPermissionLookupAssignment', array( + 'permission_id' => $iPermissionID, + 'permission_descriptor_id' => $iDescriptorID, + ), array('multi' => true, 'ids' => true, 'idfield' => 'permission_lookup_id')); + } + + function &findOrCreateLookupByPermissionDescriptorMap($aMapPermDesc) { + $aOptions = array(); + foreach ($aMapPermDesc as $iPermissionID => $iDescriptorID) { + $aThisOptions = array(); + foreach (KTPermissionLookupAssignment::_getLookupIDsByPermissionIDAndDescriptorID($iPermissionID, $iDescriptorID) as $iPLID) { + $aThisOptions[] = $iPLID; + } + $aOptions[] = $aThisOptions; + } + $aPLIDs = call_user_func_array('array_intersect', $aOptions); + if (empty($aPLIDs)) { + $oPL = KTPermissionLookup::createFromArray(array()); + $iPLID = $oPL->getID(); + foreach ($aMapPermDesc as $iPermissionID => $iDescriptorID) { + $res = KTPermissionLookupAssignment::createFromArray(array( + 'permissionlookupid' => $iPLID, + 'permissionid' => $iPermissionID, + 'permissiondescriptorid' => $iDescriptorID, + )); + } + return $oPL; + } + sort($aPLIDs); + $res = KTPermissionLookup::get($aPLIDs[0]); + return $res; + } + + +} + +?> diff --git a/lib/permissions/permissionobject.inc.php b/lib/permissions/permissionobject.inc.php new file mode 100644 index 0000000..955a713 --- /dev/null +++ b/lib/permissions/permissionobject.inc.php @@ -0,0 +1,40 @@ + "id", + ); + + var $_bUsePearError = true; + + function getID() { return $this->iId; } + function setID($iId) { $this->iId = $iId; } + + function _table () { + global $default; + return $default->permission_objects_table; + } + + // STATIC + function &get($iId) { + return KTEntityUtil::get('KTPermissionObject', $iId); + } + + // STATIC + function &createFromArray($aOptions) { + return KTEntityUtil::createFromArray('KTPermissionObject', $aOptions); + } + + // STATIC + function &getList($sWhereClause = null) { + global $default; + return KTEntityUtil::getList($default->permission_objects_table, 'KTPermissionObject', $sWhereClause); + } +} + +?> diff --git a/lib/permissions/permissionutil.inc.php b/lib/permissions/permissionutil.inc.php new file mode 100644 index 0000000..c606cc5 --- /dev/null +++ b/lib/permissions/permissionutil.inc.php @@ -0,0 +1,302 @@ + $v) { + if (empty($v)) { + continue; + } + $v = array_unique($v); + $sOutput .= "$k("; + sort($v); + $sOutput .= join(",", $v); + $sOutput .= ")"; + } + + return $sOutput; + } + + function getOrCreateDescriptor ($aAllowed) { + $sDescriptor = KTPermissionUtil::generateDescriptor($aAllowed); + $oDescriptor =& KTPermissionDescriptor::getByDescriptor(md5($sDescriptor)); + if (PEAR::isError($oDescriptor)) { + $oDescriptor =& KTPermissionDescriptor::createFromArray(array( + "descriptortext" => $sDescriptor, + )); + $oDescriptor->saveAllowed($aAllowed); + } + return $oDescriptor; + } + + function getOrCreateAssignment ($sPermission, $iObjectID) { + if (is_string($sPermission)) { + $oPermission =& KTPermission::getByName($sPermission); + } else { + $oPermission =& $sPermission; + } + if (is_numeric($iObjectID)) { + $oObject =& KTPermissionObject::get($iObjectID); + } else { + $oObject =& $iObjectID; + } + $oPA = KTPermissionAssignment::getByPermissionAndObject($oPermission, $oObject); + if (PEAR::isError($oPA)) { + $oPA = KTPermissionAssignment::createFromArray(array( + 'permissionid' => $oPermission->getID(), + 'permissionobjectid' => $oObject->getID(), + )); + } + return $oPA; + } + + function setPermissionForID($sPermission, $iObjectID, $aAllowed) { + $oPermissionAssignment = KTPermissionUtil::getOrCreateAssignment($sPermission, $iObjectID); + $oDescriptor = KTPermissionUtil::getOrCreateDescriptor($aAllowed); + $oPermissionAssignment->setPermissionDescriptorID($oDescriptor->getID()); + $oPermissionAssignment->update(); + } + + // {{{ updatePermissionLookupForPO + /** + * Updates permission lookups for all objects of a certain + * permission object. + * + * It may be that you don't have or want to have the root item for a + * permission object that you do have and have updates - then use + * this. + */ + function updatePermissionLookupForPO($oPO) { + $sWhere = 'permission_object_id = ?'; + $aParams = array($oPO->getID()); + $aFolders =& Folder::getList(array($sWhere, $aParams)); + foreach ($aFolders as $oFolder) { + KTPermissionUtil::updatePermissionLookup($oFolder); + } + $aDocuments =& Document::getList(array($sWhere, $aParams)); + foreach ($aDocuments as $oDocument) { + KTPermissionUtil::updatePermissionLookup($oDocument); + } + } + // }}} + + + // {{{ updatePermissionLookupRecursive + /** + * Updates permission lookups for this folder and any ancestors, but + * only if they use the same permission object. + * + * To be used any time a folder permission object is changed. + */ + function updatePermissionLookupRecursive($oDocumentOrFolder) { + if (is_a($oDocumentOrFolder, 'Document')) { + // XXX: metadata versions may need attention here + KTPermissionUtil::updatePermissionLookup($oDocumentOrFolder); + return; + } + + $iFolderID = $oDocumentOrFolder->getID(); + $sFolderIDs = Folder::generateFolderIDs($iFolderID); + $sFolderIDs .= '%'; + + $sWhere = 'permission_object_id = ? AND parent_folder_ids LIKE ?'; + $aParams = array($oDocumentOrFolder->getPermissionObjectID(), $sFolderIDs); + + $aFolders =& Folder::getList(array($sWhere, $aParams)); + foreach ($aFolders as $oFolder) { + KTPermissionUtil::updatePermissionLookup($oFolder); + } + + $aDocuments =& Document::getList(array($sWhere, $aParams)); + foreach ($aDocuments as $oDocument) { + KTPermissionUtil::updatePermissionLookup($oDocument); + } + } + // }}} + + // {{{ updatePermissionLookup + /** + * Update's the permission lookup on one folder or document, + * non-recursively. + */ + function updatePermissionLookup($oFolderOrDocument) { + $oPO = KTPermissionObject::get($oFolderOrDocument->getPermissionObjectID()); + $aPAs = KTPermissionAssignment::getByObjectMulti($oPO); + $aMapPermDesc = array(); + foreach ($aPAs as $oPA) { + $oPD = KTPermissionDescriptor::get($oPA->getPermissionDescriptorID()); + $aGroupIDs = $oPD->getGroups(); + $aUserIDs = array(); + $aAllowed = array( + "group" => $aGroupIDs, + "user" => $aUserIDs, + ); + $oLookupPD = KTPermissionUtil::getOrCreateDescriptor($aAllowed); + $aMapPermDesc[$oPA->getPermissionID()] = $oLookupPD->getID(); + } + + $oPL = KTPermissionLookupAssignment::findOrCreateLookupByPermissionDescriptorMap($aMapPermDesc); + $oFolderOrDocument->setPermissionLookupID($oPL->getID()); + $oFolderOrDocument->update(); + } + // }}} + + function userHasPermissionOnItem($oUser, $oPermission, $oFolderOrDocument) { + $oPL = KTPermissionLookup::get($oFolderOrDocument->getPermissionLookupID()); + $oPLA = KTPermissionLookupAssignment::getByPermissionAndLookup($oPermission, $oPL); + if (PEAR::isError($oPLA)) { + print $oPL->getID(); + return false; + } + $oPD = KTPermissionDescriptor::get($oPLA->getPermissionDescriptorID()); + $aGroups = GroupUtil::listGroupsForUser($oUser); + return $oPD->hasGroups($aGroups); + } + + function findRootObjectForPermissionObject($oPO) { + global $default; + /* + * If there are any folders with the permission object, then it + * is set by _a_ folder. All folders found will have a common + * ancestor folder, which will be the one with: + * + * Potential hack: The shortest parent_folder_ids + * + * Potential non-hack: Choose random folder, check parent for + * permission object recurringly until it changes. Last success + * is the ancestor parent... + */ + $sQuery = "SELECT id FROM $default->folders_table WHERE permission_object_id = ? ORDER BY LENGTH(parent_folder_ids) LIMIT 1"; + $aParams = array($oPO->getID()); + $res = DBUtil::getResultArrayKey(array($sQuery, $aParams), 'id'); + if (is_array($res)) { + return Folder::get($res[0]); + } + return false; + } + + function copyPermissionObject(&$oDocumentOrFolder) { + global $default; + $oOrigPO = KTPermissionObject::get($oDocumentOrFolder->getPermissionObjectID()); + $aOrigPAs =& KTPermissionAssignment::getByObjectMulti($oOrigPO); + $oNewPO = KTPermissionObject::createFromArray(array()); + foreach ($aOrigPAs as $oOrigPA) { + $oNewPA = KTPermissionAssignment::createFromArray(array( + 'permissionid' => $oOrigPA->getPermissionID(), + 'permissionobjectid' => $oNewPO->getID(), + 'permissiondescriptorid' => $oOrigPA->getPermissionDescriptorID(), + )); + } + $oDocumentOrFolder->setPermissionObjectID($oNewPO->getID()); + $oDocumentOrFolder->update(); + + if (!is_a($oDocumentOrFolder, 'Folder')) { + KTPermissionUtil::updatePermissionLookup($oDocumentOrFolder); + return; + } + + // For a folder - update permission object for all folders and + // documents under this current folder if they're using the old + // permission object id. If they are, then they're getting the + // permission object via this folder. If they are not, then + // they have their own permission object management, and thus + // this folder has no effect on their permissions. + + $iFolderID = $oDocumentOrFolder->getID(); + $sFolderIDs = Folder::generateFolderIDs($iFolderID); + $sFolderIDs .= '%'; + $sQuery = "UPDATE $default->folders_table SET + permission_object_id = ? WHERE permission_object_id = ? AND + parent_folder_ids LIKE ?"; + $aParams = array($oNewPO->getID(), $oOrigPO->getID(), $sFolderIDs); + DBUtil::runQuery(array($sQuery, $aParams)); + + $sQuery = "UPDATE $default->documents_table SET + permission_object_id = ? WHERE permission_object_id = ? AND + parent_folder_ids LIKE ?"; + DBUtil::runQuery(array($sQuery, $aParams)); + + // All objects using this PO must be new and must need their + // lookups updated... + KTPermissionUtil::updatePermissionLookupForPO($oNewPO); + } + + function isPermissionOwner(&$oDocumentOrFolder) { + $oPermissionObject = KTPermissionObject::get($oDocumentOrFolder->getPermissionObjectID()); + $oParentObject = KTPermissionUtil::findRootObjectForPermissionObject($oPermissionObject); + + // Documents might be permission owner, but then they'd be the + // only users of that permission object. + if (is_a($oParentObject, 'Document')) { + return true; + } + + // If you're a document and your permission owner isn't a + // document, that means it's some ancestor, and thus not you. + if (is_a($oDocumentOrFolder, 'Document')) { + return false; + } + + // We're dealing with folders, so just compare IDs... + if ($oDocumentOrFolder->getID() == $oParentObject->getID()) { + return true; + } + return false; + } + + function inheritPermissionObject(&$oDocumentOrFolder) { + global $default; + if (!KTPermissionUtil::isPermissionOwner($oDocumentOrFolder)) { + return PEAR::raiseError("Document or Folder doesn't own its permission object"); + } + $oOrigPO =& KTPermissionObject::get($oDocumentOrFolder->getPermissionObjectID()); + $oFolder =& Folder::get($oDocumentOrFolder->getParentID()); + $iNewPOID = $oFolder->getPermissionObjectID(); + $oNewPO =& KTPermissionObject::get($iNewPOID); + + + $oDocumentOrFolder->setPermissionObjectID($iNewPOID); + $oDocumentOrFolder->update(); + + if (is_a($oDocumentOrFolder, 'Document')) { + // If we're a document, no niggly children to worry about. + // + // Well, except for document versions, which we don't know + // how to deal with yet, really. + KTPermissionUtil::updatePermissionLookup($oDocumentOrFolder); + return; + } + + $iFolderID = $oDocumentOrFolder->getID(); + $sFolderIDs = Folder::generateFolderIDs($iFolderID); + $sFolderIDs .= '%'; + $sQuery = "UPDATE $default->folders_table SET + permission_object_id = ? WHERE permission_object_id = ? AND + parent_folder_ids LIKE ?"; + $aParams = array($oNewPO->getID(), $oOrigPO->getID(), $sFolderIDs); + DBUtil::runQuery(array($sQuery, $aParams)); + + $sQuery = "UPDATE $default->documents_table SET + permission_object_id = ? WHERE permission_object_id = ? AND + parent_folder_ids LIKE ?"; + DBUtil::runQuery(array($sQuery, $aParams)); + + KTPermissionUtil::updatePermissionLookupForPO($oNewPO); + } +} + +?>