Problem/Motivation
Flag module allows an admin to determine which roles can use a particular flag. This access control is stored as an array of role IDs in the flag object, and in turn saved in the serialized options in the {flag} table.
This has a number of drawbacks:
- The user permissions page doesn't give a clear view of what a user can achieve with respect to Flag module
- Role IDs are not portable
- A flag and its permissions can't be separated. In times of features and exported configuration, it is quite likely that one feature will set up a flag and another feature set the permissions for it. Since the flag permissions are stored in the flag object itself – not as a standard permission – you can't really export flags and permissions separately. The problem can be worked around using Features Override, but it would be nice if this was not necessary.
- More philosophically, keeping what are effectively permissions inside a flag means that flag is managing its own permissions system rather than letting Drupal core do it.
Proposed resolution
Change flags to use standard user permissions, with permissions per flag:
- flag entities with flag 'foo'
- unflag entities with flag 'foo'
The UI in the flag admin form thus reads and saves standard permissions.
Remaining tasks
- Discuss whether this is an approach more people would find useful.
- Implement it.
- Test the implementation.
User interface changes
Access to flags can now be set in the main user permissions admin page as well as on the flag.
API changes
None that affect how other modules use Flag.
Comment | File | Size | Author |
---|---|---|---|
#37 | 1525242.37.flag_.flag-permissions.patch | 19.08 KB | joachim |
#32 | 1525242.32.flag_.flag-permissions.patch | 18.97 KB | joachim |
#31 | 1525242.31.flag_.flag-permissions.patch | 18.24 KB | joachim |
#28 | 1525242.28.flag_.flag-permissions.patch | 17.27 KB | joachim |
#26 | 1525242.26.flag_.flag-permissions.patch | 16.79 KB | joachim |
Comments
Comment #1
Itangalo CreditAttribution: Itangalo commentedI'm overriding the Flag permissions with standard permissions in a custom module I have – for allowing granular export. The code I'm using would be the base for a Flag patch, if more people find this useful.
Comment #2
hefox CreditAttribution: hefox commentedInput formats switched completely over to using permission table, so it seems reasonable for flag to do the same.
Not sure, but flag currently has the issue that it stores it as role id's so doesn't transfer well to other sites with different roles (and can cause a security issue on the other site due to mismatch?). This would address that issue as well (since features role, perm support doesn't use rids).
Means about 4 permissions per flag: flag [flag name] content, unflag [flag name] content, flag [flag name] content, flag [flag name] own content, unflag [flag name] content.
could likely do something where keep the same ui, but save to permissions table for role settings, else just do like formats did (which I'm not totally sure XD).
Would probably mean some sort of handling for depracted flag definations, etc..
Comment #3
Itangalo CreditAttribution: Itangalo commented#2: I was thinking adding a new, simple, option on top of the existing permissions settings, but yeah – it makes sense to move all the permissions to the standard permissions table.
Currently Flag has hooks for altering these permissions. I'm not sure how these would translate if the permissions are moved.
Comment #4
Scyther CreditAttribution: Scyther commentedThis looks good!
Comment #5
joachim CreditAttribution: joachim commented> Means about 4 permissions per flag: flag [flag name] content, unflag [flag name] content, flag [flag name] content, flag [flag name] own content, unflag [flag name] content.
Probably only two for now:
- 'flag FLAGNAME content'
- 'unflag FLAGNAME content'
To have 'own' permissions, we need to have a notion of which flag types support it: see #879988: Flag permission for 'own entities', which I've marked as a follow-on to this.
Comment #6
joachim CreditAttribution: joachim commentedAssigning this to myself.
Comment #7
joachim CreditAttribution: joachim commentedAdding the Needs change notification tag. This should be created as a stub before this patch is committed, so that the hook_update_n() that sets up permissions based on flags can give users a link to it.
The reason for this is that this change will introduct a significant change in access to flag properties: users who can admin permissions but can't admin flags will be able to change access to a flag, whereas before they could not. This is something site admins need to be made aware of, as it could have implications for their site roles and access.
Comment #8
joachim CreditAttribution: joachim commentedThis is a work in progress:
- the update path needs testing and possibly tweaking, as I'm not sure why on my copy flags are still showing they have a roles array.
- some things need changing in flag export.
- I suspect we may need to change the flag API version to 3 to reflect that we no longer have a roles array stored in the flag object.
- possibly need a form validation on the main permissions form to warn of incompatible permissions, such as:
-- can't have unflag permission without flag permission
-- can't have only flag permission without an 'unflag denied' message
(These special rules are a good example of why flag handling its access in-house has advantages!)
Testing or review of what there is so far would be very welcome!
Comment #10
joachim CreditAttribution: joachim commentedFixed the problem the testbot was dying on.
Comment #11
joachim CreditAttribution: joachim commentedI've changed the issue summary, as it was out of sync with what I'm doing in the patch.
Previously: suggested adding an option to each flag 'use core permissions'
Changed to: all flags provide core permissions.
This is considerably simpler to implement, as it's replacing the flag access system, rather than implementing a new system to live in parallel with the current one!
Comment #12
Scyther CreditAttribution: Scyther commentedShouldn't that be inside the foreach loop?
Comment #13
joachim CreditAttribution: joachim commentedOh heck yes! Good catch! :D
Comment #14
joachim CreditAttribution: joachim commentedUpdated patch with that fix. See #8 for list of things still to do.
Comment #15
joachim CreditAttribution: joachim commentedUpdate function works fine now :)
Comment #16
joachim CreditAttribution: joachim commentedTagging.
Comment #17
joachim CreditAttribution: joachim commentedI've figured out what's going wrong in the update; will work on it soon.
In the meantime do please test this as a fresh install and report any findings.
Comment #18
joachim CreditAttribution: joachim commentedHere's the updated patch.
It would be great if this could see some testing -- it's a pretty big change!
Comment #19
joachim CreditAttribution: joachim commentedNeeds work.
I realized that loading roles into the flag object with user_roles() is adding a ton of queries to flag loading, and flag loading happens on most page requests.
Currently reworking this so we use user_access() when needed instead.
Comment #20
joachim CreditAttribution: joachim commentedComment #22
joachim CreditAttribution: joachim commentedUpdated tests.
I think we're going to have to give validation of user permissions a miss, because of #222380: No error highlighting on form checkbox or radio input types. Showing validation errors on such a large form, and with no easy way of finding the offending element is just going to be a UX horror.
Comment #24
joachim CreditAttribution: joachim commentedTest was failing because permissions cache needed clearing in the test.
But this also let me discover that changing the flag name caused permissions pollution. Fixed that too.
Comment #26
joachim CreditAttribution: joachim commentedFixed the test again.
Comment #27
joachim CreditAttribution: joachim commentedFinally! :D
Comment #28
joachim CreditAttribution: joachim commentedUpdated patch which restores the default values for the role access checkboxes when creating a new flag.
Comment #29
joachim CreditAttribution: joachim commentedAny more reviews before I commit this?
Comment #30
joachim CreditAttribution: joachim commentedAnother thing to do: somehow handle the change from $flag->roles to permissions in the flag update system.
What I'm thinking is to change the key to $flag->import_roles and then take those as incoming data only when saving a new flag (ie with no fid).
Comment #31
joachim CreditAttribution: joachim commentedAdded updating of roles on API 2 flags in code.
Comment #32
joachim CreditAttribution: joachim commentedAnd another thing. Disabling $flag->roles no longer makes sense. If you want to lock that, use something that locks permissions generally.
Comment #33
socketwench CreditAttribution: socketwench commentedYikes. Flag_bookmark tosses a nasty error when enabling:
Interestingly, the module does enable.
Beyond that, everything tests cleans and functions correctly.
Comment #34
joachim CreditAttribution: joachim commentedThanks for trying it out! I didn't think of enabling the bookmark module... for that matter, not 100% I've tested creating a new flag, which may have the same sort of problem...
> Column 'module' cannot be null: INSERT INTO {role_permission} (rid, [error]
permission, module)
Quite a showstopper! This is because the flag doesn't exist at this point, so hook_permission() doesn't define permissions for it, which means that the attempt to give users those permissions is trying to grant permissions that system doesn't know about.
Urgh. No idea how to resolve that.
Comment #35
socketwench CreditAttribution: socketwench commentedForgot to mark as 'needs work'.
Comment #36
joachim CreditAttribution: joachim commentedAh, just a cache clear thing. Phew. Will fix later.
Comment #37
joachim CreditAttribution: joachim commentedYet another patch :)
Comment #38
socketwench CreditAttribution: socketwench commentedThere we go! Enables clean, tests clean, confirmed with manual testing. Marking RTBC!
Comment #39
joachim CreditAttribution: joachim commentedWoohoo!!! let's get this in!
Thanks for the reviews.
Comment #40
joachim CreditAttribution: joachim commentedOh yes I need to write the change notification too.
Comment #41
joachim CreditAttribution: joachim commentedDone.
Comment #42
joachim CreditAttribution: joachim commentedComment #43.0
(not verified) CreditAttribution: commentedexpanded problems; changed proposed resolution to reflect actual patch!