From 8173570303ec7ee4c008c7dc896963df0bc3decd Mon Sep 17 00:00:00 2001 From: Andreas Nielsen Date: Tue, 12 Nov 2024 05:10:38 +0100 Subject: [PATCH 1/5] Updated dpl_consumers module so it prefills the new consumer fields that the simple_oauth module provides upon installation. Right now we hardcode the secret to "secret", but we will have to find a better way of setting this value on installation. Maybe through an environment variable in Lagoon? Created a new drush command for setting the GraphQL consumer secret, based on what is set in .env. Also created a new task in the Taskfile.yml, used for running our new drush commando for setting a secret locally. --- .env.example | 4 ++ Taskfile.yml | 5 ++ .../dpl_consumers/dpl_consumers.crud.php | 17 ++++++- .../custom/dpl_consumers/dpl_consumers.module | 4 +- .../custom/dpl_consumers/drush.services.yml | 2 + .../src/Commands/DplConsumersCommands.php | 47 +++++++++++++++++++ 6 files changed, 75 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index 6fcc227e2..ae4210816 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,9 @@ COMPOSE_PROJECT_NAME=dpl-cms COMPOSER_MEMORY_LIMIT=-1 + +# GraphQL Consumer environemnt variables used for local development +GRAPHQL_CONSUMER_SECRET=secret + #OPENID_CLIENT_ID=some-client-id #OPENID_CLIENT_SECRET=some-client-secret #OPENID_AGENCY_ID=some-agency-id diff --git a/Taskfile.yml b/Taskfile.yml index 9452b6c71..14e74aef8 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -382,6 +382,11 @@ tasks: cmds: - cmd: task dev:cli -- drush default-content:export-module dpl_example_content + dev:go:set-graphql-secret: + desc: Sets the GraphQL consumer secret based on the .env variable. + cmds: + - cmd: task dev:cli -- drush dpl_consumers:set-consumer-secret + dev:go:graphql-credentials: desc: Get the GraphQL consumer credentials cmds: diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php b/web/modules/custom/dpl_consumers/dpl_consumers.crud.php index 860a67d57..c7ac3cf92 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.crud.php @@ -25,11 +25,25 @@ function dpl_consumers_create_user(): void { * Create a consumer. */ function dpl_consumers_create_consumer(): void { + $user = \Drupal::entityTypeManager() + ->getStorage('user') + ->loadByProperties(['name' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_USER_NAME]); + + $user = reset($user); + + if (empty($user)) { + return; + } + $consumer = \Drupal::entityTypeManager()->getStorage('consumer')->create([ 'label' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CONSUMER_LABEL, 'id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CONSUMER_ID, 'client_id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CLIENT_ID, + 'secret' => 'secret', 'third_party' => FALSE, + 'user_id' => $user->id(), + 'roles' => [DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_ROLE_ID], + ]); $consumer->save(); @@ -40,7 +54,6 @@ function dpl_consumers_create_consumer(): void { */ function dpl_consumers_delete_user(): void { try { - // Delete the user. $user = \Drupal::entityTypeManager() ->getStorage('user') ->loadByProperties(['name' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_USER_NAME]); @@ -61,7 +74,6 @@ function dpl_consumers_delete_user(): void { */ function dpl_consumers_delete_consumer(): void { try { - // Delete the consumer. $consumer = \Drupal::entityTypeManager() ->getStorage('consumer') ->loadByProperties(['label' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CONSUMER_LABEL]); @@ -72,6 +84,7 @@ function dpl_consumers_delete_consumer(): void { } } catch (\Exception $e) { + // We just log here in the deletion. It's not critical if it fails. \Drupal::logger('dpl_consumers')->error($e->getMessage()); } } diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.module b/web/modules/custom/dpl_consumers/dpl_consumers.module index 034201aaa..a1e0423a2 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.module +++ b/web/modules/custom/dpl_consumers/dpl_consumers.module @@ -19,8 +19,8 @@ function dpl_consumers_get_consumer_uuid(string $client_id): string { if (!empty($consumer)) { $consumer = reset($consumer); - $uuid = $consumer->uuid(); - return $uuid ?? 'Consumer UUID not found.'; + + return $consumer->uuid() ?? 'Consumer UUID not found.'; } else { return 'Consumer not found.'; diff --git a/web/modules/custom/dpl_consumers/drush.services.yml b/web/modules/custom/dpl_consumers/drush.services.yml index 350f43c43..b956f4a11 100644 --- a/web/modules/custom/dpl_consumers/drush.services.yml +++ b/web/modules/custom/dpl_consumers/drush.services.yml @@ -1,5 +1,7 @@ services: dpl_consumer.commands: class: \Drupal\dpl_consumers\Commands\DplConsumersCommands + arguments: + - "@entity_type.manager" tags: - { name: drush.command } diff --git a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php index ad9496eb1..dd499e46a 100644 --- a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php +++ b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php @@ -4,6 +4,7 @@ namespace Drupal\dpl_consumers\Commands; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\dpl_consumers\DplGraphqlConsumersConstants; use Drush\Commands\DrushCommands; @@ -12,6 +13,52 @@ */ final class DplConsumersCommands extends DrushCommands { + /** + * The entity type manager service. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Constructor. + */ + public function __construct( + EntityTypeManagerInterface $entityTypeManager, + ) { + parent::__construct(); + $this->entityTypeManager = $entityTypeManager; + } + + /** + * Function is used for setting the consumer secret. + * + * @command dpl_consumers:set-consumer-secret + */ + public function setConsumerSecret(): string { + try { + /** @var \Drupal\Core\Entity\EntityStorageInterface $consumer */ + $consumer = $this->entityTypeManager + ->getStorage('consumer') + ->loadByProperties(['client_id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CLIENT_ID]); + + $consumer = reset($consumer); + + $secret = getenv('GRAPHQL_CONSUMER_SECRET'); + if (!empty($secret)) { + $consumer->secret = $secret; + $consumer->save(); + + return 'Consumer secret set successfully.'; + } + + return 'Consumer secret was not found.'; + } + catch (\Exception $e) { + return 'Error fetching consumer.'; + } + } + /** * Function is used for printing out the consumer credentials to the console. * From cf66e64d8d3e3d5e4079d04071439c9a2e52e5e8 Mon Sep 17 00:00:00 2001 From: Andreas Nielsen Date: Thu, 14 Nov 2024 10:00:10 +0100 Subject: [PATCH 2/5] Updated the GraphQL consumer and user creation with the extra fields that the simple_oauth module provides. I have decided to rename the deploy hook, as the naming convention I was using was not ideal. --- .env.example | 4 +-- .../dpl_consumers/dpl_consumers.crud.php | 25 +++++++++++-------- .../dpl_consumers/dpl_consumers.deploy.php | 9 +++++-- .../dpl_consumers/dpl_consumers.info.yml | 1 + .../src/DplGraphqlConsumersConstants.php | 2 +- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index ae4210816..2a87ecdaa 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,8 @@ COMPOSE_PROJECT_NAME=dpl-cms COMPOSER_MEMORY_LIMIT=-1 -# GraphQL Consumer environemnt variables used for local development -GRAPHQL_CONSUMER_SECRET=secret +# GraphQL Consumer environment variables used for local development +GRAPHQL_CONSUMER_SECRET=some-secret #OPENID_CLIENT_ID=some-client-id #OPENID_CLIENT_SECRET=some-client-secret diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php b/web/modules/custom/dpl_consumers/dpl_consumers.crud.php index c7ac3cf92..1b45248ca 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.crud.php @@ -35,18 +35,21 @@ function dpl_consumers_create_consumer(): void { return; } - $consumer = \Drupal::entityTypeManager()->getStorage('consumer')->create([ - 'label' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CONSUMER_LABEL, - 'id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CONSUMER_ID, - 'client_id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CLIENT_ID, - 'secret' => 'secret', - 'third_party' => FALSE, - 'user_id' => $user->id(), - 'roles' => [DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_ROLE_ID], + $secret = getenv('GRAPHQL_CONSUMER_SECRET'); - ]); + if ($secret) { + $consumer = \Drupal::entityTypeManager()->getStorage('consumer')->create([ + 'label' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_LABEL, + 'id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CONSUMER_ID, + 'client_id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CLIENT_ID, + 'secret' => $secret, + 'third_party' => FALSE, + 'user_id' => $user->id(), + 'roles' => [DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_ROLE_ID], + ]); - $consumer->save(); + $consumer->save(); + } } /** @@ -76,7 +79,7 @@ function dpl_consumers_delete_consumer(): void { try { $consumer = \Drupal::entityTypeManager() ->getStorage('consumer') - ->loadByProperties(['label' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CONSUMER_LABEL]); + ->loadByProperties(['label' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_LABEL]); if (!empty($consumer)) { $consumer = reset($consumer); diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index 7c2b50eb7..4949f5c93 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -13,12 +13,17 @@ * Run consumer creation on deploy. * * We run the user and consumer creation in a deploy_hook instead of - * a install_hook, as we run into problems with the password_policy + * an install_hook, as we run into problems with the password_policy * module not being installed when we try to create the user. Doing * it this way instead, we make sure that everything is ready for the * user and consumer creation. + * + * We make sure to delete already existing user and consumers before + * as we don't want to create duplicates. */ -function dpl_consumers_deploy_create_user(): void { +function dpl_consumers_deploy_1(): void { + dpl_consumers_delete_user(); + dpl_consumers_delete_consumer(); dpl_consumers_create_user(); dpl_consumers_create_consumer(); } diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.info.yml b/web/modules/custom/dpl_consumers/dpl_consumers.info.yml index fe1089023..b343f8744 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.info.yml +++ b/web/modules/custom/dpl_consumers/dpl_consumers.info.yml @@ -6,3 +6,4 @@ core_version_requirement: ^10 || ^11 dependencies: - drupal:user - consumers:consumers + - simple_oauth:simple_oauth diff --git a/web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php b/web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php index f7210efbd..e97c69e23 100644 --- a/web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php +++ b/web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php @@ -13,7 +13,7 @@ class DplGraphqlConsumersConstants { const GRAPHQL_CONSUMER_USER_NAME = 'GraphQL Consumer'; - const GRAPHQL_CONSUMER_CONSUMER_LABEL = 'GraphQL Consumer'; + const GRAPHQL_CONSUMER_LABEL = 'GraphQL Consumer'; const GRAPHQL_CONSUMER_CONSUMER_ID = 'graphql_consumer'; From 34bb90c41769d5fe0d22247b39d182b43eabdc42 Mon Sep 17 00:00:00 2001 From: Andreas Nielsen Date: Thu, 14 Nov 2024 15:36:58 +0100 Subject: [PATCH 3/5] Merge develop into branch and fix conflicts. --- web/modules/custom/dpl_update/dpl_update.install | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/web/modules/custom/dpl_update/dpl_update.install b/web/modules/custom/dpl_update/dpl_update.install index 9844ea343..1366fb375 100644 --- a/web/modules/custom/dpl_update/dpl_update.install +++ b/web/modules/custom/dpl_update/dpl_update.install @@ -106,9 +106,8 @@ function dpl_update_install(): string { $messages[] = dpl_update_update_10024(); // Do not uninstall dblog module on install. It is not installed by default. - // $messages[] = dpl_update_update_10025(); - - $messages[] = dpl_update_update_10026(); + // $messages[] = dpl_update_update_10025() + $messages[] = dpl_update_update_10026() return implode('\r\n', $messages); } From 4cad7deef1dbaacc0e9ff0e704a871821b4d7361 Mon Sep 17 00:00:00 2001 From: Andreas Nielsen Date: Thu, 14 Nov 2024 15:36:58 +0100 Subject: [PATCH 4/5] Merge develop into branch and fix conflicts. --- web/modules/custom/dpl_update/dpl_update.install | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/modules/custom/dpl_update/dpl_update.install b/web/modules/custom/dpl_update/dpl_update.install index 9844ea343..bd867d4c5 100644 --- a/web/modules/custom/dpl_update/dpl_update.install +++ b/web/modules/custom/dpl_update/dpl_update.install @@ -106,8 +106,7 @@ function dpl_update_install(): string { $messages[] = dpl_update_update_10024(); // Do not uninstall dblog module on install. It is not installed by default. - // $messages[] = dpl_update_update_10025(); - + // $messages[] = dpl_update_update_10025() $messages[] = dpl_update_update_10026(); return implode('\r\n', $messages); From 442844b99c1c14bf497e5cd391be616f9903ff44 Mon Sep 17 00:00:00 2001 From: Andreas Nielsen Date: Wed, 20 Nov 2024 15:53:45 +0100 Subject: [PATCH 5/5] Added comment explaining why we only expect the first consumer returned to be the correct one. We now throw exceptions whenever we do not get the expected results. Changed the delete consumer function to look for client_id instead of label, as the client_id should be unique, where as the label can be a duplicate. --- .../custom/dpl_consumers/dpl_consumers.crud.php | 4 +++- .../custom/dpl_consumers/dpl_consumers.module | 11 +++++++---- .../src/Commands/DplConsumersCommands.php | 13 +++++++++---- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php b/web/modules/custom/dpl_consumers/dpl_consumers.crud.php index 1b45248ca..5ec51c90d 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.crud.php @@ -79,8 +79,10 @@ function dpl_consumers_delete_consumer(): void { try { $consumer = \Drupal::entityTypeManager() ->getStorage('consumer') - ->loadByProperties(['label' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_LABEL]); + ->loadByProperties(['client_id' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CLIENT_ID]); + // We assume that there is only one consumer with the given client ID + // as it is used an as unique identifier (machine name). if (!empty($consumer)) { $consumer = reset($consumer); $consumer->delete(); diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.module b/web/modules/custom/dpl_consumers/dpl_consumers.module index a1e0423a2..0eb0820fb 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.module +++ b/web/modules/custom/dpl_consumers/dpl_consumers.module @@ -10,6 +10,8 @@ * * @return string * The consumer UUID. + * + * @throws \Exception */ function dpl_consumers_get_consumer_uuid(string $client_id): string { try { @@ -17,17 +19,18 @@ function dpl_consumers_get_consumer_uuid(string $client_id): string { ->getStorage('consumer') ->loadByProperties(['client_id' => $client_id]); + // We assume that there is only one consumer with the given client ID + // as it is used an as unique identifier (machine name). if (!empty($consumer)) { $consumer = reset($consumer); - return $consumer->uuid() ?? 'Consumer UUID not found.'; + return $consumer->uuid() ?? throw new \Exception('UUID not found.'); } else { - return 'Consumer not found.'; + throw new \Exception('Consumer not found.'); } } catch (\Exception $e) { - \Drupal::logger('dpl_consumers')->error($e->getMessage()); - return 'Error fetching consumer.'; + throw new \Exception($e->getMessage()); } } diff --git a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php index dd499e46a..f32d2341c 100644 --- a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php +++ b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php @@ -18,7 +18,7 @@ final class DplConsumersCommands extends DrushCommands { * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ - protected $entityTypeManager; + protected EntityTypeManagerInterface $entityTypeManager; /** * Constructor. @@ -34,6 +34,8 @@ public function __construct( * Function is used for setting the consumer secret. * * @command dpl_consumers:set-consumer-secret + * + * @throws \Exception */ public function setConsumerSecret(): string { try { @@ -51,11 +53,12 @@ public function setConsumerSecret(): string { return 'Consumer secret set successfully.'; } - - return 'Consumer secret was not found.'; + else { + throw new \Exception('Consumer secret was not found.'); + } } catch (\Exception $e) { - return 'Error fetching consumer.'; + throw new \Exception($e->getMessage()); } } @@ -63,6 +66,8 @@ public function setConsumerSecret(): string { * Function is used for printing out the consumer credentials to the console. * * @command dpl_consumers:consumer-credentials + * + * @throws \Exception */ public function getConsumerCredentials(): void { $graphql_consumer_client_id = DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CLIENT_ID;