<?php
namespace Platform\SecurityBundle\Security\Voter;
use App\Entity\Content\AbstractObject;
use App\Entity\Feed\AbstractEntry;
use App\Entity\System\School;
use Cms\ContainerBundle\Entity\Container;
use Cms\ContainerBundle\Entity\Containers\PersonalContainer;
use Cms\ContainerBundle\Entity\Containers\StorageContainer;
use Cms\ModuleBundle\Entity\ModuleEntity;
use Cms\ModuleBundle\Model\ModuleConfig;
use Platform\SecurityBundle\Entity\Identity\Account;
use Platform\SecurityBundle\Model\PlatformSubject;
use Platform\SecurityBundle\Security\PlatformVoter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
*
*/
final class CmsVoter extends PlatformVoter
{
/**
* {@inheritDoc}
*/
protected function supports(
Account $account,
string $attribute,
?PlatformSubject $subject = null
): bool
{
// for this to be a cms vote, the permission should be prefixed a certain way
if ( ! $this->sentry->isCmsPermission($attribute)) {
return false;
}
// allow passing of a school
// context for cms should always be a department if any context is given
// only check this if we are performing a real check
if ($subject) {
$context = ($subject->getContext() instanceof School) ? $subject->getContext()->getDepartment() : $subject->getContext();
if ($context && ! $context instanceof Container) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/
protected function poll(
Account $account,
string $permission,
?PlatformSubject $subject = null
): int
{
// this should have already been checked by the support method...
$context = null;
if ($subject) {
$context = ($subject->getContext() instanceof School) ? $subject->getContext()->getDepartment() : $subject->getContext();
if ($context && ! $context instanceof Container) {
throw new \LogicException();
}
}
return $this->sentry->check($account, $permission, $context)
? VoterInterface::ACCESS_GRANTED
: VoterInterface::ACCESS_ABSTAIN;
}
/**
* {@inheritdoc}
*/
protected function try(
Account $account,
string $permission
): int
{
return $this->sentry->try($account, $permission)
? VoterInterface::ACCESS_GRANTED
: VoterInterface::ACCESS_ABSTAIN;
}
/**
* {@inheritDoc}
*/
protected function attributes(
array $attributes,
Account $account,
?PlatformSubject $subject = null
): array
{
// if we have a personal site, we want to be able to do anything in it
// therefore, we should also be checking the personal sites permission
// prepend to the array as in this case, this check is likely to succeed first
if ($subject && $subject->getContext() instanceof PersonalContainer && $subject->getContext()->getAccount() === $account) {
$attributes = [
'campussuite.cms.me.sites',
...$attributes,
];
}
// hack for smm stuff
if ($subject && $subject->getContext() instanceof StorageContainer && $subject->getContext()->getSlug() === 'smm') {
$attributes = [
'campussuite.smm.manage',
...$attributes,
];
}
// do some extra checks based on the thing we are enforcing permissions on
$thing = $subject ? $subject->getThing() : null;
// if we are checking for the module management permission, and have a specific subject, we can also tack on the specific content-type permission
if ($thing instanceof ModuleEntity && in_array('campussuite.cms.module.manage', $attributes, true)) {
$attributes[] = sprintf(
'campussuite.cms.modules.%s.manage',
$this->moduleManager->getModuleConfigurationForEntity($thing)->key(),
);
}
if ($thing instanceof ModuleConfig && in_array('campussuite.cms.module.manage', $attributes, true)) {
$attributes[] = sprintf(
'campussuite.cms.modules.%s.manage',
$thing->key(),
);
}
// new object tables
if ($thing instanceof AbstractObject && in_array('campussuite.cms.module.manage', $attributes, true)) {
$attributes[] = sprintf(
'campussuite.cms.modules.%s.manage',
$thing::ROUTING_SLUG,
);
}
// handle schoolnow feed entries
if ($thing instanceof AbstractEntry && in_array('campussuite.cms.module.manage', $attributes, true)) {
$attributes = [
...$attributes,
AbstractEntry::PERMISSION_MAP[$thing->getType()],
];
}
return parent::attributes($attributes, $account, $subject);
}
}