| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  * WebHemi. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  * PHP version 5.6 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  * @copyright 2012 - 2016 Gixx-web (http://www.gixx-web.com) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  * @license   https://opensource.org/licenses/MIT The MIT License (MIT) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  * @link      http://www.gixx-web.com | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | namespace WebHemi\Middleware\Security; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use Exception; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | use WebHemi\Adapter\Auth\AuthAdapterInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | use WebHemi\Adapter\Http\ResponseInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | use WebHemi\Adapter\Http\ServerRequestInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | use WebHemi\Application\EnvironmentManager; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | use WebHemi\Auth\Result; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | use WebHemi\Data\Coupler\UserToGroupCoupler; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | use WebHemi\Data\Coupler\UserToPolicyCoupler; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | use WebHemi\Data\Coupler\UserGroupToPolicyCoupler; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | use WebHemi\Data\Entity\ApplicationEntity; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | use WebHemi\Data\Entity\AccessManagement\PolicyEntity; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | use WebHemi\Data\Entity\AccessManagement\ResourceEntity; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | use WebHemi\Data\Entity\User\UserEntity; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | use WebHemi\Data\Storage\AccessManagement\ResourceStorage; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | use WebHemi\Data\Storage\ApplicationStorage; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | use WebHemi\Middleware\MiddlewareInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | use WebHemi\Middleware\Action; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |  * Class AclMiddleware. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  | class AclMiddleware implements MiddlewareInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |     /** @var EnvironmentManager */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |     private $environmentManager; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     /** @var AuthAdapterInterface */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |     private $authAdapter; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |     /** @var UserToPolicyCoupler */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |     private $userToPolicyCoupler; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |     /** @var UserToGroupCoupler */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |     private $userToGroupCoupler; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |     /** @var UserGroupToPolicyCoupler */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |     private $userGroupToPolicyCoupler; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |     private $applicationStorage; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |     private $resourceStorage; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |     /** @var array */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     private $middlewareWhiteList = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |         Action\Auth\LoginAction::class, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |         Action\Auth\LogoutAction::class, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |     ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |      * AclMiddleware constructor. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |      * @param EnvironmentManager       $environmentManager | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |      * @param AuthAdapterInterface     $authAdapter | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |      * @param UserToPolicyCoupler      $userToPolicyCoupler | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |      * @param UserToGroupCoupler       $userToGroupCoupler | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |      * @param UserGroupToPolicyCoupler $userGroupToPolicyCoupler | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |      * @param ApplicationStorage       $applicationStorage | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |      * @param ResourceStorage          $resourceStorage | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 65 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  |     public function __construct( | 
            
                                                                        
                            
            
                                    
            
            
                | 67 |  |  |         EnvironmentManager $environmentManager, | 
            
                                                                        
                            
            
                                    
            
            
                | 68 |  |  |         AuthAdapterInterface $authAdapter, | 
            
                                                                        
                            
            
                                    
            
            
                | 69 |  |  |         UserToPolicyCoupler $userToPolicyCoupler, | 
            
                                                                        
                            
            
                                    
            
            
                | 70 |  |  |         UserToGroupCoupler $userToGroupCoupler, | 
            
                                                                        
                            
            
                                    
            
            
                | 71 |  |  |         UserGroupToPolicyCoupler $userGroupToPolicyCoupler, | 
            
                                                                        
                            
            
                                    
            
            
                | 72 |  |  |         ApplicationStorage $applicationStorage, | 
            
                                                                        
                            
            
                                    
            
            
                | 73 |  |  |         ResourceStorage $resourceStorage | 
            
                                                                        
                            
            
                                    
            
            
                | 74 |  |  |     ) { | 
            
                                                                        
                            
            
                                    
            
            
                | 75 |  |  |         $this->environmentManager = $environmentManager; | 
            
                                                                        
                            
            
                                    
            
            
                | 76 |  |  |         $this->authAdapter = $authAdapter; | 
            
                                                                        
                            
            
                                    
            
            
                | 77 |  |  |         $this->userToPolicyCoupler = $userToPolicyCoupler; | 
            
                                                                        
                            
            
                                    
            
            
                | 78 |  |  |         $this->userToGroupCoupler = $userToGroupCoupler; | 
            
                                                                        
                            
            
                                    
            
            
                | 79 |  |  |         $this->userGroupToPolicyCoupler = $userGroupToPolicyCoupler; | 
            
                                                                        
                            
            
                                    
            
            
                | 80 |  |  |         $this->applicationStorage = $applicationStorage; | 
            
                                                                        
                            
            
                                    
            
            
                | 81 |  |  |         $this->resourceStorage = $resourceStorage; | 
            
                                                                        
                            
            
                                    
            
            
                | 82 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |      * A middleware is a callable. It can do whatever is appropriate with the Request and Response objects. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |      * The only hard requirement is that a middleware MUST return an instance of \Psr\Http\Message\ResponseInterface. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |      * Each middleware SHOULD invoke the next middleware and pass it Request and Response objects as arguments. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |      * @param ServerRequestInterface $request | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |      * @param ResponseInterface      $response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |      * @throws Exception | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |      * @return ResponseInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |     public function __invoke(ServerRequestInterface &$request, ResponseInterface $response) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |         $actionMiddleware = $request->getAttribute(ServerRequestInterface::REQUEST_ATTR_RESOLVED_ACTION_CLASS); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |         $identity = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         if (in_array($actionMiddleware, $this->middlewareWhiteList)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |             return $response; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |         if (!$this->authAdapter->hasIdentity()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |             /** @var Result $result */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |             $result = $this->authAdapter->authenticate(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |             if ($result->isValid()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |                 $identity = $result->getIdentity(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |                 $this->authAdapter->setIdentity($identity); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |             $identity = $this->authAdapter->getIdentity(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |         if ($identity instanceof UserEntity) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |             /** @var array<UserGroupEntity> $userGroups */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |             $userGroups = $this->userToGroupCoupler->getEntityDependencies($identity); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |             /** @var array<PolicyEntity> $policies */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |             $policies = $this->userToPolicyCoupler->getEntityDependencies($identity); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |             foreach ($userGroups as $userGroupEntity) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |                 /** @var array<PolicyEntity> $userGroupPolicies */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |                 $userGroupPolicies = $this->userGroupToPolicyCoupler->getEntityDependencies($userGroupEntity); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |                 $policies = array_merge($userGroupPolicies, $policies); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |             $selectedApplication = $this->environmentManager->getSelectedApplication(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |             /** @var ApplicationEntity $applicationEntity */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |             $applicationEntity = $this->applicationStorage->getApplicationByName($selectedApplication); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |             /** @var ResourceEntity $resourceEntity */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |             $resourceEntity = $this->resourceStorage->getResourceByName($actionMiddleware); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |             // We assume the worst case: no access | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |             $hasAccess = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |             /** @var PolicyEntity $policyEntity */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |             foreach ($policies as $policyEntity) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |                 $policyApplication = $policyEntity->getApplicationId(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |                 $policyResource = $policyEntity->getResourceId(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |                 // The user has access when: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |                 // - user has a policy which allows access AND | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |                 // - user has a policy that connected to the current application OR any application AND | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |                 // - user has a policy that connected to the current resource OR any resource | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |                 if ($policyEntity->getAllowed() && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |                     ($policyApplication == null || $policyApplication == $applicationEntity->getApplicationId()) && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |                     ($policyResource == null || $policyResource == $resourceEntity->getResourceId()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |                 ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |                     $hasAccess = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |                     break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |             if (!$hasAccess) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |                 $response = $response->withStatus(403, 'Forbidden'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |             $response = $response->withStatus(401, 'Unauthorized'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |         return $response; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 163 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 164 |  |  |  | 
            
                        
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: