Skip to content
Snippets Groups Projects
Commit a0bbae40 authored by Matt Glaman's avatar Matt Glaman Committed by Matt Glaman
Browse files

Issue #3106889 by mglaman, gabesullice: Add link relationship types for authentication

parent 9854a3d8
Branches
Tags 8.x-1.0-alpha1
No related merge requests found
......@@ -9,6 +9,9 @@
"require": {
"drupal/core": "^8.8@alpha",
"drupal/jsonapi_resources": "^1.0@beta"
},
"require-dev": {
"drupal/jsonapi_hypermedia": "^1.4"
}
}
......@@ -26,5 +26,5 @@ build:
run_tests.functional:
types: 'PHPUnit-Functional'
testgroups: '--all'
suppress-deprecations: false
suppress-deprecations: true
halt-on-fail: false
# JSON:API User Resources's link relation types.
# See https://tools.ietf.org/html/draft-pot-authentication-link-00
authenticate:
description: "Refers to a resource where a client may authenticate for the the context URI."
reference: '[TBD]'
notes: "This is a draft link relation type that has not yet been officially registered. See https://tools.ietf.org/html/draft-pot-authentication-link-00#section-6.1."
authenticated-as:
description: "Refers to a resource that describes the authenticated entity for the HTTP response."
reference: '[TBD]'
notes: "This is a draft link relation type that has not yet been officially registered. See https://tools.ietf.org/html/draft-pot-authentication-link-00#section-6.2."
logout:
description: "Refers to an endpoint where a client may invalidate the current authentication session."
reference: '[TBD]'
notes: "This is a draft link relation type that has not yet been officially registered. See https://tools.ietf.org/html/draft-pot-authentication-link-00#section-6.3."
register-user:
description: "Refers to a resource where a client may create a new user account for the context URI."
reference: '[TBD]'
notes: "This is a draft link relation type that has not yet been officially registered. See https://tools.ietf.org/html/draft-pot-authentication-link-00#section-6.4."
<?php declare(strict_types = 1);
namespace Drupal\jsonapi_user_resources\Plugin\jsonapi_hypermedia\LinkProvider;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel;
use Drupal\jsonapi_hypermedia\AccessRestrictedLink;
use Drupal\jsonapi_hypermedia\Plugin\LinkProviderBase;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Adds an `authenticated-as` link for unauthenticated requests.
*
* @JsonapiHypermediaLinkProvider(
* id = "jsonapi.top_level.authenticated_as",
* link_relation_type = "authenticated-as",
* link_context = {
* "top_level_object" = true,
* }
* )
*/
final class AuthenticatedAsLinkProvider extends LinkProviderBase implements ContainerFactoryPluginInterface {
/**
* The current account.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* The user storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
private $userStorage;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$provider = new static($configuration, $plugin_id, $plugin_definition);
$provider->setCurrentUser($container->get('current_user'));
$provider->setUserStorage(
$container->get('entity_type.manager')->getStorage('user')
);
return $provider;
}
/**
* Sets the current account.
*
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current account.
*/
public function setCurrentUser(AccountInterface $current_user) {
$this->currentUser = $current_user;
}
/**
* Sets the user storage.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
* The user storage.
*/
public function setUserStorage(EntityStorageInterface $storage) {
$this->userStorage = $storage;
}
/**
* {@inheritdoc}
*/
public function getLink($context) {
assert($context instanceof JsonApiDocumentTopLevel);
$link_cacheability = new CacheableMetadata();
$link_cacheability->addCacheContexts(['user']);
if ($this->currentUser->isAnonymous()) {
return AccessRestrictedLink::createInaccessibleLink($link_cacheability);
}
$user = $this->userStorage->load($this->currentUser->id());
if (!$user instanceof UserInterface) {
return AccessRestrictedLink::createInaccessibleLink($link_cacheability);
}
return AccessRestrictedLink::createLink(
AccessResult::allowedIf($user->isAuthenticated())->cachePerUser(),
$link_cacheability,
Url::fromRoute('jsonapi.user--user.individual', ['entity' => $user->uuid()]),
$this->getLinkRelationType()
);
}
}
<?php declare(strict_types = 1);
namespace Drupal\Tests\jsonapi_user_resources\Functional;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\jsonapi\Functional\JsonApiRequestTestTrait;
use Drupal\Tests\jsonapi\Functional\ResourceResponseTestTrait;
use GuzzleHttp\RequestOptions;
/**
* Tests JSON:API Resource User registration.
*
* @group jsonapi_user_resources
* @requires jsonapi_hypermedia
*/
final class HypermediaIntegrationTest extends BrowserTestBase {
use JsonApiRequestTestTrait;
use ResourceResponseTestTrait;
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected static $modules = [
'jsonapi_resources',
'jsonapi_hypermedia',
'jsonapi_user_resources',
];
/**
* Tests the `authenticated-as` link.
*/
public function testAuthenticatedAsLink() {
$url = Url::fromRoute('jsonapi.resource_list');
$request_options = [];
$request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
$response = $this->request('GET', $url, $request_options);
$body = (string) $response->getBody();
$this->assertEquals(200, $response->getStatusCode(), $body);
$decoded_document = Json::decode($body);
$this->assertFalse(isset($decoded_document['links']['authenticated-as']));
$sut = $this->createUser();
$this->drupalLogin($sut);
$response = $this->request('GET', $url, $request_options);
$body = (string) $response->getBody();
$this->assertEquals(200, $response->getStatusCode(), $body);
$decoded_document = Json::decode($body);
$this->assertTrue(isset($decoded_document['links']['authenticated-as']), var_export($decoded_document, TRUE));
$link_href = $decoded_document['links']['authenticated-as']['href'];
$expected_link_href = Url::fromRoute('jsonapi.user--user.individual', ['entity' => $sut->uuid()])->setAbsolute()->toString();
$this->assertEquals($expected_link_href, $link_href);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment