From 9c4bc3b74afd4a4dffb4b0e031d9ccc24390861d Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Wed, 25 Dec 2024 21:49:23 +0100 Subject: [PATCH 01/12] Delete old graphql consumer roles and add new ones in config --- config/sync/administerusersbyrole.settings.yml | 3 ++- ...ion.user_add_role_action.bnf_graphql_client.yml | 14 ++++++++++++++ ...tion.user_add_role_action.go_graphql_client.yml | 14 ++++++++++++++ ...ction.user_add_role_action.graphql_consumer.yml | 14 -------------- ....user_remove_role_action.bnf_graphql_client.yml | 14 ++++++++++++++ ...n.user_remove_role_action.go_graphql_client.yml | 14 ++++++++++++++ ...on.user_remove_role_action.graphql_consumer.yml | 14 -------------- config/sync/user.role.bnf_graphql_client.yml | 12 ++++++++++++ ...onsumer.yml => user.role.go_graphql_client.yml} | 10 +++++----- 9 files changed, 75 insertions(+), 34 deletions(-) create mode 100644 config/sync/system.action.user_add_role_action.bnf_graphql_client.yml create mode 100644 config/sync/system.action.user_add_role_action.go_graphql_client.yml delete mode 100644 config/sync/system.action.user_add_role_action.graphql_consumer.yml create mode 100644 config/sync/system.action.user_remove_role_action.bnf_graphql_client.yml create mode 100644 config/sync/system.action.user_remove_role_action.go_graphql_client.yml delete mode 100644 config/sync/system.action.user_remove_role_action.graphql_consumer.yml create mode 100644 config/sync/user.role.bnf_graphql_client.yml rename config/sync/{user.role.graphql_consumer.yml => user.role.go_graphql_client.yml} (55%) diff --git a/config/sync/administerusersbyrole.settings.yml b/config/sync/administerusersbyrole.settings.yml index 47b951175..5d5843cbe 100644 --- a/config/sync/administerusersbyrole.settings.yml +++ b/config/sync/administerusersbyrole.settings.yml @@ -7,4 +7,5 @@ roles: mediator: safe patron: unsafe external_system: safe - graphql_consumer: unsafe + bnf_graphql_client: unsafe + go_graphql_client: unsafe diff --git a/config/sync/system.action.user_add_role_action.bnf_graphql_client.yml b/config/sync/system.action.user_add_role_action.bnf_graphql_client.yml new file mode 100644 index 000000000..21f145700 --- /dev/null +++ b/config/sync/system.action.user_add_role_action.bnf_graphql_client.yml @@ -0,0 +1,14 @@ +uuid: b74f9f26-2491-4676-831b-8bf9e1db2924 +langcode: da +status: true +dependencies: + config: + - user.role.bnf_graphql_client + module: + - user +id: user_add_role_action.bnf_graphql_client +label: 'Add the BNF GraphQL Client role to the selected user(s)' +type: user +plugin: user_add_role_action +configuration: + rid: bnf_graphql_client diff --git a/config/sync/system.action.user_add_role_action.go_graphql_client.yml b/config/sync/system.action.user_add_role_action.go_graphql_client.yml new file mode 100644 index 000000000..7109d331f --- /dev/null +++ b/config/sync/system.action.user_add_role_action.go_graphql_client.yml @@ -0,0 +1,14 @@ +uuid: 5b4da83f-bde0-4d1a-afd0-62b5a758379e +langcode: da +status: true +dependencies: + config: + - user.role.go_graphql_client + module: + - user +id: user_add_role_action.go_graphql_client +label: 'Add the GO GraphQL Client role to the selected user(s)' +type: user +plugin: user_add_role_action +configuration: + rid: go_graphql_client diff --git a/config/sync/system.action.user_add_role_action.graphql_consumer.yml b/config/sync/system.action.user_add_role_action.graphql_consumer.yml deleted file mode 100644 index e72b7b29d..000000000 --- a/config/sync/system.action.user_add_role_action.graphql_consumer.yml +++ /dev/null @@ -1,14 +0,0 @@ -uuid: 07d7f391-9749-4d69-b788-c771a16c780c -langcode: en -status: true -dependencies: - config: - - user.role.graphql_consumer - module: - - user -id: user_add_role_action.graphql_consumer -label: 'Add the GraphQl consumer role to the selected user(s)' -type: user -plugin: user_add_role_action -configuration: - rid: graphql_consumer diff --git a/config/sync/system.action.user_remove_role_action.bnf_graphql_client.yml b/config/sync/system.action.user_remove_role_action.bnf_graphql_client.yml new file mode 100644 index 000000000..a2a7eee65 --- /dev/null +++ b/config/sync/system.action.user_remove_role_action.bnf_graphql_client.yml @@ -0,0 +1,14 @@ +uuid: 64ba08c0-435a-4e68-b9db-ad5e36751432 +langcode: da +status: true +dependencies: + config: + - user.role.bnf_graphql_client + module: + - user +id: user_remove_role_action.bnf_graphql_client +label: 'Remove the BNF GraphQL Client role from the selected user(s)' +type: user +plugin: user_remove_role_action +configuration: + rid: bnf_graphql_client diff --git a/config/sync/system.action.user_remove_role_action.go_graphql_client.yml b/config/sync/system.action.user_remove_role_action.go_graphql_client.yml new file mode 100644 index 000000000..b7201037e --- /dev/null +++ b/config/sync/system.action.user_remove_role_action.go_graphql_client.yml @@ -0,0 +1,14 @@ +uuid: c8fe6acb-1517-47b9-abb1-b6e66472bf54 +langcode: da +status: true +dependencies: + config: + - user.role.go_graphql_client + module: + - user +id: user_remove_role_action.go_graphql_client +label: 'Remove the GO GraphQL Client role from the selected user(s)' +type: user +plugin: user_remove_role_action +configuration: + rid: go_graphql_client diff --git a/config/sync/system.action.user_remove_role_action.graphql_consumer.yml b/config/sync/system.action.user_remove_role_action.graphql_consumer.yml deleted file mode 100644 index d04b68c4c..000000000 --- a/config/sync/system.action.user_remove_role_action.graphql_consumer.yml +++ /dev/null @@ -1,14 +0,0 @@ -uuid: 8e2eaac6-54a6-40fe-9852-8e1324aa046e -langcode: en -status: true -dependencies: - config: - - user.role.graphql_consumer - module: - - user -id: user_remove_role_action.graphql_consumer -label: 'Remove the GraphQl consumer role from the selected user(s)' -type: user -plugin: user_remove_role_action -configuration: - rid: graphql_consumer diff --git a/config/sync/user.role.bnf_graphql_client.yml b/config/sync/user.role.bnf_graphql_client.yml new file mode 100644 index 000000000..6566e3a91 --- /dev/null +++ b/config/sync/user.role.bnf_graphql_client.yml @@ -0,0 +1,12 @@ +uuid: acb9efe1-c340-4abb-a4a6-c7acb96e41b3 +langcode: da +status: true +dependencies: + module: + - graphql +id: bnf_graphql_client +label: 'BNF GraphQL Client' +weight: 9 +is_admin: null +permissions: + - 'execute graphql_compose_server arbitrary graphql requests' diff --git a/config/sync/user.role.graphql_consumer.yml b/config/sync/user.role.go_graphql_client.yml similarity index 55% rename from config/sync/user.role.graphql_consumer.yml rename to config/sync/user.role.go_graphql_client.yml index 67b41276d..cccef3c65 100644 --- a/config/sync/user.role.graphql_consumer.yml +++ b/config/sync/user.role.go_graphql_client.yml @@ -1,12 +1,12 @@ -uuid: 2844cde3-5ba7-4a93-958a-70da917913a7 -langcode: en +uuid: 0f907e2f-f8c2-4979-85f4-bf9ab822603b +langcode: da status: true dependencies: module: - graphql -id: graphql_consumer -label: 'GraphQl consumer' -weight: 8 +id: go_graphql_client +label: 'GO GraphQL Client' +weight: 10 is_admin: null permissions: - 'execute graphql_compose_server arbitrary graphql requests' From c83f0483ddfe9dbe6ee18f44022df77bc27c357e Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Wed, 25 Dec 2024 21:55:24 +0100 Subject: [PATCH 02/12] Add tools for handling creation of new consumers and users --- .env.example | 8 +- .../custom/dpl_consumers/dpl_consumers.module | 8 ++ .../dpl_consumers/dpl_consumers.services.yml | 12 +++ .../custom/dpl_consumers/src/Consumer.php | 78 +++++++++++++++++++ .../custom/dpl_consumers/src/ConsumerRole.php | 46 +++++++++++ .../custom/dpl_consumers/src/ConsumerUser.php | 78 +++++++++++++++++++ .../src/Services/ConsumerHandler.php | 70 +++++++++++++++++ 7 files changed, 298 insertions(+), 2 deletions(-) create mode 100644 web/modules/custom/dpl_consumers/dpl_consumers.services.yml create mode 100644 web/modules/custom/dpl_consumers/src/Consumer.php create mode 100644 web/modules/custom/dpl_consumers/src/ConsumerRole.php create mode 100644 web/modules/custom/dpl_consumers/src/ConsumerUser.php create mode 100644 web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php diff --git a/.env.example b/.env.example index 63f8fe1d9..da3a3f7bd 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,12 @@ COMPOSE_PROJECT_NAME=dapple-cms COMPOSER_MEMORY_LIMIT=-1 -# GraphQL Consumer environment variables used for local development -GRAPHQL_CONSUMER_SECRET=some-secret +# GraphQL Consumer secrets and user passwords +BNF_GRAPHQL_CONSUMER_SECRET=dUOAxbWr72cnigpkZXN1SuyuXfeHxZb5 +BNF_GRAPHQL_CONSUMER_USER_PASSWORD=dUOAxbWr72cnigpkZXN1SuyuXfeHxZb5 + +GO_GRAPHQL_CONSUMER_SECRET=GVOzhK8BogbZHrEzXW0W5HYFtScQrABt +GO_GRAPHQL_CONSUMER_USER_PASSWORD=oA8mqZFxmFubREH77T3qeApeoUxoNS7Y #OPENID_CLIENT_ID=some-client-id #OPENID_CLIENT_SECRET=some-client-secret diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.module b/web/modules/custom/dpl_consumers/dpl_consumers.module index 0eb0820fb..190bc4252 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.module +++ b/web/modules/custom/dpl_consumers/dpl_consumers.module @@ -1,5 +1,13 @@ getStorage('consumer')->create([ + 'label' => $this->label, + 'id' => $this->id, + 'client_id' => $this->clientId, + 'secret' => $this->secret, + 'third_party' => FALSE, + 'user_id' => $user->id(), + 'roles' => [$role->id()], + ]); + + $consumer->save(); + + if (!($consumer instanceof ConsumerInterface)) { + throw new \RuntimeException('Failed to create consumer.'); + } + + return $consumer; + } + + /** + * Load a consumer. + */ + public static function load(string $client_id): ConsumerInterface | NULL { + $consumers = \Drupal::entityTypeManager() + ->getStorage('consumer') + ->loadByProperties(['client_id' => $client_id]); + + if (empty($consumers)) { + return NULL; + } + + $consumer = reset($consumers); + + if (!($consumer instanceof ConsumerInterface)) { + return NULL; + } + + return $consumer; + } + + /** + * Delete a consumer based on a client ID. + */ + public static function deleteByClientId(string $client_id) { + if ($consumer = self::load($client_id)) { + $consumer->delete(); + } + } + +} diff --git a/web/modules/custom/dpl_consumers/src/ConsumerRole.php b/web/modules/custom/dpl_consumers/src/ConsumerRole.php new file mode 100644 index 000000000..2318970a0 --- /dev/null +++ b/web/modules/custom/dpl_consumers/src/ConsumerRole.php @@ -0,0 +1,46 @@ +id)) { + throw new \RuntimeException(sprintf('Failed to load role: %s', $this->id)); + } + + return $role; + } + + /** + * Delete a consumer role. + */ + public function delete() { + if ($role = $this->load()) { + $role->delete(); + } + } + +} diff --git a/web/modules/custom/dpl_consumers/src/ConsumerUser.php b/web/modules/custom/dpl_consumers/src/ConsumerUser.php new file mode 100644 index 000000000..ece915c95 --- /dev/null +++ b/web/modules/custom/dpl_consumers/src/ConsumerUser.php @@ -0,0 +1,78 @@ + $this->userName, + 'pass' => $this->password, + 'status' => 1, + ]); + + $user->addRole($role->id()); + $user->save(); + + return $user; + } + + /** + * + */ + public function load(): UserInterface | NULL { + $users = \Drupal::entityTypeManager() + ->getStorage('user') + ->loadByProperties(['name' => $this->userName]); + + if (empty($users)) { + return NULL; + } + + $user = reset($users); + + if (!($user instanceof UserInterface)) { + return NULL; + } + + return $user; + } + + /** + * + */ + public function delete() { + if ($user = $this->load()) { + $user->delete(); + } + } + +} diff --git a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php new file mode 100644 index 000000000..6fd72b554 --- /dev/null +++ b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php @@ -0,0 +1,70 @@ +consumer = $consumer; + $this->user = $user; + $this->role = $role; + + return $this; + } + + /** + * Create consumer and user connected to the consumer. + */ + public function create(): void { + $role = $this->role->load(); + $user = $this->user->create($role); + $consumer = $this->consumer->create($user, $role); + $this->logger->info('Created consumer: @consumer, user: @user, role: @role', [ + '@consumer' => $consumer->label(), + '@user' => $user->getAccountName(), + '@role' => $role->label(), + ]); + } + +} From 380e99714ea371981b49225e3424633d6f4b0b7f Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Wed, 25 Dec 2024 21:56:52 +0100 Subject: [PATCH 03/12] Delete legacy consumer constants and crud operations Since we introduced an object oriented way of handling consumers, users and roles, we do not need these files anymore --- .../dpl_consumers/dpl_consumers.crud.php | 95 ------------------- .../dpl_consumers/dpl_consumers.deploy.php | 2 - .../dpl_consumers/dpl_consumers.install | 2 - .../src/DplGraphqlConsumersConstants.php | 22 ----- 4 files changed, 121 deletions(-) delete mode 100644 web/modules/custom/dpl_consumers/dpl_consumers.crud.php delete mode 100644 web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php b/web/modules/custom/dpl_consumers/dpl_consumers.crud.php deleted file mode 100644 index 5ec51c90d..000000000 --- a/web/modules/custom/dpl_consumers/dpl_consumers.crud.php +++ /dev/null @@ -1,95 +0,0 @@ - DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_USER_NAME, - 'status' => 1, - ]); - - $user->addRole(DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_ROLE_ID); - $user->save(); -} - -/** - * 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; - } - - $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(); - } -} - -/** - * Delete the user. - */ -function dpl_consumers_delete_user(): void { - try { - $user = \Drupal::entityTypeManager() - ->getStorage('user') - ->loadByProperties(['name' => DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_USER_NAME]); - - if (!empty($user)) { - $user = reset($user); - $user->delete(); - } - } - catch (\Exception $e) { - // We just log here in the deletion. It's not critical if it fails. - \Drupal::logger('dpl_consumers')->error($e->getMessage()); - } -} - -/** - * Delete the consumer. - */ -function dpl_consumers_delete_consumer(): void { - try { - $consumer = \Drupal::entityTypeManager() - ->getStorage('consumer') - ->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(); - } - } - 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.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index 9ba5cff35..1033e495a 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -7,8 +7,6 @@ declare(strict_types=1); -require_once __DIR__ . '/dpl_consumers.crud.php'; - /** * Run consumer creation on deploy. * diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.install b/web/modules/custom/dpl_consumers/dpl_consumers.install index 7e102d825..730841e6c 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.install +++ b/web/modules/custom/dpl_consumers/dpl_consumers.install @@ -7,8 +7,6 @@ declare(strict_types=1); -require_once __DIR__ . '/dpl_consumers.crud.php'; - /** * Implements hook_uninstall(). */ diff --git a/web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php b/web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php deleted file mode 100644 index e97c69e23..000000000 --- a/web/modules/custom/dpl_consumers/src/DplGraphqlConsumersConstants.php +++ /dev/null @@ -1,22 +0,0 @@ - Date: Wed, 25 Dec 2024 21:58:32 +0100 Subject: [PATCH 04/12] Delete old consumer and add new ones in new deploy hook --- .../dpl_consumers/dpl_consumers.deploy.php | 59 +++++++++++++++++-- .../custom/dpl_consumers/dpl_consumers.module | 8 --- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index 1033e495a..30e9068d0 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -7,6 +7,10 @@ declare(strict_types=1); +use Drupal\dpl_consumers\Consumer; +use Drupal\dpl_consumers\ConsumerRole; +use Drupal\dpl_consumers\ConsumerUser; + /** * Run consumer creation on deploy. * @@ -20,8 +24,55 @@ * as we don't want to create duplicates. */ function dpl_consumers_deploy_10001(): void { - dpl_consumers_delete_user(); - dpl_consumers_delete_consumer(); - dpl_consumers_create_user(); - dpl_consumers_create_consumer(); + // Noop. We don't need to do anything here. + // Since we have changed our minds. + // @see dpl_consumers_deploy_10002(). +} + +/** + * Expand the users, roles, consumers so they can handle both BNF and GO. + * + * So we delete previous entities and create new ones. + */ +function dpl_consumers_deploy_10002(): void { + // Delete consume and users that we want to handle differently. + // We want to create consumers and consumer users + // specifically for the two known consumers (BNF and Go) and connected users. + Consumer::deleteByClientId("graphql_consumer"); + (new ConsumerUser('GraphQL Consumer', ''))->delete(); + (new ConsumerUser('graphql_consumer', ''))->delete(); + + // Check if we have the necessary secrets for new consumers and their users. + if (!$bnf_consumer_secret = getenv('BNF_GRAPHQL_CONSUMER_SECRET')) { + throw new \Exception('BNF_GRAPHQL_CONSUMER_SECRET not found.'); + } + if (!$go_consumer_secret = getenv('GO_GRAPHQL_CONSUMER_SECRET')) { + throw new \Exception('GO_GRAPHQL_CONSUMER_SECRET not found.'); + } + if (!$bnf_consumer_user_password = getenv('BNF_GRAPHQL_CONSUMER_USER_PASSWORD')) { + throw new \Exception('BNF_GRAPHQL_CONSUMER_USER_PASSWORD not found.'); + } + if (!$go_consumer_user_password = getenv('GO_GRAPHQL_CONSUMER_USER_PASSWORD')) { + throw new \Exception('GO_GRAPHQL_CONSUMER_USER_PASSWORD not found.'); + } + + // Create new consumers (BNF and Go) and their users and roles. + /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $handler */ + $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); + $consumers = [ + [ + 'consumer' => new Consumer('BNF GraphQL', 'bnf_graphql', 'bnf_graphql', $bnf_consumer_secret), + 'user' => new ConsumerUser('bnf_graphql', $bnf_consumer_user_password), + 'role' => new ConsumerRole('bnf_graphql_client'), + ], + [ + 'consumer' => new Consumer('GO GraphQL', 'go_graphql', 'go_graphql', $go_consumer_secret), + 'user' => new ConsumerUser('go_graphql', $go_consumer_user_password), + 'role' => new ConsumerRole('go_graphql_client'), + ], + ]; + + foreach ($consumers as $consumer) { + $consumer_handler->setComponents($consumer['consumer'], $consumer['user'], $consumer['role'])->create(); + } } diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.module b/web/modules/custom/dpl_consumers/dpl_consumers.module index 190bc4252..0eb0820fb 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.module +++ b/web/modules/custom/dpl_consumers/dpl_consumers.module @@ -1,13 +1,5 @@ Date: Wed, 25 Dec 2024 22:05:30 +0100 Subject: [PATCH 05/12] Adjust dpl_consumers unsinstall operations So they align with the created entities --- web/modules/custom/dpl_consumers/dpl_consumers.install | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.install b/web/modules/custom/dpl_consumers/dpl_consumers.install index 730841e6c..82a00b814 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.install +++ b/web/modules/custom/dpl_consumers/dpl_consumers.install @@ -7,10 +7,15 @@ declare(strict_types=1); +use Drupal\dpl_consumers\Consumer; +use Drupal\dpl_consumers\ConsumerUser; + /** * Implements hook_uninstall(). */ function dpl_consumers_uninstall(): void { - dpl_consumers_delete_user(); - dpl_consumers_delete_consumer(); + Consumer::deleteByClientId(client_id: "bnf_graphql"); + Consumer::deleteByClientId(client_id: "go_graphql"); + (new ConsumerUser('bnf_graphql', ''))->delete(); + (new ConsumerUser('go_graphql', ''))->delete(); } From ef25703b694b6aa9972f9a4e976c17ff7a2e8ccd Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Wed, 25 Dec 2024 23:19:06 +0100 Subject: [PATCH 06/12] Tidying up class properties of consumer classes and use consumer handler for entity deletion as well. --- .../dpl_consumers/dpl_consumers.deploy.php | 10 ++++---- .../dpl_consumers/dpl_consumers.install | 23 ++++++++++++++---- .../custom/dpl_consumers/src/Consumer.php | 17 ++++++------- .../custom/dpl_consumers/src/ConsumerRole.php | 6 ----- .../custom/dpl_consumers/src/ConsumerUser.php | 24 ++++++++----------- .../src/Services/ConsumerHandler.php | 16 +++++++++++-- 6 files changed, 57 insertions(+), 39 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index 30e9068d0..cc6987d93 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -38,9 +38,9 @@ function dpl_consumers_deploy_10002(): void { // Delete consume and users that we want to handle differently. // We want to create consumers and consumer users // specifically for the two known consumers (BNF and Go) and connected users. - Consumer::deleteByClientId("graphql_consumer"); - (new ConsumerUser('GraphQL Consumer', ''))->delete(); - (new ConsumerUser('graphql_consumer', ''))->delete(); + (new Consumer("graphql_consumer"))->delete(); + (new ConsumerUser('GraphQL Consumer'))->delete(); + (new ConsumerUser('graphql_consumer'))->delete(); // Check if we have the necessary secrets for new consumers and their users. if (!$bnf_consumer_secret = getenv('BNF_GRAPHQL_CONSUMER_SECRET')) { @@ -61,12 +61,12 @@ function dpl_consumers_deploy_10002(): void { $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); $consumers = [ [ - 'consumer' => new Consumer('BNF GraphQL', 'bnf_graphql', 'bnf_graphql', $bnf_consumer_secret), + 'consumer' => new Consumer('bnf_graphql', 'BNF GraphQL', $bnf_consumer_secret), 'user' => new ConsumerUser('bnf_graphql', $bnf_consumer_user_password), 'role' => new ConsumerRole('bnf_graphql_client'), ], [ - 'consumer' => new Consumer('GO GraphQL', 'go_graphql', 'go_graphql', $go_consumer_secret), + 'consumer' => new Consumer('go_graphql', 'GO GraphQL', $go_consumer_secret), 'user' => new ConsumerUser('go_graphql', $go_consumer_user_password), 'role' => new ConsumerRole('go_graphql_client'), ], diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.install b/web/modules/custom/dpl_consumers/dpl_consumers.install index 82a00b814..ef6b08330 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.install +++ b/web/modules/custom/dpl_consumers/dpl_consumers.install @@ -14,8 +14,23 @@ use Drupal\dpl_consumers\ConsumerUser; * Implements hook_uninstall(). */ function dpl_consumers_uninstall(): void { - Consumer::deleteByClientId(client_id: "bnf_graphql"); - Consumer::deleteByClientId(client_id: "go_graphql"); - (new ConsumerUser('bnf_graphql', ''))->delete(); - (new ConsumerUser('go_graphql', ''))->delete(); + // Delete consumers (BNF and Go) and their users. + // Roles are handled by config. + /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $handler */ + $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); + + $consumers = [ + [ + 'consumer' => new Consumer('bnf_graphql'), + 'user' => new ConsumerUser('bnf_graphql'), + ], + [ + 'consumer' => new Consumer('go_graphql'), + 'user' => new ConsumerUser('go_graphql'), + ], + ]; + + foreach ($consumers as $consumer) { + $consumer_handler->setComponents($consumer['consumer'], $consumer['user'])->delete(); + } } diff --git a/web/modules/custom/dpl_consumers/src/Consumer.php b/web/modules/custom/dpl_consumers/src/Consumer.php index bbbe2c45a..937a3e123 100644 --- a/web/modules/custom/dpl_consumers/src/Consumer.php +++ b/web/modules/custom/dpl_consumers/src/Consumer.php @@ -16,19 +16,20 @@ class Consumer { public function __construct( - public string $id, - public string $label, public string $clientId, - public string $secret, + public string | NULL $label = NULL, + public string | NULL $secret = NULL, ) {} /** * Create a consumer. */ public function create(UserInterface $user, Role $role): ConsumerInterface { + if (!$this->label || !$this->clientId || !$this->secret) { + throw new \RuntimeException('Label, client ID and secret are required to create a consumer.'); + } $consumer = \Drupal::entityTypeManager()->getStorage('consumer')->create([ 'label' => $this->label, - 'id' => $this->id, 'client_id' => $this->clientId, 'secret' => $this->secret, 'third_party' => FALSE, @@ -48,10 +49,10 @@ public function create(UserInterface $user, Role $role): ConsumerInterface { /** * Load a consumer. */ - public static function load(string $client_id): ConsumerInterface | NULL { + protected function load(): ConsumerInterface | NULL { $consumers = \Drupal::entityTypeManager() ->getStorage('consumer') - ->loadByProperties(['client_id' => $client_id]); + ->loadByProperties(['client_id' => $this->clientId]); if (empty($consumers)) { return NULL; @@ -69,8 +70,8 @@ public static function load(string $client_id): ConsumerInterface | NULL { /** * Delete a consumer based on a client ID. */ - public static function deleteByClientId(string $client_id) { - if ($consumer = self::load($client_id)) { + public function delete() { + if ($consumer = $this->load()) { $consumer->delete(); } } diff --git a/web/modules/custom/dpl_consumers/src/ConsumerRole.php b/web/modules/custom/dpl_consumers/src/ConsumerRole.php index 2318970a0..e4d315eff 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerRole.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerRole.php @@ -13,12 +13,6 @@ */ class ConsumerRole { - /** - * Summary of __construct. - * - * @param string $id - * Role id. - */ public function __construct( public string $id, ) {} diff --git a/web/modules/custom/dpl_consumers/src/ConsumerUser.php b/web/modules/custom/dpl_consumers/src/ConsumerUser.php index ece915c95..4966c5fb3 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerUser.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerUser.php @@ -11,28 +11,24 @@ /** * DPL consumer user. * - * This class is responsible for creating, loading and deleting consumer related users. + * This class is responsible for creating, loading + * and deleting consumer related users. */ class ConsumerUser { - /** - * Summary of __construct. - * - * @param string $userName - * Adsdas. - * @param string $password - * Adsdasf. - */ public function __construct( public string $userName, - public string $password, + public string | NULL $password = NULL, ) {} /** - * + * Create a user. */ public function create(RoleInterface $role): UserInterface { - // Create role. + if (!$this->password) { + throw new \RuntimeException('Password is required to create a user.'); + } + // Create user and connect role. $user = User::create([ 'name' => $this->userName, 'pass' => $this->password, @@ -46,7 +42,7 @@ public function create(RoleInterface $role): UserInterface { } /** - * + * Load a user. */ public function load(): UserInterface | NULL { $users = \Drupal::entityTypeManager() @@ -67,7 +63,7 @@ public function load(): UserInterface | NULL { } /** - * + * Delete a user. */ public function delete() { if ($user = $this->load()) { diff --git a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php index 6fd72b554..1fb7b83cf 100644 --- a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php +++ b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php @@ -33,7 +33,7 @@ class ConsumerHandler { * * @param \Drupal\dpl_consumers\ConsumerRole $role */ - protected ConsumerRole $role; + protected ConsumerRole | NULL $role; /** * Constructor. @@ -45,7 +45,7 @@ public function __construct( /** * Set needed components for the handler. */ - public function setComponents(Consumer $consumer, ConsumerUser $user, ConsumerRole $role): self { + public function setComponents(Consumer $consumer, ConsumerUser $user, ?ConsumerRole $role = NULL): self { $this->consumer = $consumer; $this->user = $user; $this->role = $role; @@ -67,4 +67,16 @@ public function create(): void { ]); } + /** + * Delete consumer and user connected to the consumer. + */ + public function delete(): void { + $this->user->delete(); + $this->consumer->delete(); + $this->logger->info('Deleted consumer: @consumer and user: @user', [ + '@consumer' => $this->consumer->clientId, + '@user' => $this->user->userName, + ]); + } + } From 752e6cb427a6f7e3b8dcbffbee30e0605769c15c Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Fri, 3 Jan 2025 15:33:58 +0100 Subject: [PATCH 07/12] Only create consumers/users/roles via deploy hook To avoid confusion we handle consumers and users in one place --- Taskfile.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 1f343973c..1dc0fa543 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -230,10 +230,6 @@ tasks: - task dev:cli -- drush user:create patron --password="test" - task dev:cli -- drush user:role:add 'patron' patron - - task dev:cli -- drush user:create graphql_consumer --password="test" - - task dev:cli -- drush user:role:add 'external_system' graphql_consumer - - task dev:cli -- drush user:role:add 'graphql_consumer' graphql_consumer - dev:import-profile-translations: desc: Import our custom profile translations. This is done automatically on deploy. cmds: From d4c0ca4aac4be06f14cd3f3ef72521d1d627fb1e Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Fri, 3 Jan 2025 15:35:11 +0100 Subject: [PATCH 08/12] Use new consumer classes in drush commands Since the whole consumer/user/role part was refactored we also need to adjust the drush commands handling secrets/uuids --- .../dpl_consumers/dpl_consumers.deploy.php | 38 ++-------- .../dpl_consumers/dpl_consumers.install | 10 +-- .../custom/dpl_consumers/dpl_consumers.module | 65 +++++++++++++++++ .../src/Commands/DplConsumersCommands.php | 69 +++++++++++++------ .../custom/dpl_consumers/src/Consumer.php | 11 +-- .../custom/dpl_consumers/src/ConsumerRole.php | 2 +- .../custom/dpl_consumers/src/ConsumerUser.php | 8 ++- .../src/Services/ConsumerHandler.php | 7 +- 8 files changed, 142 insertions(+), 68 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index cc6987d93..9942c3510 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -8,7 +8,6 @@ declare(strict_types=1); use Drupal\dpl_consumers\Consumer; -use Drupal\dpl_consumers\ConsumerRole; use Drupal\dpl_consumers\ConsumerUser; /** @@ -38,41 +37,14 @@ function dpl_consumers_deploy_10002(): void { // Delete consume and users that we want to handle differently. // We want to create consumers and consumer users // specifically for the two known consumers (BNF and Go) and connected users. - (new Consumer("graphql_consumer"))->delete(); - (new ConsumerUser('GraphQL Consumer'))->delete(); - (new ConsumerUser('graphql_consumer'))->delete(); - - // Check if we have the necessary secrets for new consumers and their users. - if (!$bnf_consumer_secret = getenv('BNF_GRAPHQL_CONSUMER_SECRET')) { - throw new \Exception('BNF_GRAPHQL_CONSUMER_SECRET not found.'); - } - if (!$go_consumer_secret = getenv('GO_GRAPHQL_CONSUMER_SECRET')) { - throw new \Exception('GO_GRAPHQL_CONSUMER_SECRET not found.'); - } - if (!$bnf_consumer_user_password = getenv('BNF_GRAPHQL_CONSUMER_USER_PASSWORD')) { - throw new \Exception('BNF_GRAPHQL_CONSUMER_USER_PASSWORD not found.'); - } - if (!$go_consumer_user_password = getenv('GO_GRAPHQL_CONSUMER_USER_PASSWORD')) { - throw new \Exception('GO_GRAPHQL_CONSUMER_USER_PASSWORD not found.'); - } + (new Consumer("graphql_consumer", \Drupal::entityTypeManager()))->delete(); + (new ConsumerUser('GraphQL Consumer', \Drupal::entityTypeManager()))->delete(); + (new ConsumerUser('graphql_consumer', \Drupal::entityTypeManager()))->delete(); // Create new consumers (BNF and Go) and their users and roles. - /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $handler */ + /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $consumer_handler */ $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); - $consumers = [ - [ - 'consumer' => new Consumer('bnf_graphql', 'BNF GraphQL', $bnf_consumer_secret), - 'user' => new ConsumerUser('bnf_graphql', $bnf_consumer_user_password), - 'role' => new ConsumerRole('bnf_graphql_client'), - ], - [ - 'consumer' => new Consumer('go_graphql', 'GO GraphQL', $go_consumer_secret), - 'user' => new ConsumerUser('go_graphql', $go_consumer_user_password), - 'role' => new ConsumerRole('go_graphql_client'), - ], - ]; - - foreach ($consumers as $consumer) { + foreach (dpl_consumers_known_consumers_users_and_roles() as $consumer) { $consumer_handler->setComponents($consumer['consumer'], $consumer['user'], $consumer['role'])->create(); } } diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.install b/web/modules/custom/dpl_consumers/dpl_consumers.install index ef6b08330..5956d5b79 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.install +++ b/web/modules/custom/dpl_consumers/dpl_consumers.install @@ -16,17 +16,17 @@ use Drupal\dpl_consumers\ConsumerUser; function dpl_consumers_uninstall(): void { // Delete consumers (BNF and Go) and their users. // Roles are handled by config. - /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $handler */ + /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $consumer_handler */ $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); $consumers = [ [ - 'consumer' => new Consumer('bnf_graphql'), - 'user' => new ConsumerUser('bnf_graphql'), + 'consumer' => new Consumer('bnf_graphql', \Drupal::entityTypeManager()), + 'user' => new ConsumerUser('bnf_graphql', \Drupal::entityTypeManager()), ], [ - 'consumer' => new Consumer('go_graphql'), - 'user' => new ConsumerUser('go_graphql'), + 'consumer' => new Consumer('go_graphql', \Drupal::entityTypeManager()), + 'user' => new ConsumerUser('go_graphql', \Drupal::entityTypeManager()), ], ]; diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.module b/web/modules/custom/dpl_consumers/dpl_consumers.module index 0eb0820fb..1483b0d2c 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.module +++ b/web/modules/custom/dpl_consumers/dpl_consumers.module @@ -5,6 +5,10 @@ * DPL consumers module. */ +use Drupal\dpl_consumers\Consumer; +use Drupal\dpl_consumers\ConsumerRole; +use Drupal\dpl_consumers\ConsumerUser; + /** * Get consumer by Client ID. * @@ -34,3 +38,64 @@ function dpl_consumers_get_consumer_uuid(string $client_id): string { throw new \Exception($e->getMessage()); } } + +/** + * Get known consumers, users and roles. + * + * @return array + * An array of consumers, users and roles. + */ + +/** + * Get known consumers, users and roles. + * + * @return mixed[] + * An array of consumers, users and roles. + */ +function dpl_consumers_known_consumers_users_and_roles(): array { + // Check if we have the necessary secrets for new consumers and their users. + if (!$bnf_consumer_secret = getenv('BNF_GRAPHQL_CONSUMER_SECRET')) { + throw new \Exception('BNF_GRAPHQL_CONSUMER_SECRET not found.'); + } + if (!$go_consumer_secret = getenv('GO_GRAPHQL_CONSUMER_SECRET')) { + throw new \Exception('GO_GRAPHQL_CONSUMER_SECRET not found.'); + } + if (!$bnf_consumer_user_password = getenv('BNF_GRAPHQL_CONSUMER_USER_PASSWORD')) { + throw new \Exception('BNF_GRAPHQL_CONSUMER_USER_PASSWORD not found.'); + } + if (!$go_consumer_user_password = getenv('GO_GRAPHQL_CONSUMER_USER_PASSWORD')) { + throw new \Exception('GO_GRAPHQL_CONSUMER_USER_PASSWORD not found.'); + } + + return [ + [ + 'consumer' => new Consumer('bnf_graphql', \Drupal::entityTypeManager(), 'BNF GraphQL', $bnf_consumer_secret), + 'user' => new ConsumerUser('bnf_graphql', \Drupal::entityTypeManager(), $bnf_consumer_user_password), + 'role' => new ConsumerRole('bnf_graphql_client'), + ], + [ + 'consumer' => new Consumer('go_graphql', \Drupal::entityTypeManager(), 'GO GraphQL', $go_consumer_secret), + 'user' => new ConsumerUser('go_graphql', \Drupal::entityTypeManager(), $go_consumer_user_password), + 'role' => new ConsumerRole('go_graphql_client'), + ], + ]; +} + +/** + * Get known consumers. + * + * @return mixed[] + * An array of consumers keyed by client id. + */ +function dpl_consumers_get_known_consumers(): array { + return array_reduce( + dpl_consumers_known_consumers_users_and_roles(), + static function (array $carry, array $consumer): array { + $consumer_client_id = $consumer['consumer']->client_id; + $carry[$consumer_client_id] = $consumer['consumer']; + + return $carry; + }, + [] + ); +} diff --git a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php index f32d2341c..1c5b17d05 100644 --- a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php +++ b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php @@ -5,7 +5,6 @@ namespace Drupal\dpl_consumers\Commands; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\dpl_consumers\DplGraphqlConsumersConstants; use Drush\Commands\DrushCommands; /** @@ -33,29 +32,34 @@ public function __construct( /** * Function is used for setting the consumer secret. * + * The secret is stored as an environment variable. + * This command makes sure it is transferred to the database. + * + * @param string $client_id + * Client id of the consumer. + * * @command dpl_consumers:set-consumer-secret + * @aliases dpl-scs + * @usage dpl_consumers:set-consumer-secret [client_id of the consumer] * * @throws \Exception */ - public function setConsumerSecret(): string { + public function setConsumerSecret(string $client_id): string { + $consumers = $this->getConsumers($client_id); 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.'; + $consumer = $consumers[$client_id]; + if (!$consumer) { + throw new \Exception('Could not find consumer.'); } - else { - throw new \Exception('Consumer secret was not found.'); + if (!$consumer->secret) { + throw new \Exception('Consumer secret not found.'); } + if (!$consumer_entity = $consumer->load()) { + throw new \Exception('Could not load consumer entity.'); + } + $consumer_entity->save(); + return 'Consumer secret set successfully.'; } catch (\Exception $e) { throw new \Exception($e->getMessage()); @@ -65,14 +69,39 @@ public function setConsumerSecret(): string { /** * Function is used for printing out the consumer credentials to the console. * + * @param string $client_id + * Client id of the consumer. + * * @command dpl_consumers:consumer-credentials + * @aliases dpl-gcc + * @usage dpl_consumers:consumer-credentials [client_id of the consumer] + * + * @throws \Exception + */ + public function getConsumerCredentials(string $client_id): void { + $consumers = $this->getConsumers($client_id); + $consumer = $consumers[$client_id]; + $this->output()->writeln(sprintf('Consumer UUID: %s', $consumer->uuid)); + } + + /** + * Get consumers. + * + * @param string $client_id + * Client id of the consumer. + * + * @return mixed[] + * An array of consumer keyed by client id. * * @throws \Exception */ - public function getConsumerCredentials(): void { - $graphql_consumer_client_id = DplGraphqlConsumersConstants::GRAPHQL_CONSUMER_CLIENT_ID; - $consumer_uuid = dpl_consumers_get_consumer_uuid($graphql_consumer_client_id); - $this->output()->writeln('Consumer UUID: ' . $consumer_uuid); + protected function getConsumers(string $client_id): array { + $consumers = dpl_consumers_get_known_consumers(); + if (!in_array($client_id, array_keys($consumers), TRUE)) { + throw new \Exception(sprintf('GraphQL consumer %s is not known.', $client_id)); + } + + return $consumers; } } diff --git a/web/modules/custom/dpl_consumers/src/Consumer.php b/web/modules/custom/dpl_consumers/src/Consumer.php index 937a3e123..e97bd8ed6 100644 --- a/web/modules/custom/dpl_consumers/src/Consumer.php +++ b/web/modules/custom/dpl_consumers/src/Consumer.php @@ -5,6 +5,7 @@ namespace Drupal\dpl_consumers; use Drupal\consumers\Entity\ConsumerInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\user\Entity\Role; use Drupal\user\UserInterface; @@ -17,6 +18,7 @@ class Consumer { public function __construct( public string $clientId, + protected EntityTypeManagerInterface $entityTypeManager, public string | NULL $label = NULL, public string | NULL $secret = NULL, ) {} @@ -28,7 +30,7 @@ public function create(UserInterface $user, Role $role): ConsumerInterface { if (!$this->label || !$this->clientId || !$this->secret) { throw new \RuntimeException('Label, client ID and secret are required to create a consumer.'); } - $consumer = \Drupal::entityTypeManager()->getStorage('consumer')->create([ + $consumer = $this->entityTypeManager->getStorage('consumer')->create([ 'label' => $this->label, 'client_id' => $this->clientId, 'secret' => $this->secret, @@ -49,9 +51,8 @@ public function create(UserInterface $user, Role $role): ConsumerInterface { /** * Load a consumer. */ - protected function load(): ConsumerInterface | NULL { - $consumers = \Drupal::entityTypeManager() - ->getStorage('consumer') + public function load(): ConsumerInterface | NULL { + $consumers = $this->entityTypeManager->getStorage('consumer') ->loadByProperties(['client_id' => $this->clientId]); if (empty($consumers)) { @@ -70,7 +71,7 @@ protected function load(): ConsumerInterface | NULL { /** * Delete a consumer based on a client ID. */ - public function delete() { + public function delete(): void { if ($consumer = $this->load()) { $consumer->delete(); } diff --git a/web/modules/custom/dpl_consumers/src/ConsumerRole.php b/web/modules/custom/dpl_consumers/src/ConsumerRole.php index e4d315eff..15545b248 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerRole.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerRole.php @@ -31,7 +31,7 @@ public function load(): Role | NULL { /** * Delete a consumer role. */ - public function delete() { + public function delete(): void { if ($role = $this->load()) { $role->delete(); } diff --git a/web/modules/custom/dpl_consumers/src/ConsumerUser.php b/web/modules/custom/dpl_consumers/src/ConsumerUser.php index 4966c5fb3..2a077eedd 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerUser.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerUser.php @@ -4,6 +4,7 @@ namespace Drupal\dpl_consumers; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\user\Entity\User; use Drupal\user\RoleInterface; use Drupal\user\UserInterface; @@ -18,6 +19,7 @@ class ConsumerUser { public function __construct( public string $userName, + protected EntityTypeManagerInterface $entityTypeManager, public string | NULL $password = NULL, ) {} @@ -35,7 +37,7 @@ public function create(RoleInterface $role): UserInterface { 'status' => 1, ]); - $user->addRole($role->id()); + $user->addRole((string) $role->id()); $user->save(); return $user; @@ -45,7 +47,7 @@ public function create(RoleInterface $role): UserInterface { * Load a user. */ public function load(): UserInterface | NULL { - $users = \Drupal::entityTypeManager() + $users = $this->entityTypeManager ->getStorage('user') ->loadByProperties(['name' => $this->userName]); @@ -65,7 +67,7 @@ public function load(): UserInterface | NULL { /** * Delete a user. */ - public function delete() { + public function delete(): void { if ($user = $this->load()) { $user->delete(); } diff --git a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php index 1fb7b83cf..448da6a79 100644 --- a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php +++ b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php @@ -57,7 +57,12 @@ public function setComponents(Consumer $consumer, ConsumerUser $user, ?ConsumerR * Create consumer and user connected to the consumer. */ public function create(): void { - $role = $this->role->load(); + if (!$this->role) { + throw new \RuntimeException('Role is required to create a consumer.'); + } + if (!$role = $this->role->load()) { + throw new \RuntimeException('Role could not be loaded.'); + } $user = $this->user->create($role); $consumer = $this->consumer->create($user, $role); $this->logger->info('Created consumer: @consumer, user: @user, role: @role', [ From afe1f1891050071ca8dcacd9d803a68433e25f6c Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Sun, 5 Jan 2025 12:27:57 +0100 Subject: [PATCH 09/12] Refactor consumer drush cmds Adjust cmds to fit new way of handling consumers and be more specific about what each command actually is doing. --- .../dpl_consumers/dpl_consumers.deploy.php | 2 +- .../custom/dpl_consumers/dpl_consumers.module | 10 +-- .../src/Commands/DplConsumersCommands.php | 64 ++++++++----------- 3 files changed, 31 insertions(+), 45 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index 9942c3510..d88244628 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -44,7 +44,7 @@ function dpl_consumers_deploy_10002(): void { // Create new consumers (BNF and Go) and their users and roles. /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $consumer_handler */ $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); - foreach (dpl_consumers_known_consumers_users_and_roles() as $consumer) { + foreach (dpl_consumers_known_consumers_settings() as $consumer) { $consumer_handler->setComponents($consumer['consumer'], $consumer['user'], $consumer['role'])->create(); } } diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.module b/web/modules/custom/dpl_consumers/dpl_consumers.module index 1483b0d2c..5456178a5 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.module +++ b/web/modules/custom/dpl_consumers/dpl_consumers.module @@ -52,7 +52,7 @@ function dpl_consumers_get_consumer_uuid(string $client_id): string { * @return mixed[] * An array of consumers, users and roles. */ -function dpl_consumers_known_consumers_users_and_roles(): array { +function dpl_consumers_known_consumers_settings(): array { // Check if we have the necessary secrets for new consumers and their users. if (!$bnf_consumer_secret = getenv('BNF_GRAPHQL_CONSUMER_SECRET')) { throw new \Exception('BNF_GRAPHQL_CONSUMER_SECRET not found.'); @@ -89,10 +89,10 @@ function dpl_consumers_known_consumers_users_and_roles(): array { */ function dpl_consumers_get_known_consumers(): array { return array_reduce( - dpl_consumers_known_consumers_users_and_roles(), - static function (array $carry, array $consumer): array { - $consumer_client_id = $consumer['consumer']->client_id; - $carry[$consumer_client_id] = $consumer['consumer']; + dpl_consumers_known_consumers_settings(), + static function (array $carry, array $settings): array { + $consumer_client_id = $settings['consumer']->clientId; + $carry[$consumer_client_id] = $settings['consumer']->load(); return $carry; }, diff --git a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php index 1c5b17d05..8ef385da0 100644 --- a/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php +++ b/web/modules/custom/dpl_consumers/src/Commands/DplConsumersCommands.php @@ -30,64 +30,50 @@ public function __construct( } /** - * Function is used for setting the consumer secret. + * Used for setting the consumer secret and password. * - * The secret is stored as an environment variable. - * This command makes sure it is transferred to the database. + * The secret and password is stored as environment variables. + * This command makes sure they are transferred to the database. * - * @param string $client_id + * @param string $clientId * Client id of the consumer. * - * @command dpl_consumers:set-consumer-secret - * @aliases dpl-scs - * @usage dpl_consumers:set-consumer-secret [client_id of the consumer] + * @command dpl_consumers:set-consumer-env-credentials + * @aliases dpl-scec + * @usage dpl_consumers:set-consumer-env-credentials [client_id of the consumer] * * @throws \Exception */ - public function setConsumerSecret(string $client_id): string { - $consumers = $this->getConsumers($client_id); - try { + public function setConsumerEnvCredentials(string $clientId): string { + $consumers = $this->getConsumers($clientId); - $consumer = $consumers[$client_id]; - if (!$consumer) { - throw new \Exception('Could not find consumer.'); - } - if (!$consumer->secret) { - throw new \Exception('Consumer secret not found.'); - } - if (!$consumer_entity = $consumer->load()) { - throw new \Exception('Could not load consumer entity.'); - } - $consumer_entity->save(); - return 'Consumer secret set successfully.'; - } - catch (\Exception $e) { - throw new \Exception($e->getMessage()); - } + $consumer = $consumers[$clientId]; + $consumer->save(); + return 'Consumer secret set successfully.'; } /** - * Function is used for printing out the consumer credentials to the console. + * Used for printing out the consumer UUID to the console. * - * @param string $client_id + * @param string $clientId * Client id of the consumer. * - * @command dpl_consumers:consumer-credentials - * @aliases dpl-gcc - * @usage dpl_consumers:consumer-credentials [client_id of the consumer] + * @command dpl_consumers:get-consumer-uuid + * @aliases dpl-gcu + * @usage dpl_consumers:get-consumer-uuid [client_id of the consumer] * * @throws \Exception */ - public function getConsumerCredentials(string $client_id): void { - $consumers = $this->getConsumers($client_id); - $consumer = $consumers[$client_id]; - $this->output()->writeln(sprintf('Consumer UUID: %s', $consumer->uuid)); + public function getConsumerUuid(string $clientId): void { + $consumers = $this->getConsumers($clientId); + $consumer = $consumers[$clientId]; + $this->output()->writeln(sprintf('Consumer UUID: %s', $consumer->uuid->value)); } /** * Get consumers. * - * @param string $client_id + * @param string $clientId * Client id of the consumer. * * @return mixed[] @@ -95,10 +81,10 @@ public function getConsumerCredentials(string $client_id): void { * * @throws \Exception */ - protected function getConsumers(string $client_id): array { + protected function getConsumers(string $clientId): array { $consumers = dpl_consumers_get_known_consumers(); - if (!in_array($client_id, array_keys($consumers), TRUE)) { - throw new \Exception(sprintf('GraphQL consumer %s is not known.', $client_id)); + if (!in_array($clientId, array_keys($consumers), TRUE)) { + throw new \Exception(sprintf('GraphQL consumer %s is not known.', $clientId)); } return $consumers; From 6a9fd3d5a2ec7f7392417ec54e7aba0dae1c2d3c Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 7 Jan 2025 09:37:39 +0100 Subject: [PATCH 10/12] Make sure that lagoon deployment does not create graphql user Since our deploy hook takes care of that now --- .lagoon.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.lagoon.yml b/.lagoon.yml index 783d295f9..8b9e0fe81 100644 --- a/.lagoon.yml +++ b/.lagoon.yml @@ -109,10 +109,6 @@ tasks: drush user:create patron --password="$PR_DRUPAL_PWD" drush user:role:add 'patron' patron - - drush user:create $GRAPHQL_USER_NAME --password="$GRAPHQL_USER_PASSWORD" - drush user:role:add 'external_system' $GRAPHQL_USER_NAME - drush user:role:add 'graphql_consumer' $GRAPHQL_USER_NAME else echo "Test users already exist. Skipping creation..." fi From 5e446f8b836eacdf7cf65e324007a457783e2110 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 7 Jan 2025 09:47:01 +0100 Subject: [PATCH 11/12] Move consumer handler components to individual methods My reviewer did not like setting the components as properties of the handler. --- .../dpl_consumers/dpl_consumers.deploy.php | 2 +- .../dpl_consumers/dpl_consumers.install | 2 +- .../custom/dpl_consumers/src/Consumer.php | 17 +++-- .../custom/dpl_consumers/src/ConsumerRole.php | 2 +- .../custom/dpl_consumers/src/ConsumerUser.php | 5 +- .../src/Services/ConsumerHandler.php | 70 ++++++------------- 6 files changed, 40 insertions(+), 58 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index d88244628..375d2a7f5 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -45,6 +45,6 @@ function dpl_consumers_deploy_10002(): void { /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $consumer_handler */ $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); foreach (dpl_consumers_known_consumers_settings() as $consumer) { - $consumer_handler->setComponents($consumer['consumer'], $consumer['user'], $consumer['role'])->create(); + $consumer_handler->create($consumer['consumer'], $consumer['user'], $consumer['role']); } } diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.install b/web/modules/custom/dpl_consumers/dpl_consumers.install index 5956d5b79..fc6d5d18a 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.install +++ b/web/modules/custom/dpl_consumers/dpl_consumers.install @@ -31,6 +31,6 @@ function dpl_consumers_uninstall(): void { ]; foreach ($consumers as $consumer) { - $consumer_handler->setComponents($consumer['consumer'], $consumer['user'])->delete(); + $consumer_handler->delete($consumer['consumer'], $consumer['user']); } } diff --git a/web/modules/custom/dpl_consumers/src/Consumer.php b/web/modules/custom/dpl_consumers/src/Consumer.php index e97bd8ed6..e992b0ac4 100644 --- a/web/modules/custom/dpl_consumers/src/Consumer.php +++ b/web/modules/custom/dpl_consumers/src/Consumer.php @@ -6,8 +6,6 @@ use Drupal\consumers\Entity\ConsumerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\user\Entity\Role; -use Drupal\user\UserInterface; /** * DPL consumer. @@ -26,7 +24,16 @@ public function __construct( /** * Create a consumer. */ - public function create(UserInterface $user, Role $role): ConsumerInterface { + + /** + * Create a consumer. + * + * @param ConsumerUser $user + * The user to connect the consumer to. + * @param ConsumerRole $role + * The role to connect the consumer to. + */ + public function create(ConsumerUser $user, ConsumerRole $role): ConsumerInterface { if (!$this->label || !$this->clientId || !$this->secret) { throw new \RuntimeException('Label, client ID and secret are required to create a consumer.'); } @@ -35,8 +42,8 @@ public function create(UserInterface $user, Role $role): ConsumerInterface { 'client_id' => $this->clientId, 'secret' => $this->secret, 'third_party' => FALSE, - 'user_id' => $user->id(), - 'roles' => [$role->id()], + 'user_id' => $user->load()->id(), + 'roles' => [$role->load()->id()], ]); $consumer->save(); diff --git a/web/modules/custom/dpl_consumers/src/ConsumerRole.php b/web/modules/custom/dpl_consumers/src/ConsumerRole.php index 15545b248..83002df6a 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerRole.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerRole.php @@ -20,7 +20,7 @@ public function __construct( /** * Load a consumer role. */ - public function load(): Role | NULL { + public function load(): Role { if (!$role = Role::load($this->id)) { throw new \RuntimeException(sprintf('Failed to load role: %s', $this->id)); } diff --git a/web/modules/custom/dpl_consumers/src/ConsumerUser.php b/web/modules/custom/dpl_consumers/src/ConsumerUser.php index 2a077eedd..b84511871 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerUser.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerUser.php @@ -6,7 +6,6 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\user\Entity\User; -use Drupal\user\RoleInterface; use Drupal\user\UserInterface; /** @@ -26,7 +25,7 @@ public function __construct( /** * Create a user. */ - public function create(RoleInterface $role): UserInterface { + public function create(ConsumerRole $role): UserInterface { if (!$this->password) { throw new \RuntimeException('Password is required to create a user.'); } @@ -37,7 +36,7 @@ public function create(RoleInterface $role): UserInterface { 'status' => 1, ]); - $user->addRole((string) $role->id()); + $user->addRole((string) $role->load()->id()); $user->save(); return $user; diff --git a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php index 448da6a79..5b1706862 100644 --- a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php +++ b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php @@ -16,25 +16,6 @@ */ class ConsumerHandler { - /** - * Consumer used for guarding requests. - * - * @param \Drupal\dpl_consumers\Consumer $consumer - */ - protected Consumer $consumer; - /** - * User tied to the consumer. - * - * @param \Drupal\dpl_consumers\ConsumerUser $user - */ - protected ConsumerUser $user; - /** - * Role tied to the consumer user. - * - * @param \Drupal\dpl_consumers\ConsumerRole $role - */ - protected ConsumerRole | NULL $role; - /** * Constructor. */ @@ -42,45 +23,40 @@ public function __construct( protected LoggerInterface $logger, ) {} - /** - * Set needed components for the handler. - */ - public function setComponents(Consumer $consumer, ConsumerUser $user, ?ConsumerRole $role = NULL): self { - $this->consumer = $consumer; - $this->user = $user; - $this->role = $role; - - return $this; - } - /** * Create consumer and user connected to the consumer. + * + * @param \Drupal\dpl_consumers\Consumer $consumer + * The consumer to create. + * @param \Drupal\dpl_consumers\ConsumerUser $user + * The user to connect the consumer to. + * @param \Drupal\dpl_consumers\ConsumerRole $role + * The role to connect the consumer to. */ - public function create(): void { - if (!$this->role) { - throw new \RuntimeException('Role is required to create a consumer.'); - } - if (!$role = $this->role->load()) { - throw new \RuntimeException('Role could not be loaded.'); - } - $user = $this->user->create($role); - $consumer = $this->consumer->create($user, $role); + public function create(Consumer $consumer, ConsumerUser $user, ConsumerRole $role): void { + $createdUser = $user->create($role); + $createdConsumer = $consumer->create($user, $role); $this->logger->info('Created consumer: @consumer, user: @user, role: @role', [ - '@consumer' => $consumer->label(), - '@user' => $user->getAccountName(), - '@role' => $role->label(), + '@consumer' => $createdConsumer->label(), + '@user' => $createdUser->getAccountName(), + '@role' => $role->load()->label(), ]); } /** * Delete consumer and user connected to the consumer. + * + * @param \Drupal\dpl_consumers\Consumer $consumer + * The consumer to delete. + * @param \Drupal\dpl_consumers\ConsumerUser $user + * The user to delete. */ - public function delete(): void { - $this->user->delete(); - $this->consumer->delete(); + public function delete(Consumer $consumer, ConsumerUser $user): void { + $user->delete(); + $consumer->delete(); $this->logger->info('Deleted consumer: @consumer and user: @user', [ - '@consumer' => $this->consumer->clientId, - '@user' => $this->user->userName, + '@consumer' => $consumer->clientId, + '@user' => $user->userName, ]); } From 2548ce1b8c7826c2f1f7cafe08b7f18a5d5a8f85 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 7 Jan 2025 12:24:28 +0100 Subject: [PATCH 12/12] Adding get* methods on consumer handler In order to inject dependencies (right now entityTypeManager) into the consumer components (Consumer, ConsumerUser). --- .../dpl_consumers/dpl_consumers.deploy.php | 14 +++++------- .../dpl_consumers/dpl_consumers.services.yml | 12 +++++----- .../custom/dpl_consumers/src/Consumer.php | 18 ++++++++++----- .../custom/dpl_consumers/src/ConsumerRole.php | 10 +++++++-- .../custom/dpl_consumers/src/ConsumerUser.php | 17 +++++++++----- .../src/Services/ConsumerHandler.php | 22 +++++++++++++++++++ 6 files changed, 65 insertions(+), 28 deletions(-) diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php index 375d2a7f5..26ef46878 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php +++ b/web/modules/custom/dpl_consumers/dpl_consumers.deploy.php @@ -7,9 +7,6 @@ declare(strict_types=1); -use Drupal\dpl_consumers\Consumer; -use Drupal\dpl_consumers\ConsumerUser; - /** * Run consumer creation on deploy. * @@ -34,16 +31,17 @@ function dpl_consumers_deploy_10001(): void { * So we delete previous entities and create new ones. */ function dpl_consumers_deploy_10002(): void { + /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $consumer_handler */ + $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); + // Delete consume and users that we want to handle differently. // We want to create consumers and consumer users // specifically for the two known consumers (BNF and Go) and connected users. - (new Consumer("graphql_consumer", \Drupal::entityTypeManager()))->delete(); - (new ConsumerUser('GraphQL Consumer', \Drupal::entityTypeManager()))->delete(); - (new ConsumerUser('graphql_consumer', \Drupal::entityTypeManager()))->delete(); + $consumer_handler->getConsumer('graphql_consumer')->delete(); + $consumer_handler->getConsumerUser('GraphQL Consumer')->delete(); + $consumer_handler->getConsumerUser('graphql_consumer')->delete(); // Create new consumers (BNF and Go) and their users and roles. - /** @var \Drupal\dpl_consumers\Services\ConsumerHandler $consumer_handler */ - $consumer_handler = \Drupal::service('dpl_consumers.consumer_handler'); foreach (dpl_consumers_known_consumers_settings() as $consumer) { $consumer_handler->create($consumer['consumer'], $consumer['user'], $consumer['role']); } diff --git a/web/modules/custom/dpl_consumers/dpl_consumers.services.yml b/web/modules/custom/dpl_consumers/dpl_consumers.services.yml index a2d8a7f46..b52f33ea8 100644 --- a/web/modules/custom/dpl_consumers/dpl_consumers.services.yml +++ b/web/modules/custom/dpl_consumers/dpl_consumers.services.yml @@ -1,12 +1,10 @@ --- services: - dpl_consumers.consumer_handler: - class: Drupal\dpl_consumers\Services\ConsumerHandler - autowire: true - arguments: - $logger: '@logger.channel.dpl_consumers' - - logger.channel.dpl_consumers: + dpl_consumers.logger: parent: logger.channel_base arguments: - 'dpl_consumers' + dpl_consumers.consumer_handler: + class: Drupal\dpl_consumers\Services\ConsumerHandler + autowire: true + arguments: ['@dpl_breadcrumb.logger', '@entity_type.manager'] diff --git a/web/modules/custom/dpl_consumers/src/Consumer.php b/web/modules/custom/dpl_consumers/src/Consumer.php index e992b0ac4..a45ef286d 100644 --- a/web/modules/custom/dpl_consumers/src/Consumer.php +++ b/web/modules/custom/dpl_consumers/src/Consumer.php @@ -57,19 +57,21 @@ public function create(ConsumerUser $user, ConsumerRole $role): ConsumerInterfac /** * Load a consumer. + * + * @throws \RuntimeException */ - public function load(): ConsumerInterface | NULL { + public function load(): ConsumerInterface { $consumers = $this->entityTypeManager->getStorage('consumer') ->loadByProperties(['client_id' => $this->clientId]); if (empty($consumers)) { - return NULL; + throw new \RuntimeException('Failed to load consumer.'); } $consumer = reset($consumers); if (!($consumer instanceof ConsumerInterface)) { - return NULL; + throw new \RuntimeException('Failed to load consumer.'); } return $consumer; @@ -79,9 +81,15 @@ public function load(): ConsumerInterface | NULL { * Delete a consumer based on a client ID. */ public function delete(): void { - if ($consumer = $this->load()) { - $consumer->delete(); + try { + $consumer = $this->load(); + } + catch (\Exception $e) { + // Does not matter if loading fails. + // We just do not try to delete the consumer then. + return; } + $consumer->delete(); } } diff --git a/web/modules/custom/dpl_consumers/src/ConsumerRole.php b/web/modules/custom/dpl_consumers/src/ConsumerRole.php index 83002df6a..c790bd79b 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerRole.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerRole.php @@ -32,9 +32,15 @@ public function load(): Role { * Delete a consumer role. */ public function delete(): void { - if ($role = $this->load()) { - $role->delete(); + try { + $role = $this->load(); } + catch (\Exception $e) { + // Does not matter if loading fails. + // We just do not try to delete the role then. + return; + } + $role->delete(); } } diff --git a/web/modules/custom/dpl_consumers/src/ConsumerUser.php b/web/modules/custom/dpl_consumers/src/ConsumerUser.php index b84511871..230f132ea 100644 --- a/web/modules/custom/dpl_consumers/src/ConsumerUser.php +++ b/web/modules/custom/dpl_consumers/src/ConsumerUser.php @@ -45,19 +45,18 @@ public function create(ConsumerRole $role): UserInterface { /** * Load a user. */ - public function load(): UserInterface | NULL { + public function load(): UserInterface { $users = $this->entityTypeManager ->getStorage('user') ->loadByProperties(['name' => $this->userName]); if (empty($users)) { - return NULL; + throw new \RuntimeException('Failed to load user.'); } - $user = reset($users); if (!($user instanceof UserInterface)) { - return NULL; + throw new \RuntimeException('Failed to load user.'); } return $user; @@ -67,9 +66,15 @@ public function load(): UserInterface | NULL { * Delete a user. */ public function delete(): void { - if ($user = $this->load()) { - $user->delete(); + try { + $user = $this->load(); + } + catch (\Exception $e) { + // Does not matter if loading fails. + // We just do not try to delete the user then. + return; } + $user->delete(); } } diff --git a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php index 5b1706862..3235be40f 100644 --- a/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php +++ b/web/modules/custom/dpl_consumers/src/Services/ConsumerHandler.php @@ -4,6 +4,7 @@ namespace Drupal\dpl_consumers\Services; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\dpl_consumers\Consumer; use Drupal\dpl_consumers\ConsumerRole; use Drupal\dpl_consumers\ConsumerUser; @@ -21,6 +22,7 @@ class ConsumerHandler { */ public function __construct( protected LoggerInterface $logger, + protected EntityTypeManagerInterface $entityTypeManager, ) {} /** @@ -60,4 +62,24 @@ public function delete(Consumer $consumer, ConsumerUser $user): void { ]); } + /** + * Get consumer. + * + * @param string $clientId + * The client ID of the consumer. + */ + public function getConsumer(string $clientId): Consumer { + return new Consumer($clientId, $this->entityTypeManager); + } + + /** + * Get consumer user. + * + * @param string $userName + * The user name of the consumer user. + */ + public function getConsumerUser(string $userName): ConsumerUser { + return new ConsumerUser($userName, $this->entityTypeManager); + } + }