/** * Add the Annotated Method to the Navigation * * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint * @FLOW3\Before("method(protected TYPO3\Fluid\View\TemplateView->getLayoutPathAndFilename(.*))") * @return void */ public function addNavigationitem(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) { $layout = $joinPoint->getMethodArgument("layoutName"); if (stristr($layout, "resource://")) { $joinPoint->getProxy()->setLayoutPathAndFilename($layout); } }
/** * Add the Annotated Method to the Navigation * * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint * @FLOW3\Before("method(public .*\Controller\.*Controller->.*Action(.*))") * @return void */ public function addNavigationitem(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) { $currentClassName = $joinPoint->getClassName(); $currentMethodName = $joinPoint->getMethodName(); $controllers = $this->reflectionService->getAllSubClassNamesForClass("\\TYPO3\\FLOW3\\MVC\\Controller\\ActionController"); foreach ($controllers as $className) { $methods = get_class_methods($className); if (is_array($methods)) { foreach ($methods as $methodName) { if ($this->reflectionService->isMethodAnnotatedWith($className, $methodName, "Admin\\Annotations\\Navigation")) { $annotations = $this->reflectionService->getMethodAnnotations($className, $methodName, "Admin\\Annotations\\Navigation"); foreach ($annotations as $annotation) { $action = str_replace("Action", "", $methodName); $controller = $this->helper->getControllerByClassName($className); $package = $this->objectManager->getPackageKeyByObjectName($className); $arguments = array("action" => $action, "controller" => $controller, "package" => $package); $title = !is_null($annotation->title) ? $annotation->title : sprintf("%s (%s)", $controller, $action); \Admin\Core\API::addNavigationitem($title, $annotation->position, $arguments, $annotation->priority, $annotation->parent); } } } } } $settings = $this->helper->getSettings("Admin.Navigation"); foreach ($settings as $position => $items) { foreach ($items as $title => $conf) { $priority = isset($conf["priority"]) ? $conf["priority"] : 100; $arguments = $conf["Arguments"]; \Admin\Core\API::addNavigationitem($title, strtolower($position), $arguments, $priority); } } }
/** * Logs exceptional results of the NodeService's getNodeByContextNodePath() method which is called by FrontendNodeRoutePartHandler::matchValue() * * @FLOW3\AfterThrowing("method(TYPO3\TYPO3\Service\NodeService->getNodeByContextNodePath())") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return void */ public function logFailedMatch(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $relativeContextNodePath = $joinPoint->getMethodArgument('relativeContextNodePath'); $exception = $joinPoint->getException(); if ($exception !== NULL) { $this->systemLogger->log(sprintf('%s failed to retrieve a node for path "%s" with message: %s', $joinPoint->getClassName(), $relativeContextNodePath, $exception->getMessage()), LOG_INFO); } }
/** * Before advice, making sure we initialize before use. * * This expects $proxy->FLOW3_Persistence_LazyLoadingObject_thawProperties * to be a Closure that populates the object. That variable is unset after * initializing the object! * * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return void * @FLOW3\Before("TYPO3\FLOW3\Persistence\Generic\Aspect\LazyLoadingObjectAspect->needsLazyLoadingObjectAspect && !method(.*->__construct())") */ public function initialize(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); if (property_exists($proxy, 'FLOW3_Persistence_LazyLoadingObject_thawProperties') && $proxy->FLOW3_Persistence_LazyLoadingObject_thawProperties instanceof \Closure) { $proxy->FLOW3_Persistence_LazyLoadingObject_thawProperties->__invoke($proxy); unset($proxy->FLOW3_Persistence_LazyLoadingObject_thawProperties); } }
/** * Convert the object to its context path, if we deal with TYPO3CR nodes. * * @FLOW3\Around("method(TYPO3\FLOW3\Persistence\AbstractPersistenceManager->convertObjectToIdentityArray())") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint the joinpoint * @return string|array the context path to be used for routing */ public function convertNodeToContextPathForRouting(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $objectArgument = $joinPoint->getMethodArgument('object'); if ($objectArgument instanceof NodeInterface) { return $objectArgument->getContextPath(); } else { return $joinPoint->getAdviceChain()->proceed($joinPoint); } }
/** * Logs calls of renewId() * * @FLOW3\Around("within(TYPO3\FLOW3\Session\SessionInterface) && method(.*->renewId())") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current joinpoint * @return mixed The result of the target method if it has not been intercepted */ public function logRenewId(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $session = $joinPoint->getProxy(); $newId = $joinPoint->getAdviceChain()->proceed($joinPoint); if ($session->isStarted()) { $oldId = $session->getId(); $this->systemLogger->log(sprintf('Changed session id from %s to %s', $oldId, $newId), LOG_DEBUG); } return $newId; }
/** * Around advice, wrapping every method of a scope session object. It redirects * all method calls to the session object once there is one. * * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return mixed * @FLOW3\Around("filter(TYPO3\FLOW3\Session\Aspect\SessionObjectMethodsPointcutFilter)") */ public function callMethodOnOriginalSessionObject(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $objectName = $this->objectManager->getObjectNameByClassName(get_class($joinPoint->getProxy())); $methodName = $joinPoint->getMethodName(); $proxy = $joinPoint->getProxy(); if (!isset($this->sessionOriginalInstances[$objectName])) { $this->sessionOriginalInstances[$objectName] = $this->objectManager->get($objectName); } if ($this->sessionOriginalInstances[$objectName] === $proxy) { return $joinPoint->getAdviceChain()->proceed($joinPoint); } else { return call_user_func_array(array($this->sessionOriginalInstances[$objectName], $methodName), $joinPoint->getMethodArguments()); } }
/** * This is the default Policy voter, it votes for the access privilege for the given join point * * @param TYPO3\FLOW3\Security\Context $securityContext The current securit context * @param TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint The joinpoint to vote for * @return integer One of: VOTE_GRANT, VOTE_ABSTAIN, VOTE_DENY */ public function voteForJoinPoint(\TYPO3\FLOW3\Security\Context $securityContext, \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); if ($proxy instanceof \Admin\Controller\StandardController) { $arguments = $joinPoint->getMethodArguments(); if (isset($arguments["being"])) { $arguments["action"] = $proxy->getAction(); if ($arguments["action"] == "list") { $arguments["action"] = "view"; } #\dump($arguments, __FILE__ . ":" . __LINE__); $accessGrants = 0; $accessDenies = 0; foreach ($securityContext->getAuthenticationTokens() as $token) { if (is_callable(array($token, "getUser"))) { $user = $token->getUser(); if ($user->getAdmin()) { return self::VOTE_GRANT; } foreach ($user->getRoles() as $role) { foreach ($role->getGrant() as $policy) { if ($this->comparePolicy($arguments, $policy)) { $accessGrants++; } } #foreach ($role->getDeny() as $policy) { # if($this->comparePolicy($arguments, $policy)) $accessDenies++; #} } } } if ($accessDenies > 0) { return self::VOTE_DENY; } if ($accessGrants > 0) { return self::VOTE_GRANT; } } else { return self::VOTE_ABSTAIN; } } return self::VOTE_ABSTAIN; }
/** * @test */ public function cacheResolveCallSkipsCacheIfRouteValuesContainObjectsThatCantBeConvertedToHashes() { $mockObject = new \stdClass(); $routeValues = array('b' => 'route values', 'someObject' => $mockObject); $this->mockJoinPoint->expects($this->once())->method('getMethodArgument')->with('routeValues')->will($this->returnValue($routeValues)); $this->mockPersistenceManager->expects($this->once())->method('getIdentifierByObject')->with($mockObject)->will($this->returnValue(NULL)); $matchingUri = 'uncached/matching/uri'; $this->mockAdviceChain->expects($this->once())->method('proceed')->with($this->mockJoinPoint)->will($this->returnValue($matchingUri)); $this->mockResolveCache->expects($this->never())->method('has'); $this->mockResolveCache->expects($this->never())->method('set'); $this->routerCachingAspect->cacheResolveCall($this->mockJoinPoint); }
/** * Adds a CSRF token as argument in the URI builder * * @FLOW3\Before("setting(TYPO3.FLOW3.security.enable) && method(TYPO3\FLOW3\Mvc\Routing\UriBuilder->build())") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return void */ public function addCsrfTokenToUri(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $uriBuilder = $joinPoint->getProxy(); $arguments = $joinPoint->getMethodArgument('arguments'); $packageKey = isset($arguments['@package']) ? $arguments['@package'] : ''; $subpackageKey = isset($arguments['@subpackage']) ? $arguments['@subpackage'] : ''; $controllerName = isset($arguments['@controller']) ? $arguments['@controller'] : 'Standard'; $actionName = (isset($arguments['@action']) ? $arguments['@action'] : 'index') . 'Action'; $possibleObjectName = '@package\\@subpackage\\Controller\\@controllerController'; $possibleObjectName = str_replace('@package', str_replace('.', '\\', $packageKey), $possibleObjectName); $possibleObjectName = str_replace('@subpackage', $subpackageKey, $possibleObjectName); $possibleObjectName = str_replace('@controller', $controllerName, $possibleObjectName); $possibleObjectName = str_replace('\\\\', '\\', $possibleObjectName); $lowercaseObjectName = strtolower($possibleObjectName); $className = $this->objectManager->getClassNameByObjectName($this->objectManager->getCaseSensitiveObjectName($lowercaseObjectName)); if ($this->policyService->hasPolicyEntryForMethod($className, $actionName) && !$this->reflectionService->isMethodAnnotatedWith($className, $actionName, 'TYPO3\\FLOW3\\Annotations\\SkipCsrfProtection')) { $internalArguments = $uriBuilder->getArguments(); $internalArguments['__csrfToken'] = $this->securityContext->getCsrfProtectionToken(); $uriBuilder->setArguments($internalArguments); } }
/** * Advices the dispatch method so that illegal requests are blocked before invoking * any controller. * * @FLOW3\Around("method(TYPO3\FLOW3\MVC\Dispatcher->dispatch())") * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint The current joinpoint * @return mixed Result of the advice chain */ public function checkAccess(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) { $this->securityManager->setRequest($joinPoint->getMethodArgument('request')); $this->securityManager->setResponse($joinPoint->getMethodArgument('response')); $request = $joinPoint->getMethodArgument('request'); if (is_a($request, "\\TYPO3\\FLOW3\\MVC\\Web\\Request")) { $className = $request->getControllerObjectName(); $methodName = $request->getControllerActionName() . 'Action'; try { if (!empty($className) && $this->reflectionService->isMethodAnnotatedWith($className, $methodName, "Admin\\Annotations\\Access")) { $annotation = $this->reflectionService->getMethodAnnotation($className, $methodName, "Admin\\Annotations\\Access"); if (!is_object($user = $this->securityManager->getUser())) { return $this->securityManager->redirectToLogin($joinPoint); } if ($annotation->admin && !$user->isAdmin()) { return $this->securityManager->redirectToLogin($joinPoint); } if ($annotation->role !== null) { $hasRole = false; foreach ($user->getRoles() as $role) { if ($role->getName() == $annotation->role) { $hasRole = true; } } if (!$hasRole) { $message = new \TYPO3\FLOW3\Error\Error("You don't have access to this page!"); $this->flashMessageContainer->addMessage($message); return $this->securityManager->redirectToLogin($joinPoint); } } } } catch (\Exception $e) { } } if (is_object($adviceChain = $joinPoint->getAdviceChain())) { $result = $adviceChain->proceed($joinPoint); return $result; } }
/** * Advices the dispatch method so that access denied exceptions are transformed into the correct * response status. * * @FLOW3\Around("setting(TYPO3.FLOW3.security.enable) && method(TYPO3\FLOW3\Mvc\Dispatcher->dispatch())") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current joinpoint * @return mixed Result of the advice chain */ public function setAccessDeniedResponseHeader(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $response = $joinPoint->getMethodArgument('response'); try { return $joinPoint->getAdviceChain()->proceed($joinPoint); } catch (\TYPO3\FLOW3\Security\Exception\AccessDeniedException $exception) { if ($response instanceof \TYPO3\FLOW3\Http\Response) { $response->setStatus(403); } $response->setContent('Access denied!'); } }
/** * Returns the publish path and filename to be used to publish the specified persistent resource * * @FLOW3\Around("method(TYPO3\FLOW3\Resource\Publishing\FileSystemPublishingTarget->buildPersistentResourcePublishPathAndFilename()) && setting(TYPO3.FLOW3.security.enable)") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return mixed Result of the target method */ public function rewritePersistentResourcePublishPathAndFilenameForPrivateResources(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $resource = $joinPoint->getMethodArgument('resource'); $configuration = $resource->getPublishingConfiguration(); $returnFilename = $joinPoint->getMethodArgument('returnFilename'); if ($configuration === NULL || $configuration instanceof \TYPO3\FLOW3\Security\Authorization\Resource\SecurityPublishingConfiguration === FALSE) { return $joinPoint->getAdviceChain()->proceed($joinPoint); } $publishingPath = FALSE; $allowedRoles = $configuration->getAllowedRoles(); if (count(array_intersect($allowedRoles, $this->securityContext->getRoles())) > 0) { $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($joinPoint->getProxy()->getResourcesPublishingPath(), 'Persistent/', $this->session->getID())) . '/'; $filename = $resource->getResourcePointer()->getHash() . '.' . $resource->getFileExtension(); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($publishingPath); $this->accessRestrictionPublisher->publishAccessRestrictionsForPath($publishingPath); if ($this->settings['resource']['publishing']['fileSystem']['mirrorMode'] === 'link') { foreach ($allowedRoles as $role) { $roleDirectory = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($this->environment->getPathToTemporaryDirectory(), 'PrivateResourcePublishing/', $role)); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($roleDirectory); if (file_exists($publishingPath . $role)) { if (\TYPO3\FLOW3\Utility\Files::is_link(\TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))) && realpath(\TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))) === $roleDirectory) { continue; } unlink($publishingPath . $role); symlink($roleDirectory, \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))); } else { symlink($roleDirectory, \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))); } } $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $allowedRoles[0])) . '/'; } if ($returnFilename === TRUE) { $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $filename)); } } return $publishingPath; }
/** * Mark object as cloned after cloning. * * Note: this is not used by anything in the FLOW3 base distribution, * but might be needed by custom backends (like TYPO3.CouchDB). * * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint * @return void * @FLOW3\AfterReturning("TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicAspect->isEntityOrValueObject && method(.*->__clone())") */ public function cloneObject(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $joinPoint->getProxy()->FLOW3_Persistence_clone = TRUE; }
/** * Returns the privileges a specific role has for the given joinpoint. The returned array * contains the privilege's resource as key of each privilege. * * @param \TYPO3\FLOW3\Security\Policy\Role $role The role for which the privileges should be returned * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The joinpoint for which the privileges should be returned * @return array Array of privileges * @throws \TYPO3\FLOW3\Security\Exception\NoEntryInPolicyException */ public function getPrivilegesForJoinPoint(\TYPO3\FLOW3\Security\Policy\Role $role, \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $methodIdentifier = strtolower($joinPoint->getClassName() . '->' . $joinPoint->getMethodName()); $roleIdentifier = (string) $role; if (!isset($this->acls[$methodIdentifier])) { throw new \TYPO3\FLOW3\Security\Exception\NoEntryInPolicyException('The given joinpoint was not found in the policy cache. Most likely you have to recreate the AOP proxy classes.', 1222100851); } if (!isset($this->acls[$methodIdentifier][$roleIdentifier])) { return array(); } $privileges = array(); foreach ($this->acls[$methodIdentifier][$roleIdentifier] as $resource => $privilegeConfiguration) { if ($privilegeConfiguration['runtimeEvaluationsClosureCode'] !== FALSE) { // Make object manager usable as closure variable $objectManager = $this->objectManager; eval('$runtimeEvaluator = ' . $privilegeConfiguration['runtimeEvaluationsClosureCode'] . ';'); if ($runtimeEvaluator->__invoke($joinPoint) === FALSE) { continue; } } $privileges[$resource] = $privilegeConfiguration['privilege']; } return $privileges; }
/** * Passes the signal over to the Dispatcher * * @FLOW3\AfterReturning("methodAnnotatedWith(TYPO3\FLOW3\Annotations\Signal)") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return void */ public function forwardSignalToDispatcher(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $signalName = lcfirst(str_replace('emit', '', $joinPoint->getMethodName())); $this->dispatcher->dispatch($joinPoint->getClassName(), $signalName, $joinPoint->getMethodArguments()); }
/** * Logs calls and results of decideOnJoinPoint() * * @FLOW3\AfterThrowing("method(TYPO3\FLOW3\Security\Authorization\AccessDecisionVoterManager->decideOnJoinPoint())") * * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint * @throws \Exception * @return void */ public function logJoinPointAccessDecisions(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $exception = $joinPoint->getException(); $subjectJoinPoint = $joinPoint->getMethodArgument('joinPoint'); $message = $exception->getMessage() . ' to method ' . $subjectJoinPoint->getClassName() . '::' . $subjectJoinPoint->getMethodName() . '().'; $this->securityLogger->log($message, \LOG_INFO); throw $exception; }
/** * @FLOW3\AfterReturning("method(TYPO3\FLOW3\Tests\Functional\Aop\Fixtures\TargetClass02->publicTargetMethod())") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint * @return string */ public function anAfterReturningAdvice(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $joinPoint->getProxy()->afterReturningAdviceWasInvoked = TRUE; }