Skip to content

Commit

Permalink
Merge pull request #2488 from laboro/feature/BAP-11132_Feature_Toggle
Browse files Browse the repository at this point in the history
BAP-11132: feature toggle
  • Loading branch information
x86demon committed Sep 5, 2016
2 parents 06677e8 + d0b8d69 commit e66a7df
Show file tree
Hide file tree
Showing 93 changed files with 5,553 additions and 62 deletions.
@@ -0,0 +1,21 @@
<?php

namespace Oro\Bundle\ActionBundle\Configuration;

use Oro\Bundle\FeatureToggleBundle\Configuration\ConfigurationExtensionInterface;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;

class FeatureConfigurationExtension implements ConfigurationExtensionInterface
{
/**
* {@inheritdoc}
*/
public function extendConfigurationTree(NodeBuilder $node)
{
$node
->arrayNode('operations')
->prototype('variable')
->end()
->end();
}
}
21 changes: 21 additions & 0 deletions src/Oro/Bundle/ActionBundle/Model/Assembler/OperationAssembler.php
Expand Up @@ -115,6 +115,7 @@ protected function assembleDefinition($operationName, array $options)
$operationDefinition->setActions($name, $this->getOption($options, $name, []));
}

$this->addFeaturePrecondition($operationDefinition);
$this->addAclPrecondition($operationDefinition, $this->getOption($options, 'acl_resource'));

return $operationDefinition;
Expand All @@ -140,6 +141,26 @@ protected function addAclPrecondition(OperationDefinition $operationDefinition,
$operationDefinition->setConditions(OperationDefinition::PRECONDITIONS, $newDefinition);
}

/**
* @param OperationDefinition $operationDefinition
*/
protected function addFeaturePrecondition(OperationDefinition $operationDefinition)
{
$featureResourceDefinition = [
'@feature_resource_enabled' => [
'resource' => $operationDefinition->getName(),
'resource_type' => 'operations'
]
];
$definition = $operationDefinition->getConditions(OperationDefinition::PRECONDITIONS);
if ($definition) {
$newDefinition['@and'][] = $definition;
}
$newDefinition['@and'][] = $featureResourceDefinition;

$operationDefinition->setConditions(OperationDefinition::PRECONDITIONS, $newDefinition);
}

/**
* @param array $entities
* @return array
Expand Down
Expand Up @@ -49,3 +49,8 @@ services:
class: %oro_action.configuration_pass.replace_property_path.class%
arguments:
- "data"

oro_action.config_extension.feature:
class: 'Oro\Bundle\ActionBundle\Configuration\FeatureConfigurationExtension'
tags:
- { name: oro_feature.config_extension }
Expand Up @@ -89,7 +89,15 @@ public function assembleProvider()
->setActions(OperationDefinition::PREACTIONS, [])
->setActions(OperationDefinition::ACTIONS, [])
->setActions(OperationDefinition::FORM_INIT, [])
->setFormType(OperationType::NAME);
->setFormType(OperationType::NAME)
->setConditions(
OperationDefinition::PRECONDITIONS,
[
'@and' => [
['@feature_resource_enabled' => ['resource' => 'minimum_name', 'resource_type' => 'operations']]
]
]
);

$definition2 = clone $definition1;
$definition2
Expand All @@ -100,7 +108,15 @@ public function assembleProvider()
->setEnabled(false)
->setApplications(['application1'])
->setAttributes(['config_attr'])
->setConditions(OperationDefinition::PRECONDITIONS, ['config_pre_cond'])
->setConditions(
OperationDefinition::PRECONDITIONS,
[
'@and' => [
['config_pre_cond'],
['@feature_resource_enabled' => ['resource' => 'maximum_name', 'resource_type' => 'operations']]
]
]
)
->setConditions(OperationDefinition::CONDITIONS, ['config_cond'])
->setActions(OperationDefinition::PREACTIONS, ['config_pre_func'])
->setActions(OperationDefinition::ACTIONS, ['@action' => 'action_config'])
Expand All @@ -122,9 +138,18 @@ public function assembleProvider()
OperationDefinition::PRECONDITIONS,
[
'@and' => [
['config_pre_cond'],
[
'@and' => [
['config_pre_cond'],
[
'@feature_resource_enabled' => [
'resource' => 'maximum_name_and_acl',
'resource_type' => 'operations'
]
]
]
],
['@acl_granted' => 'test_acl']

]
]
)
Expand Down
21 changes: 21 additions & 0 deletions src/Oro/Bundle/ApiBundle/Config/FeatureConfigurationExtension.php
@@ -0,0 +1,21 @@
<?php

namespace Oro\Bundle\ApiBundle\Config;

use Oro\Bundle\FeatureToggleBundle\Configuration\ConfigurationExtensionInterface;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;

class FeatureConfigurationExtension implements ConfigurationExtensionInterface
{
/**
* {@inheritdoc}
*/
public function extendConfigurationTree(NodeBuilder $node)
{
$node
->arrayNode('api_resources')
->prototype('variable')
->end()
->end();
}
}
Expand Up @@ -6,9 +6,8 @@

use Oro\Bundle\ApiBundle\ApiDoc\CachingApiDocExtractor;
use Oro\Bundle\ApiBundle\Provider\ResourcesCache;
use Oro\Bundle\EntityExtendBundle\Event\UpdateSchemaEvent;

class UpdateSchemaListener
class ApiSourceListener
{
/** @var ResourcesCache */
protected $resourcesCache;
Expand All @@ -34,10 +33,7 @@ public function __construct(
$this->apiDocViews = $apiDocViews;
}

/**
* @param UpdateSchemaEvent $event
*/
public function onSchemaUpdate(UpdateSchemaEvent $event)
public function clearCache()
{
// clear the cache for API resources
$this->resourcesCache->clear();
Expand Down
@@ -0,0 +1,44 @@
<?php

namespace Oro\Bundle\ApiBundle\Processor\Shared;

use Oro\Bundle\ApiBundle\Processor\Context;
use Oro\Bundle\FeatureToggleBundle\Checker\FeatureChecker;
use Oro\Component\ChainProcessor\ContextInterface;
use Oro\Component\ChainProcessor\ProcessorInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

/**
* Validates whether an feature is enabled for the type of entities specified
* in the "class" property of the Context.
*/
class EntityTypeFeatureCheck implements ProcessorInterface
{
const API_RESOURCE_KEY = 'api_resources';

/**
* @var FeatureChecker
*/
protected $featureChecker;

/**
* @param FeatureChecker $featureChecker
*/
public function __construct(FeatureChecker $featureChecker)
{
$this->featureChecker = $featureChecker;
}

/**
* @param Context $context
*
* {@inheritdoc}
*/
public function process(ContextInterface $context)
{
$entityClass = $context->getClassName();
if (!$this->featureChecker->isResourceEnabled($entityClass, self::API_RESOURCE_KEY)) {
throw new AccessDeniedException();
}
}
}
@@ -0,0 +1,44 @@
<?php

namespace Oro\Bundle\ApiBundle\Processor\Subresource\Shared;

use Oro\Bundle\ApiBundle\Processor\Subresource\SubresourceContext;
use Oro\Bundle\FeatureToggleBundle\Checker\FeatureChecker;
use Oro\Component\ChainProcessor\ContextInterface;
use Oro\Component\ChainProcessor\ProcessorInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

/**
* Validates whether an feature is enabled for the type of entities specified
* in the "parentClass" property of the Context.
*/
class ParentEntityTypeFeatureCheck implements ProcessorInterface
{
const API_RESOURCE_KEY = 'api_resources';

/**
* @var FeatureChecker
*/
protected $featureChecker;

/**
* @param FeatureChecker $featureChecker
*/
public function __construct(FeatureChecker $featureChecker)
{
$this->featureChecker = $featureChecker;
}

/**
* @var SubresourceContext $context
*
* {@inheritdoc}
*/
public function process(ContextInterface $context)
{
$parentClassName = $context->getParentClassName();
if (!$this->featureChecker->isResourceEnabled($parentClassName, self::API_RESOURCE_KEY)) {
throw new AccessDeniedException();
}
}
}
Expand Up @@ -98,6 +98,13 @@ services:
# security_check
#

oro_api.add_relationship.parent_entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Subresource\Shared\ParentEntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: add_relationship, group: security_check, priority: 20 }

oro_api.add_relationship.parent_entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Subresource\Shared\ParentEntityTypeSecurityCheck
arguments:
Expand Down
Expand Up @@ -89,6 +89,13 @@ services:
# security_check
#

oro_api.create.entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: create, group: security_check, priority: 20 }

oro_api.create.entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeSecurityCheck
arguments:
Expand Down
Expand Up @@ -57,6 +57,13 @@ services:
# security_check
#

oro_api.delete.entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: delete, group: security_check, priority: 20 }

oro_api.delete.entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeSecurityCheck
arguments:
Expand Down
Expand Up @@ -98,6 +98,13 @@ services:
# security_check
#

oro_api.delete_relationship.parent_entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Subresource\Shared\ParentEntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: delete_relationship, group: security_check, priority: 20 }

oro_api.delete_relationship.parent_entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Subresource\Shared\ParentEntityTypeSecurityCheck
arguments:
Expand Down
7 changes: 7 additions & 0 deletions src/Oro/Bundle/ApiBundle/Resources/config/processors.get.yml
Expand Up @@ -95,6 +95,13 @@ services:
# if you add a new processor in this group, it should be added in the "security_check" group of
# actions that execute this action, e.g. look at "security_check" group of "create" or "update" actions

oro_api.get.entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: get, group: security_check, priority: 20 }

oro_api.get.entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeSecurityCheck
arguments:
Expand Down
Expand Up @@ -142,6 +142,13 @@ services:
# security_check
#

oro_api.get_list.entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: get_list, group: security_check, priority: 20 }

oro_api.get_list.entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeSecurityCheck
arguments:
Expand Down
Expand Up @@ -89,6 +89,13 @@ services:
# security_check
#

oro_api.update.entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: update, group: security_check, priority: 20 }

oro_api.update.entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Shared\EntityTypeSecurityCheck
arguments:
Expand Down
Expand Up @@ -93,6 +93,13 @@ services:
# security_check
#

oro_api.update_relationship.parent_entity_type_feature_check:
class: Oro\Bundle\ApiBundle\Processor\Subresource\Shared\ParentEntityTypeFeatureCheck
arguments:
- '@oro_featuretoggle.checker.feature_checker'
tags:
- { name: oro.api.processor, action: update_relationship, group: security_check, priority: 20 }

oro_api.update_relationship.parent_entity_type_security_check:
class: Oro\Bundle\ApiBundle\Processor\Subresource\Shared\ParentEntityTypeSecurityCheck
arguments:
Expand Down
10 changes: 8 additions & 2 deletions src/Oro/Bundle/ApiBundle/Resources/config/services.yml
Expand Up @@ -148,13 +148,14 @@ services:
- [ setNamespace, [ 'oro_api_resources' ] ]

oro_api.listener.update_schema:
class: Oro\Bundle\ApiBundle\EventListener\UpdateSchemaListener
class: Oro\Bundle\ApiBundle\EventListener\ApiSourceListener
arguments:
- '@oro_api.resources_cache'
- '@nelmio_api_doc.extractor.api_doc_extractor'
- '%oro_api.api_doc.views%'
tags:
- { name: kernel.event_listener, event: oro.entity_extend.entity.schema.update, method: onSchemaUpdate }
- { name: kernel.event_listener, event: oro.entity_extend.entity.schema.update, method: clearCache }
- { name: kernel.event_listener, event: oro_featuretoggle.features.change, method: clearCache }

oro_api.config_extension_registry:
class: Oro\Bundle\ApiBundle\Config\ConfigExtensionRegistry
Expand Down Expand Up @@ -189,6 +190,11 @@ services:
tags:
- { name: oro_api.config_extension }

oro_api.config_extension.feature:
class: 'Oro\Bundle\ApiBundle\Config\FeatureConfigurationExtension'
tags:
- { name: oro_feature.config_extension }

oro_api.config_bag:
class: Oro\Bundle\ApiBundle\Provider\ConfigBag
public: false
Expand Down

0 comments on commit e66a7df

Please sign in to comment.