private function getSecureMethodInvocation(MethodMetadata $method) { $code = 'new MethodInvocation(' . var_export($method->getReflection()->getDeclaringClass()->getName(), true) . ', ' . var_export($method->getReflection()->getName(), true) . ', $this' . ', array('; $arguments = array(); foreach ($method->getReflection()->getParameters() as $param) { $arguments[] = '$' . $param->getName(); } $code .= implode(', ', $arguments) . '))'; return $code; }
public function convertMethodAnnotations(\ReflectionMethod $method, array $annotations) { $parameters = array(); foreach ($method->getParameters() as $index => $parameter) { $parameters[$parameter->getName()] = $index; } $methodMetadata = new MethodMetadata($method); foreach ($annotations as $annotation) { if ($annotation instanceof Secure) { $methodMetadata->setRoles($annotation->getRoles()); } else { if ($annotation instanceof SecureParam) { if (!isset($parameters[$annotation->getName()])) { throw new \InvalidArgumentException(sprintf('The parameter "%s" does not exist for method "%s".', $annotation->getName(), $method->getName())); } $methodMetadata->addParamPermissions($parameters[$annotation->getName()], $annotation->getPermissions()); } else { if ($annotation instanceof SecureReturn) { $methodMetadata->addReturnPermissions($annotation->getPermissions()); } else { if ($annotation instanceof SatisfiesParentSecurityPolicy) { $methodMetadata->setSatisfiesParentSecurityPolicy(); } else { if ($annotation instanceof RunAs) { $methodMetadata->setRunAsRoles($annotation->getRoles()); } } } } } } return $methodMetadata; }
/** * @dataProvider getTestData */ public function testGenerate($class, $method, array $arguments) { $generator = new ProxyClassGenerator(); $metadata = new ServiceMetadata(); $reflection = new \ReflectionClass($class); $methodMetadata = new MethodMetadata($reflection->getMethod($method)); $methodMetadata->setRoles(array('ROLE_FOO')); $methodMetadata->setReturnPermissions(array('PERMISSION_RETURN')); $metadata->addMethod($method, $methodMetadata); $definition = new Definition(); $definition->setClass($reflection->getName()); list($className, $proxy) = $generator->generate($definition, $metadata); $tmpFile = tempnam(sys_get_temp_dir(), 'proxy'); file_put_contents($tmpFile, $proxy); require_once $tmpFile; unlink($tmpFile); $className = 'SecurityProxies\\' . $className; $proxyClass = new $className(); $mock = $this->getMockBuilder('JMS\\SecurityExtraBundle\\Security\\Authorization\\Interception\\MethodSecurityInterceptor')->disableOriginalConstructor()->getMock(); $mock->expects($this->once())->method('invoke')->will($this->returnValue($return = new \stdClass())); $proxyClass->jmsSecurityExtraBundle__setMethodSecurityInterceptor($mock); $this->assertSame($return, call_user_func_array(array($proxyClass, $method), $arguments)); }
private function normalizeMetadata() { $secureMethods = array(); foreach ($this->metadata->getClasses() as $class) { if ($class->getReflection()->isFinal()) { throw new \RuntimeException('Final classes cannot be secured.'); } foreach ($class->getMethods() as $name => $method) { if ($method->getReflection()->isStatic() || $method->getReflection()->isFinal()) { throw new \RuntimeException('Annotations cannot be defined on final, or static methods.'); } if (!isset($secureMethods[$name])) { $this->metadata->addMethod($name, $method); $secureMethods[$name] = $method; } else { if ($method->getReflection()->isAbstract()) { $secureMethods[$name]->merge($method); } else { if (false === $secureMethods[$name]->satisfiesParentSecurityPolicy() && $method->getReflection()->getDeclaringClass()->getName() !== $secureMethods[$name]->getReflection()->getDeclaringClass()->getName()) { throw new \RuntimeException(sprintf('Unresolved security metadata conflict for method "%s::%s" in "%s". Please copy the respective annotations, and add @SatisfiesParentSecurityPolicy to the child method.', $secureMethods[$name]->getReflection()->getDeclaringClass()->getName(), $name, $secureMethods[$name]->getReflection()->getDeclaringClass()->getFileName())); } } } } } foreach ($secureMethods as $name => $method) { if ($method->getReflection()->isAbstract()) { $previous = null; $abstractClass = $method->getReflection()->getDeclaringClass()->getName(); foreach ($this->hierarchy as $refClass) { if ($abstractClass === ($fqcn = $refClass->getName())) { $methodMetadata = new MethodMetadata($previous->getMethod($name)); $methodMetadata->merge($method); $this->metadata->addMethod($name, $methodMetadata); continue 2; } if (!$refClass->isInterface() && $this->hasMethod($refClass, $name)) { $previous = $refClass; } } } } }