8000 [WIP] Deprecate AbstractAdmin::isGranted by fbourigault · Pull Request #4287 · sonata-project/SonataAdminBundle · GitHub
[go: up one dir, main page]

Skip to content

[WIP] Deprecate AbstractAdmin::isGranted #4287

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 1 commit into from
Closed

[WIP] Deprecate AbstractAdmin::isGranted #4287

wants to merge 1 commit into from

Conversation

fbourigault
Copy link
Contributor
@fbourigault fbourigault commented Jan 23, 2017

I am targetting this branch, because I'm adding deprecation notices.

Closes #4095.

Changelog

### Deprecated
- deprecated `AbstractAdmin::isGranted`.
### Added
- added `sonata_is_granted` twig function.

To do

  • improve sonata_is_granted.
  • Write changelog.
  • Write CacheSecurityHandler tests.
  • Update the documentation.
  • Add an upgrade note.

Subject

This PR remove a responsibility from the AbstractAdmin class. The AbstractAdmin::isGranted method is now deprecated. SecurityHandlerInterface::isGranted has now to be called directly.

The caching feature has been moved to a new CacheSecurityHandler which decorates the sonata.admin.security.handler service.

A twig function is added to replace admin.is_granted calls.

There is no longer cache if admin security_handler is customized. Should I decorate the SecurityHandler once per admin class?

SecurityHandlerInterface::isGranted third argument was either the object or the admin when called through AbstractAdmin::isGranted. Does using null as SecurityHandlerInterface::isGranted third argument has also to be deprecated?

@@ -422,8 +422,6 @@
*/
protected $securityInformation = array();

protected $cacheIsGranted = array();
Copy link
Contributor

Choose a reason for hiding this comment

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

Removing a protected method is a BC-break. Accessing it could be deprecated mith magic methods if deemed worth it. WDYT @sonata-project/contributors ?

Copy link
Member

Choose a reason for hiding this comment

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

Accessing it could be deprecated mith magic methods if deemed worth it.

Dunno, dou you have some samples?

We can start by adding @deprecated annotation for IDE.

Copy link
Contributor Author
@fbourigault fbourigault Jan 24, 2017

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

@soullivaneuh yes, and a very fresh one at that : https://github.com/sonata-project/SonataAdminBundle/pull/4284/files#diff-f06e49acf2d25569dcbac961750bdb33R113 (I like this one better, more mutualization).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reaso 10000 n will be displayed to describe this comment to others. Learn more.

@greg0ire the example you showed would not work. Magic methods are only called if property is inaccessible. I can make the property private instead of protected. Moreover, is it a BC break to make the property noop?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh right, but neither would your example work then, I guess… BTW, what do you mean by "noop" here?

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 mean will always be empty, never read or write by sonata, so it may break classes extending AbstractAdmin, no?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I see… well it might. But then again, every single change you do can be considered a BC-break if you think hard enough. I think in this case it's ok to dismiss this one.

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 added the magic methods and deprecated annotations.

@@ -10,6 +10,13 @@
</parameters>
<services>
<service id="sonata.admin.security.handler.noop" class="%sonata.admin.security.handler.noop.class%" public="false"/>
<service id="sonata.admin.security.handler.cache"
class="Sonata\AdminBundle\Security\Handler\CacheSecurityHandler"
decorates="sonata.admin.security.handler"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! Didn't know this feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sadly I can't use this feature introduced in Symfony 2.5. Can I directly set the sonata.admin.security.handler to be the cache one and use the security.handler configuration value as first argument?

Copy link
Contributor

Choose a reason for hiding this comment

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

Argh. Yes, sure. But please add NEXT_MAJOR instructions explaining how to switch to native decoration


use Sonata\AdminBundle\Admin\AdminInterface;

class CacheSecurityHandler implements SecurityHandlerInterface
Copy link
Contributor

Choose a reason for hiding this comment

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

Please make this class final.

Copy link
Contributor

Choose a reason for hiding this comment

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

How about suffixing the class name with Decorator ?


/**
* @param SecurityHandlerInterface $handler
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Personal opinion : I'd remove this phpdoc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Other constructors have param comments on constructors. IMHO, should be kept for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK fine

Copy link
Member

Choose a reason for hiding this comment

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

We should keep the @param comments, because they could describe the parameters with more information

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah but when they don't, what's the point?

Copy link
Member

Choose a reason for hiding this comment

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

We always keept the comments so far. Wouldn't StyleCI fix them automatically?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think it can.


use Sonata\AdminBundle\Admin\AdminInterface;

class SecurityExtension extends \Twig_Extension
Copy link
Contributor

Choose a reason for hiding this comment

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

Please make this class final (extending twig extensions is deprecated anyway I think)

@@ -422,8 +422,6 @@
*/
protected $securityInformation = array();

protected $cacheIsGranted = array();
Copy link
Member

Choose a reason for hiding this comment

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

Accessing it could be deprecated mith magic methods if deemed worth it.

Dunno, dou you have some samples?

We can start by adding @deprecated annotation for IDE.

}
@trigger_error(
'The '.__METHOD__.' method is deprecated since version 3.12 and will be removed in 4.0.'.
' Use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface::isGranted instead.',
Copy link
Member

Choose a reason for hiding this comment

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

This method is also use from twig quite often.

We should tell the twig function replacement on this message too.

@greg0ire
Copy link
Contributor

There is no longer cache if admin security_handler is customized. Should I decorate the SecurityHandler once per admin class?

Not sure if this optimization would be worth it (and why there is a cache system in the first place). Not sure I get what you mean by decorating the SecurityHandler once per class either. Do you mean the customization happens by replacing the decorated handler with something else?

SecurityHandlerInterface::isGranted third argument was either the object or the admin when called through AbstractAdmin::isGranted. Does using null as SecurityHandlerInterface::isGranted third argument has also to be deprecated?

Are you should the security handler is not called with null from anywhere? Maybe there is a use-case for this…

@fbourigault
Copy link
Contributor Author

Not sure if this optimization would be worth it (and why there is a cache system in the first place). Not sure I get what you mean by decorating the SecurityHandler once per class either. Do you mean the customization happens by replacing the decorated handler with something else?

Decorating once per class means having one instance of the CacheSecurityHandler per admin class.

@fbourigault
Copy link
Contributor Author

How should I handle the deprecation in TestAdmin::testIsGranted?

About the new twig function, is this really useful or we just let users write admin.security_handler.is_granted(...) and don't provide any function?

@greg0ire
Copy link
Contributor
greg0ire commented Jan 24, 2017

How should I handle the deprecation in TestAdmin::testIsGranted?

You add the @group legacy annotation to the test.

About the new twig function, is this really useful or we just let users write admin.security_handler.is_granted(...) and don't provide any function?

I think sonata_is_granted should know what the current admin is, it would be more useful then. What do you think?

@fbourigault
Copy link
Contributor Author

I think sonata_is_granted should know what the current admin is, it would be more useful then. What do you think?

Have you an idea about how to handle this?

@greg0ire
Copy link
Contributor

Maybe there : https://github.com/sonata-project/SonataAdminBundle/blob/3.x/Controller/CRUDController.php#L980 , by getting the service and injecting the admin into it?

@fbourigault
Copy link
Contributor Author

To keep BC, would configuring the twig extension in CRUDController::render be better? Looks like the admin twig property may not be $this->admin: https://github.com/sonata-project/SonataAdminBundle/blob/3.x/Controller/CRUDController.php#L68-L70

@greg0ire
Copy link
Contributor

You're right, the latest the better, so just before rendering would be ideal in this case.

@trigger_error(sprintf(
'Using the "%s::$%s" property is deprecated since version 3.x and will be removed in 4.0.',
__CLASS__,
$name),
Copy link
Contributor
@greg0ire greg0ire Jan 27, 2017

Choose a reason for hiding this comment

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

This is a PSR2 violation, not fixed by php-cs-fixer yet but I made a PR

should be

    $name
), E_USER_DEPRECATED);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@greg0ire
Copy link
Contributor

I think sonata_is_granted should know what the current admin is, it would be more useful then. What do you think?

People should be able to pass the admin they want anyway, I think sometimes they want to check permissions in the parent admin for instance, it should be possible.

@fbourigault
Copy link
Contributor Author

I updated the sonata_is_granted twig function. The admin is now the latest argument with a null default value and in the CRUDController::render method, the current admin is set into the extension.

* NEXT_MAJOR: remove this property, the __get, __set, __isset, __unset magic methods and the
* triggerPropertyDeprecation method.
*/
private $cacheIsGranted = array();
Copy link
Member

Choose a reason for hiding this comment

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

making it private instead of protected is a BC break, too, isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Magic methods are added to avoid BC break.

Copy link
Member

Choose a reason for hiding this comment

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

realized this afterwards ;-)

Copy link
Contributor
@greg0ire greg0ire Jan 30, 2017

Choose a reason for hiding this comment

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

By the way, doesn't this magic make the property suddenly "public"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Technically, yes. But too many protection around this property can create BC breaks when all those stuff is removed. See symfony/symfony#20769 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok 👍 Let's keep it (relatively) simple

@@ -3326,4 +3380,16 @@ private function buildRoutes()
$extension->configureRoutes($this, $this->routes);
}
}

/**
* @internal
Copy link
Member

Choose a reason for hiding this comment

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

we should add a NEXT_MAJOR here

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 added a global NEXT_MAJOR on the $cacheIsGranted property. Should I dispatch the comment here and to magic methods too?

Copy link
Member

Choose a reason for hiding this comment

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

not sure, what do you think @greg0ire ?

Copy link
Contributor

Choose a reason for hiding this comment

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

global NEXT_MAJOR is good enough, this will be done by a human who can read.

    AbstractAdmin::isGranted is now deprecated.
    Use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface::isGranted instead.
    In twig templates, use sonata_is_granted instead of admin.is_granted
@fbourigault
Copy link
Contributor Author
fbourigault commented Jan 30, 2017

Is everybody ok with code? If so, I will write the docs, changelog and upgrade notes.

About codacy, it fails because I set $cacheIsGranted private. For coveralls, I guess it's because I added magic methods for deprecation layer.

@greg0ire
Copy link
Contributor

I'm ok with it!

@OskarStark
Copy link
Member

Looks good to me 👍

@OskarStark
Copy link
Member

@fbourigault please add something to the Changelog in your PR header, I prepared that for you!

Copy link
Member
@OskarStark OskarStark left a comment

Choose a reason for hiding this comment

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

Changelog and Tests please

@fbourigault
Copy link
Contributor Author
fbourigault commented Jan 31, 2017

@OskarStark I added the changelog entries. What do you mean by tests? I already wrote SecurityExtension and CacheSecurityHandler tests.

Should I add something in an UPGRADE file?

I'm going to update the documentation.

@OskarStark
Copy link
Member

Tests are fine 👍

Should I add something in an UPGRADE file?

yes, please!

@fbourigault
Copy link
Contributor Author

When updating documentation I get worried about the new use of checking permissions.

Before we just had to call $this->isGranted('EDIT') but now we have to call $this->getSecurityHandler()->isGranted($this, 'EDIT', $this). To keep the old behavior, developer has to pass $this as third argument when no object is provided.

Does anyone have an idea about how to avoid this extra argument?

@greg0ire
Copy link
Contributor

Does anyone have an idea about how to avoid this extra argument?

If the first argument is an instance of AdminInterface, use it also as third argument?

@greg0ire
Copy link
Contributor
greg0ire commented Jan 31, 2017

Wait, it's always supposed to be an AdminInterface

@fbourigault
Copy link
Contributor Author

Wait, it's always supposed to be an AdminInterface

The third argument could be an object if you want to check rights against a specific object.

@greg0ire
Copy link
Contributor

I was talking about the first object. But the third is optional anyway, right?

@fbourigault
Copy link
Contributor Author

First argument is type hinted to be and AdminInterface.
The third is optional but the old AbstractAdmin::isGranted code use $this if third argument was null.
So, to keep the behavior, developers have to send the admin as third argument.
Maybe we could add another decorator to keep this behavior?

@greg0ire
Copy link
Contributor

Indeed… It means we have even more things to move out of the admin. The first argument is only needed to retrieve admin->getCode() I think.

@fbourigault
Copy link
Contributor Author

After an instructive discussion with @greg0ire on slack, I'm pausing this PR to make an alternative proposal. Stay tuned :)

@jordisala1991
Copy link
Member

Why don't we use hasAccess instead of isGranted and do not introduce that twig function @fbourigault ?

/**
* @param AdminInterface $admin
*/
public function setAdmin(AdminInterface $admin)
Copy link
Member

Choose a reason for hiding this comment

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

This looks so wrong. Why would you inject one AdminInterface instance here? Twig extensions are stateless

@SonataCI
Copy link
Collaborator

Could you please rebase your PR and fix merge conflicts?

@core23
Copy link
Member
core23 commented Aug 25, 2017

Any progress here @fbourigault ?

@fbourigault
Copy link
Contributor Author

I didn't get anything that satisfy myself to make a good deprecation of the isGranted method. Moreover, as I have less and less interest in Sonata, I can't find time to work on this PR. Feel free to close it or keep it open to let someone else continue this work.

*/
public function isGranted(AdminInterface $admin, $attributes, $object = null)
{
$key = md5(json_encode($attributes)).'/'.spl_object_hash($object);
Copy link
Contributor

Choose a reason for hiding this comment

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

spl_object_hash($object) throws an error if it is null.

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
0