![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/mautic.corals.io/app/bundles/CoreBundle/Security/Permissions/ |
<?php namespace Mautic\CoreBundle\Security\Permissions; use Mautic\UserBundle\Form\Type\PermissionListType; use Symfony\Component\Form\FormBuilderInterface; abstract class AbstractPermissions { /** * @var array */ protected $permissions = []; public function __construct( protected array $params ) { } /** * This method is called before the permissions object is used. * Define permissions with `addExtendedPermissions` here instead of constructor. */ public function definePermissions(): void { // Override this method in the final class } /** * Returns bundle's permissions array. * * @return array */ public function getPermissions() { return $this->permissions; } /** * Checks to see if the requested permission is supported by the bundle. * * @param string $name * @param string $level * * @return bool */ public function isSupported($name, $level = '') { [$name, $level] = $this->getSynonym($name, $level); if (empty($level)) { // verify permission name only return isset($this->permissions[$name]); } // verify permission name and level as well return isset($this->permissions[$name][$level]); } /** * Allows permission classes to be disabled if criteria is not met (such as bundle is disabled). */ public function isEnabled(): bool { return true; } /** * Returns the value assigned to a specific permission. * * @param string $name * @param string $perm * * @return int */ public function getValue($name, $perm) { return ($this->isSupported($name, $perm)) ? $this->permissions[$name][$perm] : 0; } /** * Builds the bundle's specific form elements for its permissions. */ public function buildForm(FormBuilderInterface &$builder, array $options, array $data): void { } /** * Returns the name of the permission set (should be the bundle identifier). * * @return string|void */ abstract public function getName(); /** * Takes an array from PermissionRepository::getPermissionsByRole() and converts the bitwise integers to an array * of permission names that can be used in forms, for example. * * @return mixed */ public function convertBitsToPermissionNames(array $permissions) { static $permissionLevels = []; $bundle = $this->getName(); if (!in_array($bundle, $permissionLevels)) { $permissionLevels[$bundle] = []; if (isset($permissions[$bundle])) { if ($this->isEnabled()) { foreach ($permissions[$bundle] as $details) { $permName = $details['name']; $permBitwise = $details['bitwise']; // ensure the permission still exists if ($this->isSupported($permName)) { $levels = $this->permissions[$permName]; // ensure that at least keys exist $permissionLevels[$bundle][$permName] = []; // $permissionLevels[$bundle][$permName]["$bundle:$permName"] = $permId; foreach ($levels as $levelName => $levelBit) { // compare bit against levels to see if it is a match if ($levelBit & $permBitwise) { // bitwise compares so add the level $permissionLevels[$bundle][$permName][] = $levelName; continue; } } } } } } } return $permissionLevels[$bundle]; } /** * Allows the bundle permission class to utilize synonyms for permissions. * * @param string $name * @param string $level * * @return array */ protected function getSynonym($name, $level) { if (in_array($level, ['viewown', 'viewother'])) { if (isset($this->permissions[$name]['view'])) { $level = 'view'; } } elseif ('view' == $level) { if (isset($this->permissions[$name]['viewown'])) { $level = 'viewown'; } } elseif (in_array($level, ['editown', 'editother'])) { if (isset($this->permissions[$name]['edit'])) { $level = 'edit'; } } elseif ('edit' == $level) { if (isset($this->permissions[$name]['editown'])) { $level = 'editown'; } } elseif (in_array($level, ['deleteown', 'deleteother'])) { if (isset($this->permissions[$name]['delete'])) { $level = 'delete'; } } elseif ('delete' == $level) { if (isset($this->permissions[$name]['deleteown'])) { $level = 'deleteown'; } } elseif (in_array($level, ['publishown', 'publishother'])) { if (isset($this->permissions[$name]['publish'])) { $level = 'publish'; } } elseif ('publish' == $level) { if (isset($this->permissions[$name]['publishown'])) { $level = 'publishown'; } } return [$name, $level]; } /** * Determines if the user has access to the specified permission. * * @param array $userPermissions * @param string $name * @param string $level * * @return bool */ public function isGranted($userPermissions, $name, $level) { [$name, $level] = $this->getSynonym($name, $level); if (!isset($userPermissions[$name])) { // the user doesn't have implicit access return false; } elseif (isset($this->permissions[$name]['full']) && $this->permissions[$name]['full'] & $userPermissions[$name]) { return true; } else { // otherwise test for specific level $result = ($this->permissions[$name][$level] & $userPermissions[$name]); return ($result) ? true : false; } } /** * @param bool $isSecondRound * * @return bool Return true if a second round is required after all other bundles have analyzed it's permissions */ public function analyzePermissions(array &$permissions, $allPermissions, $isSecondRound = false): bool { $hasViewAccess = false; foreach ($permissions as $level => &$perms) { foreach ($perms as $perm) { $required = []; switch ($perm) { case 'editother': case 'edit': $required = ['viewother', 'viewown']; break; case 'deleteother': case 'delete': $required = ['editother', 'viewother', 'viewown']; break; case 'publishother': case 'publish': $required = ['viewother', 'viewown']; break; case 'viewother': case 'editown': case 'deleteown': case 'publishown': case 'create': $required = ['viewown']; break; } foreach ($required as $r) { [$ignore, $r] = $this->getSynonym($level, $r); if ($this->isSupported($level, $r) && !in_array($r, $perms)) { $perms[] = $r; } } } $hasViewAccess = (!$hasViewAccess && (in_array('view', $perms) || in_array('viewown', $perms))); } // check categories for view permissions and add it if the user has view access to the other permissions if (isset($this->permissions['categories']) && $hasViewAccess && (!isset($permissions['categories']) || !in_array('view', $permissions['categories']))) { $permissions['categories'][] = 'view'; } return false; } /** * Generates an array of granted and total permissions. * * @return array */ public function getPermissionRatio(array $data) { $totalAvailable = $totalGranted = 0; foreach ($this->permissions as $level => $perms) { $perms = array_keys($perms); $totalAvailable += count($perms); if (in_array('full', $perms)) { if (1 === count($perms)) { // full is the only permission so count as 1 if (!empty($data[$level]) && !in_array('full', $data[$level])) { ++$totalGranted; } } else { // remove full from total count --$totalAvailable; if (!empty($data[$level]) && in_array('full', $data[$level])) { // user has full access so sum perms minus full $totalGranted += count($perms) - 1; // move on to the next level continue; } } } if (isset($data[$level])) { $totalGranted += count($data[$level]); } } return [$totalGranted, $totalAvailable]; } /** * Gives the bundle an opportunity to change how JavaScript calculates permissions granted. */ public function parseForJavascript(array &$perms): void { } /** * @param array<int|string> $permissions */ protected function addCustomPermission(string $level, array $permissions): void { $this->permissions[$level] = $permissions; } /** * Adds a custom permission to the form builder, i.e. config only bundles. * * @param array<string> $choices * @param array<string> $data */ protected function addCustomFormFields(string $bundle, string $level, FormBuilderInterface &$builder, string $label, array $choices, array $data): void { $builder->add("$bundle:$level", PermissionListType::class, [ 'choices' => $choices, 'label' => $label, 'data' => (!empty($data[$level]) ? $data[$level] : []), 'bundle' => $bundle, 'level' => $level, ]); } /** * Adds the standard permission set of view, edit, create, delete, publish and full. * * @param array $permissionNames * @param bool $includePublish */ protected function addStandardPermissions($permissionNames, $includePublish = true) { if (!is_array($permissionNames)) { $permissionNames = [$permissionNames]; } foreach ($permissionNames as $p) { $this->permissions[$p] = [ 'view' => 4, 'edit' => 16, 'create' => 32, 'delete' => 128, 'full' => 1024, ]; if ($includePublish) { $this->permissions[$p]['publish'] = 512; } } } /** * Adds the standard permission set of view, edit, create, delete, publish and full to the form builder. * * @param string $bundle * @param string $level * @param FormBuilderInterface $builder * @param array $data * @param bool $includePublish */ protected function addStandardFormFields($bundle, $level, &$builder, $data, $includePublish = true) { $choices = [ 'mautic.core.permissions.view' => 'view', 'mautic.core.permissions.edit' => 'edit', 'mautic.core.permissions.create' => 'create', 'mautic.core.permissions.delete' => 'delete', ]; if ($includePublish) { $choices['mautic.core.permissions.publish'] = 'publish'; } $choices['mautic.core.permissions.full'] = 'full'; $label = ('categories' == $level) ? 'mautic.category.permissions.categories' : "mautic.$bundle.permissions.$level"; $builder->add( "$bundle:$level", PermissionListType::class, [ 'choices' => $choices, 'label' => $label, 'bundle' => $bundle, 'level' => $level, 'data' => (!empty($data[$level]) ? $data[$level] : []), ] ); } /** * @param string $bundle * @param string $level * * @return string */ protected function getLabel($bundle, $level) { return ('categories' === $level) ? 'mautic.category.permissions.categories' : "mautic.{$bundle}.permissions.{$level}"; } /** * Add a single full permission. * * @param array $permissionNames */ protected function addManagePermission($permissionNames) { if (!is_array($permissionNames)) { $permissionNames = [$permissionNames]; } foreach ($permissionNames as $p) { $this->permissions[$p] = [ 'manage' => 1024, ]; } } /** * Adds a single full permission to the form builder, i.e. config only bundles. * * @param string $bundle * @param string $level * @param FormBuilderInterface $builder * @param array $data */ protected function addManageFormFields($bundle, $level, &$builder, $data) { $choices = [ 'mautic.core.permissions.manage' => 'manage', ]; $builder->add( "$bundle:$level", PermissionListType::class, [ 'choices' => $choices, 'label' => "mautic.$bundle.permissions.$level", 'data' => (!empty($data[$level]) ? $data[$level] : []), 'bundle' => $bundle, 'level' => $level, ] ); } /** * Adds the standard permission set of viewown, viewother, editown, editother, create, deleteown, deleteother, * publishown, publishother and full. * * @param array|string $permissionNames * @param bool $includePublish */ protected function addExtendedPermissions($permissionNames, $includePublish = true) { if (!is_array($permissionNames)) { $permissionNames = [$permissionNames]; } foreach ($permissionNames as $p) { $this->permissions[$p] = [ 'viewown' => 2, 'viewother' => 4, 'editown' => 8, 'editother' => 16, 'create' => 32, 'deleteown' => 64, 'deleteother' => 128, 'full' => 1024, ]; if ($includePublish) { $this->permissions[$p]['publishown'] = 256; $this->permissions[$p]['publishother'] = 512; } } } /** * Adds the standard permission set of viewown, viewother, editown, editother, create, deleteown, deleteother, * publishown, publishother and full to the form builder. * * @param string $bundle * @param string $level * @param FormBuilderInterface $builder * @param array $data * @param bool $includePublish */ protected function addExtendedFormFields($bundle, $level, &$builder, $data, $includePublish = true) { $choices = [ 'mautic.core.permissions.viewown' => 'viewown', 'mautic.core.permissions.viewother' => 'viewother', 'mautic.core.permissions.editown' => 'editown', 'mautic.core.permissions.editother' => 'editother', 'mautic.core.permissions.create' => 'create', 'mautic.core.permissions.deleteown' => 'deleteown', 'mautic.core.permissions.deleteother' => 'deleteother', 'mautic.core.permissions.full' => 'full', ]; if ($includePublish) { $choices['mautic.core.permissions.publishown'] = 'publishown'; $choices['mautic.core.permissions.publishother'] = 'publishother'; } $builder->add( "$bundle:$level", PermissionListType::class, [ 'choices' => $choices, 'choices_as_values' => true, 'label' => $this->getLabel($bundle, $level), 'data' => (!empty($data[$level]) ? $data[$level] : []), 'bundle' => $bundle, 'level' => $level, ] ); } }