src/Cms/CoreBundle/Model/Contexts/GlobalContext.php line 231

Open in your IDE?
  1. <?php
  2. namespace Cms\CoreBundle\Model\Contexts;
  3. use Cms\CoreBundle\Model\Context;
  4. use Cms\CoreBundle\Util\Doctrine\EntityManager;
  5. use Doctrine\DBAL\Types\Types;
  6. use Platform\SecurityBundle\Entity\Identity\Account;
  7. use Cms\TenantBundle\Entity\Tenant;
  8. use Cms\TenantBundle\Util\TenantDoctrineFilter;
  9. use Platform\SecurityBundle\Service\AccountProvider;
  10. use Products\NotificationsBundle\Entity\Profile;
  11. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  12. use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
  13. /**
  14.  * Class GlobalContext
  15.  *
  16.  * @package Cms\CoreBundle\Model\Contexts
  17.  *
  18.  * @method Tenant|null getTenant()
  19.  * @method string getMode()
  20.  * @method GlobalContext clearTenant()
  21.  * @method GlobalContext clearMode()
  22.  */
  23. final class GlobalContext extends Context
  24. {
  25.     /**
  26.      * @var EntityManager
  27.      */
  28.     private EntityManager $em;
  29.     /**
  30.      * @var TokenStorageInterface
  31.      */
  32.     private TokenStorageInterface $tokenStorage;
  33.     /**
  34.      * @var AccountProvider
  35.      */
  36.     private AccountProvider $accountProvider;
  37.     /**
  38.      * @var string
  39.      */
  40.     private string $dashboardHostname;
  41.     /**
  42.      * @param EntityManager $em
  43.      * @param TokenStorageInterface $tokenStorage
  44.      * @param AccountProvider $accountProvider
  45.      * @param string $mode
  46.      * @param string $dashboardHostname
  47.      */
  48.     public function __construct(
  49.         EntityManager $em,
  50.         TokenStorageInterface $tokenStorage,
  51.         AccountProvider $accountProvider,
  52.         string $mode,
  53.         string $dashboardHostname
  54.     )
  55.     {
  56.         parent::__construct(
  57.             array(
  58.                 'tenant' => Context::LOCKED,
  59.                 'mode' => Context::LOCKED,
  60.             )
  61.         );
  62.         $this->em $em;
  63.         $this->tokenStorage $tokenStorage;
  64.         $this->accountProvider $accountProvider;
  65.         $this->escort(
  66.             function () use ($mode) {
  67.                 $this->setMode($mode);
  68.             }
  69.         );
  70.         $this->dashboardHostname $dashboardHostname;
  71.     }
  72.     /**
  73.      * Quick helper function to return a dashboard hostname.
  74.      * Paramter allows to choose a tenanted (such as "foobar.app.campussuite.com") or a tenant-less (such as "app.campussuite.com") domain.
  75.      *
  76.      * @param bool $tenantless
  77.      * @return string
  78.      */
  79.     public function getDashboard(bool $tenantless false): string
  80.     {
  81.         $hostname $this->dashboardHostname;
  82.         if ($tenantless !== true) {
  83.             if ($this->getTenant() === null) {
  84.                 throw new \RuntimeException();
  85.             }
  86.             $hostname sprintf(
  87.                 '%s.%s',
  88.                 $this->getTenant()->getSlug(),
  89.                 $hostname
  90.             );
  91.         }
  92.         return $hostname;
  93.     }
  94.     /**
  95.      * Quick helper function to return a dashboard URL.
  96.      * Paramter allows to choose a tenanted (such as "foobar.app.campussuite.com") or a tenant-less (such as "app.campussuite.com") domain.
  97.      *
  98.      * @param bool $tenantless
  99.      * @return string
  100.      */
  101.     public function getDashboardUrl(bool $tenantless false): string
  102.     {
  103.         return sprintf(
  104.             'https://%s/',
  105.             $this->getDashboard($tenantless)
  106.         );
  107.     }
  108.     /**
  109.      * Returns the account of the user who is currently logged in and authenticated with the system.
  110.      * In any context, like in the dashboard, when a user should be active, this function should not return NULL.
  111.      * For public-facing, unathenticated pages and things like CLI commands, this may return NULL.
  112.      * When impersonating, this function will still return the "original" account, NOT that account that has been chosen by that user to be impersonated.
  113.      *
  114.      * @return Account|null
  115.      */
  116.     public function getAuthenticatedAccount(): ?Account
  117.     {
  118.         // obtain the token
  119.         $token $this->tokenStorage->getToken();
  120.         if ( ! $token) {
  121.             return null;
  122.         }
  123.         // get the user from the token
  124.         $user $token->getUser();
  125.         // if we are in an impersonation situation, get the user from the original token
  126.         // this user may need to be refreshed...
  127.         if ($token instanceof SwitchUserToken) {
  128.             $user $token->getOriginalToken()->getUser();
  129.             if ($user) {
  130.                 $user $this->accountProvider->refreshUser($user);
  131.             }
  132.         }
  133.         if ($user instanceof Profile) {
  134.             return null;
  135.         }
  136.         // make sure we have a proper type
  137.         if ( ! $user instanceof Account) {
  138.             throw new \LogicException();
  139.         }
  140.         return $user;
  141.     }
  142.     /**
  143.      * Will return the account of the user being impersonated if impersonation is in effect.
  144.      * This is the account that the authenticated user has selected to impersonate.
  145.      * If no impersonation is being done, this returns NULL.
  146.      *
  147.      * @return Account|null
  148.      */
  149.     public function getImpersonatedAccount(): ?Account
  150.     {
  151.         // obtain the token
  152.         $token $this->tokenStorage->getToken();
  153.         // must be an impersonation token, grab the user from it
  154.         if ($token instanceof SwitchUserToken) {
  155.             return $token->getUser();
  156.         }
  157.         // not impersonating
  158.         return null;
  159.     }
  160.     /**
  161.      * Returns the account for which security checks should run against by default.
  162.      * If an account is being impersonated, that object will be returned.
  163.      * Otherwise, it returns the currently authenticated account.
  164.      * This is the general function to be used when trying to get the "current user" in a situation, unless there is a need to differentiate authenticated versus impersonated account.
  165.      *
  166.      * @return Account|null
  167.      */
  168.     public function getEffectiveAccount(): ?Account
  169.     {
  170.         // profiler toolbar is not loading on /_portal/login if the return type is not Account|null
  171.         return $this->getImpersonatedAccount() ?: $this->getAuthenticatedAccount();
  172.     }
  173.     /**
  174.      * @return bool
  175.      */
  176.     public function isImpersonating(): bool
  177.     {
  178.         return (bool) $this->getImpersonatedAccount();
  179.     }
  180.     /**
  181.      * TODO: remove this function and fix all uses; should be using the "kernel.environment" parameter instead.
  182.      *
  183.      * @param string $value
  184.      * @return $this
  185.      * @deprecated
  186.      */
  187.     public function setMode(string $value): self
  188.     {
  189.         // ensure mode is legit
  190.         switch ($value) {
  191.             case 'dev':
  192.             case 'test':
  193.             case 'prod':
  194.                 break;
  195.             default:
  196.                 throw new \RuntimeException();
  197.         }
  198.         // call parent to actually set
  199.         return $this->set('mode'$value);
  200.     }
  201.     /**
  202.      * Sets, or clears, the currently associated tenant with the request/command.
  203.      * This stores the given tenant and enables it on the core background mechanisms that are responsible for attaching the tenant information to each tenanted record in the database.
  204.      *
  205.      * @param Tenant|null $value
  206.      * @return $this
  207.      */
  208.     public function setTenant(Tenant $value null): self
  209.     {
  210.         // branch on null values
  211.         if ($value !== null) {
  212.             // enable doctrine filter
  213.             $this->em
  214.                 ->getFilters()
  215.                 ->enable(TenantDoctrineFilter::FILTER)
  216.                 ->setParameter(
  217.                     'id',
  218.                     $value->getId(),
  219.                     Types::INTEGER,
  220.                 );
  221.         } else if ($this->em->getFilters()->isEnabled(TenantDoctrineFilter::FILTER)) {
  222.             // disable the filter
  223.             $this->em
  224.                 ->getFilters()
  225.                 ->disable(TenantDoctrineFilter::FILTER)
  226.                 ->setParameter(
  227.                     'id',
  228.                     0,
  229.                     Types::INTEGER,
  230.                 );
  231.         }
  232.         // call our parent to set value
  233.         return $this->set('tenant'$value);
  234.     }
  235. }