Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Add a configuration entity access controller with some extra super-duper amazing access control features that are available only to those entities who can call themselves configuration.
Initially, add support for enable
and disable
operations, as those are a combination of an access check for the update
permission, and a check to see whether the entity can technically be enabled or disabled at all.
Later we may add support for a duplicate
operation in combination with a specific link template key and an entity list controller operation.
Comment | File | Size | Author |
---|---|---|---|
#51 | drupal_2200183_51.patch | 12.93 KB | Xano |
Comments
Comment #1
XanoComment #2
XanoTo do: make any config entity type's access controller extend ConfigAccessController.
Comment #4
XanoComment #6
XanoComment #8
XanoComment #9
tim.plunkettLet's rename this ConfigEntityAccessController, its a bit clearer (we should have another for ConfigStorageController too)
This line is the only part of the patch that is confusing. 'toggleable' is not really a word, and it needs a code comment, and the $entity->status() : !$entity->status() is really odd looking...
Nice!
Comment #10
damiankloip CreditAttribution: damiankloip commentedSo what happens if you want to check if someone has access to enable an entity that is currently already enabled? This patch means it will always deny access. Yeah, that is what we want when building operation links, but that seems like the only time we want that behaviour?
Comment #11
XanoComment #14
tim.plunkettI just meant the ConfigEntityAccessController class itself, not sandwiching 'Entity' in after the entity type name.
Love the commit message though :)
Comment #15
Xano#11 was faulty. Refactoring went wrong in PhpStorm. Because of that, the attached interdiff is against #8.
On a related note: #2201137: Introduce a "duplicate" entity operation.
Comment #16
Xano15: drupal_2200183_14.patch queued for re-testing.
Comment #17
Xano15: drupal_2200183_14.patch queued for re-testing.
Comment #19
XanoComment #20
yanniboi CreditAttribution: yanniboi commentedI've had a look at this:
Only thing I could spot is you haven't fixed the terminology of 'toggleable' as @tim.plunkett pointed out.
If you fix that I would say this is RTBC.
Comment #21
XanoCool! I changed the variable name now. Forgot to do that last time.
Comment #22
yanniboi CreditAttribution: yanniboi commentedGreat, this looks good to me!
Comment #23
damiankloip CreditAttribution: damiankloip commentedS0, regarding my comment in #10, we are happy that when a config entity is enabled, access for ENTITY_TYPE:enable will always be false, regardless of the usage?
Comment #24
XanoI think we do, as it makes no sense to have access to enable a particular entity in its current state if you cannot enable it anyway. Access control depends on the entity's state.
Comment #26
XanoRe-roll.
Comment #28
XanoComment #29
XanoRTBC per #22.
Comment #30
alexpott#10 does seem like a problem - and the logic is wrong with the current patch. A user who has access to enable a config entity should have that access regardless of the state of that entity.
Comment #31
XanoWhen would that be a problem? Entity access control is bound to an entity's state anyway. That's how the entire system currently works.
Comment #32
tstoecklerYeah, I'm with Xano on this one. Why would you want to allow enabling an already enabled entity? Can you elaborate @alexpott or @damiankloip?
Comment #33
Xano@tim.plunkett did a similar thing in #2235347: Field instance operations are out of order for deleting field instance configs.Tim obviously did no such thing. My sleepy other me must have posted this.
Comment #34
tim.plunkettWhat I did in the other issue is not related, because it's about delete.
It's not as much about the state of the entity, IMO.
If the entity is enabled, and we allow you to enable it, it's a no-op.
Do we want to deny access for no-op cases?
That's the question we need to answer here.
I don't have a strong opinion either way.
Comment #35
BerdirThe last patch in #2084323: EntityForm::actions() adds 'delete' without checking access is about the same, that is about delete there but it's exactly the same pattern for deciding that access is not allowed if the entity is in a given state (new).
Comment #36
tstoecklerSo in theory - from an API design perspective - I don't have a strong preference either. However due to the fact that we bind the visibility of the operation links to the access of the operation itself already I see no reason to loosen that binding here just for the sake of allowing people to enable already enabled entities on an API level. That's the reason why I'm in favor of that approach.
Comment #37
BerdirYeah, we obviously do not want to show enable for a config entity that is already enabled, the only question I think is who is responsible for preventing that, is it the list builder that shouldn't even try to show that operation or should the operation exist but you wouldn't have access?
Given that we eventually ( in 9.x or contrib) want to move toward separately defined entity operations as plugins or whatever and tie them even more to the entity access control system, it makes more sense for me as well to handle visibility of operations in the access class.
Comment #38
XanoAre there any concrete arguments against doing this? To me, this is about asking access controllers Can this user perform this operation on this entity, yes or no?. We so far do not and probably should not not care about the internals, and since entity access control returns computed values, the possible use cases are limited to deciding whether a user can or cannot do something anyway.
Regardless, this patch does make writing secure and sensible code a little easier, and we can more easily change the internals after release, because calling code will no longer have to check multiple requirements when it comes to operations.
Comment #39
tstoecklerWell, this is needs review at least.
Comment #40
Xano28: drupal_2200183_28.patch queued for re-testing.
Comment #42
XanoRe-roll.
Comment #43
Xano42: drupal_2200183_42.patch queued for re-testing.
Comment #44
Xano42: drupal_2200183_42.patch queued for re-testing.
Comment #45
tstoecklerAssigning to @alexpott as apparently there's no further progress here.
So @tim.plunkett doesn't really have a strong preference and it seems @Berdir seems to be leaning slightly towards going with the current approach. @Xano and I also favor the current approach.
@alexpott Do you feel strongly that the current approach is incorrect? And if so, can you explain why? Thanks a lot.
Comment #46
Xano42: drupal_2200183_42.patch queued for re-testing.
Comment #47
alexpottOkay let's proceed with this. I feel it might come back to bite us since access != visibility but I'm not going to argue anymore - as @Xano says it does make things more secure by default.
Comment #48
XanoAlright. Putting this back to RTBC as per #22.
Comment #49
Xano42: drupal_2200183_42.patch queued for re-testing.
Comment #51
XanoRe-roll.
Comment #52
XanoRTBC as per #22 if the tests pass.
Comment #53
damiankloip CreditAttribution: damiankloip commentedSo say I am trying to enable some entity via a rest api I have created for my site, I would just get a 403? So I could not use entity access alone for anything like that?
Comment #54
XanoYou can still enable the entity. You *could* respond with a 403 by checking access, but you are not required to.
Comment #55
damiankloip CreditAttribution: damiankloip commentedBut how does that work generically? You cannot just have a call that enables things without access checking.
Comment #56
XanoI don't know. Is denying access a problem in this case?
Comment #57
damiankloip CreditAttribution: damiankloip commentedThen how do you know if the entity is already enabled or you actually don't have access? :)
Comment #58
XanoYou won't be able to know if the entity is already enabled without this check either. You will just get a 200 instead of a 403 regardless of the entity was enabled or disabled before the request.
Comment #60
XanoComment #61
tstoecklerHmmm... that's a very interesting use-case/question @damiankloip. I suppose 404 would be a more semantic response code for an enabling an already enabled entity. Then it would be consistent with e.g. delete:
That said, enable/disable, is really a different animal that delete (especially in REST-world), so maybe the above is not really a very semantic analogy. Maybe we really do want to return 200 in that case. Hmm...
Comment #62
damiankloip CreditAttribution: damiankloip commentedIf I was building an API, and from past experience of its consumption, returning a 200 in the case it is already enabled usually works out best. Which kind of goes against how this patch would work? or not?
Comment #63
BerdirInteresting question.
Keep in mind that...
- We have no actual integration with entity operations/links in rest.module. The links are there based on the link templates, but they are not actually useful for rest.module because it doesn't implement them nor are they how rest.module works otherwise. A delete is *not* "POST /node/1/delete", it's "DELETE /node/1".
The way to enable/disable a config entity *would* be to do a POST and change the status property. and we have no way to interact or check that, because config entity entities have no field/property level access control or validation. At least not until we have a typed data wrapper system that would work based on the config schema.
*Would* because we have no config entity integration *at all* for rest.module right now anyway ;)
So based on that, it's a problem that we currently don't have (because we have far bigger problems before we would even get to this ;)) but it's still an interesting use case why this would be the wrong approach.
Comment #64
damiankloip CreditAttribution: damiankloip commentedSure, I am saying if I was building an API though :) Not just what is provided by REST module. Yes, the examples from #61 were not correct but this is not a question about guidelines of a REST API :)
Maybe I misunderstand, but I am not reading into it as much as you are ....
I am thinking I basically cannot do this:
Comment #65
tstoecklerWell, that would work fine. If the entity is enabled, then the acces() call would yield FALSE, but in that case the ->enable() call would be a no-op anyway. So the code would work either way. Or am I missing something?
Comment #66
damiankloip CreditAttribution: damiankloip commentedI would rather a no-op and a sensible return value than an access denied. The point is I cannot just call access() with this patch. So if I did get a 403 back, is it because I am really not allowed, or that the entity is already enabled? If I try to enable and already enabled entity, returning with access denied would not be useful IMO.
Comment #67
jcnventura CreditAttribution: jcnventura commentedIf someone works at this in Montpellier, feel free to add it back
Comment #79
smustgrave CreditAttribution: smustgrave at Mobomo commentedMoving to NW for some of the follow up discussion after it moved to NR
Wondering if this is still needed for 9.5?