Commit 5b87b056 authored by totten's avatar totten
Browse files

Enforce customizable `permission` for server routes. Add E2E test for server-routes.

parent 9d7ff5b1
......@@ -18,7 +18,13 @@ pushd "$AFF_CORE" >> /dev/null
popd >> /dev/null
pushd "$AFF_MOCK" >> /dev/null
if ! phpunit6 "$@" ; then
if ! phpunit6 --group e2e "$@" ; then
EXIT=1
fi
popd >> /dev/null
pushd "$AFF_MOCK" >> /dev/null
if ! phpunit6 --group headless "$@" ; then
EXIT=1
fi
popd >> /dev/null
......
......@@ -452,13 +452,34 @@ function afform_civicrm_alterMenu(&$items) {
'page_callback' => 'CRM_Afform_Page_AfformBase',
'page_arguments' => 'afform=' . urlencode($name),
'title' => $meta['title'] ?? '',
'access_arguments' => [['access CiviCRM'], 'and'], // FIXME
'access_arguments' => [["@afform:$name"], 'and'],
'is_public' => $meta['is_public'],
];
}
}
}
/**
* Implements hook_civicrm_permission_check().
*
* @see CRM_Utils_Hook::permission_check()
*/
function afform_civicrm_permission_check($permission, &$granted, $contactId) {
if ($permission{0} !== '@') {
// Micro-optimization - this function may get hit a lot.
return;
}
if (preg_match('/^@afform:(.*)/', $permission, $m)) {
$name = $m[1];
/** @var CRM_Afform_AfformScanner $scanner */
$scanner = \Civi::container()->get('afform_scanner');
$meta = $scanner->getMeta($name);
$granted = CRM_Core_Permission::check($meta['permission'], $contactId);
}
}
/**
* Clear any local/in-memory caches based on afform data.
*/
......
<?php
/**
* Ensure that the routes created by Afform are working.
* @group e2e
*/
class api_v4_AfformRoutingTest extends \PHPUnit\Framework\TestCase implements \Civi\Test\EndToEndInterface {
protected $formName = 'mockPage';
public static function setUpBeforeClass() {
\Civi\Test::e2e()
->install(['org.civicrm.afform', 'org.civicrm.afform-mock'])
->apply();
}
public function setUp() {
parent::setUp();
Civi\Api4\Afform::revert()
->setCheckPermissions(FALSE)
->addWhere('name', '=', $this->formName)
->execute();
}
public function tearDown() {
parent::tearDown();
Civi\Api4\Afform::revert()
->setCheckPermissions(FALSE)
->addWhere('name', '=', $this->formName)
->execute();
}
public function testChangingPermissions() {
$http = new \GuzzleHttp\Client(['http_errors' => FALSE]);
$url = function ($path, $query = NULL) {
return CRM_Utils_System::url($path, $query, TRUE, NULL, FALSE);
};
$result = $http->get($url('civicrm/mock-page'));
$this->assertNotAuthorized($result);
Civi\Api4\Afform::update()
->setCheckPermissions(FALSE)
->addWhere('name', '=', $this->formName)
->addValue('permission', CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION)
->execute();
$result = $http->get($url('civicrm/mock-page'));
$this->assertOpensPage($result, 'mock-page');
}
public function testChangingPath() {
$http = new \GuzzleHttp\Client(['http_errors' => FALSE]);
$url = function ($path, $query = NULL) {
return CRM_Utils_System::url($path, $query, TRUE, NULL, FALSE);
};
Civi\Api4\Afform::update()
->setCheckPermissions(FALSE)
->addWhere('name', '=', $this->formName)
->addValue('permission', CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION)
->execute();
$this->assertOpensPage($http->get($url('civicrm/mock-page')), 'mock-page');
$this->assertNotAuthorized($http->get($url('civicrm/mock-page-renamed')));
Civi\Api4\Afform::update()
->setCheckPermissions(FALSE)
->addWhere('name', '=', $this->formName)
->addValue('server_route', 'civicrm/mock-page-renamed')
->execute();
$this->assertNotAuthorized($http->get($url('civicrm/mock-page')));
$this->assertOpensPage($http->get($url('civicrm/mock-page-renamed')), 'mock-page');
}
/**
* @param $result
*/
private function assertNotAuthorized(Psr\Http\Message\ResponseInterface $result) {
$contents = $result->getBody()->getContents();
$this->assertEquals(403, $result->getStatusCode());
$this->assertRegExp(';You are not authorized to access;', $contents);
$this->assertNotRegExp(';afform":\{"open":".*"\};', $contents);
}
/**
* @param $result
* @param string $directive
* The name of the directive which auto-opens.
*/
private function assertOpensPage(Psr\Http\Message\ResponseInterface $result, $directive) {
$contents = $result->getBody()->getContents();
$this->assertEquals(200, $result->getStatusCode());
$this->assertNotRegExp(';You are not authorized to access;', $contents);
$this->assertRegExp(';afform":\{"open":"' . preg_quote($directive, ';') . '"\};', $contents);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment