Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Workflow] add guard is_valid() method support #23499

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

Merged
merged 2 commits into from
Oct 6, 2017

Conversation

halundraN
Copy link
Contributor

@halundraN halundraN commented Jul 13, 2017

Q A
Branch? 3.4
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? Yes
License MIT

Workflow guard configuration support expression language like is_fully_authenticated(), has_role() or is_granted(), etc...
I would like to add the support for a new is_valid() expression.
Configuration allow to validate subject against specific validation groups to check if a transition can be applied.

In the next configuration exemple, my issue must validate "affectable" validation group to apply "affect" transistion:

framework:
    workflows:
        issue:
            marking_store:
                type: single_state
                arguments:
                    - state
            supports: AppBundle\Entity\Issue
            initial_place: created
            places:
                - created
                - affected
                - closed
            transitions:
                affect:
                    guard: "is_valid(subject, ['affectable'])"
                    from: created
                    to:   affected
                close:
                    from: completed
                    to: closed

@fabpot
Copy link
Member

fabpot commented Jul 14, 2017

/cc @lyrixx

@nicolas-grekas nicolas-grekas added this to the 3.4 milestone Jul 17, 2017
Copy link
Member

@lyrixx lyrixx left a comment

Choose a reason for hiding this comment

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

I like the idea, but some code need to be updated.

@@ -29,5 +29,13 @@ protected function registerFunctions()
}, function (array $variables, $attributes, $object = null) {
return $variables['auth_checker']->isGranted($attributes, $object);
});

$this->register('is_valid', function ($object = 'null', $groups = 'null') {
return sprintf('$validator->validate(%s, null, %s)', $object, $groups);
Copy link
Member

Choose a reason for hiding this comment

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

you should add count() === 0 here too

AuthorizationCheckerInterface $authenticationChecker,
AuthenticationTrustResolverInterface $trustResolver,
ValidatorInterface $validator,
RoleHierarchyInterface $roleHierarchy = null
Copy link
Member

Choose a reason for hiding this comment

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

  1. should be on one line
  2. could you put the validator at the last position?
  3. could you make the validator optional to preserve the BC + a runtime exception is the validator is not defined but the user want to use it.

@halundraN halundraN force-pushed the workflow_guard_is_valid branch 2 times, most recently from cf7d0d9 to 6293a4c Compare July 17, 2017 09:08
@lyrixx
Copy link
Member

lyrixx commented Jul 17, 2017

👍

@halundraN
Copy link
Contributor Author

Hello @lyrixx is there something else i can do ?
The build fails but it seems that it does not come from my developments.

@lyrixx
Copy link
Member

lyrixx commented Jul 18, 2017

@alain-flaus Nothing ;) I'm just waiting for the "2 days" ;)

Actually, could you rebase and push -f ?

@halundraN halundraN force-pushed the workflow_guard_is_valid branch from 6293a4c to adb227f Compare July 18, 2017 08:42
@halundraN
Copy link
Contributor Author

@lyrixx ok rebase done. Thanks!

@lyrixx
Copy link
Member

lyrixx commented Jul 20, 2017

Sorry, I forgot to ask you to add a note in the CHANGELOG.
Could you do it? I'm gonna merge it just after ;)

@halundraN
Copy link
Contributor Author

@lyrixx Hi, I updated the CHANGELOG but I'm not sure about my modification, is it ok?

CHANGELOG-3.3.md Outdated
@@ -7,6 +7,8 @@ in 3.3 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1

* feature #23499 [Workflow] add guard is_valid() method support
Copy link
Member

@lyrixx lyrixx Jul 21, 2017

Choose a reason for hiding this comment

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

Your need to update this changelog only

The current one is updated automatically.

@halundraN halundraN force-pushed the workflow_guard_is_valid branch from 1e8e0f6 to c1fc500 Compare July 21, 2017 11:24
@halundraN
Copy link
Contributor Author

@lyrixx ok done!

3.4.0
-----

* Add guard is_valid() method support
Copy link
Member

Choose a reason for hiding this comment

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

is_valid() should be enclosed by backticks

return sprintf('count($validator->validate(%s, null, %s)) === 0', $object, $groups);
}, function (array $variables, $object = null, $groups = null) {
if (!$variables['validator'] instanceof ValidatorInterface) {
throw new RuntimeException('Validator not defined, did you install the component ?');
Copy link
Member

Choose a reason for hiding this comment

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

the space in front of the question mark should be removed

@@ -633,6 +633,7 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
new Reference('security.authorization_checker'),
new Reference('security.authentication.trust_resolver'),
new Reference('security.role_hierarchy'),
new Reference('validator'),
Copy link
Member

Choose a reason for hiding this comment

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

this will fail when the Validator component is not installed or the validation section is not enabled

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I will add :

new Reference('validator', ContainerInterface::NULL_ON_INVALID_REFERENCE),

Should I also add

new Reference('security.role_hierarchy', ContainerInterface::NULL_ON_INVALID_REFERENCE),

As $roleHierarchy parameter in Symfony\Component\Workflow\EventListener\GuardListener can be null too ?

Copy link
Member

Choose a reason for hiding this comment

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

that should be done on older branches as a bugfix


public function __construct($configuration, ExpressionLanguage $expressionLanguage, TokenStorageInterface $tokenStorage, AuthorizationCheckerInterface $authenticationChecker, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null)
public function __construct($configuration, ExpressionLanguage $expressionLanguage, TokenStorageInterface $tokenStorage, AuthorizationCheckerInterface $authenticationChecker, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null, ValidatorInterface $validator = null)
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we shouldn't register a new listener with the validator as this part is not a security related listener

Copy link
Contributor Author

@halundraN halundraN Jul 21, 2017

Choose a reason for hiding this comment

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

I may be wrong, but I thought that the "guard" option was designed to protect the execution of the transition and not only from a security point of view.

In this case, this does seem to me problematic that the expresion is_valid is in the guard listener ?

Copy link
Member

Choose a reason for hiding this comment

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

My fear is that the GuardListener could potentially become very big in the future if add support for other things here. Maybe splitting it into a SecurityGuardListener (as a replacement for the existing one) and a ValidatorGuardListener could be an idea.

Copy link
Contributor Author

@halundraN halundraN Jul 21, 2017

Choose a reason for hiding this comment

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

I don't know how many types of conditions can bloc a transistion but yes we can imagine a lot of thing.

Then I could split GuardListener into SecurityGuardListener (the same as GuardListener before my PR) and a ValidatorGuardListener with the new behavior.

In FrameworkExtension, I need to create a new definition for ValidatorGuardListener.
For the definition id are you ok with :

sprintf('%s.listener.guard.security', $workflowId)
and
sprintf('%s.listener.guard.validator', $workflowId)

And I plug it on the same event ?

sprintf('workflow.%s.guard.%s', $name, $transitionName)

Copy link
Member

Choose a reason for hiding this comment

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

looks okay to me, but let's wait for @lyrixx and the other @symfony/deciders to share their opinion before spending time on this

Copy link
Member

Choose a reason for hiding this comment

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

I think adding a new listener event is a bad idea, you should only use the guard event.

Then, the GuardListener name is not very well chosen indeed. I should have name it ExpressionGuardListener

Finally, splitting it in 2 parts will be hard because you will need to duplicate everything (config in the .yml, .xml etc etc). More over the end user will not be able to mix security stuff and validation stuff in the same expression.

So I'm 👍 with the current implement (except you need to fix issue spotted by @xabbuh)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok. I made a code review commit but I don't understand why github don't close "is_valid() should be enclosed by backticks" discussion because it's done (you can see it in the files changed).

Copy link
Member

Choose a reason for hiding this comment

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

Don't worry I see it in the diff.
I guess it's because you have an anchor in your URL, so github re-expand it

@lyrixx
Copy link
Member

lyrixx commented Jul 21, 2017

👍

@lyrixx
Copy link
Member

lyrixx commented Jul 21, 2017

@xabbuh Is that OK for you?


$errors = $variables['validator']->validate($object, null, $groups);

return count($errors) === 0;
Copy link
Member

Choose a reason for hiding this comment

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

Minor comment. Should this be changed to return 0 === count($errors); ?

Copy link
Member

Choose a reason for hiding this comment

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

Indeed ;)

@@ -29,5 +31,17 @@ protected function registerFunctions()
}, function (array $variables, $attributes, $object = null) {
return $variables['auth_checker']->isGranted($attributes, $object);
});

$this->register('is_valid', function ($object = 'null', $groups = 'null') {
return sprintf('count($validator->validate(%s, null, %s)) === 0', $object, $groups);
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, should be yoda style

@lyrixx lyrixx force-pushed the workflow_guard_is_valid branch 4 times, most recently from d56974a to c193d37 Compare August 21, 2017 09:45
@lyrixx
Copy link
Member

lyrixx commented Aug 21, 2017

Failures on AppVeyor are not related.

👍

return sprintf('0 === count($validator->validate(%s, null, %s))', $object, $groups);
}, function (array $variables, $object = null, $groups = null) {
if (!$variables['validator'] instanceof ValidatorInterface) {
throw new RuntimeException('Validator not defined, did you install the component?');
Copy link
Member

Choose a reason for hiding this comment

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

is_valid cannot be used as the Validator component is not installed.

'security.authorization_checker',
'security.authentication.trust_resolver',
'security.role_hierarchy',
'validator',
Copy link
Member

Choose a reason for hiding this comment

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

That makes validator a new "hard" requirement? Why?

Copy link
Member

Choose a reason for hiding this comment

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

Are you suggesting to inject null instead of the validator service if this one is not available?
If yes, It's a good idea. I will update the PR.

Copy link
Member

Choose a reason for hiding this comment

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

Correct

@lyrixx lyrixx force-pushed the workflow_guard_is_valid branch from c193d37 to 5969d68 Compare October 5, 2017 16:51
@lyrixx
Copy link
Member

lyrixx commented Oct 5, 2017

I totally forgot this PR. I rebased it on top of master (I guess it's toot late for 3.4?)
And I addressed Fab's comments

@lyrixx lyrixx changed the base branch from 3.4 to master October 5, 2017 16:52
@@ -589,6 +590,10 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
throw new LogicException('Cannot guard workflows as the Security component is not installed.');
}

if (!interface_exists(ValidatorInterface::class)) {
throw new LogicException('Cannot guard workflows as the Validator component is not installed.');
}
Copy link
Member

Choose a reason for hiding this comment

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

This should be removed now, right?

Copy link
Member

Choose a reason for hiding this comment

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

Good catch. Fixed.

@@ -9,6 +9,7 @@ CHANGELOG
3.4.0
-----

* Add guard `is_valid()` method support.
Copy link
Member

Choose a reason for hiding this comment

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

added

Copy link
Member

Choose a reason for hiding this comment

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

Fixed.

@fabpot
Copy link
Member

fabpot commented Oct 6, 2017

@lyrixx Can you fix fabbot error and rebase before I merge? Thanks.

@fabpot
Copy link
Member

fabpot commented Oct 6, 2017

Thank you @alain-flaus.

@fabpot fabpot merged commit 06d8198 into symfony:3.4 Oct 6, 2017
fabpot added a commit that referenced this pull request Oct 6, 2017
…flaus, lyrixx)

This PR was merged into the 3.4 branch.

Discussion
----------

[Workflow] add guard is_valid() method support

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | Yes
| License       | MIT

Workflow guard configuration support expression language like **is_fully_authenticated()**, **has_role()** or **is_granted()**, etc...
I would like to add the support for a new **is_valid()** expression.
Configuration allow to validate subject against specific validation groups to check if a transition can be applied.

In the next configuration exemple, my issue must validate "affectable" validation group to apply "affect" transistion:

```yaml
framework:
    workflows:
        issue:
            marking_store:
                type: single_state
                arguments:
                    - state
            supports: AppBundle\Entity\Issue
            initial_place: created
            places:
                - created
                - affected
                - closed
            transitions:
                affect:
                    guard: "is_valid(subject, ['affectable'])"
                    from: created
                    to:   affected
                close:
                    from: completed
                    to: closed
```

Commits
-------

06d8198 [Workflow] Added tests for the is_valid() guard expression
9499bc2 [Workflow] Added guard 'is_valid()' method support
@halundraN
Copy link
Contributor Author

Hello! Glad to have contributed.
I am sorry some personal problems have limited my availability.
Thanks to you, @lyrixx and @fabpot for finalizing.

@lyrixx
Copy link
Member

lyrixx commented Oct 6, 2017

@fabpot Sorry, I did not see your message sooner :/

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.

8 participants