<commit_before><?php

/*
 * This file is part of the Access to Memory (AtoM) software.
 *
 * Access to Memory (AtoM) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Access to Memory (AtoM) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Access to Memory (AtoM).  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Access Control List (ACL) functionality
 *
 * @package    AccesstoMemory
 * @subpackage qbAclPlugin
 * @author     <NAME> <<EMAIL>>
 */
class QubitAcl
{
  const GRANT = 2;
  const INHERIT = 1;
  const DENY  = 0;

  public static $ACTIONS = array(
    'read' => 'Read',
    'create' => 'Create',
    'update' => 'Update',
    'delete' => 'Delete',
    'translate' => 'Translate'
  );

  protected static $_instance;

  protected
    $_roles = array(),
    $_resources = array(),
    $_user;

  public
    $acl;

  public function __construct($user = null)
  {
    if (null === $user)
    {
      $this->_user = sfContext::getInstance()->user;
    }
    else
    {
      $this->_user = $user;
    }

    $this->acl = new Zend_Acl;
    $this->buildUserRoleList($this->_user);
  }

  public static function getInstance()
  {
    if (null === self::$_instance)
    {
      self::$_instance = new self();
    }

    return self::$_instance;
  }

  /**
   * Each request is completely unique in PHP however our workers run in a loop
   * where state is held across jobs. This class was built as a singleton so we
   * need this extra method to void the instance when needed when running ACL
   * checks from a worker process.
   *
   */
  public static function destruct()
  {
    self::$_instance = null;
  }

  /**
   * Test user access to the given resource
   *
   * Note: Current sf_user is assumed, but can be overridden with
   * $options['userId'].
   *
   * @param mixed   $resource object to which user is requesting access
   * @param integer $actions requested action key
   * @param array   $options optional parameters
   */
  public static function check($resource, $actions, $options = array())
  {
    if ($resource instanceof sfOutputEscaper)
    {
      $resource = sfOutputEscaper::unescape($resource);
    }

    $hasAccess = false;

    // Skip ACL checks for command-line tasks
    if ('cli' == sfContext::getInstance()->getConfiguration()->getEnvironment())
    {
      return true;
    }

    if (!is_array($actions))
    {
      $actions = array($actions);
    }

    $user = sfContext::getInstance()->user;
    if (isset($options['user']))
    {
      $user = $options['user'];
    }

    // Loop through actions and return on first "true" result (OR condition)
    while ($action = array_shift($actions))
    {
      // Short-circuit decision tree for 'translate', because we want
      // translate permissions to apply system-wide
      //
      // TODO: Get rid of this when we are using ACL system-wide
      //
      if ('translate' == $action)
      {
        if (self::isAllowed($user, $resource, 'translate', $options))
        {
          return true;
        }
        else
        {
          continue;
        }
      }

      // OR condition, first "true" result returns
      if ($hasAccess = self::checkAccessByClass($resource, $user, $action, $options))
      {
        return $hasAccess;
      }
    }

    return $hasAccess;
  }

  /*
   * Check if the current user has access to this resource, based on
   * class specific rules. This is a helper function to QubitAcl::check().
   *
   * @param $resource  The current resource we're checking user access against.
   * @param $user  The current user
   * @param $action  Which permissions action we're checking
   * @param $options  Access check options.
   */
  private static function checkAccessByClass($resource, $user, $action, $options)
  {
    switch (get_class($resource))
    {
      // Allow access to editors and administrators
      case 'QubitAccession':
      case 'QubitDeaccession':
      case 'QubitDonor':
      case 'QubitFunction':
      case 'QubitRightsHolder':
        $hasAccess = $user->isAuthenticated() && ($user->hasGroup(QubitAclGroup::ADMINISTRATOR_ID) ||
                     $user->hasGroup(QubitAclGroup::EDITOR_ID));
        break;

      // Administrator only
      case 'QubitUser':
      case 'QubitMenu':
      case 'QubitStaticPage':
      case 'QubitAclGroup':
      case 'QubitAclUser':
        $hasAccess = $user->hasGroup(QubitAclGroup::ADMINISTRATOR_ID);
        break;

      // Rely on ACL for authorization
      // TODO Switch *all* authorization to ACL
      default:
        $hasAccess = self::isAllowed($user, $resource, $action, $options);
    }

    return $hasAccess;
  }

  public static function isAllowed($role, $resource, $action, $options = array())
  {
    if (!($role instanceOf myUser))
    {
      self::getInstance()->addRole($role);
    }

    // If attempting to read a draft information object, check viewDraft permission
    if ('read' == $action && $resource instanceOf QubitInformationObject)
    {<commit_msg>Make check work with LDAP user class, refs #9765<commit_after><?php

/*
 * This file is part of the Access to Memory (AtoM) software.
 *
 * Access to Memory (AtoM) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Access to Memory (AtoM) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Access to Memory (AtoM).  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Access Control List (ACL) functionality
 *
 * @package    AccesstoMemory
 * @subpackage qbAclPlugin
 * @author     <NAME> <<EMAIL>>
 */
class QubitAcl
{
  const GRANT = 2;
  const INHERIT = 1;
  const DENY  = 0;

  public static $ACTIONS = array(
    'read' => 'Read',
    'create' => 'Create',
    'update' => 'Update',
    'delete' => 'Delete',
    'translate' => 'Translate'
  );

  protected static $_instance;

  protected
    $_roles = array(),
    $_resources = array(),
    $_user;

  public
    $acl;

  public function __construct($user = null)
  {
    if (null === $user)
    {
      $this->_user = sfContext::getInstance()->user;
    }
    else
    {
      $this->_user = $user;
    }

    $this->acl = new Zend_Acl;
    $this->buildUserRoleList($this->_user);
  }

  public static function getInstance()
  {
    if (null === self::$_instance)
    {
      self::$_instance = new self();
    }

    return self::$_instance;
  }

  /**
   * Each request is completely unique in PHP however our workers run in a loop
   * where state is held across jobs. This class was built as a singleton so we
   * need this extra method to void the instance when needed when running ACL
   * checks from a worker process.
   *
   */
  public static function destruct()
  {
    self::$_instance = null;
  }

  /**
   * Test user access to the given resource
   *
   * Note: Current sf_user is assumed, but can be overridden with
   * $options['userId'].
   *
   * @param mixed   $resource object to which user is requesting access
   * @param integer $actions requested action key
   * @param array   $options optional parameters
   */
  public static function check($resource, $actions, $options = array())
  {
    if ($resource instanceof sfOutputEscaper)
    {
      $resource = sfOutputEscaper::unescape($resource);
    }

    $hasAccess = false;

    // Skip ACL checks for command-line tasks
    if ('cli' == sfContext::getInstance()->getConfiguration()->getEnvironment())
    {
      return true;
    }

    if (!is_array($actions))
    {
      $actions = array($actions);
    }

    $user = sfContext::getInstance()->user;
    if (isset($options['user']))
    {
      $user = $options['user'];
    }

    // Loop through actions and return on first "true" result (OR condition)
    while ($action = array_shift($actions))
    {
      // Short-circuit decision tree for 'translate', because we want
      // translate permissions to apply system-wide
      //
      // TODO: Get rid of this when we are using ACL system-wide
      //
      if ('translate' == $action)
      {
        if (self::isAllowed($user, $resource, 'translate', $options))
        {
          return true;
        }
        else
        {
          continue;
        }
      }

      // OR condition, first "true" result returns
      if ($hasAccess = self::checkAccessByClass($resource, $user, $action, $options))
      {
        return $hasAccess;
      }
    }

    return $hasAccess;
  }

  /*
   * Check if the current user has access to this resource, based on
   * class specific rules. This is a helper function to QubitAcl::check().
   *
   * @param $resource  The current resource we're checking user access against.
   * @param $user  The current user
   * @param $action  Which permissions action we're checking
   * @param $options  Access check options.
   */
  private static function checkAccessByClass($resource, $user, $action, $options)
  {
    switch (get_class($resource))
    {
      // Allow access to editors and administrators
      case 'QubitAccession':
      case 'QubitDeaccession':
      case 'QubitDonor':
      case 'QubitFunction':
      case 'QubitRightsHolder':
        $hasAccess = $user->isAuthenticated() && ($user->hasGroup(QubitAclGroup::ADMINISTRATOR_ID) ||
                     $user->hasGroup(QubitAclGroup::EDITOR_ID));
        break;

      // Administrator only
      case 'QubitUser':
      case 'QubitMenu':
      case 'QubitStaticPage':
      case 'QubitAclGroup':
      case 'QubitAclUser':
        $hasAccess = $user->hasGroup(QubitAclGroup::ADMINISTRATOR_ID);
        break;

      // Rely on ACL for authorization
      // TODO Switch *all* authorization to ACL
      default:
        $hasAccess = self::isAllowed($user, $resource, $action, $options);
    }

    return $hasAccess;
  }

  public static function isAllowed($role, $resource, $action, $options = array())
  {
    if (!isset(class_implements($role)['Zend_Acl_Role_Interface']))
    {
      self::getInstance()->addRole($role);
    }

    // If attempting to read a draft information object, check viewDraft permission
    if ('read' == $action && $resource instanceOf QubitInformationObject)
    {
{'fraction_non_alphanumeric': 0.11529004644385757, 'fraction_numerical': 0.0010927966487569438, 'mean_word_length': 2.6790619765494137, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '516223', 'n_tokens_mistral': 3259, 'n_tokens_neox': 3168, 'n_words': 1068}