Problem/Motivation

This is part of the #2028027: [META] Missing access control for base fields meta issue. Please read the meta issue for the reasoning.

Proposed resolution

FIrst, the patch adds a simplified logic that allows entity access control handlers to provide default access logic for their base fields, instead of having to provide a custom class for each specific case and use that as a list class.

Adds base field access logic for node base fields. Specifically, status, promote, sticky, created, uid and revision_log can only be changed by users with the administer nodes permission, and changed, revision_uid and revision_timestamp can not be changed by any user as they are automatically managed by the system.

Remaining tasks

User interface changes

API changes

No changes, only adds a new method that access control handlers can optionally implement.

Original report by @fago

This issue is for implementing default access for all base fields of a node. We need to go through them and look for existing access restrictions and make sure they are covered as part of the default Access of their field's item classes.

Example: We've got a permission for editing user names, that needs to be covered.

What to do: For each field that has a default access being not TRUE, we
- have to add a custom FieldItem class extending the field type's one
- implement defaultAccess() for it
- write a unit test case to prove it works as it should

Comments

fago’s picture

fago’s picture

guedressel’s picture

Assigned: Unassigned » guedressel
guedressel’s picture

Status: Active » Needs work
StatusFileSize
new8.97 KB

For now I built a defaultAccess check for the status field. The status field might be the most important one..

To accomplish this check I also introduced two new permissions to the node module:
* "change status of own %type content"
* "change status of any %type content"

..hope you like that.

It would be nice if I could get a review of my current patch. Even if there are more fields which needs to be covered and even if the UnitTest is not covering 100% of the cases.
It's my first patch for D8 and I made some comments in the code where I wasn't sure if I'm applying D8 stuff correctly...

And by the way:
Thanks for the drupalcon in prague!
I enjoyed to see (at least some of) you guys in person.

guedressel’s picture

Status: Needs work » Needs review

...just set it back to "needs work" when you put your experienced and valuable 2 cents to my patch ;-)

Status: Needs review » Needs work

The last submitted patch, node-base_fields_default_access-2098355.patch, failed testing.

guedressel’s picture

Okay.
I see.
The Create Resource Test from REST gave me answers to some questions ;-)
I need to refactor the permission checks.

guedressel’s picture

After working on this issue at drupalcon in prague I'm sitting now at the Schnitzelcamp (DrupalCamp Vienna).
Great time again with you guys :-)

I'm submitting a new - refactored - patch to let drupal.org run it's tests on it.
It should fit better than the last one.
I also removed to custom permissions I mentioned above and will propose them in an extra issue.

guedressel’s picture

Issue summary: View changes
StatusFileSize
new12.45 KB
guedressel’s picture

Status: Needs work » Needs review
guedressel’s picture

After discussing with klausi and fago I have to admit, that I was wrong - in a couple things:
Operations in the defaultAccess method may only be "view" or "edit".
I don't need to check the entity for type "node" in the access method.
The permissions "edit [any|own] content" is not applicable for the status field. Only "bypass access control" and "administer nodes" are of interest.
And my test case was unnecessarily expensive by using WebTestBase class.

Thank you two guys for helping me on this.

guedressel’s picture

klausi’s picture

  1. +++ b/core/modules/node/lib/Drupal/node/NodeFieldStatus.php
    @@ -0,0 +1,59 @@
    +
    ...
    +
    ...
    + *
    ...
    +
    

    superflous whitespace

  2. +++ b/core/modules/node/lib/Drupal/node/NodeFieldStatus.php
    @@ -0,0 +1,59 @@
    +    switch ($operation) {
    +
    ...
    +        if ($account->hasPermission('bypass node access') || $account->hasPermission('administer nodes')) {
    
    +++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldAccessTest.php
    @@ -0,0 +1,119 @@
    +  function setUp() {
    

    inheritdoc missing.

  3. +++ b/core/modules/node/lib/Drupal/node/NodeFieldStatus.php
    @@ -0,0 +1,59 @@
    +        // The status of a node may be read by everyone who has access to the node.
    

    longer than 80 characters.

  4. +++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldAccessTest.php
    @@ -0,0 +1,119 @@
    +    $this->chuck_norris = $this->createUser(array(), array('bypass node access'));
    

    document that chuck norris is almighty.

  5. +++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldAccessTest.php
    @@ -0,0 +1,119 @@
    +   *
    

    white space

  6. +++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldAccessTest.php
    @@ -0,0 +1,119 @@
    +      if ( ! $node1->status->access("view", $account) ) {
    

    no white space before and after "!"

  7. +++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldAccessTest.php
    @@ -0,0 +1,119 @@
    +        $permission_denied = TRUE;
    

    should be tested for all users

  8. +++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldAccessTest.php
    @@ -0,0 +1,119 @@
    +  // TODO: create more tests for more base-fields of node.
    

    @todo

  9. +++ b/core/modules/node/node.module
    @@ -1563,7 +1563,7 @@ function node_node_access($node, $op, $account) {
    + * @param $type
    

    unrelated change, should be removed.

klausi’s picture

further fields:

administrative edit permission: uid, status, promote, created, updated, sticky

revision_timestamp, revision_uid, log: revision permissions?

Status: Needs review » Needs work

The last submitted patch, 12: node-base_fields_default_access-2098355-10.patch, failed testing.

guedressel’s picture

guedressel’s picture

Now all administrative fields are handled through the NodeAdministrativeField (which restricts editing withoud administrative permissions).

jibran’s picture

Status: Needs work » Needs review

Test this please.

The last submitted patch, 16: node-base_fields_default_access-2098355-13.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 17: node-base_fields_default_access-2098355-14.patch, failed testing.

berdir’s picture

Status: Needs work » Needs review
StatusFileSize
new10.23 KB

Here is a new patch based on the approach in #2029855: Missing access control for user base fields, with the tests from this issue. I think this issue has a better chance at getting in and getting the API in. We can implement the other entity types any time, but we need to have the API in asap.

Added revision_log to the administrative list.

revision_uid and revision_timestamp and changed are managed automatically, no user should have access to edit them, so updated accordingly. changed could possibly even do that by default.

Cleaned up and updated the test, but conceptually still the same + tests for the new rules.

catch’s picture

Priority: Normal » Critical

Should be critical no?

klausi’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/node/src/NodeAccessController.php
    @@ -131,6 +133,21 @@ protected function checkCreateAccess(AccountInterface $account, array $context,
    +      return $account->hasPermission('administer nodes');
    

    why don't we also check for "bypass node access" here? Please add a comment.

  2. +++ b/core/modules/node/src/NodeAdministrativeField.php
    @@ -0,0 +1,39 @@
    +/**
    + * Status field of node.
    + */
    +class NodeAdministrativeField extends FieldItemList {
    

    Status field? I think it applies to more than that?

    And why do we need this administrative field class? Please add a comment.

    And where is this class used? Shouldn't the NodeAccessController cover this already?

berdir’s picture

1. Because NodeForm is not doing that either.

2. That class is dead, accidently ended up in the patch again.

klausi’s picture

Then the test case is flawed, because it claims that $chuck_norris is all mighty having only the "bypass node access" permission.

berdir’s picture

Status: Needs work » Needs review
StatusFileSize
new8.79 KB
new4.35 KB

Yep, it is. The uid 1 problem again.

berdir’s picture

I will update the change record at https://www.drupal.org/node/2101719 to mention the new easier way for base field access, no need to add a new one IMHO.

effulgentsia’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

I like the approach in #26. Patch looks great to me, but the issue summary is now out of date.

effulgentsia’s picture

Would it make sense to convert NodeForm::form() to use this as part of this patch, or is there a reason for that to be done separately?

klausi’s picture

  1. +++ b/core/modules/node/src/NodeAccessController.php
    @@ -131,6 +133,21 @@ protected function checkCreateAccess(AccountInterface $account, array $context,
    +    return parent::checkFieldAccess($operation, $field_definition, $account, $items);
    

    Not really useful to call the parent here, just return TRUE? And this should have a comment like "Per default all node fields can be viewed."

  2. +++ b/core/modules/node/src/Tests/NodeFieldAccessTest.php
    @@ -0,0 +1,128 @@
    +      //'uid' => $chuck_norris->id(),
    

    This should be removed.

Content types have the "Display author and date information" config option. Shouldn't we deny view access to the node author and the created date if this option is set? Might be a consideration for a followup issue.

berdir’s picture

#2226493: Apply formatters and widgets to Node base fields should take care of removing the manual access checks I think.

I don't think we should restrict access based on that setting. That is about visiblity of that default output, not access. It's perfectly valid to disable that and show that information in a different way.

berdir’s picture

Assigned: guedressel » Unassigned
Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs issue summary update +beta target
StatusFileSize
new8.75 KB
new494 bytes

#31.1: Can't imagine why now, but would not be the first time we'd later on add something to the base class, so I'd prefer calling it.
#32.2, Ups, debug left-over, removed.

Updated the issue summary.

Status: Needs review » Needs work

The last submitted patch, 33: node-base_fields_default_access-2098355-33.patch, failed testing.

berdir’s picture

Status: Needs work » Needs review
StatusFileSize
new8.74 KB

AccessController is now AccessControlHandler.

Re-roll proudly presented by git rebase.

effulgentsia’s picture

Status: Needs review » Reviewed & tested by the community

:)

xjm’s picture

Category: Task » Bug report
Parent issue: » #2028027: [META] Missing access control for base fields
xjm’s picture

Title: Implement default access for all node fields » Missing default access for all node fields
fago’s picture

Thanks berdir, patch looks great - I second the RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 8d61447 and pushed to 8.0.x. Thanks!

  • alexpott committed 8d61447 on 8.0.x
    Issue #2098355 by Berdir, guedressel | fago: Fixed Missing default...
andypost’s picture

+++ b/core/modules/node/src/NodeAccessControlHandler.php
@@ -129,6 +131,21 @@ protected function checkCreateAccess(AccountInterface $account, array $context,
+    $read_only_fields = array('changed', 'revision_timestamp', 'revision_uid');
+    if ($operation == 'edit' && in_array($field_definition->getName(), $administrative_fields)) {

I was wondered by "readonly" because there's setReadOnly(TRUE) for some base fields but seems that have different meaning

Status: Fixed » Closed (fixed)

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