external form problems after 8.5.4 upgrade
Permalink
I've recently upgraded a site to C5 8.5.4 from 8.4.3 and am now having trouble with some external forms. Oddly some external forms still seem to work but others don't.
Using, for example, the test form view:
and the test form controller:
When I add the external form block to a page and submit the form I get a url like:
/ccm/system/block/action/edit/1/Main/77513/test_search
and the message 'Access Denied'. I traced this through to the 'edit' method of Concrete\Controller\Backend\Block\Action
On form submission, this method is passed the variables in the url:
cID: 1 arHandle: Main bID: 77513 action: test_search
The if block with validateEditBlockPassThruAction($b) fails because the 'guests' group does not have edit permissions on the block and I end up seeing the 'Access Denied' response. I checked the 8.4.3 version of this method and it has the same validateEditBlockPassThruAction($b) check, though I've never had to allow guest edit permissions on an external form block before. If I do set guest edit permissions on the block and submit the form then the $this->deliverResponse() line is run and the action_test_search method is run in the external form controller except that the bID is not passed in so nothing happens.
Looking for 8.5.4 issues on github I saw thishttps://github.com/concrete5/concrete5/issues/8771.... I ran `concrete/bin/concrete5 migrations:status` and it seems like the migrations are up to date at
>> Current Version: 2020-06-09 14:53:07 (20200609145307)
All the tables in the database have the right character set and collation but I do have a lot (+1500) of columns in the C5 database with NULL character sets and collations. Could that even affect external forms and should I try to alter the character set and collation of these columns?
Using, for example, the test form view:
<?php $form = Loader::helper('form'); defined('C5_EXECUTE') or die("Access Denied."); if (isset($response)) { ?> <div class="alert alert-info"><?php echo $response?></div> <?php } ?> <form method="post" action="<?php echo $view->action('test_search')?>"> <p><?php echo $message?></p> <div class="form-group"> <label class="control-label"><?php echo t('Test')?></label> <?php echo $form->text('test_text_field')?> </div> <div class="form-group"> <input type="submit" name="submit" value="submit" class="btn btn-default" /> </div>
Viewing 15 lines of 16 lines. View entire code block.
and the test form controller:
<?php namespace Application\Block\ExternalForm\Form\Controller; use Concrete\Core\Controller\AbstractController; class TestForm extends AbstractController { public function action_test_search($bID = false) { if ($this->bID == $bID) { $this->set('response', t('Thanks!')); return true; } } public function view() { $this->set('message', t('This is just an example of how a custom form works.'));
Viewing 15 lines of 17 lines. View entire code block.
When I add the external form block to a page and submit the form I get a url like:
/ccm/system/block/action/edit/1/Main/77513/test_search
and the message 'Access Denied'. I traced this through to the 'edit' method of Concrete\Controller\Backend\Block\Action
public function edit($cID, $arHandle, $bID, $action) { $c = \Page::getByID($cID); if (is_object($c) && !$c->isError()) { $this->request->setCurrentPage($c); $a = \Area::getOrCreate($c, $arHandle); $ax = $a; $cx = $c; if ($a->isGlobalArea()) { $cx = \Stack::getByName($arHandle); $ax = \Area::get($cx, STACKS_AREA_NAME); } $b = \Block::getByID($bID, $cx, $ax); if (is_object($b)) { $controller = $b->getController();
Viewing 15 lines of 23 lines. View entire code block.
On form submission, this method is passed the variables in the url:
cID: 1 arHandle: Main bID: 77513 action: test_search
The if block with validateEditBlockPassThruAction($b) fails because the 'guests' group does not have edit permissions on the block and I end up seeing the 'Access Denied' response. I checked the 8.4.3 version of this method and it has the same validateEditBlockPassThruAction($b) check, though I've never had to allow guest edit permissions on an external form block before. If I do set guest edit permissions on the block and submit the form then the $this->deliverResponse() line is run and the action_test_search method is run in the external form controller except that the bID is not passed in so nothing happens.
Looking for 8.5.4 issues on github I saw thishttps://github.com/concrete5/concrete5/issues/8771.... I ran `concrete/bin/concrete5 migrations:status` and it seems like the migrations are up to date at
>> Current Version: 2020-06-09 14:53:07 (20200609145307)
All the tables in the database have the right character set and collation but I do have a lot (+1500) of columns in the C5 database with NULL character sets and collations. Could that even affect external forms and should I try to alter the character set and collation of these columns?
By "submit the form" I mean clicking the submit button of the form while not logged in. Caching is off and I've tried clearing cache but the problem persists.
I spun up an 8.4.3 version of the site and the test form works fine there. I noticed that the result of $view->action('test_search') is different between the two:
8.5.4 => /ccm/system/block/action/edit/316/ColumnRightTop/77512/test_search
8.4.3 => /page-name/test_search/80115
I've found a fix that basically involves commenting out the line:
in Concrete\Core\Block\View\BlockView::action and pasting in the 8.4.3 version of that method.
Not pretty but beats having all the forms broken.
That logic seems to have been moved to Concrete\Core\Block\BlockController::getActionURL($task) and although the action 'test_search' is passed in as $task, the method calls $this->getAction() to set the action which appears to end up calling the method on the AbstractController. That is coming back blank, so it falls through to the else block and returns the edit url.
So maybe the action property of the AbstractController isn't being set somewhere? I haven't noticed where that happens yet.
I spun up an 8.4.3 version of the site and the test form works fine there. I noticed that the result of $view->action('test_search') is different between the two:
8.5.4 => /ccm/system/block/action/edit/316/ColumnRightTop/77512/test_search
8.4.3 => /page-name/test_search/80115
I've found a fix that basically involves commenting out the line:
return call_user_func_array([$this->controller, 'getActionURL'], func_get_args());
in Concrete\Core\Block\View\BlockView::action and pasting in the 8.4.3 version of that method.
Not pretty but beats having all the forms broken.
That logic seems to have been moved to Concrete\Core\Block\BlockController::getActionURL($task) and although the action 'test_search' is passed in as $task, the method calls $this->getAction() to set the action which appears to end up calling the method on the AbstractController. That is coming back blank, so it falls through to the else block and returns the edit url.
So maybe the action property of the AbstractController isn't being set somewhere? I haven't noticed where that happens yet.
Do you have caching turned on? If so, does this issue persist if you turn it off and clear the cache?