Skip to content
Snippets Groups Projects
Commit 7433fbf7 authored by Christian Foidl's avatar Christian Foidl
Browse files

Issue #3417803: Do not require a Consumer to verify a magic code

parent 8a297833
No related branches found
No related tags found
1 merge request!1Issue #3417803: Do not require a Consumer to verify a magic code
Pipeline #84341 passed
......@@ -10,6 +10,7 @@ services:
- '@config.factory'
- '@datetime.time'
- '@flood'
- '@consumer.negotiator'
- '@logger.channel.magic_code'
magic_code.collector:
......
......@@ -6,6 +6,7 @@ namespace Drupal\magic_code;
use Drupal\Component\Datetime\Time;
use Drupal\consumers\Entity\ConsumerInterface;
use Drupal\consumers\Negotiator;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Flood\FloodInterface;
......@@ -32,6 +33,8 @@ class MagicCodeManager implements MagicCodeManagerInterface {
* The time service.
* @param \Drupal\Core\Flood\FloodInterface $flood
* The flood service.
* @param \Drupal\consumers\Negotiator $consumerNegotiator
* The consumer request negotiator.
* @param \Psr\Log\LoggerInterface $logger
* The logger.
*/
......@@ -40,13 +43,14 @@ class MagicCodeManager implements MagicCodeManagerInterface {
protected ConfigFactoryInterface $configFactory,
protected Time $time,
protected FloodInterface $flood,
protected Negotiator $consumerNegotiator,
protected LoggerInterface $logger,
) {}
/**
* {@inheritdoc}
*/
public function createNew(string $operation, AccountInterface $user, ConsumerInterface $consumer, ?string $email = NULL): MagicCodeInterface {
public function createNew(string $operation, AccountInterface $user, ?ConsumerInterface $consumer = NULL, ?string $email = NULL): MagicCodeInterface {
$loginPermittedOperations = $this->getLoginPermittedOperations();
$allowLogin = in_array($operation, $loginPermittedOperations);
......@@ -54,6 +58,11 @@ class MagicCodeManager implements MagicCodeManagerInterface {
$code = $this->createUniqueCode();
$targetEmail = $email ?? $user->getEmail();
// Load consumer via negotiator if not set.
if (!$consumer) {
$consumer = $this->consumerNegotiator->negotiateFromRequest();
}
$payload = [
'auth_user_id' => $user->id(),
'value' => $code,
......@@ -81,7 +90,7 @@ class MagicCodeManager implements MagicCodeManagerInterface {
string $operation,
int $mode,
AccountInterface $user,
ConsumerInterface $consumer,
?ConsumerInterface $consumer = NULL,
?string $email = NULL,
): MagicCodeResult {
$floodConfig = $this->getFloodConfig();
......@@ -125,6 +134,11 @@ class MagicCodeManager implements MagicCodeManagerInterface {
return MagicCodeResult::BlockedByUser;
}
// Load consumer via negotiator if not set.
if (!$consumer) {
$consumer = $this->consumerNegotiator->negotiateFromRequest();
}
// User and IP are not blocked, continue with verification.
$query = $this->entityTypeManager->getStorage('magic_code')->getQuery();
......
......@@ -27,8 +27,9 @@ interface MagicCodeManagerInterface {
* The operation this code authorizes.
* @param \Drupal\Core\Session\AccountInterface $user
* The user to create the magic code for.
* @param \Drupal\consumers\Entity\ConsumerInterface $consumer
* The consumer this code is for.
* @param \Drupal\consumers\Entity\ConsumerInterface|null $consumer
* The consumer this code is for. If null, the consumer is
* negotiated from the request.
* @param string|null $email
* The email address this code is sent to. If NULL the
* email is set to the user's email address.
......@@ -42,7 +43,7 @@ interface MagicCodeManagerInterface {
public function createNew(
string $operation,
AccountInterface $user,
ConsumerInterface $consumer,
?ConsumerInterface $consumer = NULL,
?string $email = NULL,
): MagicCodeInterface;
......@@ -63,8 +64,9 @@ interface MagicCodeManagerInterface {
* self::VERIFY_MODE_OPERATION.
* @param \Drupal\Core\Session\AccountInterface $user
* The user to create the magic code for.
* @param \Drupal\consumers\Entity\ConsumerInterface $consumer
* The consumer this code is for.
* @param \Drupal\consumers\Entity\ConsumerInterface|null $consumer
* The consumer this code is for. If null, the consumer is
* negotiated from the request.
* @param string|null $email
* The email address this code is sent to. If NULL the
* email is set to the user's email address.
......@@ -77,7 +79,7 @@ interface MagicCodeManagerInterface {
string $operation,
int $mode,
AccountInterface $user,
ConsumerInterface $consumer,
?ConsumerInterface $consumer = NULL,
?string $email = NULL,
): MagicCodeResult;
......
......@@ -51,6 +51,7 @@ class MagicCodeManagerTest extends EntityKernelTestBase {
$this->client = Consumer::create([
'client_id' => 'test',
'label' => 'test',
'is_default' => TRUE,
]);
$this->client->save();
......@@ -353,4 +354,34 @@ class MagicCodeManagerTest extends EntityKernelTestBase {
$this->assertEquals($result, MagicCodeResult::Invalid);
}
/**
* Test scenarios where consumer is not set explicitly.
*/
public function testConsumerNegotiation() {
$operation = 'demo-operation';
$user = \Drupal::currentUser();
$otherClient = Consumer::create([
'client_id' => 'other',
'label' => 'Other client',
]);
$otherClient->save();
$mode = MagicCodeManagerInterface::VERIFY_MODE_OPERATION;
// Create with default client, validate with explicit.
$codeEntity = $this->manager->createNew($operation, $user);
$result = $this->manager->verify($codeEntity->label(), $operation, $mode, $user, $otherClient);
$this->assertEquals($result, MagicCodeResult::Invalid);
// Create with default client, validate with default.
$codeEntity = $this->manager->createNew($operation, $user);
$result = $this->manager->verify($codeEntity->label(), $operation, $mode, $user);
$this->assertEquals($result, MagicCodeResult::Success);
// Create with other client, validate with default.
$codeEntity = $this->manager->createNew($operation, $user, $otherClient);
$result = $this->manager->verify($codeEntity->label(), $operation, $mode, $user);
$this->assertEquals($result, MagicCodeResult::Invalid);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment