<?php
namespace Galilee\GraphQlBundle\DependencyInjection;
use Galilee\GraphQlBundle\Services\Security\AskResetPasswordSecurityInterface;
use Galilee\GraphQlBundle\Services\Security\ImpersonateUserSecurityInterface;
use Galilee\GraphQlBundle\Services\Security\LoginSecurityInterface;
use Galilee\GraphQlBundle\Services\Security\ResetPasswordSecurityInterface;
use Galilee\GraphQlBundle\Services\Security\SignupSecurityInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('graph_ql');
$treeBuilder->getRootNode()
->children()
->arrayNode("jwtSecuredRoutes")
->info("DataHub config names exposed as JWT secured")
->useAttributeAsKey('shortName')
->requiresAtLeastOneElement()
->prototype('array')
->children()
->arrayNode('security')
->info("Allow user to impersonate another (attribute must be part of user, front has to manage on its own, back will apply filters based upon impersonated one)")
->addDefaultsIfNotSet()
->children()
->arrayNode('userConfiguration')
->info("front user configuration")
->addDefaultsIfNotSet()
->children()
->scalarNode('frontUserPimcoreClass')
->cannotBeEmpty()
->isRequired()
->info('Class or Interface that will represent frontUser, must implement UserInterface')
->validate()
->ifTrue(function ($v) { return !(file_exists(PIMCORE_PROJECT_ROOT . '/deploy.flag') || class_exists($v) || interface_exists($v, false)); })
->thenInvalid('The supported class or interface "%s" do not exist')
->ifTrue(function ($v) { return !(file_exists(PIMCORE_PROJECT_ROOT . '/deploy.flag') || is_subclass_of($v, UserInterface::class)); })
->thenInvalid('The supported class or interface "%s" do not implement ' . UserInterface::class)
->end()
->end()
->scalarNode("frontUserIdentifierAttribute")
->defaultValue('email')
->info("User.attribute used to identify user from JWT token, default: 'email'")
->end()
->scalarNode("frontUserPasswordAttribute")
->defaultValue('password')
->info("User.attribute used as password, default: 'password'")
->end()
->end()
->end()
->arrayNode('login')
->info("Allow user to impersonate another (attribute must be part of user, front has to manage on its own, back will apply filters based upon impersonated one)")
->addDefaultsIfNotSet()
->children()
->scalarNode('guard')
->cannotBeEmpty()
->isRequired()
->defaultValue('Galilee\GraphQlBundle\Services\Security\Default\DefaultLoginSecurityService')
->info('Class or Interface that will validate frontUser login, must implement ' . LoginSecurityInterface::class)
->validate()
->ifTrue(function ($v) { return !(class_exists($v) || interface_exists($v, false)); })
->thenInvalid('The supported class or interface "%s" do not exist')
->ifTrue(function ($v) { return !is_subclass_of($v, LoginSecurityInterface::class); })
->thenInvalid('The supported class or interface "%s" do not implement ' . LoginSecurityInterface::class)
->end()
->end()
->end()
->end()
->arrayNode('signup')
->info("Allow user to impersonate another (attribute must be part of user, front has to manage on its own, back will apply filters based upon impersonated one)")
->addDefaultsIfNotSet()
->children()
->scalarNode('guard')
->defaultValue(null)
->info('Class or Interface that will validate frontUser signup, to disable use null as value, otherwise must implement ' . SignupSecurityInterface::class)
->validate()
->ifTrue(function ($v) { return !(is_null($v) || (class_exists($v) || interface_exists($v, false))); })
->thenInvalid('The supported class or interface "%s" do not exist')
->ifTrue(function ($v) { return !(is_null($v) || is_subclass_of($v, SignupSecurityInterface::class)); })
->thenInvalid('The supported class or interface "%s" do not implement ' . SignupSecurityInterface::class)
->end()
->end()
->end()
->end()
->arrayNode('resetPassword')
->info("Allow user to impersonate another (attribute must be part of user, front has to manage on its own, back will apply filters based upon impersonated one)")
->addDefaultsIfNotSet()
->children()
->scalarNode('guardAskResetPassword')
->defaultValue(null)
->info('Class or Interface that will validate frontUser asking for new password, to disable use null as value, otherwise must implement ' . AskResetPasswordSecurityInterface::class)
->validate()
->ifTrue(function ($v) { return !(is_null($v) || (class_exists($v) || interface_exists($v, false))); })
->thenInvalid('The supported class or interface "%s" do not exist')
->ifTrue(function ($v) { return !(is_null($v) || is_subclass_of($v, AskResetPasswordSecurityInterface::class)); })
->thenInvalid('The supported class or interface "%s" do not implement ' . AskResetPasswordSecurityInterface::class)
->end()
->end()
->scalarNode('guardResetPassword')
->defaultValue(null)
->info('Class or Interface that will validate frontUser resetting his password post asking for reset, to disable use null as value, otherwise must implement ' . ResetPasswordSecurityInterface::class)
->validate()
->ifTrue(function ($v) { return !(is_null($v) || (class_exists($v) || interface_exists($v, false))); })
->thenInvalid('The supported class or interface "%s" do not exist')
->ifTrue(function ($v) { return !(is_null($v) || is_subclass_of($v, ResetPasswordSecurityInterface::class)); })
->thenInvalid('The supported class or interface "%s" do not implement ' . ResetPasswordSecurityInterface::class)
->end()
->end()
->end()
->end()
->arrayNode('impersonatingUserFeature')
->info("Allow user to impersonate another (attribute must be part of user, front has to manage on its own, back will apply filters based upon impersonated one)")
->addDefaultsIfNotSet()
->children()
->scalarNode('userAttributeName')
->defaultValue('impersonatedUser')
->end()
->scalarNode('guard')
->defaultValue(null)
->info('Class or Interface that will define permissions to allow some front user to impersonate another, to disable use null as value, otherwise must implement ' . ResetPasswordSecurityInterface::class)
->validate()
->ifTrue(function ($v) { return !(is_null($v) || (class_exists($v) || interface_exists($v, false))); })
->thenInvalid('The supported class or interface "%s" does not exist.')
->ifTrue(function ($v) { return !(is_null($v) || is_subclass_of($v, ImpersonateUserSecurityInterface::class)); })
->thenInvalid('The supported class "%s" do not implement ' . ImpersonateUserSecurityInterface::class)
->end()
->end()
->end()
->end()
->end()
->end()
->arrayNode("unsecuredOperations")
->scalarPrototype()->end()
->info("Allow gql operations despite absence of JWT token")
->end()
->arrayNode("disabledOperations")
->scalarPrototype()->end()
->info("Disable gql operations despite dataHubConfig")
->end()
->arrayNode("unsecuredClassDefinition")
->info("Allow to define some allowed classDefinitionQuery based upon classname and attributes")
->useAttributeAsKey('className')
->prototype('array')
->children()
->arrayNode("allowedAttributes")
->prototype('scalar')
->end()
->end()
->end()
->end();
return $treeBuilder;
}
}