function manager() { if (!$this->manager instanceof SharingTables) { $this->manager = SharingTables::instance(); } return $this->manager; }
function after_permission_changed($group = null, $permissions = null) { @set_time_limit(0); $die = false; if ($group == null || $permissions == null) { $die = true; if ($group == null) { $group = array_var($_REQUEST, 'group'); } if ($permissions == null) { $permissions = json_decode(array_var($_REQUEST, 'permissions')); } } // CHECK PARAMETERS if(!count($permissions)){ return false; } if (!is_numeric($group) || !$group) { throw new Error("Error filling sharing table. Invalid Paramenters for afterPermissionChanged method"); } // INIT LOCAL VARS $stManager = SharingTables::instance(); $affectedObjects = array(); $members = array(); $general_condition = ''; $read_condition = ''; $delete_condition = ''; $delete_conditions = array(); // BUILD OBJECT_IDs SUB-QUERIES $from = "FROM ".TABLE_PREFIX."object_members om INNER JOIN ".TABLE_PREFIX."objects o ON o.id = om.object_id"; foreach ($permissions as $permission) { $memberId = $permission->m; $objectTypeId = $permission->o; if (!$memberId || !$objectTypeId) continue; $delete_conditions[] = " ( object_type_id = '$objectTypeId' AND om.member_id = '$memberId' ) "; if ($permission->r) { $read_conditions[] = " ( object_type_id = '$objectTypeId' AND om.member_id = '$memberId' ) "; } } // DELETE THE AFFECTED OBJECTS FROM SHARING TABLE $stManager->delete("object_id IN (SELECT object_id $from WHERE ".implode(' OR ' , $delete_conditions ).") AND group_id = '$group'"); // 2. POPULATE THE SHARING TABLE AGAIN WITH THE READ-PERMISSIONS (If there are) if (isset($read_conditions) && count($read_conditions)) { $st_new_rows = " SELECT $group AS group_id, object_id $from WHERE om.is_optimization=0 AND (". implode(' OR ', $read_conditions) . ")"; $st_insert_sql = "INSERT INTO ".TABLE_PREFIX."sharing_table(group_id, object_id) $st_new_rows "; DB::execute($st_insert_sql); } if ($die) die(); }
function delete() { if (!can_manage_dimension_members(logged_user())) { flash_error(lang('no access permissions')); ajx_current("empty"); return; } $member = Members::findById(get_id()); try { DB::beginWork(); if (!$member->canBeDeleted($error_message)) { throw new Exception($error_message); } $dim_id = $member->getDimensionId(); // Remove from shring table SharingTables::instance()->delete(" \n\t\t\t\tobject_id IN (\n \t\t\t\t SELECT distinct(object_id) FROM " . TABLE_PREFIX . "object_members WHERE member_id = " . get_id() . " AND is_optimization = 0\n\t\t\t\t)\n\t\t\t"); $affectedObjectsRows = DB::executeAll("SELECT distinct(object_id) AS object_id FROM " . TABLE_PREFIX . "object_members where member_id = " . get_id() . " AND is_optimization = 0"); if (is_array($affectedObjectsRows) && count($affectedObjectsRows) > 0) { foreach ($affectedObjectsRows as $row) { $oid = $row['object_id']; $object = Objects::findObject($row['object_id']); // return an instance of Message, contact, etc. /* @var $object ContentDataObject */ if ($object) { if ($object instanceof ContentDataObject) { $object->addToSharingTable(); } } } } $args = $member; Hook::fire('delete_member', $args, $ret); // ApplicationLogs::createLog($member, ApplicationLogs::ACTION_DELETE, false, true); $ok = $member->delete(); if ($ok) { evt_add("reload dimension tree", $dim_id); } DB::commit(); flash_success(lang('success delete member', $member->getName())); if (get_id('start')) { ajx_current("start"); } else { if (get_id('dont_reload')) { ajx_current("empty"); } else { ajx_current("reload"); } } } catch (Exception $e) { DB::rollback(); flash_error($e->getMessage()); ajx_current("empty"); } }
static function addObjToSharingTable($oid, $tid, $obj_mem_ids) { $gids = array(); $table_prefix = defined('FORCED_TABLE_PREFIX') && FORCED_TABLE_PREFIX ? FORCED_TABLE_PREFIX : TABLE_PREFIX; //1. clear sharing table for this object SharingTables::delete("object_id={$oid}"); //2. get dimensions of this object's members that defines permissions $res = DB::execute("SELECT d.id as did FROM " . $table_prefix . "dimensions d INNER JOIN " . $table_prefix . "members m on m.dimension_id=d.id\r\n\t\t\t\tWHERE m.id IN ( SELECT member_id FROM " . $table_prefix . "object_members WHERE object_id = {$oid} AND is_optimization = 0 ) AND d.defines_permissions = 1"); $dids_tmp = array(); while ($row = $res->fetchRow()) { $dids_tmp[$row['did']] = $row['did']; } $res->free(); $dids = array_values($dids_tmp); $dids_tmp = null; $sql_from = "" . $table_prefix . "contact_member_permissions cmp\r\n\t\tLEFT JOIN " . $table_prefix . "members m ON m.id = cmp.member_id\r\n\t\tLEFT JOIN " . $table_prefix . "dimensions d ON d.id = m.dimension_id"; $member_where_conditions = ""; $dim_where_conditions = ""; // if users can add objects without classifying then check for permissions with member_id=0 if (config_option('let_users_create_objects_in_root')) { $member_where_conditions = "member_id=0 OR "; $dim_where_conditions = " OR d.id IS NULL"; } $sql_where = "({$member_where_conditions} member_id IN ( SELECT member_id FROM " . $table_prefix . "object_members WHERE object_id = {$oid} AND is_optimization = 0)) AND cmp.object_type_id = {$tid}"; //3. If there are dimensions that defines permissions containing any of the object members if (count($dids)) { // 3.1 get permission groups with permissions over the object. $sql_fields = "permission_group_id AS group_id"; $sql = "\r\n\t\t\t\tSELECT\r\n\t\t\t\t{$sql_fields}\r\n\t\t\t\tFROM\r\n\t\t\t\t{$sql_from}\r\n\t\t\t\tWHERE\r\n\t\t\t\t{$sql_where} AND (d.id IN (" . implode(',', $dids) . ") {$dim_where_conditions})\r\n\t\t\t"; $res = DB::execute($sql); $gids_tmp = array(); while ($row = $res->fetchRow()) { $gids_tmp[$row['group_id']] = $row['group_id']; } $res->free(); // allow all permission groups $allow_all_rows = DB::executeAll("SELECT DISTINCT permission_group_id FROM " . $table_prefix . "contact_dimension_permissions cdp\r\n\t\t\t\t\tINNER JOIN " . $table_prefix . "members m on m.dimension_id=cdp.dimension_id\r\n\t\t\t\t\tWHERE cdp.permission_type='allow all' AND cdp.dimension_id IN (" . implode(',', $dids) . ");"); if (is_array($allow_all_rows)) { foreach ($allow_all_rows as $row) { $gids_tmp[$row['permission_group_id']] = $row['permission_group_id']; } } $gids = array_values($gids_tmp); $gids_tmp = null; // check for mandatory dimensions $enabled_dimensions_sql = ""; $enabled_dimensions_ids = implode(',', config_option('enabled_dimensions')); if ($enabled_dimensions_ids != "") { $enabled_dimensions_sql = "AND id IN ({$enabled_dimensions_ids})"; } $mandatory_dim_ids = Dimensions::findAll(array('id' => true, 'conditions' => "`defines_permissions`=1 {$enabled_dimensions_sql} AND `permission_query_method`='" . DIMENSION_PERMISSION_QUERY_METHOD_MANDATORY . "'")); if (count($gids) > 0 && count($mandatory_dim_ids) > 0) { $sql = "SELECT om.member_id, m.dimension_id FROM " . $table_prefix . "object_members om\r\n\t\t\t\t\tINNER JOIN " . $table_prefix . "members m ON m.id=om.member_id INNER JOIN " . $table_prefix . "dimensions d ON d.id=m.dimension_id\r\n\t\t\t\t\tWHERE om.object_id = {$oid} AND om.is_optimization = 0 AND d.id IN (" . implode(",", $mandatory_dim_ids) . ")"; // Object members in mandatory dimensions $object_member_ids_res = DB::executeAll($sql); $mandatory_dim_members = array(); if (!is_null($object_member_ids_res)) { foreach ($object_member_ids_res as $row) { if (!isset($mandatory_dim_members[$row['dimension_id']])) { $mandatory_dim_members[$row['dimension_id']] = array(); } $mandatory_dim_members[$row['dimension_id']][] = $row['member_id']; } $mandatory_dim_allowed_pgs = array(); // Check foreach group that it has permissions over at least one member of each mandatory dimension foreach ($mandatory_dim_members as $mdim_id => $mmember_ids) { $sql = "SELECT pg.id FROM " . $table_prefix . "permission_groups pg\r\n\t\t\t\t\t\t\tINNER JOIN " . $table_prefix . "contact_dimension_permissions cdp ON cdp.permission_group_id=pg.id\r\n\t\t\t\t\t\t\tINNER JOIN " . $table_prefix . "contact_member_permissions cmp ON cmp.permission_group_id=pg.id\r\n\t\t\t\t\t\t\tWHERE cdp.dimension_id = '{$mdim_id}' AND (\r\n\t\t\t\t\t\t\tcdp.permission_type='allow all' OR cdp.permission_type='check' AND cmp.permission_group_id IN (" . implode(',', $gids) . ")\r\n\t\t\t\t\t\t\tAND cmp.member_id IN (" . implode(',', $mmember_ids) . ")\r\n\t\t\t\t\t\t)"; $permission_groups_res = DB::executeAll($sql); $mandatory_dim_allowed_pgs[$mdim_id] = array(); if (!is_null($permission_groups_res)) { foreach ($permission_groups_res as $row) { if (!in_array($row['id'], $mandatory_dim_allowed_pgs[$mdim_id])) { $mandatory_dim_allowed_pgs[$mdim_id][] = $row['id']; } } } } if (isset($mandatory_dim_allowed_pgs) && count($mandatory_dim_allowed_pgs) > 0) { $original_mandatory_dim_allowed_pgs = $mandatory_dim_allowed_pgs; $allowed_gids = array_pop($mandatory_dim_allowed_pgs); foreach ($mandatory_dim_allowed_pgs as $pg_array) { $allowed_gids = array_intersect($allowed_gids, $pg_array); } // If an user has permissions in one dim using a group and in other dim using his personal permissions then add to sharing table its personal permission group $pg_ids = array_unique(array_flat($original_mandatory_dim_allowed_pgs)); if (count($pg_ids) == 0) { $pg_ids[0] = 0; } $contact_pgs = array(); $contact_pg_rows = DB::executeAll("SELECT * FROM " . TABLE_PREFIX . "contact_permission_groups WHERE permission_group_id IN (" . implode(',', $pg_ids) . ") ORDER BY permission_group_id"); if (is_array($contact_pg_rows)) { foreach ($contact_pg_rows as $cpgr) { if (!isset($contact_pgs[$cpgr['contact_id']])) { $contact_pgs[$cpgr['contact_id']] = array(); } $contact_pgs[$cpgr['contact_id']][] = $cpgr['permission_group_id']; } } // each user must have at least one pg for every dimension foreach ($contact_pgs as $contact_id => $permission_groups) { $has_one = array_flip(array_keys($original_mandatory_dim_allowed_pgs)); foreach ($has_one as $k => &$v) { $v = false; } foreach ($permission_groups as $pg_id) { foreach ($original_mandatory_dim_allowed_pgs as $dim_id => $allowedpgs) { if (in_array($pg_id, $allowedpgs)) { $has_one[$dim_id] = true; break; } } } // all dims must be true in this array to allow permissions $has_permission = !in_array(false, $has_one); if ($has_permission) { $contact_row = DB::executeOne("SELECT permission_group_id FROM " . TABLE_PREFIX . "contacts where object_id = {$contact_id}"); if (is_array($contact_row) && $contact_row['permission_group_id'] > 0) { $allowed_gids[] = $contact_row['permission_group_id']; } } } $gids = array_unique($allowed_gids, SORT_NUMERIC); } else { $gids = array(); } } } } else { if ($obj_mem_ids) { // 3.2 No memeber dimensions defines permissions. // No esta en ninguna dimension que defina permisos, El objecto esta en algun lado // => En todas las dimensiones en la que está no definen permisos => Busco todos los grupos $gids = PermissionGroups::instance()->findAll(array('id' => true, 'conditions' => "type != 'roles'")); } else { // if this object is an email and it is unclassified => add to sharing table the permission groups of the users that have permissions in the email's account if (Plugins::instance()->isActivePlugin('mail')) { $mail_ot = ObjectTypes::instance()->findByName('mail'); if ($mail_ot instanceof ObjectType && $tid == $mail_ot->getId()) { $gids = array_flat(DB::executeAll("\r\n\t\t\t\t\t\t\tSELECT cpg.permission_group_id\r\n\t\t\t\t\t\t\tFROM " . TABLE_PREFIX . "contact_permission_groups cpg\r\n\t\t\t\t\t\t\tINNER JOIN " . TABLE_PREFIX . "contacts c ON c.permission_group_id=cpg.permission_group_id\r\n\t\t\t\t\t\t\tWHERE cpg.contact_id IN (\r\n\t\t\t\t\t\t\t SELECT mac.contact_id FROM " . TABLE_PREFIX . "mail_account_contacts mac WHERE mac.account_id = (SELECT mc.account_id FROM " . TABLE_PREFIX . "mail_contents mc WHERE mc.object_id={$oid})\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t")); } } } } if (count($gids)) { $stManager = SharingTables::instance(); $stManager->populateGroups($gids, $oid); $gids = null; } }
/** * This function will return paginated result. Result is an array where first element is * array of returned object and second populated pagination object that can be used for * obtaining and rendering pagination data using various helpers. * * Items and pagination array vars are indexed with 0 for items and 1 for pagination * because you can't use associative indexing with list() construct * * @access public * @param array $arguments Query argumens (@see find()) Limit and offset are ignored! * @param integer $items_per_page Number of items per page * @param integer $current_page Current page number * @return array */ function paginate($arguments = null, $items_per_page = 10, $current_page = 1) { if (isset($this) && instance_of($this, 'SharingTables')) { return parent::paginate($arguments, $items_per_page, $current_page); } else { return SharingTables::instance()->paginate($arguments, $items_per_page, $current_page); } // if }
function delete() { if(!can_manage_dimension_members(logged_user())) { flash_error(lang('no access permissions')); ajx_current("empty"); return; } $member = Members::findById(get_id()); try { DB::beginWork(); if (!$member->canBeDeleted($error_message)) { throw new Exception($error_message); } $dim_id = $member->getDimensionId(); // Remove from shring table SharingTables::instance()->delete(" object_id IN ( SELECT distinct(object_id) FROM ".TABLE_PREFIX."object_members WHERE member_id = ".$member->getId()." AND is_optimization = 0 ) "); $affectedObjectsRows = DB::executeAll("SELECT distinct(object_id) AS object_id FROM ".TABLE_PREFIX."object_members where member_id = ".$member->getId()." AND is_optimization = 0") ; if (is_array($affectedObjectsRows) && count($affectedObjectsRows) > 0) { foreach ( $affectedObjectsRows as $row ) { $oid = $row['object_id']; $object = Objects::findObject($row['object_id']); // return an instance of Message, contact, etc. /* @var $object ContentDataObject */ if ($object instanceof ContentDataObject) { $object->addToSharingTable(); } } } // remove member associations MemberPropertyMembers::delete('member_id = '.$member->getId().' OR property_member_id = '.$member->getId()); MemberRestrictions::delete('member_id = '.$member->getId().' OR restricted_member_id = '.$member->getId()); // remove from permissions tables ContactMemberPermissions::delete('member_id = '.$member->getId()); PermissionContexts::delete('member_id = '.$member->getId()); // remove associated content object if ($member->getObjectId() > 0) { $mobj = Objects::findObject($member->getObjectId()); if ($mobj instanceof ContentDataObject) $mobj->delete(); } // delete from object_members ObjectMembers::delete('member_id = '.$member->getId()); Hook::fire('delete_member', $member, $ret); // ApplicationLogs::createLog($member, ApplicationLogs::ACTION_DELETE, false, true); $ok = $member->delete(false); if ($ok) { evt_add("reload dimension tree", array('dim_id' => $dim_id, 'node' => null)); evt_add("select dimension member", array('dim_id' => $dim_id, 'node' => 'root')); } DB::commit(); flash_success(lang('success delete member', $member->getName())); if (get_id('start')) { ajx_current("start"); } else { if (get_id('dont_reload')) { ajx_current("empty"); } else { ajx_current("reload"); } } } catch (Exception $e) { DB::rollback(); flash_error($e->getMessage()); ajx_current("empty"); } }
/** * * @author Ignacio Vazquez - elpepe.uy@gmail.com */ function addToSharingTable() { $oid = $this->getId(); $tid = $this->getObjectTypeId(); $gids = array(); $table_prefix = defined('FORCED_TABLE_PREFIX') && FORCED_TABLE_PREFIX ? FORCED_TABLE_PREFIX : TABLE_PREFIX; //1 clear sharing table for this object SharingTables::delete("object_id={$oid}"); //2 get dimensions of this object's members that defines permissions $res = DB::execute("SELECT d.id as did FROM " . $table_prefix . "dimensions d INNER JOIN " . $table_prefix . "members m on m.dimension_id=d.id\n\t\t\tWHERE m.id IN ( SELECT member_id FROM " . $table_prefix . "object_members WHERE object_id = {$oid} AND is_optimization = 0 ) AND d.defines_permissions = 1"); $dids_tmp = array(); while ($row = $res->fetchRow()) { $dids_tmp[$row['did']] = $row['did']; } $res->free(); $dids = array_values($dids_tmp); $dids_tmp = null; $sql_from = "" . $table_prefix . "contact_member_permissions cmp\n\t\t\tINNER JOIN " . $table_prefix . "members m ON m.id = cmp.member_id\n\t\t\tINNER JOIN " . $table_prefix . "dimensions d ON d.id = m.dimension_id"; $sql_where = "member_id IN ( SELECT member_id FROM " . $table_prefix . "object_members WHERE object_id = {$oid} AND is_optimization = 0) AND cmp.object_type_id = {$tid}"; //3 If there are dimensions that defines permissions containing any of the object members if (count($dids)) { // 3.1 get permission groups with permissions over the object. $sql_fields = "permission_group_id AS group_id"; $sql = "\n\t\t\t\tSELECT \n\t\t\t\t {$sql_fields}\t\n\t\t\t\tFROM\n\t\t\t\t {$sql_from}\n\t\t\t\tWHERE\n\t\t\t\t {$sql_where} AND d.id IN (" . implode(',', $dids) . ")"; $res = DB::execute($sql); $gids_tmp = array(); while ($row = $res->fetchRow()) { $gids_tmp[$row['group_id']] = $row['group_id']; } $res->free(); // allow all permission groups $allow_all_rows = DB::executeAll("SELECT DISTINCT permission_group_id FROM " . $table_prefix . "contact_dimension_permissions cdp \n\t\t\t\tINNER JOIN " . $table_prefix . "members m on m.dimension_id=cdp.dimension_id\n\t\t\t\tWHERE cdp.permission_type='allow all' AND cdp.dimension_id IN (" . implode(',', $dids) . ");"); if (is_array($allow_all_rows)) { foreach ($allow_all_rows as $row) { $gids_tmp[$row['permission_group_id']] = $row['permission_group_id']; } } $gids = array_values($gids_tmp); $gids_tmp = null; } else { if (count($this->getMemberIds()) > 0) { // 3.2 No memeber dimensions defines permissions. // No esta en ninguna dimension que defina permisos, El objecto esta en algun lado // => En todas las dimensiones en la que está no definen permisos => Busco todos los grupos $gids = PermissionGroups::instance()->findAll(array('id' => true)); } } if (count($gids)) { $stManager = SharingTables::instance(); $stManager->populateGroups($gids, $oid); $gids = null; } }
/** * Return true is $user can read the $object. False otherwise. * Query executed in sharing table * * @param Contact $user * @param $object_id * @return boolean */ function can_read_sharing_table(Contact $user, $object_id) { $perm = SharingTables::instance()->findOne(array('conditions' => array("object_id=? AND group_id IN (SELECT permission_group_id FROM " . TABLE_PREFIX . "contact_permission_groups WHERE contact_id = '" . $user->getId() . "')", $object_id))); return !is_null($perm); }
function adjust_root_permissions($group, $root_perm_info = null) { // ROOT PERMISSIONS if (!is_null($root_perm_info)) { // user does not have permissions for object_type_ids $root_permissions_sharing_table_delete = array_var($root_perm_info, 'root_permissions_sharing_table_delete'); if (is_array($root_permissions_sharing_table_delete)) { foreach ($root_permissions_sharing_table_delete as $object_type_id) { $cond = "group_id={$group} AND object_id IN (SELECT o.id FROM " . TABLE_PREFIX . "objects o WHERE o.object_type_id = {$object_type_id} AND NOT EXISTS(\r\n\t\t\t\t\t\tSELECT om.object_id FROM " . TABLE_PREFIX . "object_members om WHERE om.object_id=o.id AND om.member_id IN (SELECT m.id FROM " . TABLE_PREFIX . "members m WHERE m.dimension_id IN (\r\n\t\t\t\t\t\t\tSELECT d.id FROM " . TABLE_PREFIX . "dimensions d WHERE d.is_manageable=1\r\n\t\t\t\t\t\t))\r\n\t\t\t\t\t))"; SharingTables::instance()->delete($cond); } } // user has permissions for object_type_ids $root_permissions_sharing_table_add = array_var($root_perm_info, 'root_permissions_sharing_table_add'); if (is_array($root_permissions_sharing_table_add)) { $file_ot = ObjectTypes::findByName('file'); foreach ($root_permissions_sharing_table_add as $object_type_id) { $additional_where = ""; $additional_join = ""; if ($file_ot->getId() == $object_type_id && Plugins::instance()->isActivePlugin('mail')) { $additional_join .= "INNER JOIN " . TABLE_PREFIX . "project_files e ON e.object_id=o.id"; $additional_where .= "AND IF(e.mail_id=0, true, EXISTS (SELECT mac.contact_id FROM " . TABLE_PREFIX . "mail_account_contacts mac \r\n\t\t\t\t\t\t\tWHERE mac.contact_id IN (SELECT cpg.contact_id FROM " . TABLE_PREFIX . "contact_permission_groups cpg WHERE permission_group_id={$group}) \r\n\t\t\t\t\t\t\t\tAND mac.account_id=(SELECT mc.account_id FROM " . TABLE_PREFIX . "mail_contents mc WHERE mc.object_id=e.mail_id)))"; } $sql = "SELECT o.id FROM " . TABLE_PREFIX . "objects o {$additional_join} WHERE o.object_type_id = {$object_type_id} AND NOT EXISTS(\r\n\t\t\t\t\t\tSELECT om.object_id FROM " . TABLE_PREFIX . "object_members om WHERE om.object_id=o.id AND om.member_id IN (SELECT m.id FROM " . TABLE_PREFIX . "members m WHERE m.dimension_id IN (\r\n\t\t\t\t\t\t\tSELECT d.id FROM " . TABLE_PREFIX . "dimensions d WHERE d.is_manageable=1\r\n\t\t\t\t\t\t))\r\n\t\t\t\t\t) {$additional_where}"; $rows = DB::executeAll($sql); $ids = array_flat($rows); $values = ""; foreach ($ids as $id) { $values .= ($values == "" ? "" : ",") . "('{$id}','{$group}')"; } DB::execute("INSERT INTO " . TABLE_PREFIX . "sharing_table (object_id, group_id) VALUES {$values} ON DUPLICATE KEY UPDATE group_id=group_id;"); } } } }
/** * Return true is $user can read the $object. False otherwise. * Query executed in sharing table * * @param Contact $user * @param $object_id * @return boolean */ function can_read_sharing_table(Contact $user, $object_id, $allow_super_admin = true) { if ($allow_super_admin && $user->isAdministrator()) { return true; } $perm = SharingTables::instance()->findOne(array('conditions' => array("object_id=? AND group_id IN (SELECT permission_group_id FROM " . TABLE_PREFIX . "contact_permission_groups WHERE contact_id = '" . $user->getId() . "')", $object_id))); return !is_null($perm); }
/** * * */ function addToSharingTable() { $oid = $this->getId(); $tid = $this->getObjectTypeId() ; $gids = array(); $table_prefix = defined('FORCED_TABLE_PREFIX') && FORCED_TABLE_PREFIX ? FORCED_TABLE_PREFIX : TABLE_PREFIX; //1. clear sharing table for this object SharingTables::delete("object_id=$oid"); //2. get dimensions of this object's members that defines permissions $res = DB::execute("SELECT d.id as did FROM ".$table_prefix."dimensions d INNER JOIN ".$table_prefix."members m on m.dimension_id=d.id WHERE m.id IN ( SELECT member_id FROM ".$table_prefix."object_members WHERE object_id = $oid AND is_optimization = 0 ) AND d.defines_permissions = 1"); $dids_tmp = array(); while ($row = $res->fetchRow() ) { $dids_tmp[$row['did']] = $row['did'] ; } $res->free(); $dids = array_values($dids_tmp); $dids_tmp = null; $sql_from = "".$table_prefix."contact_member_permissions cmp INNER JOIN ".$table_prefix."members m ON m.id = cmp.member_id INNER JOIN ".$table_prefix."dimensions d ON d.id = m.dimension_id"; $sql_where = "member_id IN ( SELECT member_id FROM ".$table_prefix."object_members WHERE object_id = $oid AND is_optimization = 0) AND cmp.object_type_id = $tid"; //3. If there are dimensions that defines permissions containing any of the object members if ( count($dids) ){ // 3.1 get permission groups with permissions over the object. $sql_fields = "permission_group_id AS group_id"; $sql = " SELECT $sql_fields FROM $sql_from WHERE $sql_where AND d.id IN (". implode(',',$dids).")"; $res = DB::execute($sql); $gids_tmp = array(); while ( $row = $res->fetchRow() ) { $gids_tmp[$row['group_id']] = $row['group_id']; } $res->free(); // allow all permission groups $allow_all_rows = DB::executeAll("SELECT DISTINCT permission_group_id FROM ".$table_prefix."contact_dimension_permissions cdp INNER JOIN ".$table_prefix."members m on m.dimension_id=cdp.dimension_id WHERE cdp.permission_type='allow all' AND cdp.dimension_id IN (". implode(',',$dids).");"); if (is_array($allow_all_rows)) { foreach ($allow_all_rows as $row) { $gids_tmp[$row['permission_group_id']] = $row['permission_group_id']; } } $gids = array_values($gids_tmp); $gids_tmp = null; // check for mandatory dimensions $mandatory_dim_ids = Dimensions::findAll(array('id' => true, 'conditions' => "`defines_permissions`=1 AND `permission_query_method`='".DIMENSION_PERMISSION_QUERY_METHOD_MANDATORY."'")); if (count($gids) > 0 && count($mandatory_dim_ids) > 0) { $sql = "SELECT om.member_id, m.dimension_id FROM ".$table_prefix."object_members om INNER JOIN ".$table_prefix."members m ON m.id=om.member_id INNER JOIN ".$table_prefix."dimensions d ON d.id=m.dimension_id WHERE om.object_id = $oid AND om.is_optimization = 0 AND d.id IN (".implode(",", $mandatory_dim_ids).")"; // Object members in mandatory dimensions $object_member_ids_res = DB::executeAll($sql); $mandatory_dim_members = array(); if (!is_null($object_member_ids_res)) { foreach ($object_member_ids_res as $row) { if (!isset($mandatory_dim_members[$row['dimension_id']])) $mandatory_dim_members[$row['dimension_id']] = array(); $mandatory_dim_members[$row['dimension_id']][] = $row['member_id']; } $mandatory_dim_allowed_pgs = array(); // Check foreach group that it has permissions over at least one member of each mandatory dimension foreach ($mandatory_dim_members as $mdim_id => $mmember_ids) { $sql = "SELECT pg.id FROM ".$table_prefix."permission_groups pg INNER JOIN ".$table_prefix."contact_dimension_permissions cdp ON cdp.permission_group_id=pg.id INNER JOIN ".$table_prefix."contact_member_permissions cmp ON cmp.permission_group_id=pg.id WHERE cdp.dimension_id = '$mdim_id' AND ( cdp.permission_type='allow all' OR cdp.permission_type='check' AND cmp.permission_group_id IN (".implode(',', $gids).") AND cmp.member_id IN (".implode(',', $mmember_ids).") )"; $permission_groups_res = DB::executeAll($sql); $mandatory_dim_allowed_pgs[$mdim_id] = array(); if (!is_null($permission_groups_res)) { foreach ($permission_groups_res as $row) { if (!in_array($row['id'], $mandatory_dim_allowed_pgs[$mdim_id])) $mandatory_dim_allowed_pgs[$mdim_id][] = $row['id']; } } } if (isset($mandatory_dim_allowed_pgs) && count($mandatory_dim_allowed_pgs) > 0) { $original_mandatory_dim_allowed_pgs = $mandatory_dim_allowed_pgs; $allowed_gids = array_pop($mandatory_dim_allowed_pgs); foreach ($mandatory_dim_allowed_pgs as $pg_array) { $allowed_gids = array_intersect($allowed_gids, $pg_array); } // If an user has permissions in one dim using a group and in other dim using his personal permissions then add to sharing table its personal permission group $pg_ids = array_unique(array_flat($original_mandatory_dim_allowed_pgs)); $pgs_data = DB::executeAll("SELECT * FROM ".TABLE_PREFIX."permission_groups WHERE id IN (".implode(',',$pg_ids).")"); $contact_pgs = array(); $contact_pg_rows = DB::executeAll("SELECT * FROM ".TABLE_PREFIX."contact_permission_groups WHERE permission_group_id IN (".implode(',',$pg_ids).") ORDER BY permission_group_id"); foreach ($contact_pg_rows as $cpgr) { if (!isset($contact_pgs[$cpgr['contact_id']])) $contact_pgs[$cpgr['contact_id']] = array(); $contact_pgs[$cpgr['contact_id']][] = $cpgr['permission_group_id']; } // each user must have at least one pg for every dimension foreach ($contact_pgs as $contact_id => $permission_groups) { $has_one = array_flip(array_keys($original_mandatory_dim_allowed_pgs)); foreach ($has_one as $k => &$v) $v = false; foreach ($permission_groups as $pg_id) { foreach ($original_mandatory_dim_allowed_pgs as $dim_id => $allowedpgs) { if (in_array($pg_id, $allowedpgs)) { $has_one[$dim_id] = true; break; } } } // all dims must be true in this array to allow permissions $has_permission = !in_array(false, $has_one); if ($has_permission) { $contact_row = DB::executeOne("SELECT permission_group_id FROM ".TABLE_PREFIX."contacts where object_id = $contact_id"); if (is_array($contact_row) && $contact_row['permission_group_id'] > 0) { $allowed_gids[] = $contact_row['permission_group_id']; } } } $gids = array_unique($allowed_gids, SORT_NUMERIC); } else { $gids = array(); } } } }else { if ( count($this->getMemberIds()) > 0 ) { // 3.2 No memeber dimensions defines permissions. // No esta en ninguna dimension que defina permisos, El objecto esta en algun lado // => En todas las dimensiones en la que está no definen permisos => Busco todos los grupos $gids = PermissionGroups::instance()->findAll(array('id' => true)); } } if(count($gids)) { $stManager = SharingTables::instance(); $stManager->populateGroups($gids, $oid); $gids = null; } }
function sharing_table_partial_rebuild() { $start_date = config_option('last_sharing_table_rebuild'); _log("Rebuilding sharing table since {$start_date} ..."); $obj_count = SharingTables::instance()->rebuild($start_date); _log("Finished rebuilding sharing table - {$obj_count} objects."); }