Разрешения и учетные данные [[AND OR]] не работают с фрагментом кода, который проверяет базу данных, а не учетные данные сеанса - PullRequest
0 голосов
/ 20 марта 2012

Я нашел этот великолепный фрагмент кода, который прекрасно работает при обстоятельствах, которые изменяют учетные данные пользователя во время сеанса этого пользователя. Метод hasCredential () по умолчанию смотрит на базу данных, а не на сеанс пользователя - что полностью соответствует моим потребностям (поскольку учетные данные пользователя часто меняются программно во время сеанса пользователя). Поэтому мне действительно нужно сохранить эту функциональность.

Однако для обстоятельств, имеющих несколько учетных данных, либо обстоятельство ИЛИ: [[A, B]], либо обстоятельство AND: [A, B] фрагмент кода не выполняется, поскольку он проверяет только один экземпляр и не читает файл безопасности yaml для экземпляров AND OR.

Мне нужна помощь в настройке фрагмента кода с учетом ИЛИ разрешений на доступ к учетным данным. Вот фрагмент кода:

public function hasCredential($permission_name)
{
//this overrides the default action (hasCredential) and instead of checking
//the user's session, it now checks the database directly.  
if (!$this->isAuthenticated()) {
  return false;
}
$gu = $this->getGuardUser();
$groups = $gu->getGroups();
$permissions = $gu->getPermissions();

$permission_names = array();
foreach($permissions as $permission) {
  $permission_names[] = $permission->getName();
}
foreach($groups as $group) {
  $group_permissions = $group->getPermissions();
  foreach($group_permissions as $group_permission) {
    $permission_names = array_merge($permission_names, array($group_permission->getName()));
  }
}
$permission_names = array_unique($permission_names);
return (in_array($permission_name, $permission_names)) ? true : false;
}

EDIT:

Я думаю, что мне нужно объединить приведенный выше код с оригинальным hasCredential () ниже, но я борюсь с логикой:

public function hasCredential($credentials, $useAnd = true)
{
if (null === $this->credentials)
{
  return false;
}

if (!is_array($credentials))
{
  return in_array($credentials, $this->credentials);
}

// now we assume that $credentials is an array
$test = false;

foreach ($credentials as $credential)
{
  // recursively check the credential with a switched AND/OR mode
  $test = $this->hasCredential($credential, $useAnd ? false : true);

  if ($useAnd)
  {
    $test = $test ? false : true;
  }

  if ($test) // either passed one in OR mode or failed one in AND mode
  {
    break; // the matter is settled
  }
}

if ($useAnd) // in AND mode we succeed if $test is false
{
  $test = $test ? false : true;
}

return $test;
}

1 Ответ

0 голосов
/ 24 июня 2012

Я думаю, что нашел правильную реализацию метода hasCredential, который переопределяет исходный код, найденный в классе sfGuardSecurityUser. Код просит базовую модель GuardUser перезагрузить все разрешения и группы из базы данных и добавляет эти учетные данные в объект SecurityUser перед проверкой учетных данных.

/**
 * Returns whether or not the user has the given credential.
 * 
 * EXTENDED to reload all permission so that changes take
 * immediate effect and user does not have to log out
 *
 * @param string $credential The credential name
 * @param boolean $useAnd Whether or not to use an AND condition
 * @return boolean
 */
public function hasCredential($credential, $useAnd = true)
{
  if (empty($credentials))
  {
    return true;
  }

  if (!$this->getGuardUser())
  {
    return false;
  }

  if ($this->getGuardUser()->getIsSuperAdmin())
  {
    return true;
  }

  if (!$this->isAuthenticated()) {
    return false;
  }

  $gu = $this->getGuardUser();
  $groups = $gu->getGroups();
  $permissions = $gu->getPermissions();

  $permission_names = array();
  foreach($permissions as $permission) {
    $permission_names[] = $permission->getName();
  }
  foreach($groups as $group) {
    $group_permissions = $group->getPermissions();
    foreach($group_permissions as $group_permission) {
      $permission_names = array_merge($permission_names, array($group_permission->getName()));
    }
  }
  $permission_names = array_unique($permission_names);

  if (!is_array($credentials))
  {
    return in_array($credentials, $permission_names);
  }

  // now we assume that $credentials is an array
  $test = false;

  foreach ($credentials as $credential)
  {
    // recursively check the credential with a switched AND/OR mode
    $test = $this->hasCredential($credential, $useAnd ? false : true);

    if ($useAnd)
    {
      $test = $test ? false : true;
    }

    if ($test) // either passed one in OR mode or failed one in AND mode
    {
      break; // the matter is settled
    }
  }

  if ($useAnd) // in AND mode we succeed if $test is false
  {
    $test = $test ? false : true;
  }

  return $test;
}
...