The issue
After upgrading to 7.x-3.6, when I create a new variant and try to manage it using the page manager interface, alert boxes pop up with access denied warnings. This happens for types node_view and node_edit, I haven't tried this for any other variants.
When viewing the server's response to my request, we can see it returns this:
[{"command":"settings","settings":{"basePath":"\/","pathPrefix":"","ajaxPageState":{"theme":"test","theme_token":"spbxx9XOVrYbM7Bn8rLAlk8zT_fglX6jybMsK-sVPLM"}},"merge":true},{"command":"alert","text":"You are not authorized to access this page."}]
The workaround
As a temporary workaround to this issue, the system administrator could apply the patch mentioned by klausi #13 at https://www.drupal.org/node/2785915. If this doesn't work, you could try commenting out the return on line 1458 inside the "panels_ajax_router" function of the panels.module (version 7.x-3.7). I'm talking about this piece of code:
$op = $renderer->get_panels_storage_op_for_ajax($method);
if (!$cache->display->access($op)) {
return MENU_ACCESS_DENIED;
}
Be aware that both mentioned solutions are meant as temporary workarounds and should not be utilized on a live production site. They could expose your site to security hazards.
Why does this occur
This error finds its roots inside the "panel_context.inc" file.
During the variant creation process the function "panels_panel_context_edit_choose" is called. This function determines the initial values of the "storage_type" and "storage_id" variables.
// Grab the storage_type and storage_id and inject it into the display.
if (empty($form_state['display']->storage_type)) {
if (!isset($form_state[$form_state['task_id']]->storage_type)) {
watchdog('panels', "Unable to find the storage type for specified storage. Read 'Upgrading task handlers' in CHANGELOG.txt", array(), WATCHDOG_ERROR);
$form_state['display']->storage_type = 'unknown';
}
else {
$form_state['display']->storage_type = $form_state[$form_state['task_id']]->storage_type;
}
// When adding variants, we don't know the handler id yet. In that case,
// Mark it as new. We'll assign it later.
$form_state['display']->storage_id = !empty($form_state['handler_id']) ? $form_state['handler_id'] : 'new';
}
When I create new variants, no matter what I try, the type will always be "unknown" and the id will always be "new". The Watchdog will file a report about the type being unknown. This is the first issue, because the "access" function inside the "panels.module" will return FALSE when ($this->storage_type == 'unknown').
http://i.imgur.com/yKfCrkY.png
This was the first issue, the second issue takes place inside the "panels_panel_context_edit_content_submit" function of "panel_context.inc". Inside we will find:
// Update the storage_id if this is a new variant before saving.
if ($form_state['display']->storage_id == 'new') {
$form_state['display']->storage_id = $form_state['handler_id'];
}
When also taking a look in the first code snipper, we can observe that we set the id to "new" if the "handler_id" is empty, but in the second code snippet, we disregard that situation and set it to "handler_id" anyway. Now I don't have experience with Drupal coding, so the situation in between might as well have changed, making the handler_id available. But not for me.
The result of this is that the submitted variant has a storage_type with value "unknown" and the storage_id will be an empty string. We can observe this in the database:
http://i.imgur.com/d8lIn0X.png
The "access" function inside the "panels.module" returns FALSE when empty($this->storage_type) || empty($this->storage_id).
I've been trying some things and I'd like to propose the following. Please feel free to change things, I have no idea if my code is any good. But it does solve the issue for me.
My proposal (needs review)
Proposal #1: Replace the first code snippet with the following
// Grab the storage_type and storage_id and inject it into the display.
if (empty($form_state['display']->storage_type)) {
if (!isset($form_state[$form_state['task_id']]->storage_type)) {
watchdog('panels', "Unable to find the storage type for specified storage. Set to default 'page_manager'.", array(), WATCHDOG_NOTICE);
$form_state['display']->storage_type = 'page_manager';
}
else {
$form_state['display']->storage_type = $form_state[$form_state['task_id']]->storage_type;
}
// When adding variants, we don't know the handler id yet. In that case,
// Mark it as new. We'll assign it later.
$form_state['display']->storage_id = !empty($form_state['handler_id']) ? $form_state['handler_id'] : 'new';
}
I replaced the 'unknown' with 'page_manager' and changed the watchdog message and error level to be less confusing. ("Unable to find the storage type for specified storage. Read 'Upgrading task handlers' in CHANGELOG.txt" is nowhere to be found inside the changelog.)
Proposal #2: Replace the second code snipped with this
// Update the storage_id if this is a new variant before saving.
if ($form_state['display']->storage_id == 'new') {
$name = $form_state['task_name'] . '__' . $form_state['handler']->conf['name'];
$form_state['display']->storage_id = !empty($form_state['handler_id']) ? $form_state['handler_id'] : $name;
}
I check again if the handler_id is empty, if this is the case, I use my own auto generated machine name, else I use the handler_id. I don't know if it's necessary to check for the handler_id again, feel free to remove if unnecessary.
I would like to repeat that I'm not very experienced with Drupal and do not fully understand the implications of my proposed 'solution'.
I hope this was helpful.
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | panels-storage-alt-task-2787637-6.patch | 3.83 KB | dsnopek |
Comments
Comment #2
damienmckennaThanks @matman476.
FYI, when you initially create an issue you should leave the status at "Active", "Needs work" is for indicating that a patch someone has already added to the issue needs work, it isn't a generic way of stating "there's a problem here that needs to be worked on" :)
Comment #3
matman476 commentedOops, thank you @DamienMcKenna :)
Comment #4
matman476 commentedComment #5
dsnopek@matman476: Thanks for the bug report!
I'm able to reproduce the issue with the 'node_edit' page. :-/
I suspect this has to do with adding variants to tasks other than 'page'. Our page manager integration needs to work regardless of the task, since "tasks" are really a page manager thing, ie. all of them will use 'page_manager' as the storage type.
Comment #6
dsnopekHere's a patch that basically completely rewrites the way we're setting storage_type/storage_id for page_manager. It's much simpler than the old way, and hopefully less error prone. Please let me know if it works for you!
Comment #7
dsnopekComment #8
othermachines commented#6 patch resolves the watchdog errors for me when creating a new variant of 'node_view' type. It also resolves the 'Access denied' prompts when I attempt to add content to the newly created variant.
Watchdog before patch:
Watchdog after patch:
Thanks -
Comment #9
kerrymick commented#6 patch also resolved our access denied prompts for new variants.
Comment #10
potassiumchloride commented#6 resolved our "Access Denied" prompts that were appearing for adding new variants to the node_view page for sites using 7.x-3.7.
Comment #11
matman476 commentedGreat! #6 Works like a charm! Manual storage_id's I set in my database got updated as well. Thanks for the quick response and fix!
Comment #12
LavR. commentedWow! its works!. @dsnopek Thanks for Save me.
Comment #13
msningrum commented#6 fixes the authorization issue within taxonomy term panels. Thanks!
Comment #14
albertski commentedPatch looks good and it fixed the issue.
Comment #15
dshields commentedPatch #6 saved me as well.
Comment #16
damienmckennaComment #17
capfive commentedYou sir are a life saver!
Patch 6 fixed the issue with me, thank you thank you thank you!
Comment #18
couloir007 commented#6 Solved my general access denied. Thank you.
Comment #19
phernand42 commentedPatch #6 worked for me as well! Thanks
Comment #20
andrbmgi commented#6 fixed the problem, confirmed.
Comment #21
JMC commented#6 worked for me too, thanks.
Comment #22
amme commentedConfirm patch #6 works!
Comment #23
damienmckennaI want to add tests for this but we need #2808983: Add tests to Panels committed first.
Comment #24
capfive commentedNot sure if this patch is configured to fix paragraph items? I am still getting an unauthorised message for a paragraph bundle as used from the Paragraphs module.
https://www.drupal.org/project/paragraphs
Can anyone confirm as I don't have the capacity to really read the code form the patch.
Switching back to needs work until we can confirm it isn't related.
Anyone else having this issue?
Comment #25
damienmckenna@capfive: This has nothing to do with the Paragraphs module. If you're adding Paragraph types to panes using Paragraph Panes and are getting an Access Denied error you might want to open up an issue in the Paragraph Panes module.
Comment #26
capfive commentedSorry Damien I should've been more specific.
I am user ID 1 (super admin)
I tried to "panelize" a paragraphs bundle and once i did so, any time i tried to edit or add a new pane (of any kind) I was getting the unauthorized message.
I understand that Panelizer is being used, should I be looking in that issue queue?
Please let me know if this still has anything to do with the original issue
Comment #27
damienmckenna@capfive: Yes, please take a look at the latest dev snapshot for Panelizer and open a new issue there if you still run into problems. Thanks.
Comment #29
japerryThanks everyone for testing and verifying this patch. Its now committed.
Comment #31
charlie-s commentedI've uninstalled Panels & CTools, downloaded 7.x-3.x-dev and 7.x-1.14 respectively, but I'm still getting this issue. Is there anything else I can try?