feat: New granular save and edit permissions#7896
feat: New granular save and edit permissions#7896lukaskleinschmidt wants to merge 12 commits intogetkirby:develop-minorfrom
Conversation
| } | ||
| } | ||
|
|
||
| public function for( |
There was a problem hiding this comment.
I noticed that the bool return type is expected but not really enforced and could lead to errors.
Maybe it should be more strict and always return false if a check does not yield the expected return type?
Example:
$permissions->for('pages') would throw an exception.
$extendedActions might deviate from the convention.
There was a problem hiding this comment.
You mean that an $extendedAction could be defined with a non-boolean value, which will make return $this->actions[$category][$action]; try to return it, causing a TypeError?
To be honest I prefer a TypeError over silent conversion to false (makes it easier to spot issues in the code). However I think PHP sometimes tries to be smart about the conversion and doesn't always trigger a TypeError. So an alternative could be to throw a LogicException for any values that aren't booleans.
There was a problem hiding this comment.
Throwing a exception would make the intended behaviour consistent. So a LogicException for non false values works for me.
There was a problem hiding this comment.
Now that I'm looking at it again the main headache came from the imposed bool $default = false.
I would assume it to return the default if no matching or expected permission was found.
There was a problem hiding this comment.
Hm, but I think there's a difference between "no matching permission" (which is the use case for the default) and "invalid permission" (which points to a bug).
There was a problem hiding this comment.
fa1acb0 I could also add the exception in the translations but not sure when/why to pick one over the other.
throw new LogicException(
key: 'permission.type',
data: ['key' => $key, 'type' => gettype($permission)]
);There was a problem hiding this comment.
In an ideal world, all exceptions would be translated. However we sometimes omit that for exceptions that are unlikely to be thrown to the user and/or unlikely to occur at all. Because every translation key needs to be translated by all our community translators, but it doesn't really seem worth it for all exceptions.
lukasbestle
left a comment
There was a problem hiding this comment.
General comment: The alias solution for the old update permission (with callback and array support) looks very useful and clean. 👍 At first glance I think it perfectly covers the migration matrix from the concept, we should test the different variants at the end of review before the PR gets merged though.
Three more uses of the update permission we IMO need to adapt:
config/areas/languages/views.php:35Panel\File::isFocusable()Panel\Ui\Buttons\LanguageSettingsButton
| ]; | ||
|
|
||
| // normalize core actions | ||
| $this->actions = $this->normalize( |
There was a problem hiding this comment.
Question: As the update permissions will be deprecated and aliased, do we need to set them in the actions array? I honestly don't know how the aliases in individual model blueprint classes interact with the Permissions class.
There was a problem hiding this comment.
Could you elaborate a bit more. Don't quite get the implication right now.
There was a problem hiding this comment.
I don't either TBH. We will need to look into this in more detail.
src/Cms/Permissions.php
Outdated
|
|
||
| if (is_array($settings) === true) { | ||
| return $this->setCategories($settings); | ||
| protected function normalize( |
There was a problem hiding this comment.
Thought: TBH I think this combined normalize() method is quite hard to read. We are actually trying to get away from long methods with a lot of logic. The old separate methods were a lot more readable and easier to follow.
There was a problem hiding this comment.
Problem was that I need the context of what was passed in initially to not overwrite already set values with an alias (L200). The seperate methods would make it way harder to keep that context.
I also dont like the big nested foreach + if list but it was actually the most sane way I could think of with all the back referencing and only setting not yet set values during the normalization.
There was a problem hiding this comment.
I will have another stab at this and see if I can make it more maintainable
There was a problem hiding this comment.
I think it also depends on the other question above. Maybe @bastianallgeier can comment on that.
There was a problem hiding this comment.
Just added a refactored version for the normalization 0c0b390 that makes it a bit more easy to read
There was a problem hiding this comment.
I like the new refactored version for its readability. However I'm still not 100% sure the aliasing should happen in this class. We will discuss this in our team meeting today.
|
I think the languages do not use content versions/drafts at all. So not sure how we would tie that in or if it makes sense to add the distinction. |
Yes, language settings and language variables are saved directly to the PHP files, there are currently no versions for those. We could add version support later and we also have plans for separate permissions for language variables. But that doesn't need to happen in this PR. I think it's fine to keep |
|
|
||
| public function for( | ||
| string|null $category = null, | ||
| string $category, |
There was a problem hiding this comment.
Question: Is there a specific reason why we need to remove the option to pass $category = null? This would be a breaking change.
There was a problem hiding this comment.
No. Just figured there would be no use for this method without at least specificing a category. But could be rolled back easily
There was a problem hiding this comment.
You are right, that doesn't make any sense. The old implementation requires $category to be string as all called methods and the array access cannot deal with null.
Suggestion: For this PR, keep the nullable argument but check for it and call:
Helpers::deprecated('Passing `$category = null` to `Permissions::for()` is not supported', 'permissions-for-category-null')
We could then switch it over in 6.0, which is technically a breaking change then but probably not relevant in practice. But with the deprecation warning, we could find any remaining uses of this early.
Description
Adds granular more
saveandeditpermissions for versioned content.There are still a few concerns regarding the implementation and possible side effects.
I'm not completely happy with the current Vue implementation as it requires passing down the permissions to the
FormControlscomponent.But I haven't found a better way to do it yet.
Second the way form fields currently get disabled in the
Kirby\Form\Fieldsclass is tied to a specific action name.Which kinda works for the use case here, but it clashes for example with the permissions for langugages which only have a
updatepermission and don't use versioned content. Which is not an issue as far as I can tell, but still not ideal.