public function setUp() { $this->mockSecurityContext = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock(); $this->mockSecurityContext->expects($this->any())->method('withoutAuthorizationChecks')->will($this->returnCallback(function ($callback) { return $callback->__invoke(); })); }
/** * Add the current node and all parent identifiers to be used for cache entry tagging * * @Flow\Before("method(Neos\Flow\Mvc\Routing\RouterCachingService->extractUuids())") * @param JoinPointInterface $joinPoint The current join point * @return void */ public function addCurrentNodeIdentifier(JoinPointInterface $joinPoint) { $values = $joinPoint->getMethodArgument('values'); if (!isset($values['node']) || strpos($values['node'], '@') === false) { return; } // Build context explicitly without authorization checks because the security context isn't available yet // anyway and any Entity Privilege targeted on Workspace would fail at this point: $this->securityContext->withoutAuthorizationChecks(function () use($joinPoint, $values) { $contextPathPieces = NodePaths::explodeContextPath($values['node']); $context = $this->contextFactory->create(['workspaceName' => $contextPathPieces['workspaceName'], 'dimensions' => $contextPathPieces['dimensions'], 'invisibleContentShown' => true]); $node = $context->getNode($contextPathPieces['nodePath']); if (!$node instanceof NodeInterface) { return; } $values['node-identifier'] = $node->getIdentifier(); $node = $node->getParent(); $values['node-parent-identifier'] = array(); while ($node !== null) { $values['node-parent-identifier'][] = $node->getIdentifier(); $node = $node->getParent(); } $joinPoint->setMethodArgument('values', $values); }); }
/** * Checks the given token for validity and sets the token authentication status * accordingly (success, wrong credentials or no credentials given). * * @param TokenInterface $authenticationToken The token to be authenticated * @return void * @throws UnsupportedAuthenticationTokenException */ public function authenticate(TokenInterface $authenticationToken) { if (!$authenticationToken instanceof UsernamePassword) { throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1217339840); } /** @var $account Account */ $account = null; $credentials = $authenticationToken->getCredentials(); if ($authenticationToken->getAuthenticationStatus() !== TokenInterface::AUTHENTICATION_SUCCESSFUL) { $authenticationToken->setAuthenticationStatus(TokenInterface::NO_CREDENTIALS_GIVEN); } if (!is_array($credentials) || !isset($credentials['username']) || !isset($credentials['password'])) { return; } $providerName = $this->name; $accountRepository = $this->accountRepository; $this->securityContext->withoutAuthorizationChecks(function () use($credentials, $providerName, $accountRepository, &$account) { $account = $accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($credentials['username'], $providerName); }); $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); if ($account === null) { $this->hashService->validatePassword($credentials['password'], 'bcrypt=>$2a$14$DummySaltToPreventTim,.ingAttacksOnThisProvider'); return; } if ($this->hashService->validatePassword($credentials['password'], $account->getCredentialsSource())) { $account->authenticationAttempted(TokenInterface::AUTHENTICATION_SUCCESSFUL); $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL); $authenticationToken->setAccount($account); } else { $account->authenticationAttempted(TokenInterface::WRONG_CREDENTIALS); } $this->accountRepository->update($account); $this->persistenceManager->whitelistObject($account); }
/** * The policy enforcement advice. This advices applies the security enforcement interceptor to all methods configured in the policy. * Note: If we have some kind of "run as" functionality in the future, we would have to manipulate the security context * before calling the policy enforcement interceptor * * @Flow\Around("filter(Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilegePointcutFilter)") * @param JoinPointInterface $joinPoint The current joinpoint * @return mixed The result of the target method if it has not been intercepted */ public function enforcePolicy(JoinPointInterface $joinPoint) { if ($this->securityContext->areAuthorizationChecksDisabled() !== true) { $this->policyEnforcementInterceptor->setJoinPoint($joinPoint); $this->policyEnforcementInterceptor->invoke(); } return $joinPoint->getAdviceChain()->proceed($joinPoint); }
/** * Try to set the current account identifier emitting the events, if possible * * @return void */ protected function initializeAccountIdentifier() { if ($this->securityContext->canBeInitialized()) { $account = $this->securityContext->getAccount(); if ($account !== null) { $this->eventEmittingService->setCurrentAccountIdentifier($account->getAccountIdentifier()); } } }
/** * Returns TRUE, if at least one of the currently authenticated accounts holds * a role with the given identifier, also recursively. * * @param string $roleIdentifier The string representation of the role to search for * @return boolean TRUE, if a role with the given string representation was found */ public function hasRole($roleIdentifier) { if ($roleIdentifier === 'Neos.Flow:Everybody') { return true; } if ($this->securityContext->canBeInitialized()) { return $this->securityContext->hasRole($roleIdentifier); } return false; }
/** * Create an action request from stored route match values and dispatch to that * * @param ComponentContext $componentContext * @return void */ public function handle(ComponentContext $componentContext) { $httpRequest = $componentContext->getHttpRequest(); /** @var $actionRequest ActionRequest */ $actionRequest = $this->objectManager->get(ActionRequest::class, $httpRequest); $this->securityContext->setRequest($actionRequest); $routingMatchResults = $componentContext->getParameter(Routing\RoutingComponent::class, 'matchResults'); $actionRequest->setArguments($this->mergeArguments($httpRequest, $routingMatchResults)); $this->setDefaultControllerAndActionNameIfNoneSpecified($actionRequest); $componentContext->setParameter(self::class, 'actionRequest', $actionRequest); $this->dispatcher->dispatch($actionRequest, $componentContext->getHttpResponse()); }
/** * @param NodeInterface $node * @return string * @throws NeosException */ public function render(NodeInterface $node) { if ($this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess') === false) { return ''; } /** @var $actionRequest ActionRequest */ $actionRequest = $this->controllerContext->getRequest(); $innerView = new StandaloneView($actionRequest); $innerView->setTemplatePathAndFilename('resource://Neos.Neos/Private/Templates/Backend/Content/Container.html'); $innerView->setFormat('html'); $innerView->setPartialRootPath('resource://Neos.Neos/Private/Partials'); $user = $this->partyService->getAssignedPartyOfAccount($this->securityContext->getAccount()); $innerView->assignMultiple(array('node' => $node, 'modules' => $this->menuHelper->buildModuleList($this->controllerContext), 'sites' => $this->menuHelper->buildSiteList($this->controllerContext), 'user' => $user)); return $innerView->render(); }
/** * @test */ public function getContextHashReturnsStaticStringIfAuthorizationChecksAreDisabled() { $self = $this; $this->securityContext->withoutAuthorizationChecks(function () use($self) { $self->assertSame(Context::CONTEXT_HASH_UNINITIALIZED, $self->securityContext->getContextHash()); }); }
/** * Sends the given HTTP request * * @param Http\Request $httpRequest * @return Http\Response * @throws Http\Exception * @api */ public function sendRequest(Http\Request $httpRequest) { $requestHandler = $this->bootstrap->getActiveRequestHandler(); if (!$requestHandler instanceof FunctionalTestRequestHandler) { throw new Http\Exception('The browser\'s internal request engine has only been designed for use within functional tests.', 1335523749); } $this->securityContext->clearContext(); $this->validatorResolver->reset(); $response = new Http\Response(); $componentContext = new ComponentContext($httpRequest, $response); $requestHandler->setComponentContext($componentContext); $objectManager = $this->bootstrap->getObjectManager(); $baseComponentChain = $objectManager->get(\Neos\Flow\Http\Component\ComponentChain::class); $componentContext = new ComponentContext($httpRequest, $response); try { $baseComponentChain->handle($componentContext); } catch (\Throwable $throwable) { $this->prepareErrorResponse($throwable, $componentContext->getHttpResponse()); } catch (\Exception $exception) { $this->prepareErrorResponse($exception, $componentContext->getHttpResponse()); } $session = $this->bootstrap->getObjectManager()->get(SessionInterface::class); if ($session->isStarted()) { $session->close(); } $this->persistenceManager->clearState(); return $componentContext->getHttpResponse(); }
/** * Returns the static value of the given operand, this might be also a global object * * @param mixed $expression The expression string representing the operand * @return mixed The calculated value */ public function getValueForOperand($expression) { if (is_array($expression)) { $result = []; foreach ($expression as $expressionEntry) { $result[] = $this->getValueForOperand($expressionEntry); } return $result; } elseif (is_numeric($expression)) { return $expression; } elseif ($expression === true) { return true; } elseif ($expression === false) { return false; } elseif ($expression === null) { return null; } elseif (strpos($expression, 'context.') === 0) { $objectAccess = explode('.', $expression, 3); $globalObjectsRegisteredClassName = $this->globalObjects[$objectAccess[1]]; $globalObject = $this->objectManager->get($globalObjectsRegisteredClassName); $this->securityContext->withoutAuthorizationChecks(function () use($globalObject, $objectAccess, &$globalObjectValue) { $globalObjectValue = $this->getObjectValueByPath($globalObject, $objectAccess[2]); }); return $globalObjectValue; } else { return trim($expression, '"\''); } }
/** * @test */ public function handleSetsRequestInSecurityContext() { $this->mockHttpRequest->expects($this->any())->method('getArguments')->will($this->returnValue([])); $this->mockPropertyMapper->expects($this->any())->method('convert')->with('', 'array', $this->mockPropertyMappingConfiguration)->will($this->returnValue([])); $this->mockSecurityContext->expects($this->once())->method('setRequest')->with($this->mockActionRequest); $this->dispatchComponent->handle($this->mockComponentContext); }
/** * @test * @todo adjust when AfterInvocationInterceptor is used again */ public function enforcePolicyDoesNotInvokeInterceptorIfAuthorizationChecksAreDisabled() { $this->mockAdviceChain->expects($this->once())->method('proceed')->with($this->mockJoinPoint); $this->mockJoinPoint->expects($this->once())->method('getAdviceChain')->will($this->returnValue($this->mockAdviceChain)); $this->mockSecurityContext->expects($this->atLeastOnce())->method('areAuthorizationChecksDisabled')->will($this->returnValue(true)); $this->mockPolicyEnforcementInterceptor->expects($this->never())->method('invoke'); $this->policyEnforcementAspect->enforcePolicy($this->mockJoinPoint); }
/** * Matches a \Neos\Flow\Mvc\RequestInterface against the configured CSRF pattern rules and * searches for invalid csrf tokens. If this returns TRUE, the request is invalid! * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws AuthenticationRequiredException */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest || $request->getHttpRequest()->isMethodSafe()) { $this->systemLogger->log('CSRF: No token required, safe request', LOG_DEBUG); return false; } if ($this->authenticationManager->isAuthenticated() === false) { $this->systemLogger->log('CSRF: No token required, not authenticated', LOG_DEBUG); return false; } if ($this->securityContext->areAuthorizationChecksDisabled() === true) { $this->systemLogger->log('CSRF: No token required, authorization checks are disabled', LOG_DEBUG); return false; } $controllerClassName = $this->objectManager->getClassNameByObjectName($request->getControllerObjectName()); $actionMethodName = $request->getControllerActionName() . 'Action'; if (!$this->hasPolicyEntryForMethod($controllerClassName, $actionMethodName)) { $this->systemLogger->log(sprintf('CSRF: No token required, method %s::%s() is not restricted by a policy.', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; } if ($this->reflectionService->isMethodTaggedWith($controllerClassName, $actionMethodName, 'skipcsrfprotection')) { $this->systemLogger->log(sprintf('CSRF: No token required, method %s::%s() is tagged with a "skipcsrfprotection" annotation', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; } $httpRequest = $request->getHttpRequest(); if ($httpRequest->hasHeader('X-Flow-Csrftoken')) { $csrfToken = $httpRequest->getHeader('X-Flow-Csrftoken'); } else { $internalArguments = $request->getMainRequest()->getInternalArguments(); $csrfToken = isset($internalArguments['__csrfToken']) ? $internalArguments['__csrfToken'] : null; } if (empty($csrfToken)) { $this->systemLogger->log(sprintf('CSRF: token was empty but a valid token is required for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return true; } if (!$this->securityContext->hasCsrfProtectionTokens()) { throw new AuthenticationRequiredException(sprintf('CSRF: No CSRF tokens in security context, possible session timeout. A valid token is required for %s::%s()', $controllerClassName, $actionMethodName), 1317309673); } if ($this->securityContext->isCsrfProtectionTokenValid($csrfToken) === false) { $this->systemLogger->log(sprintf('CSRF: token was invalid but a valid token is required for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return true; } $this->systemLogger->log(sprintf('CSRF: Successfully verified token for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; }
/** * Returns a string message, giving insights what happened during privilege evaluation. * * @param string $privilegeReasonMessage * @return string */ protected function renderDecisionReasonMessage($privilegeReasonMessage) { if (count($this->securityContext->getRoles()) === 0) { $rolesMessage = 'No authenticated roles'; } else { $rolesMessage = 'Authenticated roles: ' . implode(', ', array_keys($this->securityContext->getRoles())); } return sprintf('Access denied for method' . chr(10) . 'Method: %s::%s()' . chr(10) . chr(10) . '%s' . chr(10) . chr(10) . '%s', $this->joinPoint->getClassName(), $this->joinPoint->getMethodName(), $privilegeReasonMessage, $rolesMessage); }
/** * Prepares the environment for and conducts an account authentication * * @param \Neos\Flow\Security\Account $account * @return void * @api */ protected function authenticateAccount(\Neos\Flow\Security\Account $account) { $this->testingProvider->setAuthenticationStatus(\Neos\Flow\Security\Authentication\TokenInterface::AUTHENTICATION_SUCCESSFUL); $this->testingProvider->setAccount($account); $this->securityContext->clearContext(); $requestHandler = self::$bootstrap->getActiveRequestHandler(); $actionRequest = $this->route($requestHandler->getHttpRequest()); $this->securityContext->setRequest($actionRequest); $this->authenticationManager->authenticate(); }
/** * @test */ public function csrfTokenFieldIsRenderedForUnsafeRequests() { /** @var FormViewHelper|\PHPUnit_Framework_MockObject_MockObject $viewHelper */ $viewHelper = $this->getAccessibleMock(\Neos\FluidAdaptor\ViewHelpers\FormViewHelper::class, null, array(), '', false); $this->injectDependenciesIntoViewHelper($viewHelper); $this->securityContext->expects($this->any())->method('isInitialized')->will($this->returnValue(true)); $this->mockAuthenticationManager->expects($this->any())->method('isAuthenticated')->will($this->returnValue(true)); $this->securityContext->expects($this->atLeastOnce())->method('getCsrfProtectionToken')->will($this->returnValue('CSRFTOKEN')); $this->assertEquals('<input type="hidden" name="__csrfToken" value="CSRFTOKEN" />' . chr(10), $viewHelper->_call('renderCsrfTokenField')); }
/** * Calls the authentication manager to authenticate all active tokens * and redirects to the original intercepted request on success if there * is one stored in the security context. If no intercepted request is * found, the function simply returns. * * If authentication fails, the result of calling the defined * $errorMethodName is returned. * * Note: Usually there is no need to override this action. You should use * the according callback methods instead (onAuthenticationSuccess() and * onAuthenticationFailure()). * * @return string * @Flow\SkipCsrfProtection */ public function authenticateAction() { $authenticationException = null; try { $this->authenticationManager->authenticate(); } catch (AuthenticationRequiredException $exception) { $authenticationException = $exception; } if ($this->authenticationManager->isAuthenticated()) { $storedRequest = $this->securityContext->getInterceptedRequest(); if ($storedRequest !== null) { $this->securityContext->setInterceptedRequest(null); } return $this->onAuthenticationSuccess($storedRequest); } else { $this->onAuthenticationFailure($authenticationException); return call_user_func([$this, $this->errorMethodName]); } }
/** * Returns a node from the given $nodeIdentifier (disabling authorization checks) * * @param string $nodeIdentifier * @return NodeInterface */ protected function getNodeByIdentifier($nodeIdentifier) { $context = $this->contextFactory->create(); $node = null; $this->securityContext->withoutAuthorizationChecks(function () use($nodeIdentifier, $context, &$node) { $node = $context->getNodeByIdentifier($nodeIdentifier); }); $context->getFirstLevelNodeCache()->setByIdentifier($nodeIdentifier, null); return $node; }
/** * Render the a hidden field with a CSRF token * * @return string the CSRF token field */ protected function renderCsrfTokenField() { if (strtolower($this->arguments['method']) === 'get') { return ''; } if (!$this->securityContext->isInitialized() || !$this->authenticationManager->isAuthenticated()) { return ''; } $csrfToken = $this->securityContext->getCsrfProtectionToken(); return '<input type="hidden" name="__csrfToken" value="' . htmlspecialchars($csrfToken) . '" />' . chr(10); }
/** * @test */ public function isPrivilegeTargetGrantedReturnsTrueIfThereIsNoDenyVoteAndOneGrantVote() { $mockRole1 = $this->getMockBuilder(Security\Policy\Role::class)->disableOriginalConstructor()->getMock(); $mockRole1->expects($this->any())->method('getPrivilegeForTarget')->will($this->returnValue($this->abstainPrivilege)); $mockRole2 = $this->getMockBuilder(Security\Policy\Role::class)->disableOriginalConstructor()->getMock(); $mockRole2->expects($this->any())->method('getPrivilegeForTarget')->will($this->returnValue($this->grantPrivilege)); $mockRole3 = $this->getMockBuilder(Security\Policy\Role::class)->disableOriginalConstructor()->getMock(); $mockRole3->expects($this->any())->method('getPrivilegeForTarget')->will($this->returnValue($this->abstainPrivilege)); $this->mockSecurityContext->expects($this->any())->method('getRoles')->will($this->returnValue([$mockRole1, $mockRole2, $mockRole3])); $this->assertTrue($this->privilegeManager->isPrivilegeTargetGranted('somePrivilegeTargetIdentifier')); }
/** * @test */ public function logoutRefreshesTokensInSecurityContext() { $this->authenticationProviderManager = $this->getAccessibleMock(AuthenticationProviderManager::class, ['emitLoggedOut'], [], '', false); $this->inject($this->authenticationProviderManager, 'securityContext', $this->mockSecurityContext); $this->inject($this->authenticationProviderManager, 'session', $this->mockSession); $this->mockSession->expects($this->any())->method('canBeResumed')->will($this->returnValue(true)); $this->mockSession->expects($this->any())->method('isStarted')->will($this->returnValue(true)); $token = $this->getMockBuilder(TokenInterface::class)->disableOriginalConstructor()->getMock(); $token->expects($this->any())->method('isAuthenticated')->will($this->returnValue(true)); $this->mockSecurityContext->expects($this->any())->method('getAuthenticationTokens')->will($this->returnValue([$token])); $this->mockSecurityContext->expects($this->once())->method('refreshTokens'); $this->authenticationProviderManager->logout(); }
/** * @test */ public function handleInjectsActionRequestToSecurityContext() { $mockWidgetId = 'SomeWidgetId'; $mockControllerObjectName = 'SomeControllerObjectName'; $this->mockHttpRequest->expects($this->at(0))->method('hasArgument')->with('__widgetId')->will($this->returnValue(true)); $this->mockHttpRequest->expects($this->atLeastOnce())->method('getArgument')->with('__widgetId')->will($this->returnValue($mockWidgetId)); $mockWidgetContext = $this->getMockBuilder(\Neos\FluidAdaptor\Core\Widget\WidgetContext::class)->getMock(); $mockWidgetContext->expects($this->atLeastOnce())->method('getControllerObjectName')->will($this->returnValue($mockControllerObjectName)); $this->mockAjaxWidgetContextHolder->expects($this->atLeastOnce())->method('get')->with($mockWidgetId)->will($this->returnValue($mockWidgetContext)); $mockActionRequest = $this->getMockBuilder(\Neos\Flow\Mvc\ActionRequest::class)->disableOriginalConstructor()->getMock(); $this->mockObjectManager->expects($this->atLeastOnce())->method('get')->with(\Neos\Flow\Mvc\ActionRequest::class)->will($this->returnValue($mockActionRequest)); $this->mockSecurityContext->expects($this->once())->method('setRequest')->with($mockActionRequest); $this->ajaxWidgetComponent->handle($this->mockComponentContext); }
/** * Calls a behat step method * * @Flow\Internal * @param string $testHelperObjectName * @param string $methodName * @param boolean $withoutSecurityChecks */ public function callBehatStepCommand($testHelperObjectName, $methodName, $withoutSecurityChecks = false) { $testHelper = $this->objectManager->get($testHelperObjectName); $rawMethodArguments = $this->request->getExceedingArguments(); $mappedArguments = []; for ($i = 0; $i < count($rawMethodArguments); $i += 2) { $mappedArguments[] = $this->propertyMapper->convert($rawMethodArguments[$i + 1], $rawMethodArguments[$i]); } $result = null; try { if ($withoutSecurityChecks === true) { $this->securityContext->withoutAuthorizationChecks(function () use($testHelper, $methodName, $mappedArguments, &$result) { $result = call_user_func_array([$testHelper, $methodName], $mappedArguments); }); } else { $result = call_user_func_array([$testHelper, $methodName], $mappedArguments); } } catch (\Exception $exception) { $this->outputLine('EXCEPTION: %s %d %s in %s:%s %s', [get_class($exception), $exception->getCode(), $exception->getMessage(), $exception->getFile(), $exception->getLine(), $exception->getTraceAsString()]); return; } $this->output('SUCCESS: %s', [$result]); }
/** * Logout all active authentication tokens * * @return void */ public function logout() { if ($this->isAuthenticated() !== true) { return; } $this->isAuthenticated = null; /** @var $token TokenInterface */ foreach ($this->securityContext->getAuthenticationTokens() as $token) { $token->setAuthenticationStatus(TokenInterface::NO_CREDENTIALS_GIVEN); } $this->emitLoggedOut(); if ($this->session->isStarted()) { $this->session->destroy('Logout through AuthenticationProviderManager'); } $this->securityContext->refreshTokens(); }
/** * Renders an identifier for a content cache entry * * @param string $typoScriptPath * @param array $cacheIdentifierValues * @return string An MD5 hash built from the typoScriptPath and certain elements of the given identifier values * @throws CacheException If an invalid entry identifier value is given */ protected function renderContentCacheEntryIdentifier($typoScriptPath, array $cacheIdentifierValues) { ksort($cacheIdentifierValues); $identifierSource = ''; foreach ($cacheIdentifierValues as $key => $value) { if ($value instanceof CacheAwareInterface) { $identifierSource .= $key . '=' . $value->getCacheEntryIdentifier() . '&'; } elseif (is_string($value) || is_bool($value) || is_integer($value)) { $identifierSource .= $key . '=' . $value . '&'; } elseif ($value !== null) { throw new CacheException(sprintf('Invalid cache entry identifier @cache.entryIdentifier.%s for path "%s". A entry identifier value must be a string or implement CacheAwareInterface.', $key, $typoScriptPath), 1395846615); } } $identifierSource .= 'securityContextHash=' . $this->securityContext->getContextHash(); return md5($typoScriptPath . '@' . $identifierSource); }
/** * Gets the SQL query part to add to a query. * * @param ClassMetaData $targetEntity Metadata object for the target entity to be filtered * @param string $targetTableAlias The target table alias used in the current query * @return string The constraint SQL if there is available, empty string otherwise */ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) { $this->initializeDependencies(); /* * TODO: Instead of checking for class account we could introduce some interface for white listing entities from entity security checks * Problem with checking the Account is, that this filter calls getRoles() on the security context while accounts are not * yet fully initialized. By this we get a half built account object that will end up in access denied exception, * as it has no roles (and other properties) set */ if ($this->securityContext->areAuthorizationChecksDisabled() || $targetEntity->getName() === Account::class) { return ''; } if (!$this->securityContext->isInitialized()) { if (!$this->securityContext->canBeInitialized()) { return ''; } $this->securityContext->initialize(); } // This is needed to include the current context of roles into query cache identifier $this->setParameter('__contextHash', $this->securityContext->getContextHash(), 'string'); $sqlConstraints = []; $grantedConstraints = []; $deniedConstraints = []; foreach ($this->securityContext->getRoles() as $role) { $entityPrivileges = $role->getPrivilegesByType(EntityPrivilegeInterface::class); /** @var EntityPrivilegeInterface $privilege */ foreach ($entityPrivileges as $privilege) { if (!$privilege->matchesEntityType($targetEntity->getName())) { continue; } $sqlConstraint = $privilege->getSqlConstraint($targetEntity, $targetTableAlias); if ($sqlConstraint === null) { continue; } $sqlConstraints[] = ' NOT (' . $sqlConstraint . ')'; if ($privilege->isGranted()) { $grantedConstraints[] = ' NOT (' . $sqlConstraint . ')'; } elseif ($privilege->isDenied()) { $deniedConstraints[] = ' NOT (' . $sqlConstraint . ')'; } } } $grantedConstraints = array_diff($grantedConstraints, $deniedConstraints); $effectiveConstraints = array_diff($sqlConstraints, $grantedConstraints); if (count($effectiveConstraints) > 0) { return ' (' . implode(') AND (', $effectiveConstraints) . ') '; } return ''; }
/** * Filter a node by the current context. * Will either return the node or NULL if it is not permitted in current context. * * @param NodeInterface $node * @param Context $context * @return NodeInterface|NULL */ protected function filterNodeByContext(NodeInterface $node, Context $context) { $this->securityContext->withoutAuthorizationChecks(function () use(&$node, $context) { if (!$context->isRemovedContentShown() && $node->isRemoved()) { $node = null; return; } if (!$context->isInvisibleContentShown() && !$node->isVisible()) { $node = null; return; } if (!$context->isInaccessibleContentShown() && !$node->isAccessible()) { $node = null; } }); return $node; }
/** * @param array $module * @return mixed * @throws DisabledModuleException */ public function indexAction(array $module) { $moduleRequest = new ActionRequest($this->request); $moduleRequest->setArgumentNamespace('moduleArguments'); $moduleRequest->setControllerObjectName($module['controller']); $moduleRequest->setControllerActionName($module['action']); if (isset($module['format'])) { $moduleRequest->setFormat($module['format']); } if ($this->request->hasArgument($moduleRequest->getArgumentNamespace()) === true && is_array($this->request->getArgument($moduleRequest->getArgumentNamespace()))) { $moduleRequest->setArguments($this->request->getArgument($moduleRequest->getArgumentNamespace())); } foreach ($this->request->getPluginArguments() as $argumentNamespace => $argument) { $moduleRequest->setArgument('--' . $argumentNamespace, $argument); } $modules = explode('/', $module['module']); $moduleConfiguration = Arrays::getValueByPath($this->settings['modules'], implode('.submodules.', $modules)); $moduleConfiguration['path'] = $module['module']; if (!$this->menuHelper->isModuleEnabled($moduleConfiguration['path'])) { throw new DisabledModuleException(sprintf('The module "%s" is disabled. You can enable it with the "enabled" flag in Settings.yaml.', $module['module']), 1437148922); } $moduleBreadcrumb = array(); $path = array(); foreach ($modules as $moduleIdentifier) { array_push($path, $moduleIdentifier); $config = Arrays::getValueByPath($this->settings['modules'], implode('.submodules.', $path)); $moduleBreadcrumb[implode('/', $path)] = $config; } $moduleRequest->setArgument('__moduleConfiguration', $moduleConfiguration); $moduleResponse = new Response($this->response); $this->dispatcher->dispatch($moduleRequest, $moduleResponse); if ($moduleResponse->hasHeader('Location')) { $this->redirectToUri($moduleResponse->getHeader('Location'), 0, $moduleResponse->getStatusCode()); } elseif ($moduleRequest->getFormat() !== 'html') { $mediaType = MediaTypes::getMediaTypeFromFilename('file.' . $moduleRequest->getFormat()); if ($mediaType !== 'application/octet-stream') { $this->controllerContext->getResponse()->setHeader('Content-Type', $mediaType); } return $moduleResponse->getContent(); } else { $user = $this->partyService->getAssignedPartyOfAccount($this->securityContext->getAccount()); $sites = $this->menuHelper->buildSiteList($this->controllerContext); $this->view->assignMultiple(array('moduleClass' => implode('-', $modules), 'moduleContents' => $moduleResponse->getContent(), 'title' => $moduleRequest->hasArgument('title') ? $moduleRequest->getArgument('title') : $moduleConfiguration['label'], 'rootModule' => array_shift($modules), 'submodule' => array_shift($modules), 'moduleConfiguration' => $moduleConfiguration, 'moduleBreadcrumb' => $moduleBreadcrumb, 'user' => $user, 'modules' => $this->menuHelper->buildModuleList($this->controllerContext), 'sites' => $sites)); } }
/** * @test */ public function dispatchCallsStartAuthenticationOnAllActiveEntryPoints() { $this->mockActionRequest->expects($this->any())->method('isDispatched')->will($this->returnValue(true)); $mockAuthenticationToken1 = $this->getMockBuilder(TokenInterface::class)->getMock(); $mockEntryPoint1 = $this->getMockBuilder(EntryPointInterface::class)->getMock(); $mockAuthenticationToken1->expects($this->any())->method('getAuthenticationEntryPoint')->will($this->returnValue($mockEntryPoint1)); $mockAuthenticationToken2 = $this->getMockBuilder(TokenInterface::class)->getMock(); $mockEntryPoint2 = $this->getMockBuilder(EntryPointInterface::class)->getMock(); $mockAuthenticationToken2->expects($this->any())->method('getAuthenticationEntryPoint')->will($this->returnValue($mockEntryPoint2)); $this->mockSecurityContext->expects($this->atLeastOnce())->method('getAuthenticationTokens')->will($this->returnValue([$mockAuthenticationToken1, $mockAuthenticationToken2])); $this->mockFirewall->expects($this->once())->method('blockIllegalRequests')->will($this->throwException(new AuthenticationRequiredException())); $mockEntryPoint1->expects($this->once())->method('startAuthentication')->with($this->mockHttpRequest, $this->mockHttpResponse); $mockEntryPoint2->expects($this->once())->method('startAuthentication')->with($this->mockHttpRequest, $this->mockHttpResponse); try { $this->dispatcher->dispatch($this->mockActionRequest, $this->mockHttpResponse); } catch (AuthenticationRequiredException $exception) { } }