Пример #1
0
 /**
  * Construct a WHERE clause to handle permissions to $object_*
  *
  * @param array ref $tables -   Any tables that may be needed in the FROM
  * @param string $operation -   The operation being attempted
  * @param string $object_table -    The table of the object in question
  * @param int $object_id    -   The ID of the object in question
  * @param int $acl_id   -       If it's a grant/revoke operation, the ACL ID
  * @param boolean $acl_role -  For grant operations, this flag determines if we're granting a single acl (false) or an entire group.
  *
  * @return string           -   The WHERE clause, or 0 on failure
  * @access public
  * @static
  */
 public static function permissionClause(&$tables, $operation, $object_table = NULL, $object_id = NULL, $acl_id = NULL, $acl_role = FALSE)
 {
     $dao = new CRM_ACL_DAO_ACL();
     $t = array('ACL' => self::getTableName(), 'ACLRole' => 'civicrm_acl_role', 'ACLEntityRole' => CRM_ACL_DAO_EntityRole::getTableName(), 'Contact' => CRM_Contact_DAO_Contact::getTableName(), 'Group' => CRM_Contact_DAO_Group::getTableName(), 'GroupContact' => CRM_Contact_DAO_GroupContact::getTableName());
     $session = CRM_Core_Session::singleton();
     $contact_id = $session->get('userID');
     $where = " {$t['ACL']}.operation = '" . CRM_Utils_Type::escape($operation, 'String') . "'";
     /* Include clause if we're looking for a specific table/id permission */
     if (!empty($object_table)) {
         $where .= " AND ( {$t['ACL']}.object_table IS null\n                         OR ({$t['ACL']}.object_table   = '" . CRM_Utils_Type::escape($object_table, 'String') . "'";
         if (!empty($object_id)) {
             $where .= " AND ({$t['ACL']}.object_id IS null\n                            OR {$t['ACL']}.object_id = " . CRM_Utils_Type::escape($object_id, 'Integer') . ')';
         }
         $where .= '))';
     }
     /* Include clause if we're granting an ACL or ACL Role */
     if (!empty($acl_id)) {
         $where .= " AND ({$t['ACL']}.acl_id IS null\n                        OR {$t['ACL']}.acl_id   = " . CRM_Utils_Type::escape($acl_id, 'Integer') . ')';
         if ($acl_role) {
             $where .= " AND {$t['ACL']}.acl_table = '{$t['ACLRole']}'";
         } else {
             $where .= " AND {$t['ACL']}.acl_table = '{$t['ACL']}'";
         }
     }
     $query = array();
     /* Query for permissions granted to all contacts in the domain */
     $query[] = "SELECT      {$t['ACL']}.*, 0 as override\n                    FROM        {$t['ACL']}\n\n                    WHERE       {$t['ACL']}.entity_table    = '{$t['Domain']}'\n                            AND ({$where})";
     /* Query for permissions granted to all contacts through an ACL group */
     $query[] = "SELECT      {$t['ACL']}.*, 0 as override\n                    FROM        {$t['ACL']}\n\n                    INNER JOIN  {$t['ACLEntityRole']}\n                            ON  ({$t['ACL']}.entity_table = '{$t['ACLRole']}'\n                            AND     {$t['ACL']}.entity_id =\n                                    {$t['ACLEntityRole']}.acl_role_id)\n\n                    INNER JOIN  {$t['ACLRole']}\n                            ON      {$t['ACL']}.entity_id =\n                                    {$t['ACLRole']}.id\n\n                    WHERE       {$t['ACLEntityRole']}.entity_table =\n                                    '{$t['Domain']}'\n                            AND {$t['ACLRole']}.is_active      = 1\n                            AND ({$where})";
     /* Query for permissions granted directly to the contact */
     $query[] = "SELECT      {$t['ACL']}.*, 1 as override\n                    FROM        {$t['ACL']}\n\n                    INNER JOIN  {$t['Contact']}\n                            ON  ({$t['ACL']}.entity_table = '{$t['Contact']}'\n                            AND     {$t['ACL']}.entity_id = {$t['Contact']}.id)\n\n                    WHERE       {$t['Contact']}.id          = {$contact_id}\n                            AND ({$where})";
     /* Query for permissions granted to the contact through an ACL group */
     $query[] = "SELECT      {$t['ACL']}.*, 1 as override\n                    FROM        {$t['ACL']}\n\n                    INNER JOIN  {$t['ACLEntityRole']}\n                            ON  ({$t['ACL']}.entity_table = '{$t['ACLRole']}'\n                            AND     {$t['ACL']}.entity_id =\n                                    {$t['ACLEntityRole']}.acl_role_id)\n\n                    INNER JOIN  {$t['ACLRole']}\n                            ON  {$t['ACL']}.entity_id = {$t['ACLRole']}.id\n\n                    WHERE       {$t['ACLEntityRole']}.entity_table =\n                                    '{$t['Contact']}'\n                        AND     {$t['ACLRole']}.is_active      = 1\n                        AND     {$t['ACLEntityRole']}.entity_id  = {$contact_id}\n                        AND     ({$where})";
     /* Query for permissions granted to the contact through a group */
     $query[] = "SELECT      {$t['ACL']}.*, 0 as override\n                    FROM        {$t['ACL']}\n\n                    INNER JOIN  {$t['GroupContact']}\n                            ON  ({$t['ACL']}.entity_table = '{$t['Group']}'\n                            AND     {$t['ACL']}.entity_id =\n                                    {$t['GroupContact']}.group_id)\n\n                    WHERE       ({$where})\n                        AND     {$t['GroupContact']}.contact_id = {$contact_id}\n                        AND     {$t['GroupContact']}.status     = 'Added')";
     /* Query for permissions granted through an ACL group to a Contact
      * group */
     $query[] = "SELECT      {$t['ACL']}.*, 0 as override\n                    FROM        {$t['ACL']}\n\n                    INNER JOIN  {$t['ACLEntityRole']}\n                            ON  ({$t['ACL']}.entity_table = '{$t['ACLRole']}'\n                            AND     {$t['ACL']}.entity_id =\n                                    {$t['ACLEntityRole']}.acl_role_id)\n\n                    INNER JOIN  {$t['ACLRole']}\n                            ON  {$t['ACL']}.entity_id = {$t['ACLRole']}.id\n\n                    INNER JOIN  {$t['GroupContact']}\n                            ON  ({$t['ACLEntityRole']}.entity_table =\n                                    '{$t['Group']}'\n                            AND     {$t['ACLEntityRole']}.entity_id =\n                                    {$t['GroupContact']}.group_id)\n\n                    WHERE       ({$where})\n                        AND     {$t['ACLRole']}.is_active      = 1\n                        AND     {$t['GroupContact']}.contact_id = {$contact_id}\n                        AND     {$t['GroupContact']}.status     = 'Added'";
     $union = '(' . implode(') UNION DISTINCT (', $query) . ')';
     $dao->query($union);
     $allow = array(0);
     $deny = array(0);
     $override = array();
     while ($dao->fetch()) {
         /* Instant bypass for the following cases:
          * 1) the rule governs all tables
          * 2) the rule governs all objects in the table in question
          * 3) the rule governs the specific object we want
          */
         if (empty($dao->object_table) || $dao->object_table == $object_table && (empty($dao->object_id) || $dao->object_id == $object_id)) {
             $clause = 1;
         } else {
             /* Otherwise try to generate a clause for this rule */
             $clause = self::getClause($dao->object_table, $dao->object_id, $tables);
             /* If the clause returned is null, then the rule is a blanket
              * (id is null) on a table other than the one we're interested
              * in.  So skip it. */
             if (empty($clause)) {
                 continue;
             }
         }
         /* Now we figure out if this is an allow or deny rule, and possibly
          * a contact-level override */
         if ($dao->deny) {
             $deny[] = $clause;
         } else {
             $allow[] = $clause;
             if ($dao->override) {
                 $override[] = $clause;
             }
         }
     }
     $allows = '(' . implode(' OR ', $allow) . ')';
     $denies = '(' . implode(' OR ', $deny) . ')';
     if (!empty($override)) {
         $denies = '(NOT (' . implode(' OR ', $override) . ") AND {$denies})";
     }
     return "({$allows} AND NOT {$denies})";
 }