Problem/Motivation

#2295469: Add support for static permission definitions with *.permissions.yml Added support for defining static permissions in *.permissions.yml files which is great. It would also be nice to be able to declare dynamic permissions form these files too. Similar to how we allow this for routes.

Proposed resolution

Allow defining a 'permission_callbacks' array in *.permissions.yml files to allow controllers/callbacks to return permissions.

Remaining tasks

Approach, tests, etc..

User interface changes

None

API changes

Addition for 'permission_callbacks' keys in *.permissions.yml files. Help with total removal of hook_permission?

Comments

damiankloip’s picture

Status: Active » Needs review
StatusFileSize
new14.71 KB

Here is an initial patch:

- Adds support for the permission_callbacks key. Merging these with the static permissions separately. We can then make sure static permissions run strings through t() and dynamic ones do not. I think this is what we want?
- Conversion for node module
- Quick test coverage

It all likely still needs work, but this is a start. Reviews welcome.

Status: Needs review » Needs work

The last submitted patch, 1: 2329485.patch, failed testing.

damiankloip’s picture

Status: Needs work » Needs review
StatusFileSize
new17.99 KB
new3.55 KB

Added another test method to test a permissions file with a static permission and a callback. Fixed KernelTestBaseTest failure.

Status: Needs review » Needs work

The last submitted patch, 3: 2329485-3.patch, failed testing.

dawehner’s picture

It is looking great so far!

  1. +++ b/core/modules/node/node.permissions.yml
    @@ -0,0 +1,27 @@
    +'bypass node access':
    +  title: 'Bypass content access control'
    +  description: 'View edit and delete all content regardless of permission restrictions.'
    +  'restrict access': TRUE
    +'administer content types':
    +  title: 'Administer content types'
    +  description: 'Promote change ownership edit revisions and perform other tasks across all content types.'
    +  'restrict access': TRUE
    +'administer nodes':
    +  title: 'Administer content'
    +  'restrict access': TRUE
    +'access content':
    +  title: 'View published content'
    +'view own unpublished content':
    +  title: 'View own unpublished content'
    +'view all revisions':
    +  title: 'View all revisions'
    +'revert all revisions':
    +  title: 'Revert all revisions'
    +  description: 'Role requires permission <em>view revisions</em> and <em>edit rights</em> for nodes in question or <em>administer nodes</em>.'
    +'delete all revisions':
    +  title: 'Delete all revisions'
    +  description: 'Role requires permission to <em>view revisions</em> and <em>delete rights</em> for nodes in question or <em>administer nodes</em>.'
    +
    

    You don't need quotes for the keys ... see #2328411: Convert all permissions to yml files and permission callbacks

  2. +++ b/core/modules/node/node.permissions.yml
    @@ -0,0 +1,27 @@
    +  - '\Drupal\node\NodePermissions::nodeTypePermissions'
    +  - '\Drupal\node\NodePermissions::contentPermissions'
    

    yeah you also don't need keys here.

  3. +++ b/core/modules/node/src/NodePermissions.php
    @@ -0,0 +1,47 @@
    +class NodePermissions extends ControllerBase {
    

    oh, this feels wrong to be honest. we do have traits for t() and url(), in general.

  4. +++ b/core/modules/node/src/NodePermissions.php
    @@ -0,0 +1,47 @@
    +      'access content overview' => array(
    +        'title' => $this->t('Access the Content overview page'),
    +        'description' => $this->t('Get an overview of <a href="!url">all content</a>.', array('!url' => $this->url('system.admin_content'))),
    +      ),
    

    webchick and I talked about that and considered this to be an edge case. If it would be really needed we thought of allowing twig inline templates here

  5. +++ b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
    @@ -77,8 +77,8 @@ function testEnableModulesLoad() {
       function testEnableModulesInstall() {
    -    $module = 'node';
    -    $table = 'node_access';
    +    $module = 'module_test';
    +    $table = 'module_test';
     
    

    I really hate that these test fails

  6. +++ b/core/modules/user/src/PermissionHandler.php
    @@ -94,7 +103,38 @@ public function getPermissions() {
    +          if ($callback_permissions = call_user_func($callback)) {
    

    can't you just use $callback()? Afaik ['class', 'method']() works

damiankloip’s picture

Status: Needs work » Needs review
StatusFileSize
new18.57 KB
new3.13 KB

Thanks for the review.

1. Fixed
2. Fixed
3. Yeah :) That was a hack that I did last night and forgot to implement properly! Fixed.
4. That sounds like a nice idea, we can get a follow up for that one.
5. Yeah, that is not a cool fail. It's quite a strange test though tbh. Depending on a test module is better than node though IMO. So I think this is an improvement too.
6. That is cool, but let's not do that right now. Plus my IDE doesn't like it.

dawehner’s picture

5. Yeah, that is not a cool fail. It's quite a strange test though tbh. Depending on a test module is better than node though IMO. So I think this is an improvement too.

If you convert all other permissions, as done in my other issue, you will see that there are even more places where this happens to break. There are quite some implementation
details in the kernel test base.

dawehner’s picture

I am fine with the patch at it is. We have to work on additional issue anyway.

@damiankloip
Did you thought of a chance record?

damiankloip’s picture

I will update https://www.drupal.org/node/2311427 to reflect this. I think that is best?

claudiu.cristea’s picture

+++ b/core/modules/node/node.permissions.yml
@@ -0,0 +1,27 @@
+bypass node access:
+  title: 'Bypass content access control'
+  description: 'View edit and delete all content regardless of permission restrictions.'
+  'restrict access': TRUE
+administer content types:
+  title: 'Administer content types'
...
+permission_callbacks:
+  - \Drupal\node\NodePermissions::nodeTypePermissions
+  - \Drupal\node\NodePermissions::contentPermissions

I don't like that permission_callbacks shares the same level as static permission keys. I think we should avoid this possible confusion. Possible structure:

static:
  bypass node access:
    title: 'Bypass content access control'
    description: 'View edit and delete all content regardless of permission restrictions.'
    'restrict access': TRUE
  administer content types:
    title: 'Administer content types'
...
callbacks:
  - \Drupal\node\NodePermissions::nodeTypePermissions
  - \Drupal\node\NodePermissions::contentPermissions
dawehner’s picture

@claudiu.cristea
We do have a similar structure on the routing.yml already, so there is no reason to change this here.

views.ajax:
  path: '/views/ajax'
  defaults:
    _controller: '\Drupal\views\Controller\ViewAjaxController::ajaxView'
  options:
    _theme: ajax_base_page
  requirements:
    _access: 'TRUE'

route_callbacks:
  - 'views.route_subscriber:routes'

@damiankloip
Yes this is the best.

damiankloip’s picture

Agree, changing that here is not an option IMO. This makes the regular use case slightly more complex (yes, not much) and if we changed that, we would have to change routing.yml structure too. Which seems like a no go at this stage.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Let's get this one in first.

damiankloip’s picture

Cool. Just to clarify our plan - Let's update the change notice when this is just about to/has just been committed. Otherwise we will have a change notice published that has functionality not in HEAD yet.

tim.plunkett’s picture

+1 for RTBC, this matches the dynamic code in RouteBuilder and looks great.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 6: 2329485-6.patch, failed testing.

dawehner’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new18.59 KB

Quick rebase

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/node/src/NodePermissions.php
    @@ -0,0 +1,51 @@
    +      $perms += node_list_permissions($type);
    

    Let's move all of node_list_permissions() into NodePermissions::nodeTypePermissions() - this is the only usage.

  2. +++ b/core/modules/user/src/PermissionHandler.php
    @@ -52,11 +60,12 @@ class PermissionHandler implements PermissionHandlerInterface {
        * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
        *   The string translation.
        */
    -  public function __construct(ModuleHandlerInterface $module_handler, TranslationInterface $string_translation) {
    +  public function __construct(ModuleHandlerInterface $module_handler, TranslationInterface $string_translation, ControllerResolverInterface $controller_resolver) {
    

    Need to update doc block for new param.

damiankloip’s picture

Status: Needs work » Needs review
StatusFileSize
new22.48 KB
new5.34 KB

Good points Alex. Here is an updated patch.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Okay, cool

  • alexpott committed bd8cb79 on 8.0.x
    Issue #2329485 by damiankloip, dawehner: Allow permissions.yml files to...
alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed bd8cb79 and pushed to 8.0.x. Thanks!

Can someone update the CR https://www.drupal.org/node/2311427 and link this issue. Thanks.

geerlingguy’s picture

Status: Fixed » Needs work
Issue tags: +Needs change record updates

Setting to needs work until change record is updated... https://www.drupal.org/node/2311427

dawehner’s picture

Status: Needs work » Fixed
Issue tags: -Needs change record updates

Updated.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.