clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
<?php
namespace Drupal\simple_oauth\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
/**
* Plugin implementation of the 'OAuth2 scope reference label' formatter.
*
* @FieldFormatter(
* id = "oauth2_scope_reference_label",
* label = @Translation("Label"),
* description = @Translation("Display the label of the referenced OAuth2 scopes."),
* field_types = {
* "oauth2_scope_reference"
* }
* )
*/
class Oauth2ScopeReferenceLabelFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
foreach ($items as $delta => $item) {
// Make sure the scope exists.
if ($item->isEmpty()) {
continue;
}
$elements[$delta] = [
'#markup' => $item->scope_id,
];
}
return $elements;
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace Drupal\simple_oauth\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\OptionsProviderInterface;
use Drupal\simple_oauth\Oauth2ScopeInterface;
/**
* Plugin implementation of the 'oauth2_scope_reference' field type.
*
* @FieldType(
* id = "oauth2_scope_reference",
* label = @Translation("OAuth2 scope reference"),
* description = @Translation("An entity field containing a oauth2_scope reference."),
* category = @Translation("Reference"),
* default_widget = "oauth2_scope_reference",
* list_class = "\Drupal\simple_oauth\Plugin\Field\FieldType\Oauth2ScopeReferenceItemList",
* )
*/
class Oauth2ScopeReferenceItem extends FieldItemBase implements Oauth2ScopeReferenceItemInterface, OptionsProviderInterface {
/**
* {@inheritdoc}
*/
public static function mainPropertyName() {
return 'scope_id';
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['scope_id'] = DataDefinition::create('string')
->setLabel(t('Scope ID'))
->setRequired(TRUE);
return $properties;
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'scope_id' => [
'description' => 'The scope id',
'type' => 'varchar',
'length' => 255,
],
],
'indexes' => ['scope_id' => ['scope_id']],
];
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
$value = $this->get('scope_id')->getValue();
return $value === NULL || $value === '';
}
/**
* {@inheritdoc}
*/
public function getScope(): ?Oauth2ScopeInterface {
if (empty($this->scope_id)) {
return NULL;
}
/** @var \Drupal\simple_oauth\Oauth2ScopeAdapterInterface $scope_provider */
$scope_provider = \Drupal::service('simple_oauth.oauth2_scope.provider');
return $scope_provider->load($this->scope_id);
}
/**
* {@inheritdoc}
*/
public function getPossibleValues(AccountInterface $account = NULL) {
return array_keys($this->getPossibleOptions($account));
}
/**
* {@inheritdoc}
*/
public function getPossibleOptions(AccountInterface $account = NULL) {
/** @var \Drupal\simple_oauth\Oauth2ScopeAdapterInterface $scope_provider */
$scope_provider = \Drupal::service('simple_oauth.oauth2_scope.provider');
$scopes = $scope_provider->loadMultiple();
return array_map(function (Oauth2ScopeInterface $scope) {
return $scope->getName();
}, $scopes);
}
/**
* {@inheritdoc}
*/
public function getSettableValues(AccountInterface $account = NULL) {
return array_keys($this->getPossibleOptions($account));
}
/**
* {@inheritdoc}
*/
public function getSettableOptions(AccountInterface $account = NULL) {
return $this->getPossibleOptions($account);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Drupal\simple_oauth\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\simple_oauth\Oauth2ScopeInterface;
/**
* Defines an interface for the oauth2_scope_reference field item.
*/
interface Oauth2ScopeReferenceItemInterface extends FieldItemInterface {
/**
* Get scope object.
*
* @return null|\Drupal\simple_oauth\Oauth2ScopeInterface
* Return the scope object or NULL if the scope does not exist.
*/
public function getScope(): ?Oauth2ScopeInterface;
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Drupal\simple_oauth\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemList;
/**
* Defines an item list class for OAuth2 Scope reference fields.
*/
class Oauth2ScopeReferenceItemList extends FieldItemList implements Oauth2ScopeReferenceItemListInterface {
/**
* {@inheritdoc}
*/
public function getConstraints() {
$constraints = parent::getConstraints();
$constraint_manager = $this->getTypedDataManager()->getValidationConstraintManager();
$constraints[] = $constraint_manager->create('Oauth2ScopeReference', []);
return $constraints;
}
/**
* {@inheritdoc}
*/
public function getScopes(): array {
if (empty($this->list)) {
return [];
}
$scopes = $ids = [];
foreach ($this->list as $delta => $item) {
$ids[$delta] = $item->scope_id;
}
/** @var \Drupal\simple_oauth\Oauth2ScopeAdapterInterface $scope_provider */
$scope_provider = \Drupal::service('simple_oauth.oauth2_scope.provider');
$loaded_scopes = $scope_provider->loadMultiple($ids);
foreach ($ids as $delta => $scope_id) {
if (isset($loaded_scopes[$scope_id])) {
$scopes[$delta] = $loaded_scopes[$scope_id];
}
}
// Ensure the returned array is ordered by deltas.
ksort($scopes);
return $scopes;
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Drupal\simple_oauth\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemListInterface;
/**
* Interface for entity reference lists of field items.
*/
interface Oauth2ScopeReferenceItemListInterface extends FieldItemListInterface {
/**
* Gets the scopes referenced by this field, preserving field item deltas.
*
* @return \Drupal\simple_oauth\Oauth2ScopeInterface[]
* An array of scope objects keyed by field item deltas.
*/
public function getScopes(): array;
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Drupal\simple_oauth\Plugin\Field\FieldWidget;
use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsButtonsWidget;
/**
* Plugin implementation of the 'oauth2_scope_reference' widget.
*
* @FieldWidget(
* id = "oauth2_scope_reference",
* label = @Translation("OAuth2 scope reference widget"),
* field_types = {
* "oauth2_scope_reference"
* },
* multiple_values = TRUE
* )
*/
class Oauth2ScopeReferenceWidget extends OptionsButtonsWidget {}

View File

@@ -0,0 +1,118 @@
<?php
namespace Drupal\simple_oauth\Plugin\Oauth2Grant;
use Drupal\consumers\Entity\Consumer;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\simple_oauth\Plugin\Oauth2GrantBase;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Grant\GrantTypeInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The authorization code grant plugin.
*
* @Oauth2Grant(
* id = "authorization_code",
* label = @Translation("Authorization Code"),
* )
*/
class AuthorizationCode extends Oauth2GrantBase implements ContainerFactoryPluginInterface {
/**
* The authorization code repository.
*
* @var \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface
*/
protected AuthCodeRepositoryInterface $authCodeRepository;
/**
* The refresh token repository.
*
* @var \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface
*/
protected RefreshTokenRepositoryInterface $refreshTokenRepository;
/**
* Class constructor.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, AuthCodeRepositoryInterface $auth_code_repository, RefreshTokenRepositoryInterface $refresh_token_repository) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->authCodeRepository = $auth_code_repository;
$this->refreshTokenRepository = $refresh_token_repository;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('simple_oauth.repositories.auth_code'),
$container->get('simple_oauth.repositories.refresh_token')
);
}
/**
* {@inheritdoc}
*/
public function getGrantType(Consumer $client): GrantTypeInterface {
$auth_code_ttl = new \DateInterval(
sprintf('PT%dS', $client->get('access_token_expiration')->value)
);
$refresh_token_enabled = $this->isRefreshTokenEnabled($client);
/** @var \Drupal\simple_oauth\Repositories\OptionalRefreshTokenRepositoryInterface $refresh_token_repository */
$refresh_token_repository = $this->refreshTokenRepository;
if (!$refresh_token_enabled) {
$refresh_token_repository->disableRefreshToken();
}
$grant_type = new AuthCodeGrant(
$this->authCodeRepository,
$refresh_token_repository,
$auth_code_ttl
);
if ($refresh_token_enabled) {
$refresh_token = !$client->get('refresh_token_expiration')->isEmpty ? $client->get('refresh_token_expiration')->value : 1209600;
$refresh_token_ttl = new \DateInterval(
sprintf('PT%dS', $refresh_token)
);
$grant_type->setRefreshTokenTTL($refresh_token_ttl);
}
// Make PKCE optional.
$pkce_enabled = $client->get('pkce')->value;
if (!$pkce_enabled) {
$grant_type->disableRequireCodeChallengeForPublicClients();
}
return $grant_type;
}
/**
* Checks if refresh token is enabled on the client.
*
* @param \Drupal\consumers\Entity\Consumer $client
* The consumer entity.
*
* @return bool
* Returns boolean.
*/
protected function isRefreshTokenEnabled(Consumer $client): bool {
foreach ($client->get('grant_types')->getValue() as $grant_type) {
if ($grant_type['value'] === 'refresh_token') {
return TRUE;
}
}
return FALSE;
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Drupal\simple_oauth\Plugin\Oauth2Grant;
use Drupal\consumers\Entity\ConsumerInterface;
use Drupal\simple_oauth\Plugin\Oauth2GrantBase;
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
use League\OAuth2\Server\Grant\GrantTypeInterface;
/**
* The client credentials grant plugin.
*
* @Oauth2Grant(
* id = "client_credentials",
* label = @Translation("Client Credentials")
* )
*/
class ClientCredentials extends Oauth2GrantBase {
/**
* {@inheritdoc}
*/
public function getGrantType(ConsumerInterface $client): GrantTypeInterface {
return new ClientCredentialsGrant();
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Drupal\simple_oauth\Plugin\Oauth2Grant;
use Drupal\consumers\Entity\Consumer;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\simple_oauth\Plugin\Oauth2GrantBase;
use League\OAuth2\Server\Grant\GrantTypeInterface;
use League\OAuth2\Server\Grant\RefreshTokenGrant;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The refresh token grant plugin.
*
* @Oauth2Grant(
* id = "refresh_token",
* label = @Translation("Refresh Token")
* )
*/
class RefreshToken extends Oauth2GrantBase implements ContainerFactoryPluginInterface {
/**
* The refresh token repository.
*
* @var \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface
*/
protected RefreshTokenRepositoryInterface $refreshTokenRepository;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RefreshTokenRepositoryInterface $refresh_token_repository) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->refreshTokenRepository = $refresh_token_repository;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('simple_oauth.repositories.refresh_token')
);
}
/**
* {@inheritdoc}
*/
public function getGrantType(Consumer $client): GrantTypeInterface {
/** @var \Drupal\simple_oauth\Repositories\OptionalRefreshTokenRepositoryInterface $refresh_token_repository */
$refresh_token_repository = $this->refreshTokenRepository;
$grant_type = new RefreshTokenGrant($refresh_token_repository);
$refresh_token_ttl = !$client->get('refresh_token_expiration')->isEmpty ? $client->get('refresh_token_expiration')->value : 1209600;
$duration = new \DateInterval(sprintf('PT%dS', $refresh_token_ttl));
$grant_type->setRefreshTokenTTL($duration);
return $grant_type;
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Component\Plugin\PluginBase;
/**
* Base class for OAuth2 Grant plugins.
*/
abstract class Oauth2GrantBase extends PluginBase implements Oauth2GrantInterface {
/**
* {@inheritdoc}
*/
public function label(): string {
return $this->pluginDefinition['label'];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\consumers\Entity\Consumer;
use League\OAuth2\Server\Grant\GrantTypeInterface;
/**
* Defines an interface for OAuth2 Grant plugins.
*/
interface Oauth2GrantInterface extends PluginInspectionInterface {
/**
* Gets the grant object.
*
* @param \Drupal\consumers\Entity\Consumer $client
* The consumer entity.
*
* @return \League\OAuth2\Server\Grant\GrantTypeInterface
* The grant type object.
*
* @throws \Exception
*/
public function getGrantType(Consumer $client): GrantTypeInterface;
/**
* Get the grant type label.
*
* @return string
* Returns the grant type label.
*/
public function label(): string;
}

View File

@@ -0,0 +1,78 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
/**
* Provides the OAuth2 Grant plugin manager.
*/
class Oauth2GrantManager extends DefaultPluginManager implements Oauth2GrantManagerInterface {
/**
* The plugin instances.
*
* @var array
*/
protected array $instances = [];
/**
* Constructor for Oauth2GrantManager objects.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler to invoke the alter hook with.
*
* @throws \Exception
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/Oauth2Grant', $namespaces, $module_handler, 'Drupal\simple_oauth\Plugin\Oauth2GrantInterface', 'Drupal\simple_oauth\Annotation\Oauth2Grant');
$this->alterInfo('simple_oauth_oauth2_grant_info');
$this->setCacheBackend($cache_backend, 'simple_oauth_oauth2_grant_plugins');
}
/**
* {@inheritdoc}
*/
public function getInstances(array $ids = NULL): array {
$instances = [];
if (empty($ids)) {
$ids = array_keys($this->getDefinitions());
}
foreach ($ids as $plugin_id) {
if (!isset($this->instances[$plugin_id])) {
$this->instances[$plugin_id] = $this->createInstance($plugin_id);
}
$instances[$plugin_id] = $this->instances[$plugin_id];
}
return $instances;
}
/**
* Get the available plugins as form element options.
*
* @return array
* Returns the options.
*/
public static function getAvailablePluginsAsOptions(): array {
/** @var \Drupal\simple_oauth\Plugin\Oauth2GrantManagerInterface $plugin_manager */
$plugin_manager = \Drupal::service('plugin.manager.oauth2_grant.processor');
$options = [];
foreach ($plugin_manager->getDefinitions() as $plugin_id => $definition) {
$options[$plugin_id] = $definition['label'];
}
return $options;
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Component\Plugin\PluginManagerInterface;
/**
* Manages the OAuth2 grant plugins.
*/
interface Oauth2GrantManagerInterface extends PluginManagerInterface {
/**
* Gets all grant type plugin instances.
*
* @param array|null $ids
* (optional) An array of plugin IDs, or NULL to load all plugins.
*
* @return \Drupal\simple_oauth\Plugin\Oauth2GrantInterface[]
* Returns array of all plugin instances.
*/
public function getInstances(array $ids = NULL): array;
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Drupal\simple_oauth\Plugin\ScopeProvider;
use Drupal\simple_oauth\Plugin\ScopeProviderBase;
/**
* The Dynamic scope provider.
*
* @ScopeProvider(
* id = "dynamic",
* label = @Translation("Dynamic (entity)"),
* adapter_class = "Drupal\simple_oauth\Entity\Oauth2ScopeEntityAdapter"
* )
*/
class DynamicScopeProvider extends ScopeProviderBase {}

View File

@@ -0,0 +1,73 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\simple_oauth\Oauth2ScopeAdapterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Base class for Scope Provider plugins.
*/
abstract class ScopeProviderBase extends PluginBase implements ScopeProviderInterface, ContainerFactoryPluginInterface {
/**
* The class resolver.
*
* @var \Drupal\Core\DependencyInjection\ClassResolverInterface
*/
protected ClassResolverInterface $classResolver;
/**
* Oauth2GrantBase constructor.
*
* @param array $configuration
* The plugin configuration array.
* @param string $pluginId
* The plugin id.
* @param array $pluginDefinition
* The plugin definition array.
* @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
* The class resolver.
*/
public function __construct(array $configuration, $pluginId, array $pluginDefinition, ClassResolverInterface $class_resolver) {
parent::__construct($configuration, $pluginId, $pluginDefinition);
$this->classResolver = $class_resolver;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('class_resolver')
);
}
/**
* {@inheritdoc}
*/
public function label(): string {
return $this->pluginDefinition['label'];
}
/**
* {@inheritdoc}
*/
public function getScopeProviderAdapter(): Oauth2ScopeAdapterInterface {
$adapter = $this->classResolver->getInstanceFromDefinition($this->pluginDefinition['adapter_class']);
if (!$adapter instanceof Oauth2ScopeAdapterInterface) {
throw new PluginException(sprintf('The plugin "%s" did not specify a valid class, must implement "%s".', $this->getPluginId(), Oauth2ScopeAdapterInterface::class));
}
return $adapter;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\simple_oauth\Oauth2ScopeAdapterInterface;
/**
* Defines an interface for Scope Provider plugins.
*/
interface ScopeProviderInterface extends PluginInspectionInterface {
/**
* Get the scope provider label.
*
* @return string
* Returns the plugin label.
*/
public function label(): string;
/**
* Get the scope provider adapter.
*
* @return \Drupal\simple_oauth\Oauth2ScopeAdapterInterface
* Returns the scope provider class.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
*/
public function getScopeProviderAdapter(): Oauth2ScopeAdapterInterface;
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
/**
* Provides the Scope Provider plugin manager.
*/
class ScopeProviderManager extends DefaultPluginManager implements ScopeProviderManagerInterface {
/**
* The plugin instances.
*
* @var array
*/
protected array $instances = [];
/**
* Constructor for Oauth2GrantManager objects.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler to invoke the alter hook with.
*
* @throws \Exception
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct(
'Plugin/ScopeProvider',
$namespaces, $module_handler,
'Drupal\simple_oauth\Plugin\ScopeProviderInterface',
'Drupal\simple_oauth\Annotation\ScopeProvider'
);
$this->alterInfo('simple_oauth_scope_provider_info');
$this->setCacheBackend($cache_backend, 'simple_oauth_scope_provider_plugins');
}
/**
* {@inheritdoc}
*/
public function getInstance(array $options) {
$plugin_id = $options['id'];
if (!isset($this->instances[$plugin_id])) {
$this->instances[$plugin_id] = $this->createInstance($plugin_id);
}
return $this->instances[$plugin_id];
}
/**
* {@inheritdoc}
*/
public function getInstances(): array {
foreach (array_keys($this->getDefinitions()) as $plugin_id) {
if (!isset($this->instances[$plugin_id])) {
$this->instances[$plugin_id] = $this->createInstance($plugin_id);
}
}
return $this->instances;
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Drupal\simple_oauth\Plugin;
use Drupal\Component\Plugin\PluginManagerInterface;
/**
* Manages discovery and instantiation of Scope Provider plugins.
*/
interface ScopeProviderManagerInterface extends PluginManagerInterface {
/**
* Gets all scope provider plugin instances.
*
* @return \Drupal\simple_oauth\Plugin\ScopeProviderInterface[]
* Returns array of all plugin instances.
*/
public function getInstances(): array;
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Drupal\simple_oauth\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Validation constraint for valid OAuth2 redirect URI.
*
* @Constraint(
* id = "Oauth2RedirectUri",
* label = @Translation("OAuth2 redirect URI", context = "Validation"),
* type = "string"
* )
*/
class Oauth2RedirectUri extends Constraint {
/**
* The default violation message.
*
* @var string
*/
public string $oauth2RedirectUriMessage = 'The URL %url is not valid.';
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Drupal\simple_oauth\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the Oauth2RedirectUri constraint.
*/
class Oauth2RedirectUriValidator extends ConstraintValidator {
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint) {
foreach ($value->getValue() as $item) {
if (!preg_match("
/^
[a-z0-9\-]+:\/\/ # Supporting various URL schemes
(?:
(?:[a-z0-9\-\.]|%[0-9a-f]{2})+ # A domain name or a IPv4 address
|(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\]) # or a well formed IPv6 address
)
(?::[0-9]+)? # Server port number (optional)
(?:[\/|\?]
(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
*)?
$/xi", $item['value'])) {
$this->context->addViolation($constraint->oauth2RedirectUriMessage, ['%url' => $item['value']]);
}
}
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Drupal\simple_oauth\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* OAuth2 scope reference constraint.
*
* Verifies that referenced OAuth2 scopes are valid.
*
* @Constraint(
* id = "Oauth2ScopeReference",
* label = @Translation("OAuth2 scope reference", context = "Validation")
* )
*/
class Oauth2ScopeReference extends Constraint {
/**
* Violation message when the OAuth2 scope does not exist.
*
* @var string
*/
public string $nonExistingMessage = "The referenced OAuth2 scope '%id' does not exist.";
}

View File

@@ -0,0 +1,65 @@
<?php
namespace Drupal\simple_oauth\Plugin\Validation\Constraint;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\simple_oauth\Oauth2ScopeProviderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Checks if referenced OAuth2 scopes are valid.
*/
class Oauth2ScopeReferenceValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* The scope provider.
*
* @var \Drupal\simple_oauth\Oauth2ScopeProviderInterface
*/
protected Oauth2ScopeProviderInterface $scopeProvider;
/**
* Constructs a Oauth2ScopeReferenceValidator object.
*
* @param \Drupal\simple_oauth\Oauth2ScopeProviderInterface $scope_provider
* The scope provider.
*/
public function __construct(Oauth2ScopeProviderInterface $scope_provider) {
$this->scopeProvider = $scope_provider;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('simple_oauth.oauth2_scope.provider')
);
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint) {
$referenced_scope_ids = [];
foreach ($value as $item) {
$referenced_scope_ids[] = $item->scope_id;
}
$scopes = $this->scopeProvider->loadMultiple($referenced_scope_ids);
foreach ($referenced_scope_ids as $delta => $referenced_scope_id) {
if (!isset($scopes[$referenced_scope_id])) {
$this->context->buildViolation($constraint->nonExistingMessage)
->setParameter('%id', $referenced_scope_id)
->atPath((string) $delta . '.scope_id')
->setInvalidValue($referenced_scope_id)
->addViolation();
}
}
}
}