Problem/Motivation
Per #2294177-5: Allow Drupal\Core to provide [config] entity types, we want to move some config entity types from a core module into core/lib, but that's impeded for entity types that define an "admin_permission" in their annotation, since hook_permissions() is a hook, and we don't currently support hook implementations in core/lib.
Proposed resolution
Change hook_permissions() to a YAML file, which is more inline with D8 patterns. Then core.permissions.yml could define permissions needed by core/lib classes.
Remaining tasks
Decide if that's still an allowable change for D8. If so, do it. If not, decide if system_permissions() is an acceptable place in which to define those permissions.
Comment | File | Size | Author |
---|---|---|---|
#77 | d8.oops_.patch | 553 bytes | damiankloip |
#71 | interdiff.txt | 1.48 KB | dawehner |
#71 | 2295469-71.patch | 30.41 KB | dawehner |
#69 | interdiff.txt | 3.79 KB | dawehner |
#69 | 2295469-69.patch | 30.41 KB | dawehner |
Comments
Comment #1
xjmComment #2
dawehnerReally like that.
There are modules, especially in contrib which provide permissions based upon config entities, like node types, so we have
to provide a way to register dynamic ones, similar to routing.
There will be issues with some permission descriptions in core which are dynamic, depending on the access of the user. Yes, I do think this is total BS and not doing that any longer would be a win, as it is fragil by nature.
If we care about this API change so late we can always support both but given that the change itself will not be hard for module developers and people learn the D8 APIs will think that the yml file is way more consistent.
procrastination!
Comment #3
BerdirThought that @timplunkett already opened an issue for this quite some time ago.
Some things to consider:
- A fair amount of permissions are dynamic... so we would also need object callbacks similar to local tasks and so on. Making that part more complex than it is now...
- It would also mean that yet another system needs custom localization and integration with potx to identify translatable strings.
Comment #4
effulgentsia CreditAttribution: effulgentsia commentedRe #3.2: #2296219: Create schema for non-config YAML files?
Comment #5
catchSince this isn't a runtime hook, I wouldn't rule out adding YAML and keeping hook_permission() for bc. Although the dynamic permissions is tricky.
Changing this from 'beta deadline' to 'minor verson target'. If there's a good reason to not put it into 8.x when it comes down to it, we can bump it to 9.x at that point.
Comment #6
dawehnerI am not sure at which level we do want to sort the permissions by module name.
Comment #8
dawehnerThere are a couple of places where the module handler is used to dermine the list of available permissions.
Comment #10
dawehnerA bit more work.
Comment #11
tim.plunkettWhy two lines here and one elsewhere?
Two spaces after the =
Yay! Inject the classes with what we actually need.
Off-topic thought: For non-alter hooks that we still invoke, why not wrap them in a service so we can change them out later?
Keying by a string with quotes looks weird, but nothing wrong with it.
Do we want to keep the quotes around these keys? They're optional for the first two, and we could always change it to restrict_access if we wanted.
Comment #12
geerlingguy CreditAttribution: geerlingguy commentedRe: your point about quoted YAML keys. I have almost never seen an example of YAML with spaces in the keys*, and I've also wondered why the Drupalism of spaces in permission machine names has persisted so long. I wholeheartedly vote for using underscores where possible (so
restrict_access
), and would also vote to move to better machine names (no spaces) for permissions, but that would probably need to be a separate discussion/issue.*One exception: When a key would contain special YAML characters, like
'>>':'value'
, but that, too, is rare and feels wrong as well.Comment #13
dawehnerGood idea!
Do you think that we could convert the permissions with a space to "_" and with "_" to "__" ? This could be even done in a temporary layer to support both.
Comment #14
geerlingguy CreditAttribution: geerlingguy commentedAre there permissions with underscores? I don't ever remember seeing any, but I guess they exist. Could we just leave the ones that have underscores alone?
Comment #15
BerdirYou can end up with permissions in node type specific permissions for example, which often include _ or another other machine-name based permissions.
Comment #16
dawehnerYeah it also happens really easy if you mention the module name in there, just as example.
Sounds like a good idea, but are there actually a lot still?
It looks really wrong to have quotes around just some of them. I would love to change the permissions to machine only in a follow up.
Comment #17
geerlingguy CreditAttribution: geerlingguy commentedI just added #2309869: Use proper machine names for permissions, and set it to postponed on this issue until the conversion has been completed.
Comment #18
tim.plunkettAgreed the permission names should happen in a follow-up.
I still think we shouldn't quote these. Supporting both
restrict access
for old-style hooks andrestrict_access
for YAML seems fineComment #19
dawehnerThis just removes the quotes, any additional work should be discussed on top of this.
Comment #20
tim.plunkettOne of the reasons we wanted this is so that Drupal\Core can provide an entity type and the relevant permissions, without needing a module. Can we still accomplish this, maybe by using container.namespaces?
It'd be really nice to split up this method, and provide a unit test for it!
Comment #21
dawehnerWorked on some unit tests.
Comment #22
tim.plunkettThat is *exactly* what I envisioned, AND it uses vfsStream! Very cool.
I think the follow-up about quoted strings is fine.
Comment #23
xjmComment #24
dawehnerAdded a change record: https://www.drupal.org/node/2311427
Comment #25
xjmThanks for the change record!
Middle-of-night thought: Do we have a sense of the performance implications of this, were we to move most permission definitions to YAML? Presumably the discovery is cached somewhere? And caching nonwithstanding, will the admin permissions page crash and burn like admin/config/development/testing currently does on first visit if you don't have approximately one bajillion memory? (The page is already touch-and-go in D7 and D6 with a lot of contrib).
Also I don't see any mention of translations on the issue after @Berdir's comment, which seemed to suggest it'd be more complicated than simply StringTranslationTrait and a passed-in translation. Am I missing something?
Comment #26
xjmOh, when adding change records, remember to add a reference to the issue so it doesn't get lost forever and so that it appears in the sidebar. :) I also have no idea how you keep filing these with a blank project which is a required field... Anyway I've updated https://www.drupal.org/node/2311427 with the reference:
https://www.drupal.org/node/2311427/revisions/view/7479921/7480951
Comment #27
BerdirPerformance: AFAIK, the hook is only used on the permission UI page and simpletest uses it to validate permissions when you create users (where we until recently had a cache and removed it, but I don't think that's a problem). At runtime, permissions are just strings, nobody cares if they are defined or not. So it's not much of a problem. For the UI, the only problem is count($roles) * count($permissions) => lots of checkboxes, it doesn't matter much if they're defined in files or not. We're talking abbout max 1 file per module, while we often have dozens of tests in modules.
Translations: The main problem is discovering translatable strings, which is something that potx/localize.drupal.org need to solve, it's not something that core can provide.
Comment #28
dawehnerThere is one general advantage as described by catch in #2295469-5: Add support for static permission definitions with *.permissions.yml hook_permission()/yml parsing is just executed for the admin page
so there is a small, neglectable, boost for any other page as the module files will be smaller. HEAD just does a invokeAll('permission') so this patch also does not introduce caching of them.
I don't think though it is worth, at least for now.
I cannot proove this but for core services we always inject the string translation as well, and just use the trait for t()/formatPlural(). Yes potx would need another patch, but they are really used to scanning
all YML files out there.
Someone has to explain me that: All I do is to copy&paste the title of the issue, and do some dishwashing until the autocomplete is done and then hit save.
Comment #29
yched CreditAttribution: yched commentedWhat's the use of PermissionsManager::$permissions if getPermissions() always rebuilds the full list ? As is, this property acts as a static cache we write to but never read from ?
Also, I tried (but failed) to have us standardize on FooPluginManager for plugin managers. I lost that battle, so we currently have a lot of FooManagers that are plugin managers. PermissionsManager, in turn, is *not* a plugin manager, and more like ModuleHandler, so why not PermissionHandler ?
Comment #30
catchComment #31
dawehnerYeah when I start writing it, I thought caching would be required.
I don't care. We have all kind of names all over the place. As a non-native speaker handle and manage is kind of similar anyway.
Comment #33
dawehnerWhy should it work that easy ...
Comment #34
tim.plunkettO_o?!
Comment #35
dawehner@tim.plunkett
Nice, three attemps for that trivial change
@xjm
#2311935: Add support for .permissions.yml files
Comment #36
dawehnerI am bored so here is just another one.
Comment #37
tim.plunkettThanks, that last patch looks good, and thanks for the translation extractor issue!
Comment #38
xjm+1, thanks @dawehner!
Comment #40
dawehnerReroll
Comment #41
kim.pepperSmall nitpick:
Should be plural: buildPermissionsYaml()
Comment #42
Gábor HojtsyI was asked to chime in for the localize.drupal.org effects. The issue summary does not make it clear if the YML file is the new suggested way of defining permissions or should be the only one for static permissions or not. The code both supports the hook and the YML file. Is the hook the long term (AKA Drupal 8 release) plan for defining any dynamic permissions? As for parsing the permission YML file, it is one more alongside the links.ymls, routing.yml, etc. #2311935: Add support for .permissions.yml files is a good start. @herom has some good ideas in #2088371-36: YAML discovery incompatible with translations to make this work with contrib's new YML files as well. Either way, we can continue here, and figure out the localize.drupal.org stuff later, its not a big deal at this point :)
Comment #43
dawehner@Gábor Hojtsy
Well, we cannot get rid of dynamic permissions like permissions based upon node types, but I think the YML file should be the way to go.
Comment #44
dawehnerComment #46
Gábor HojtsyRight, we do need dynamic permissions. The question was how. Would it be a plugin, referenced via a class file from the permissions YML (like tasks) or via a provider class like routes or via a hook like as is now. What's the eventual plan? :)
Comment #47
dawehnerReroll after tim's mega patch.
Ah yeah, one idea I do have in mind is to adapt the routes_callback pattern ([#2122201]) for permissions.
Comment #50
star-szrRerolled, just a context change in core/modules/user/user.services.yml.
Comment #51
tim.plunkett+1 for that in a follow-up
Comment #52
alexpottNeed to also remove the
use ModuleHandlerInterface
from this file.Missing a class property for this and let's call it yamlDiscovery() to be consistent.
Could just return the result here.
Very minor nit but can this be moved to the bottom of the class - it has very little to do with the functionality. In some ways I don't get why we have this method at all - like why not just inline with the sortPermissions method?
How is it possible for $this->moduleHandler to be set at this point?
Nice use of file system mocking!
Comment #53
dawehnerThank you for the review.
It never had a property and the only usage was removed from the patch itself.
Good point.
Moved the function. Well inlining a one-time method is a bad idea if you ask me. This makes it simply harder to understand, potentially harder to fix bugs
and especially there is no reason for optimizing the performance here.
No idea what I was thinking.
Comment #55
alexpottre #53.1 I meant core/modules/user/src/Form/UserPermissionsForm.php now has an unused use for ModuleHandlerInterface... ie.
can be removed.
Comment #56
dawehnerOH
I would have loved to use php 5.5 here.
Comment #58
dawehnerSorry for all that comments.
Comment #60
dawehnerFixed the silly test failure.
Comment #62
dawehnermeh.
Comment #65
m1r1k CreditAttribution: m1r1k commentedComment #66
dawehner--3way
helpedComment #67
m1r1k CreditAttribution: m1r1k commentedNow we can just hide it https://www.drupal.org/node/2324025
Comment #68
XanoWe should add an explanation to the @todo that illustrates why this needs to be done.
It's probably only a minor performance tweak, but shouldn't we sort permissions only when we need to?
@return array
is never acceptable documentation. Instead, document the array contents. In this case@return array[]
and the description should contain the actual structure or refer to documentation elsewhere that does.Same here.
Same here.
@return string[]
, and document that keys are module machine names.We also need an
@covers ::__construct
annotation inPermissionHandlerTest
.Comment #69
dawehnerIsn't that out of scope of this issue?
I would rather let the code be readable, instead of having better performance on a non existing edge case.
Fixed.
Comment #70
swentel CreditAttribution: swentel commentedTwo nitpicks:
80 chars
same here
- edit - note, looks good otherwise.
Comment #71
dawehnerCool, here is a nitpickfix.
Comment #72
tim.plunkettI think all reviews and nitpicks have been addressed.
Comment #74
webchickI actually think this is a good change to make, despite how late in the cycle. My rationale is from teaching module development for 5+ years at Lullabot. We would always use hook_perm (and later hook_permission) as the intro hook for new developers to get the lay of the land of how things are done in Drupal because it's very simple to wrap your head around. In Drupal 8 though, things these days are very rarely done with hooks, and when they are, they're generally done for event-style things, such as saving a node or running cron, not for "info-style" things which have almost exclusively moved elsewhere (and mostly to YAML). So by moving static permissions to YAML, it not only brings permissions more inline with what D8 does, but we also now regain a "simple" example to teach people before we thrust them into the thorn-covered land of routing.yml. ;)
dawehner walked me through the patch in IRC and I didn't see anything to really take issue with. The patch is very benign in that it leaves hook_permission() in place; I am concerned about what "phase 2" of switching hook_permission() to something else might entail and whether it'll be consistent with others, but in the worst case if we don't get to that we can always leave hook_permission() is as BC.
There were also concerns raised in IRC about whether or not moving to YAML, with its tempting human-editableness, could present a security risk but in the end these files are only loaded one place in core, which is on the permission form itself. Everywhere else is simple string matching, so we think we're covered there.
We also need the rest of the permissions converted. I talked to dawehner and he thinks he can script all of them in one go, which would be great. I'm about full-up on 5,000 sub-issue meta issues, esp. when I'm the lone committer this week. ;)
Therefore!
Committed and pushed to 8.x. Thanks!
Comment #75
dawehnerHere is an issue to convert all static yml files: #2328411: Convert all permissions to yml files and permission callbacks
Comment #76
star-szrReally happy to see this in! I definitely shouldn't be first in the commit message though :( filed https://github.com/dreditor/dreditor/issues/226 after some testing.
Comment #77
damiankloip CreditAttribution: damiankloip commentedSmall point, Looks like some stray backticks crept in!
Comment #78
dawehnerOh
Comment #79
alexpottCommitted c1dd108 and pushed to 8.0.x. Thanks!
Comment #81
clemens.tolboomThis patch makes calling module_invoke($module, 'permissions') useless. So I created followup #2342229: Add permissionByModule to user.permissions service