Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix caching issues with Event permissions #12769

Merged
merged 2 commits into from
Oct 30, 2018

Conversation

mattwire
Copy link
Contributor

@mattwire mattwire commented Sep 4, 2018

Overview

Follow up to #12424

Calling checkPermission() with an event ID and then with no ID (to get all permissions) only returns permission for the first event, meaning all subsequent events are returned as having no permission when they probably do.

Before

If CRM_Event_BAO_Event::checkPermission() is called with a single event ID the static cache is "populated" but actually only has a single event ID in. If the same function is called again with no ID the cache is returned rather than building an array of all events with permissions.

After

Refactor CRM_Event_BAO_Event::checkPermission() into two separate functions as they return two different things - an array of permissions in the case of all events, and TRUE/FALSE in the case of a single event ID.
A separate cache is implemented for all event permissions and for a single event permission.
So if you:

  1. Call checkPermission() with an event ID you will get a TRUE/FALSE response and that will be cached.
  2. Call checkPermission() with no event ID you will be "redirected" to getAllPermissions() which will build it's own cache and return an array of all event permissions.

Technical Details

If CRM_Event_BAO_Event::checkPermission() is called with a single event ID the static cache is "populated" but actually only has a single event ID in. If the same function is called again with no ID the cache is returned rather than building an array of all events with permissions.

Comments

@alifrumin Would you be able to review this one? It may need some further work on the existing unit tests as well if you have chance to take a look?

@alifrumin
Copy link
Contributor

alifrumin commented Sep 5, 2018

Hey @mattwire, I can take a look at this later this week.

@totten totten added the master label Sep 5, 2018
@alifrumin
Copy link
Contributor

alifrumin commented Sep 7, 2018

I tested this lightly locally,

I logged in as a user with the permission "CiviEvent: access CiviEvent" and could create but not edit an event.

I got a permissions error immediately after creating the event:

error

Expected behaviour as outlined in #12424 is that users with the permission "CiviEvent: access CiviEvent" can create events and then edit the events they create.

I like the concept of the code @mattwire, thoughts?

*/
public static function checkPermission($eventId = NULL, $type = CRM_Core_Permission::VIEW) {
if (empty($eventId)) {
return self::getAllPermissions($type);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree - ideally add a deprecation notice

// Note: for a multisite setup, a user with edit all events, can edit all events
// including those from other sites
if (($type == CRM_Core_Permission::EDIT) && CRM_Core_Permission::check('edit all events')) {
Civi::$statics[__CLASS__]['permission'][$eventId] = TRUE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need an action nuance in your keys? ie

Civi::$statics[CLASS]['permission']['edit'][$eventId] = TRUE;
Civi::$statics[CLASS]['permission']['view'][$eventId] = TRUE;

(set both on edit perm, only one on view )

@mattwire mattwire changed the title Fix caching issues with Event permissions WIP Fix caching issues with Event permissions Sep 13, 2018
@mattwire mattwire force-pushed the civievent_permissions branch from aae6cec to f20dc79 Compare October 20, 2018 22:28
@mattwire
Copy link
Contributor Author

@alifrumin Do you have time to test this again? I've refactored it since you found the original error but it could really do with some more tests as it was a very messy function before.

@mattwire mattwire changed the title WIP Fix caching issues with Event permissions Fix caching issues with Event permissions Oct 23, 2018
@mattwire
Copy link
Contributor Author

@spalmstr Are you able to test this please? It relates to #11716

@alifrumin
Copy link
Contributor

Taking a look now

@alifrumin
Copy link
Contributor

I tested this by:

  1. logging into the demo site created by jenkins.
  2. creating a new drupal user "event" with the role "authenticated user"
  3. giving the "authenticated user" role the following permissions in civi:
  • CiviEvent: access CiviEvent
  • CiviCRM: access CiviCRM backend and API
  • CiviEvent: view event info -- I was prompted to when trying to view event info however according to the description of CiviEvent: access CiviEvent - "Create events, view all events, and view participant records (for visible contacts)" I should not need it.
  1. Logging in as the user "event"
  2. Attempting to create an event - I am able to see the form to create an event, however on save of the event, it seems the event is created but I do not have permission to edit it the event, see screenshot below. This is the same behavior as described on September 7th.

error

@mattwire mattwire force-pushed the civievent_permissions branch from f20dc79 to 01e5965 Compare October 24, 2018 15:20
@mattwire
Copy link
Contributor Author

@alifrumin Thanks. I just found the same thing :-( and realised how fragile it all is. So I've just written a pile of tests. testDeleteOwnEvent() will fail currently... is that even possible? And, if so, what permissions do they need to do that?

@mattwire
Copy link
Contributor Author

@alifrumin And it looks like we may need to "improve" the descriptions of some of the event permissions once we've worked out how they are actually meant to work!

@mattwire mattwire force-pushed the civievent_permissions branch 2 times, most recently from e96aa1d to b263942 Compare October 24, 2018 15:47
@eileenmcnaughton
Copy link
Contributor

eileenmcnaughton commented Oct 24, 2018

I worked through this & it looks pretty good -some thoughts

  1. I'd like to see calling checkPermission deprecated - at least to the extent of a code comment saying that - I realise more deprecation in this PR might be scope creep.

  2. I think you could get some efficiencies by setting 'view' keys when you set edit keys.

  3. I find the 2 statics key names kinda confusing 'permission' vs 'permissions'

  4. I think you could check the 'permissions' statics before doing a query - since it's like that 'all events a contact can access' would be loaded in one call & then 'can they access x event ' in a second one

  5. I think the rule for delete should be that they have 'delete in CiviEvent' AND edit access to the event in question. Arguably they should be able to delete events they created without 'delete in CiviEvent' but I think I'd be more worried about accidentally opening up delete permissions than accidentally reducing them

e.g

        if (CRM_Core_Permission::check('delete in CiviEvent') && CRM_Event_BAO_Event::checkPermission($eventId, CRM_Core_Permission::EDIT)) {
          Civi::$statics[__CLASS__]['permission']['delete'][$eventId] = TRUE;
        }

(you'd need to change the tests slightly for this assumption)

NOTE - other than resolving the test issue my comments are non-blocking & it would be fine to leave those thoughts for later

@mattwire mattwire force-pushed the civievent_permissions branch from b263942 to 544571f Compare October 25, 2018 10:31
@mattwire mattwire changed the title Fix caching issues with Event permissions WIP Fix caching issues with Event permissions Oct 25, 2018
@mattwire mattwire force-pushed the civievent_permissions branch from 544571f to 069f4ab Compare October 29, 2018 21:22
@mattwire
Copy link
Contributor Author

  1. I'd like to see calling checkPermission deprecated - at least to the extent of a code comment saying that - I realise more deprecation in this PR might be scope creep.

Deprecated warning added when we should be calling checkAllPermissions instead.

  1. I think you could get some efficiencies by setting 'view' keys when you set edit keys.

Yes, good idea. Done.

  1. I find the 2 statics key names kinda confusing 'permission' vs 'permissions'

So do I, but for now it solves the main issue here, that caching for a single event was preventing caching from all from happening. And because of the difference in the way each of the caches are generated and the general confusion about what each permission actually does... this seemed most sensible for now. But I've added a code comment.

  1. I think you could check the 'permissions' statics before doing a query - since it's like that 'all events a contact can access' would be loaded in one call & then 'can they access x event ' in a second one

I think there are definitely further improvements but my head starts to spin if I improve it too much.

  1. I think the rule for delete should be that they have 'delete in CiviEvent' AND edit access to the event in question. Arguably they should be able to delete events they created without 'delete in CiviEvent' but I think I'd be more worried about accidentally opening up delete permissions than accidentally reducing them

Yes. So I've updated the tests so that 'Delete in CiviEvent' is required. I can see someone submitting a PR with either a new permission 'Delete own events' or an adjustment to how the existing permissions work.

@eileenmcnaughton @alifrumin Assuming tests pass are you both happy with this now from a "it's less broken than it was before" point of view?

@mattwire mattwire changed the title WIP Fix caching issues with Event permissions Fix caching issues with Event permissions Oct 29, 2018
@eileenmcnaughton
Copy link
Contributor

@mattwire style error

@mattwire mattwire force-pushed the civievent_permissions branch from 069f4ab to d0853f7 Compare October 29, 2018 21:59
@alifrumin
Copy link
Contributor

I tested this and it looks good to me!

There is an error that shows up on the events dashboard for a user with the permissions:

  • CiviEvent: access CiviEvent
  • CiviCRM: access CiviCRM backend and API
  • CiviEvent: view event info

but it sounds like that might be on purpose.

Error text:

"User deprecated function: Deprecated function CRM_Event_BAO_Event::checkPermission, use CRM_Event_BAO_Event::getAllPermissions. Array ( [civi.tag] => deprecated ) in CRM_Core_Error_Log->log() (line 69 of /home/jenkins/bknix-dfl/build/core-12769-pu8u/sites/all/modules/civicrm/CRM/Core/Error/Log.php)."

userdeprecatedfunction

@seamuslee001
Copy link
Contributor

Given Eileen's comments and Alice's test i believe this is good to merge

(CiviCRM Review Template WORD-1.1)

@seamuslee001 seamuslee001 merged commit acaaa16 into civicrm:master Oct 30, 2018
@eileenmcnaughton
Copy link
Contributor

Thanks @seamuslee001 - @mattwire @alifrumin

We should try to fix those places where it calls the now-deprecated version of the function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants