Skip to content

[SecurityBundle] fix allow_if expression service compilation to support custom functions #24309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

dmaicher
Copy link
Contributor

@dmaicher dmaicher commented Sep 24, 2017

Q A
Branch? 2.7
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #23208
License MIT
Doc PR -

I would like to discuss possibilities to fix #23208 (also see closed duplicate #24306).

The proposed solution in this PR is to simply not dump the parsed expression but simply the "raw" expressions

Question: Will this have a big negative performance impact? As far as I understand the ExpressionLanguage should have a cache anyway for parsed expressions? Or not?

Idea: maybe we can add an additional CacheWarmer that warms the cache for all those expressions?

Or is there a way to perform the compilation into parsed expressions at the very end of the container compilation when we could instantiate the actual ExpressionLanguage service with all its custom extensions?

Edit: the new approach is to still dump the parsed expressions but we do it using the "real" expression language service with all custom extensions.

@dmaicher
Copy link
Contributor Author

dmaicher commented Oct 2, 2017

@chalasr did you have a chance yet to look at this? Feedback welcome 😊

@chalasr chalasr requested review from xabbuh and removed request for chalasr October 2, 2017 15:43
@chalasr
Copy link
Member

chalasr commented Oct 2, 2017

@dmaicher sorry, I didn't find time to look at this and I miss the whole picture, so I ping @xabbuh who participates to the fixed ticket already :)

@xabbuh
Copy link
Member

xabbuh commented Oct 11, 2017

Can't we just move the serialisation of the expression language to a compiler pass that is processed after the AddExpressionLanguageProvidersPass?

@dmaicher
Copy link
Contributor Author

@xabbuh this seems to be working indeed 😊 👍 I will update the PR later today

@dmaicher dmaicher changed the base branch from 2.7 to 3.3 October 11, 2017 13:02
foreach ($container->findTaggedServiceIds('security.expression_language_provider', true) as $id => $attributes) {
$definition->addMethodCall('addExpressionLanguageProvider', array(new Reference($id)));
$definition->addMethodCall('registerProvider', array(new Reference($id)));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me this makes more sense than to "take a detour" via the ExpressionVoter to extend the ExpressionLanguage service.

Should not break BC?

@dmaicher
Copy link
Contributor Author

@xabbuh before I will fix the tests + add more tests: Is this what you meant?

Also I had to change the base to 3.3 as we cannot set priorities for compiler passes before 😢

@xabbuh
Copy link
Member

xabbuh commented Oct 11, 2017

Removing ParseSecurityExpressionsPass and doing the work in AddExpressionLanguageProvidersPass::process() should work on 2.7 too, right?

@dmaicher
Copy link
Contributor Author

You mean doing that only for 2.7 and 2.8? Seems a bit wrong though to put that into AddExpressionLanguageProvidersPass as the name suggests it only adds/processes the custom providers 😕

@xabbuh
Copy link
Member

xabbuh commented Oct 13, 2017

Alternatively, we can add the new compiler pass to the FrameworkBundle instead. This shouldn't be a big problem as we already have the handling for registering custom provider there.

@dmaicher dmaicher changed the base branch from 3.3 to 2.7 October 13, 2017 15:58
@dmaicher
Copy link
Contributor Author

@xabbuh indeed that seems better. Done 😉

->setPublic(false)
->addArgument($expression)
->addArgument(serialize($this->getExpressionLanguage()->parse($expression, array('token', 'user', 'object', 'roles', 'request', 'trust_resolver'))->getNodes()))
->addTag('security.expression.unparsed')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like this tag name. Can't we just use something like security.expression?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah why not 😊 Done 👍

return;
}

$expressionLanguage = $container->get('security.expression_language');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findDefinition()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this should actually get the instantiated service 😉

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh hm, I missed that. To be honest I am not really happy with having compiler passes that force the creation of the actual service during compilation. Can't we solve the problem by letting the serialization happening in a cache warmer where the service is actually available?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point. I'm also not 100% happy with this solution.

The only other option I see is to use a proper persisting cache by default for the expression language service. Currently it only uses an ArrayAdapter:

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php#L37

https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml#L82

On 3.3+ we could use the system cache pool for it?

And then we could add a CacheWarmer for it.

Or do you have another idea?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I had something like that in mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will have a look and maybe also prepare some benchmarks to see the impact of the change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$expressionLanguage = $container->get('security.expression_language');

foreach ($container->findTaggedServiceIds('security.expression') as $id => $attributes) {
$defition = $container->getDefinition($id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: $definition

@dmaicher
Copy link
Contributor Author

dmaicher commented Nov 8, 2017

will work on a different solution within a separate PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants