View source
<?php
namespace Drupal\Tests\apigee_edge\Functional;
use Apigee\Edge\Api\Management\Entity\App;
use Drupal\apigee_edge\Entity\Developer;
use Drupal\apigee_edge\Entity\DeveloperApp;
use Drupal\user\RoleInterface;
class DeveloperAppPermissionTest extends ApigeeEdgeFunctionalTestBase {
protected const ADMINISTER_PERMISSION = 'administer developer_app';
protected const PERMISSION_MATRIX = [
'create developer_app' => [
'add-form-for-developer',
],
'delete any developer_app' => [
'delete-form',
'delete-form-for-developer',
],
'delete own developer_app' => [
'delete-form',
'delete-form-for-developer',
],
'update any developer_app' => [
'edit-form',
'edit-form-for-developer',
],
'update own developer_app' => [
'edit-form',
'edit-form-for-developer',
],
'view any developer_app' => [
'canonical',
'canonical-by-developer',
'api-keys',
],
'view own developer_app' => [
'canonical',
'canonical-by-developer',
'collection-by-developer',
'api-keys',
],
'analytics any developer_app' => [
'analytics',
'analytics-for-developer',
],
'analytics own developer_app' => [
'analytics',
'analytics-for-developer',
],
'access developer_app overview' => [
'collection',
],
'add_api_key own developer_app' => [
'add-api-key-form',
],
'add_api_key any developer_app' => [
'add-api-key-form',
],
self::ADMINISTER_PERMISSION => [],
];
protected $entityType;
protected $myAccount;
protected $otherAccount;
protected $myDeveloperApp;
protected $otherDeveloperApp;
protected $roles;
protected $entityRoutes;
protected function setUp() {
parent::setUp();
$this->entityType = $this->container
->get('entity_type.manager')
->getDefinition('developer_app');
$links = array_filter($this->entityType
->get('links'), function ($path) {
return strpos($path, '{consumer_key}') === FALSE;
});
$this->entityRoutes = array_keys($links);
$this
->revokeDefaultAuthUserPermissions();
$this->myAccount = $this
->createAccount([]);
$this->otherAccount = $this
->createAccount([]);
$myDeveloper = Developer::load($this->myAccount
->getEmail());
$otherDeveloper = Developer::load($this->otherAccount
->getEmail());
$this->myDeveloperApp = DeveloperApp::create([
'name' => $this
->randomMachineName(),
'status' => App::STATUS_APPROVED,
'developerId' => $myDeveloper
->uuid(),
]);
$this->myDeveloperApp
->save();
$this->myDeveloperApp
->setOwner($this->myAccount);
$this->otherDeveloperApp = DeveloperApp::create([
'name' => $this
->randomMachineName(),
'status' => App::STATUS_APPROVED,
'developerId' => $otherDeveloper
->uuid(),
]);
$this->otherDeveloperApp
->save();
$this->otherDeveloperApp
->setOwner($this->otherAccount);
foreach (array_keys(static::PERMISSION_MATRIX) as $permission) {
$this->roles[$permission] = $this
->createRole([
$permission,
]);
}
}
protected function tearDown() {
try {
if ($this->otherAccount !== NULL) {
$this->otherAccount
->delete();
}
} catch (\Exception $exception) {
$this
->logException($exception);
}
try {
if ($this->myAccount !== NULL) {
$this->myAccount
->delete();
}
} catch (\Exception $exception) {
$this
->logException($exception);
}
parent::tearDown();
}
public function testPermissions() {
foreach (array_keys(static::PERMISSION_MATRIX) as $permission) {
$this
->assertPermission($permission);
}
}
protected function revokeDefaultAuthUserPermissions() {
$definition = $this->entityType;
$user_permissions = user_role_permissions([
RoleInterface::AUTHENTICATED_ID,
]);
$authenticated_user_permissions = array_filter($user_permissions[RoleInterface::AUTHENTICATED_ID], function ($perm) use ($definition) {
return preg_match("/own {$definition->id()}\$/", $perm);
});
$authenticated_user_permissions[] = "create {$definition->id()}";
user_role_revoke_permissions(RoleInterface::AUTHENTICATED_ID, $authenticated_user_permissions);
}
protected function assertPermission(string $permission) {
if ($this->loggedInUser) {
$this
->drupalLogout();
}
$old_roles = $this->myAccount
->getRoles(TRUE);
foreach ($old_roles as $old_role) {
$this->myAccount
->removeRole($old_role);
}
$this->myAccount
->addRole($this->roles[$permission]);
$this
->disableUserPresave();
$this->myAccount
->save();
$this
->enableUserPresave();
$routesWithAccess = static::PERMISSION_MATRIX[$permission];
if ($permission === static::ADMINISTER_PERMISSION) {
$routesWithAccess = $this->entityRoutes;
}
foreach ($this->entityRoutes as $rel) {
$myUrl = static::fixUrl((string) $this->myDeveloperApp
->toUrl($rel)
->toString());
$otherUrl = static::fixUrl((string) $this->otherDeveloperApp
->toUrl($rel)
->toString());
$shouldAccess = in_array($rel, $routesWithAccess);
if (strpos($permission, ' any ') !== FALSE) {
$this
->visitPages($myUrl, $shouldAccess, $rel, $permission);
$this
->visitPages($otherUrl, $shouldAccess, $rel, $permission);
}
elseif (strpos($permission, ' own ') !== FALSE) {
$this
->visitPages($myUrl, $shouldAccess, $rel, $permission);
$this
->visitPages($otherUrl, FALSE, $rel, $permission);
}
else {
$this
->visitPages($myUrl, $shouldAccess, $rel, $permission);
$otherShouldAccess = $permission === 'create developer_app' ? FALSE : $shouldAccess;
$this
->visitPages($otherUrl, $otherShouldAccess, $rel, $permission);
}
}
}
protected function visitPages(string $url, bool $my_access, string $rel, string $permission) {
$this
->drupalLogin($this->myAccount);
$this
->visitPage($url, $my_access, $rel, $permission);
$this
->drupalLogin($this->otherAccount);
$this
->visitPage($url, FALSE, $rel, $permission);
$this
->drupalLogout();
}
protected function visitPage(string $url, bool $access, string $rel, string $permission) {
$this
->drupalGet($url);
$code = $this
->getSession()
->getStatusCode();
$username = 'unknown';
if ($this->loggedInUser
->id() === $this->myAccount
->id()) {
$username = 'my user';
}
elseif ($this->loggedInUser
->id() === $this->otherAccount
->id()) {
$username = 'other user';
}
$debug = "{$url} ({$rel}) with \"{$permission}\" as {$username}";
if ($access) {
$this
->assertEquals(200, $code, "Couldn't access {$debug} when it should have. Got HTTP {$code}, expected HTTP 200.");
}
else {
$this
->assertEquals(403, $code, "Could access {$debug} when it should not have. Got HTTP {$code}, expected HTTP 403.");
}
}
}