From 7e45ec452742e73f081ac587dce30dd2db2f6386 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 14 Aug 2024 16:25:51 -0400 Subject: [PATCH 01/30] feat(YSP-593): add a working block creation --- .../modules/custom/ys_servicenow/README.md | 0 ...ervicenow_knowledge_base_article_block.yml | 50 +++++ .../servicenow_knowledge_base_articles.yml | 52 +++++ ...rvicenow_knowledge_base_layout_builder.yml | 43 ++++ .../src/Controller/RunMigrations.php | 83 ++++++++ .../src/Form/ServiceNowSettings.php | 163 +++++++++++++++ .../ys_servicenow/src/MetaFieldsManager.php | 0 .../migrate/process/LayoutBuilderSections.php | 89 ++++++++ .../ys_servicenow/src/ServiceNowManager.php | 195 ++++++++++++++++++ .../ys_servicenow/ys_servicenow.info.yml | 9 + .../ys_servicenow.links.menu.yml | 6 + .../custom/ys_servicenow/ys_servicenow.module | 7 + .../ys_servicenow.permissions.yml | 4 + .../ys_servicenow/ys_servicenow.routing.yml | 14 ++ .../ys_servicenow/ys_servicenow.services.yml | 5 + 15 files changed, 720 insertions(+) create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Controller/RunMigrations.php create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/MetaFieldsManager.php create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.permissions.yml create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.routing.yml create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.services.yml diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml new file mode 100644 index 0000000000..b34b4c6fb9 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml @@ -0,0 +1,50 @@ +id: servicenow_knowledge_base_article_block +label: 'ServiceNow knowledge base article blocks' +source: + plugin: url + data_fetcher_plugin: http + data_parser_plugin: json + headers: + Accept: 'application/json; charset=utf-8' + Content-Type: application/json + authentication: + plugin: basic + username: USERNAME + password: PASSWORD + track_changes: true + urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 + item_selector: result + fields: + - name: servicenow_number + label: 'ServiceNow number' + selector: number + - name: servicenow_title + label: 'ServiceNow title' + selector: short_description + - name: servicenow_text + label: 'ServiceNow text' + selector: text + ids: + servicenow_number: + type: string +process: + field_text/value: servicenow_text + field_text/format: + plugin: default_value + default_value: basic_html + info: servicenow_title + reusable: + plugin: default_value + default_value: 0 +destination: + plugin: 'entity:block_content' + default_bundle: text + overwrite_properties: + - field_text + - info +dependencies: + enforced: + module: + - migrate_plus + - migrate_tools + - layout_builder diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml new file mode 100644 index 0000000000..acd34a1a65 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml @@ -0,0 +1,52 @@ +id: servicenow_knowledge_base_articles +label: 'ServiceNow knowledge base articles' +source: + plugin: url + data_fetcher_plugin: http + data_parser_plugin: json + headers: + Accept: 'application/json; charset=utf-8' + Content-Type: application/json + authentication: + plugin: basic + username: USERNAME + password: PASSWORD + track_changes: true + urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 + item_selector: result + fields: + - name: servicenow_number + label: 'ServiceNow number' + selector: number + - name: servicenow_title + label: 'ServiceNow title' + selector: short_description + - name: servicenow_text + label: 'ServiceNow text' + selector: text + ids: + servicenow_number: + type: string +process: + title: servicenow_title + block_id: + plugin: migration_lookup + migration: servicenow_knowledge_base_article_block + source: servicenow_number + layout_builder__layout: + source: servicenow_title + plugin: layout_builder_sections +destination: + plugin: 'entity:node' + default_bundle: page + overwrite_properties: + - title +migration_dependencies: + required: + - servicenow_knowledge_base_article_block +dependencies: + enforced: + module: + - migrate_plus + - migrate_tools + - layout_builder diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml new file mode 100644 index 0000000000..d93214e601 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml @@ -0,0 +1,43 @@ +id: servicenow_knowledge_base_layout_builder +label: 'ServiceNow knowledge base articles' +source: + plugin: url + data_fetcher_plugin: http + data_parser_plugin: json + headers: + Accept: 'application/json; charset=utf-8' + Content-Type: application/json + authentication: + plugin: basic + username: USERNAME + password: PASSWORD + track_changes: true + urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 + item_selector: result + fields: + - name: servicenow_number + label: 'ServiceNow number' + selector: number + ids: + servicenow_number: + type: string +process: + id: servicenow_number + field_text: servicenow_content + block: + plugin: migration_lookup + migration: servicenow_knowledge_base_article_block + source: servicenow_number + node: + plugin: migration_lookup + migration: servicenow_knowledge_base_articles + source: servicenow_number +destination: + plugin: append_block_to_node + source: servicenow_number +dependencies: + enforced: + module: + - migrate_plus + - migrate_tools + - layout_builder diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Controller/RunMigrations.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Controller/RunMigrations.php new file mode 100644 index 0000000000..33bf45b569 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Controller/RunMigrations.php @@ -0,0 +1,83 @@ +servicenowConfig = $config_factory->get('ys_servicenow.settings'); + $this->servicenowManager = $servicenow_manager; + $this->messenger = $messenger; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('config.factory'), + $container->get('ys_servicenow.manager'), + $container->get('messenger'), + ); + + } + + /** + * Runs all ServiceNow migrations. + */ + public function runAllMigrations() { + if ($this->servicenowConfig->get('enable_servicenow_sync')) { + $this->messenger->addMessage('Running ServiceNow migrations...'); + $this->servicenowManager->runAllMigrations(); + $this->messenger->addMessage('ServiceNow migrations complete.'); + } + else { + $this->messenger->addMessage('ServiceNow sync is disabled. No sync was performed.'); + } + + $redirectUrl = Url::fromRoute('ys_servicenow.settings')->toString(); + $response = new RedirectResponse($redirectUrl); + return $response; + } + +} diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php new file mode 100644 index 0000000000..c286acda11 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php @@ -0,0 +1,163 @@ +entityTypeManager = $entity_type_manager; + $this->servicenowManager = $servicenow_manager; + $this->currentUserSession = $current_user_session; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('config.factory'), + $container->get('entity_type.manager'), + $container->get('ys_servicenow.manager'), + $container->get('current_user'), + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'ys_servicenow_settings'; + } + + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['ys_servicenow.settings']; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $config = $this->config('ys_servicenow.settings'); + + $allowSecretItems = function_exists('ys_core_allow_secret_items') ? ys_core_allow_secret_items($this->currentUserSession) : FALSE; + + if ( + $config->get('enable_servicenow_sync') && + $config->get('servicenow_endpoint') + ) { + $form['sync_now_button'] = [ + '#type' => 'markup', + '#markup' => 'Sync now', + ]; + } + + $form['enable_servicenow_sync'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enable ServiceNow sync'), + '#description' => $this->t('Once enabled, ServiceNow data will sync knowledge base articles roughly every hour.'), + '#default_value' => $config->get('enable_servicenow_sync') ?: FALSE, + '#disabled' => !$allowSecretItems, + ]; + + $form['servicenow_endpoint'] = [ + '#type' => 'url', + '#title' => $this->t('ServiceNow endpoint base URL'), + '#description' => $this->t('Ex: https://apiendpoint'), + '#default_value' => $config->get('servicenow_endpoint') ?: '', + '#disabled' => !$allowSecretItems, + ]; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + $enabled = $form_state->getValue('enable_servicenow_sync'); + if ($enabled) { + $requiredFields = [ + 'servicenow_endpoint', + ]; + + foreach ($requiredFields as $field) { + if (!$form_state->getValue($field)) { + $form_state->setErrorByName( + $field, + $this->t("%required_field is required.", ['%required_field' => $form_state->getCompleteForm()[$field]['#title']->__toString()]) + ); + } + } + + } + + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + + $this->configFactory->getEditable('ys_servicenow.settings') + // Set the submitted configuration setting. + ->set('enable_servicenow_sync', $form_state->getValue('enable_servicenow_sync')) + ->set('servicenow_endpoint', rtrim($form_state->getValue('servicenow_endpoint'), "/")) + ->save(); + + parent::submitForm($form, $form_state); + } + +} diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/MetaFieldsManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/MetaFieldsManager.php new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php new file mode 100644 index 0000000000..f82a519a11 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php @@ -0,0 +1,89 @@ +addMessage("Value: " . $value, 'status', TRUE); + + if ($value == NULL) { + \Drupal::messenger()->addError("value is NULL", 'status', TRUE); + return NULL; + } + + // Setup some variables we'll need: + // - components holds all the components to be written into our section + // - generator connects to the uuid generator service. + $components = []; + $generator = \Drupal::service('uuid'); + $entityTypeManager = \Drupal::entityTypeManager(); + $entityQuery = $entityTypeManager->getStorage('block_content')->getQuery(); + $entityQuery->condition('info', $value) + ->accessCheck(FALSE); + $ids = $entityQuery->execute(); + + $block_content = NULL; + if (!empty($ids)) { + $block_content = $entityTypeManager->getStorage('block_content')->load(reset($ids)); + } + + if (is_null($block_content)) { + \Drupal::messenger()->addError("Could not load " . $value . ' ???', 'status', TRUE); + return NULL; + } + + \Drupal::messenger()->addMessage("Got a block content"); + + $config = [ + 'id' => 'inline_block:text', + 'label' => $block_content->label(), + 'provider' => 'layout_builder', + 'label_display' => FALSE, + 'view_mode' => 'full', + 'block_revision_id' => $block_content->getRevisionId(), + 'block_serialized' => serialize($block_content), + 'context_mapping' => [], + ]; + + $components[] = new SectionComponent($generator->generate(), 'content', $config); + + \Drupal::messenger()->addMessage("Made a section component"); + + // If you were doing multiple sections, you'd want this to be an array + // somehow. @TODO figure out how to do that ;) + // PARAMS: $layout_id, $layout_settings, $components. + $sections = new Section('layout_onecol', [], $components); + + \Drupal::messenger()->addMessage("Made a section"); + + return $sections; + } + + /** + * {@inheritdoc} + */ + public function multiple() { + // Perhaps if multiple() returned TRUE this would help allow + // multiple Sections. ;) + return FALSE; + } + +} diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php new file mode 100644 index 0000000000..dba002520c --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -0,0 +1,195 @@ +servicenowConfig = $config_factory->get('ys_servicenow.settings'); + $this->httpClient = $http_client; + $this->entityTypeManager = $entity_type_manager; + $this->migrationManager = $migration_manager; + $this->moduleHandler = $module_handler; + $this->time = $time; + $this->messenger = $messenger; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('config.factory'), + $container->get('http_client'), + $container->get('entity_type.manager'), + $container->get('plugin.manager.migration'), + $container->get('module_handler'), + $container->get('date.formatter'), + $container->get('messenger'), + ); + + } + + /** + * Runs specific migration. + * + * @param string $migration + * The migration ID. + */ + public function runMigration($migration) { + // Loop over the list of the migrations and check if they require + // execution. + // Prevent non-existent migrations from breaking cron. + $migrationInstance = $this->migrationManager->createInstance($migration); + if ($migrationInstance) { + // Check if the migration status is IDLE, if not, make it so. + $status = $migrationInstance->getStatus(); + if ($status !== MigrationInterface::STATUS_IDLE) { + $migrationInstance->setStatus(MigrationInterface::STATUS_IDLE); + } + + /* + * @todo Possibly implement the following flags, if needed. + * Runs migration with the --update flag. + * $migration_update = $migration->getIdMap(); + * $migration_update->prepareUpdate(); + * Runs migration with the --sync flag. + * The problem here is if editor adds layout builder, this will wipe those + * changes out before recreating. So, this not be a good idea. + * $migrationInstance->set('syncSource', TRUE); + */ + + $message = new MigrateMessage(); + $executable = new MigrateExecutable($migrationInstance, $message); + $executable->import(); + + /* If using migrate_plus module, update the migrate_last_imported value + * for the migration. + */ + + if ($this->moduleHandler->moduleExists('migrate_plus')) { + $migrate_last_imported_store = $this->keyValue('migrate_last_imported'); + $migrate_last_imported_store->set($migrationInstance->id(), round($this->time->getCurrentMicroTime() * 1000)); + } + } + } + + /** + * Gets the migration status such as number of items imported. + * + * @return int + * For now, just the number of items imported. + */ + public function getMigrationStatus($migration_id) { + $migration = $this->migrationManager->createInstance($migration_id); + $map = $migration->getIdMap(); + $imported = $map->importedCount(); + return $imported; + } + + /** + * Runs all Localist migrations. + * + * @return array + * Array of status of all migrations run. + */ + public function runAllMigrations() { + foreach (self::SERVICENOW_MIGRATIONS as $migration) { + $this->runMigration($migration); + $messageData[$migration] = [ + 'imported' => $this->getMigrationStatus($migration), + ]; + } + return $messageData; + } + +} diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml new file mode 100644 index 0000000000..7806a85b9b --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml @@ -0,0 +1,9 @@ +name: 'YS ServiceNow' +type: module +description: 'Provides integration with the ServiceNow knowledge base platform' +package: YaleSites +core_version_requirement: ^10 +dependencies: + - drupal:migrate + - migrate_plus:migrate_plus + - migrate_tools:migrate_tools diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml new file mode 100644 index 0000000000..29996dbfff --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml @@ -0,0 +1,6 @@ +ys_servicenow.settings: + title: 'ServiceNow settings' + description: 'Configure ServiceNow sync settings' + route_name: ys_servicenow.settings + parent: ys_core.admin_yalesites + weight: 0 diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module new file mode 100644 index 0000000000..f4587d9d82 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module @@ -0,0 +1,7 @@ + Date: Thu, 15 Aug 2024 12:29:23 -0400 Subject: [PATCH 02/30] feat(YSP-593): create keys-based basic auth plugin --- .../migrate_plus/authentication/BasicKeys.php | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php new file mode 100644 index 0000000000..4072741fa5 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php @@ -0,0 +1,79 @@ +getKey('ServiceNow'); + + $key_object = $this->getKeyValues($key); + + $username = $key_object->username; + $password = $key_object->password; + + // Get the key from keys module called "ServiceNow". + return [ + 'auth' => [ + $username, + $password, + ], + ]; + } + + /** + * Given a key ID, return the key object. + * + * @param string $key_id + * The key ID. + * + * @return \Drupal\key\KeyInterface + * The key object + */ + protected function getKey($key_id) { + $key = \Drupal::service('key.repository')->getKey($key_id); + + if (!$key) { + throw new \Exception("Key '$key_id' not found"); + } + + return $key; + } + + /** + * Given a key, return the key values. + * + * @param \Drupal\key\KeyInterface $key + * The key object. + * + * @return object + * The key values. + */ + protected function getKeyValues($key) { + $json_key = $key->getKeyValue(); + + if (!$json_key) { + throw new \Exception("Key 'ServiceNow' has no value"); + } + + return json_decode($json_key); + } + +} From 7b266bba5d49410218f3aa3424dce2967bd846b5 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 15 Aug 2024 13:34:41 -0400 Subject: [PATCH 03/30] feat(YSP-593): successfully use keys to provide auth --- ...ervicenow_knowledge_base_article_block.yml | 4 +--- .../servicenow_knowledge_base_articles.yml | 4 +--- ...rvicenow_knowledge_base_layout_builder.yml | 4 +--- .../migrate_plus/authentication/BasicKeys.php | 21 +++++++------------ 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml index b34b4c6fb9..de136f3483 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml @@ -8,9 +8,7 @@ source: Accept: 'application/json; charset=utf-8' Content-Type: application/json authentication: - plugin: basic - username: USERNAME - password: PASSWORD + plugin: basic_keys track_changes: true urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 item_selector: result diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml index acd34a1a65..4eb1b0a885 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml @@ -8,9 +8,7 @@ source: Accept: 'application/json; charset=utf-8' Content-Type: application/json authentication: - plugin: basic - username: USERNAME - password: PASSWORD + plugin: basic_keys track_changes: true urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 item_selector: result diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml index d93214e601..4da52b9c96 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml @@ -8,9 +8,7 @@ source: Accept: 'application/json; charset=utf-8' Content-Type: application/json authentication: - plugin: basic - username: USERNAME - password: PASSWORD + plugin: basic_keys track_changes: true urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 item_selector: result diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php index 4072741fa5..93c68f3a3d 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php @@ -1,39 +1,34 @@ getKey('ServiceNow'); + $key = $this->getKey('servicenow'); $key_object = $this->getKeyValues($key); - $username = $key_object->username; - $password = $key_object->password; - - // Get the key from keys module called "ServiceNow". return [ 'auth' => [ - $username, - $password, + $key_object->username, + $key_object->password, ], ]; } From 9eda713648af7540ecd8105cdf192747173407f8 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 15 Aug 2024 13:43:24 -0400 Subject: [PATCH 04/30] feat(YSP-593): make key selectable --- .../ys_servicenow/src/Form/ServiceNowSettings.php | 7 +++++++ .../Plugin/migrate_plus/authentication/BasicKeys.php | 11 +++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php index c286acda11..e9a98bdc08 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php @@ -120,6 +120,12 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#disabled' => !$allowSecretItems, ]; + $form['servicenow_auth_key'] = [ + '#type' => 'key_select', + '#title' => $this->t('ServiceNow Authentication Credentials'), + '#default_value' => $config->get('servicenow_auth_key') ?: '', + ]; + return parent::buildForm($form, $form_state); } @@ -155,6 +161,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Set the submitted configuration setting. ->set('enable_servicenow_sync', $form_state->getValue('enable_servicenow_sync')) ->set('servicenow_endpoint', rtrim($form_state->getValue('servicenow_endpoint'), "/")) + ->set('servicenow_auth_key', $form_state->getValue('servicenow_auth_key')) ->save(); parent::submitForm($form, $form_state); diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php index 93c68f3a3d..cd151facb2 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php @@ -8,7 +8,7 @@ use Drupal\migrate_plus\AuthenticationPluginBase; /** - * Provides basic authentication for the HTTP resource. + * Provides basic authentication using keys module for the HTTP resource. * * @Authentication( * id = "basic_keys", @@ -21,7 +21,14 @@ class BasicKeys extends AuthenticationPluginBase implements ContainerFactoryPlug * {@inheritdoc} */ public function getAuthenticationOptions(): array { - $key = $this->getKey('servicenow'); + $servicenow_config = \Drupal::config('ys_servicenow.settings'); + $servicenow_key_id = $servicenow_config->get('servicenow_auth_key'); + + if (!$servicenow_key_id) { + throw new \Exception("ServiceNow key not set"); + } + + $key = $this->getKey($servicenow_key_id); $key_object = $this->getKeyValues($key); From be6e315e8a57d88e9b2796cc0cb7271f7ad4a74a Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 15 Aug 2024 13:44:51 -0400 Subject: [PATCH 05/30] feat(YSP-593): rely on key module --- .../modules/custom/ys_servicenow/ys_servicenow.info.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml index 7806a85b9b..7a3d69928d 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.info.yml @@ -7,3 +7,4 @@ dependencies: - drupal:migrate - migrate_plus:migrate_plus - migrate_tools:migrate_tools + - drupal:key From be8b29de306aa087cbfb41098e4a6b0095a0c389 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 15 Aug 2024 14:19:50 -0400 Subject: [PATCH 06/30] feat(YSP-593): create abstraction for reusable key auth In case we need to use this in the future, we now have a way to do this without specifying servicenow specifically. --- ...ervicenow_knowledge_base_article_block.yml | 2 +- .../servicenow_knowledge_base_articles.yml | 2 +- ...rvicenow_knowledge_base_layout_builder.yml | 2 +- .../BasicKeys.php => BasicAuthWithKeys.php} | 51 +++++++++++++------ .../authentication/ServiceNowAuth.php | 31 +++++++++++ 5 files changed, 70 insertions(+), 18 deletions(-) rename web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/{Plugin/migrate_plus/authentication/BasicKeys.php => BasicAuthWithKeys.php} (55%) create mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/ServiceNowAuth.php diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml index de136f3483..80814ebee0 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml @@ -8,7 +8,7 @@ source: Accept: 'application/json; charset=utf-8' Content-Type: application/json authentication: - plugin: basic_keys + plugin: servicenow_auth track_changes: true urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 item_selector: result diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml index 4eb1b0a885..addf1a2bf4 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml @@ -8,7 +8,7 @@ source: Accept: 'application/json; charset=utf-8' Content-Type: application/json authentication: - plugin: basic_keys + plugin: servicenow_auth track_changes: true urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 item_selector: result diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml index 4da52b9c96..0158119268 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml @@ -8,7 +8,7 @@ source: Accept: 'application/json; charset=utf-8' Content-Type: application/json authentication: - plugin: basic_keys + plugin: servicenow_auth track_changes: true urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 item_selector: result diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/BasicAuthWithKeys.php similarity index 55% rename from web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php rename to web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/BasicAuthWithKeys.php index cd151facb2..cc8f66410b 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/BasicKeys.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/BasicAuthWithKeys.php @@ -2,10 +2,7 @@ declare(strict_types=1); -namespace Drupal\ys_servicenow\Plugin\migrate_plus\authentication; - -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\migrate_plus\AuthenticationPluginBase; +namespace Drupal\ys_servicenow; /** * Provides basic authentication using keys module for the HTTP resource. @@ -15,23 +12,47 @@ * title = @Translation("Basic Keys") * ) */ -class BasicKeys extends AuthenticationPluginBase implements ContainerFactoryPluginInterface { +class BasicAuthWithKeys { /** - * {@inheritdoc} + * The key ID. + * + * @var string */ - public function getAuthenticationOptions(): array { - $servicenow_config = \Drupal::config('ys_servicenow.settings'); - $servicenow_key_id = $servicenow_config->get('servicenow_auth_key'); + protected $keyId; - if (!$servicenow_key_id) { - throw new \Exception("ServiceNow key not set"); - } + /** + * The configuration. + * + * @var \Drupal\Core\Config\Config + */ + protected $configuration; - $key = $this->getKey($servicenow_key_id); + /** + * Constructs a new BasicAuthWithKeys object. + * + * @param \Drupal\Core\Config\Config $configuration + * The configuration. + * @param string $key_id + * The key ID. + */ + public function __construct($configuration, $key_id) { + $this->keyId = $key_id; + $this->configuration = $configuration; + } + /** + * Get the authentication options. + * + * @return array + * The authentication options. + */ + public function getAuthenticationOptions() { + if (!$this->keyId) { + throw new \Exception("Key not set"); + } + $key = $this->getKey($this->keyId); $key_object = $this->getKeyValues($key); - return [ 'auth' => [ $key_object->username, @@ -72,7 +93,7 @@ protected function getKeyValues($key) { $json_key = $key->getKeyValue(); if (!$json_key) { - throw new \Exception("Key 'ServiceNow' has no value"); + throw new \Exception("Key has no value"); } return json_decode($json_key); diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/ServiceNowAuth.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/ServiceNowAuth.php new file mode 100644 index 0000000000..b4b4f1d530 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate_plus/authentication/ServiceNowAuth.php @@ -0,0 +1,31 @@ +get('servicenow_auth_key'); + $basicAuthWithKeys = new BasicAuthWithKeys($servicenow_config, $servicenow_key_id); + return $basicAuthWithKeys->getAuthenticationOptions(); + } + +} From 661e6f3e22584c87898221b0bf754d4a312b2065 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Mon, 19 Aug 2024 12:37:00 -0400 Subject: [PATCH 07/30] feat(YSP-593): set sync source so we recreate layout builder A byproduct of setting syncSource is that the layout builder items need to be recreated. This is a benefit to us I believe in that we don't need to figure out if it needs updating, we just add a new block with the new content. My only worry is that database data is not being deleted when this happens; I need to look more into this. --- .../src/Plugin/migrate/process/LayoutBuilderSections.php | 4 ++++ .../modules/custom/ys_servicenow/src/ServiceNowManager.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php index f82a519a11..e1cb2a34b3 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php @@ -11,6 +11,10 @@ /** * Process plugin to migrate a source field into a Layout Builder Section. * + * Inspiration/references: + * https://github.com/dsasser/d8-migrate-paragraphs-layout-builder/blob/master/web/modules/custom/d8_migrations/src/LayoutBase.php + * https://github.com/chrisfromredfin/dcon21-milb/blob/main/web/modules/custom/my_migrations/src/Plugin/migrate/process/LayoutBuilderSectionsPages.php. + * * @MigrateProcessPlugin( * id = "layout_builder_sections", * ) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php index dba002520c..a13c30740a 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -148,6 +148,9 @@ public function runMigration($migration) { * $migrationInstance->set('syncSource', TRUE); */ + $migrationInstance->set('syncSource', TRUE); + $migration_update = $migrationInstance->getIdMap(); + $migration_update->prepareUpdate(); $message = new MigrateMessage(); $executable = new MigrateExecutable($migrationInstance, $message); $executable->import(); From 4c01afb3e8a1ba4be850d350e6f34cdd4b741851 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:09:24 -0400 Subject: [PATCH 08/30] feat(YSP-593): give platform admins access to servicenow --- .../yalesites_profile/config/sync/user.role.platform_admin.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml b/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml index bc661139ee..ae57a86a06 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml @@ -79,6 +79,7 @@ dependencies: - ys_alert - ys_core - ys_localist + - ys_servicenow id: platform_admin label: 'Platform administrator' weight: -5 @@ -411,4 +412,5 @@ permissions: - 'view unpublished paragraphs' - 'yalesites manage alerts' - 'yalesites manage localist' + - 'yalesites manage servicenow' - 'yalesites manage settings' From 5022beef9f70d6fb828cad67f95549817110ea0e Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:09:49 -0400 Subject: [PATCH 09/30] fix(YSP-593): remove endpoint Remove the endpoint since it's hardcoded into the YAML. --- .../custom/ys_servicenow/src/Form/ServiceNowSettings.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php index e9a98bdc08..0b74b2715b 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php @@ -112,14 +112,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#disabled' => !$allowSecretItems, ]; - $form['servicenow_endpoint'] = [ - '#type' => 'url', - '#title' => $this->t('ServiceNow endpoint base URL'), - '#description' => $this->t('Ex: https://apiendpoint'), - '#default_value' => $config->get('servicenow_endpoint') ?: '', - '#disabled' => !$allowSecretItems, - ]; - $form['servicenow_auth_key'] = [ '#type' => 'key_select', '#title' => $this->t('ServiceNow Authentication Credentials'), @@ -160,7 +152,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $this->configFactory->getEditable('ys_servicenow.settings') // Set the submitted configuration setting. ->set('enable_servicenow_sync', $form_state->getValue('enable_servicenow_sync')) - ->set('servicenow_endpoint', rtrim($form_state->getValue('servicenow_endpoint'), "/")) ->set('servicenow_auth_key', $form_state->getValue('servicenow_auth_key')) ->save(); From 3b8906599141d337f26473543661aecb953b0244 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:15:23 -0400 Subject: [PATCH 10/30] feat(YSP-593): only sync block data --- .../custom/ys_servicenow/src/ServiceNowManager.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php index a13c30740a..175a805099 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -148,9 +148,12 @@ public function runMigration($migration) { * $migrationInstance->set('syncSource', TRUE); */ - $migrationInstance->set('syncSource', TRUE); - $migration_update = $migrationInstance->getIdMap(); - $migration_update->prepareUpdate(); + // We choose to use syncSource since we want to recreate the block for update. + if ($migration === 'servicenow_knowledge_base_article_block') { + $migrationInstance->set('syncSource', TRUE); + $migration_update = $migrationInstance->getIdMap(); + $migration_update->prepareUpdate(); + } $message = new MigrateMessage(); $executable = new MigrateExecutable($migrationInstance, $message); $executable->import(); From f7e39162ba4c0058b9b0cb5a3d393f0d120cdb83 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:21:46 -0400 Subject: [PATCH 11/30] fix(YSP-593): enable servicenow --- .../custom/yalesites_profile/config/sync/core.extension.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/web/profiles/custom/yalesites_profile/config/sync/core.extension.yml b/web/profiles/custom/yalesites_profile/config/sync/core.extension.yml index 9cd2218d72..86a2966cd4 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/core.extension.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/core.extension.yml @@ -148,6 +148,7 @@ module: ys_localist: 0 ys_mail: 0 ys_node_access: 0 + ys_servicenow: 0 ys_starterkit: 0 ys_toolbar: 0 ys_views_basic: 0 From 273b19eca8be43203f054f12e11e0eeef5d9964b Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:24:12 -0400 Subject: [PATCH 12/30] fix(YSP-593): move servicenow to admin --- .../modules/custom/ys_servicenow/ys_servicenow.links.menu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml index 29996dbfff..e8c0c1e650 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml @@ -2,5 +2,5 @@ ys_servicenow.settings: title: 'ServiceNow settings' description: 'Configure ServiceNow sync settings' route_name: ys_servicenow.settings - parent: ys_core.admin_yalesites + parent: system.admin_config weight: 0 From b457df69670ad2245cd8ea66321bfa8141a2633d Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:25:33 -0400 Subject: [PATCH 13/30] fix(YSP-593): remove permission for platform admins --- .../yalesites_profile/config/sync/user.role.platform_admin.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml b/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml index ae57a86a06..bc661139ee 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/user.role.platform_admin.yml @@ -79,7 +79,6 @@ dependencies: - ys_alert - ys_core - ys_localist - - ys_servicenow id: platform_admin label: 'Platform administrator' weight: -5 @@ -412,5 +411,4 @@ permissions: - 'view unpublished paragraphs' - 'yalesites manage alerts' - 'yalesites manage localist' - - 'yalesites manage servicenow' - 'yalesites manage settings' From 1c4b6e56294446f8a2cc51bca8f4833d175606ee Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:29:35 -0400 Subject: [PATCH 14/30] fix(YSP-593): don't validate deleted element --- .../custom/ys_servicenow/src/Form/ServiceNowSettings.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php index 0b74b2715b..12946eb8fb 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php @@ -127,9 +127,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { public function validateForm(array &$form, FormStateInterface $form_state) { $enabled = $form_state->getValue('enable_servicenow_sync'); if ($enabled) { - $requiredFields = [ - 'servicenow_endpoint', - ]; + $requiredFields = []; foreach ($requiredFields as $field) { if (!$form_state->getValue($field)) { From 5fb694ce6eb35de0260592428e96428118c3072b Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:31:02 -0400 Subject: [PATCH 15/30] fix(YSP-593): use credentials as sync condition --- .../custom/ys_servicenow/src/Form/ServiceNowSettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php index 12946eb8fb..f68b3af086 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php @@ -96,7 +96,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { if ( $config->get('enable_servicenow_sync') && - $config->get('servicenow_endpoint') + $config->get('servicenow_auth_key') ) { $form['sync_now_button'] = [ '#type' => 'markup', From ed8b1edec343d0aefff49de51c11736781a51e0f Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:33:42 -0400 Subject: [PATCH 16/30] feat(YSP-593): make imported items published --- .../migrations/servicenow_knowledge_base_articles.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml index addf1a2bf4..e5b8ac0931 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml @@ -34,11 +34,15 @@ process: layout_builder__layout: source: servicenow_title plugin: layout_builder_sections + moderation_state: + plugin: default_value + default_value: 'published' destination: plugin: 'entity:node' default_bundle: page overwrite_properties: - title + - moderation_state migration_dependencies: required: - servicenow_knowledge_base_article_block From b51993c52b7e6bce7aadca4e370d71301b9d506c Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 21 Aug 2024 16:42:58 -0400 Subject: [PATCH 17/30] docs(YSP-539): add some useful documentation --- .../modules/custom/ys_servicenow/README.md | 19 +++++++++++++++++++ .../ys_servicenow/src/ServiceNowManager.php | 3 ++- .../custom/ys_servicenow/ys_servicenow.module | 1 - 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md index e69de29bb2..f8f9b83c98 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md @@ -0,0 +1,19 @@ +# YaleSites ServiceNow + +This is a YaleSites integration to allow ServiceNow knowledge base articles to import into the platform. The ultimate goal of this is to allow it to then go through our AI pipeline so that you can ask questions that will consider the articles synced. + +## Features + +Features include: + +- Key-based authentication +- Block-based syncing + +## Usage + +1. Install the module +2. Create a new key in the keys module with the ServiceNow endpoint username and password credentials +3. Visit the ServiceNow Settings under Configuration +4. Enable the module and select the key you created +5. Save +6. Upon reload, you'll notice a Sync button; click this button to do a manual sync diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php index 175a805099..80c7f76107 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -148,7 +148,8 @@ public function runMigration($migration) { * $migrationInstance->set('syncSource', TRUE); */ - // We choose to use syncSource since we want to recreate the block for update. + // We choose to use syncSource since we want to recreate the block for + // update. if ($migration === 'servicenow_knowledge_base_article_block') { $migrationInstance->set('syncSource', TRUE); $migration_update = $migrationInstance->getIdMap(); diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module index f4587d9d82..303cbfcb4d 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module @@ -4,4 +4,3 @@ * @file * Primary module hooks for YS ServiceNow module. */ - From 3ed2f6295c8da3ddf67cb94c42a744b6a3111065 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 22 Aug 2024 10:43:03 -0400 Subject: [PATCH 18/30] fix(YSP-593): save node so that update pipelines can run It seems when migrations happen, they skip the callbacks that items would normally have. In our case, it's not triggering our ai module hook to update. This is an attempt to save them so that it can pick it up. --- .../custom/ys_servicenow/src/ServiceNowManager.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php index 80c7f76107..e3c62dea67 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -196,6 +196,17 @@ public function runAllMigrations() { 'imported' => $this->getMigrationStatus($migration), ]; } + + $articleMigration = 'servicenow_knowledge_base_articles'; + + $migration = $this->migrationManager->createInstance($articleMigration); + $map = $migration->getIdMap(); + foreach ($map->fetchLastImported() as $id) { + $node = $this->entityTypeManager->getStorage('node')->load($id); + // Save the node so that proper hooks can be called on resulting data. + $node->save(); + } + return $messageData; } From 2132a6760075c931fc0f1cbec8abbbf89e2e5fc0 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 22 Aug 2024 10:53:36 -0400 Subject: [PATCH 19/30] fix(YSP-593): Do dirty update (revert later) --- .../custom/ys_servicenow/src/ServiceNowManager.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php index e3c62dea67..9441f42eb8 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -201,10 +201,12 @@ public function runAllMigrations() { $migration = $this->migrationManager->createInstance($articleMigration); $map = $migration->getIdMap(); - foreach ($map->fetchLastImported() as $id) { - $node = $this->entityTypeManager->getStorage('node')->load($id); - // Save the node so that proper hooks can be called on resulting data. - $node->save(); + + // Get each node from the map. + $ids = $map->lookupDestinationIds(); + foreach ($ids as $id) { + $entity = $this->entityTypeManager->getStorage('node')->load($id); + \Drupal::service('ai_engine_embedding.entity_update')->update($entity); } return $messageData; From 3eb29c2d5e24cc3ae615f4f7bb8f27bfc01d6e9a Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 22 Aug 2024 10:57:30 -0400 Subject: [PATCH 20/30] revert(YSP-593): revert dumb fixes for pipeline --- .../custom/ys_servicenow/src/ServiceNowManager.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php index 9441f42eb8..23a60b549a 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -197,18 +197,6 @@ public function runAllMigrations() { ]; } - $articleMigration = 'servicenow_knowledge_base_articles'; - - $migration = $this->migrationManager->createInstance($articleMigration); - $map = $migration->getIdMap(); - - // Get each node from the map. - $ids = $map->lookupDestinationIds(); - foreach ($ids as $id) { - $entity = $this->entityTypeManager->getStorage('node')->load($id); - \Drupal::service('ai_engine_embedding.entity_update')->update($entity); - } - return $messageData; } From 0d364fccc9914b342ce964b154c379a06e266bef Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 5 Sep 2024 09:34:26 -0400 Subject: [PATCH 21/30] fix(YSP-593): remove limit from servicenow endpoint --- .../migrations/servicenow_knowledge_base_article_block.yml | 2 +- .../migrations/servicenow_knowledge_base_articles.yml | 2 +- .../migrations/servicenow_knowledge_base_layout_builder.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml index 80814ebee0..dd3412b22d 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml @@ -10,7 +10,7 @@ source: authentication: plugin: servicenow_auth track_changes: true - urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 + urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category item_selector: result fields: - name: servicenow_number diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml index e5b8ac0931..f9ab601d87 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml @@ -10,7 +10,7 @@ source: authentication: plugin: servicenow_auth track_changes: true - urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 + urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category item_selector: result fields: - name: servicenow_number diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml index 0158119268..5a2a577b62 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml @@ -10,7 +10,7 @@ source: authentication: plugin: servicenow_auth track_changes: true - urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category&sysparm_limit=10 + urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category item_selector: result fields: - name: servicenow_number From a5853e541e441d5e02226e70d8ca9e921ba7d5df Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Fri, 6 Sep 2024 11:38:59 -0400 Subject: [PATCH 22/30] feat(YSP-593): config ignore servicenow settings --- .../yalesites_profile/config/sync/config_ignore.settings.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml b/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml index 814e7b3bd3..007ac237c4 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml @@ -8,3 +8,4 @@ ignored_config_entities: - ys_themes.theme_settings - 'ys_localist*' - 'ai_engine*' + - 'ys_servicenow*' From f522f7c32a22fa229f7e8cab76918fd8aaa7c91c Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 11 Sep 2024 11:05:38 -0400 Subject: [PATCH 23/30] feat(YSP-593): enable cron job --- .../custom/ys_servicenow/ys_servicenow.module | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module index 303cbfcb4d..f0c6134097 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module @@ -4,3 +4,22 @@ * @file * Primary module hooks for YS ServiceNow module. */ + +/** + * Implements hook_cron(). + */ +function ys_servicenow_cron() { + $config = \Drupal::config('ys_servicenow.settings'); + if ($config->get('enable_servicenow_sync')) { + + $state = \Drupal::state(); + + $next_execution_time = $state->get("servicenow_migrations", 0); + $current_time = \Drupal::time()->getRequestTime(); + if ($current_time > $next_execution_time) { + $state->set("servicenow_migrations", $current_time + 3600); + $servicenowManager = \Drupal::service('ys_servicenow.manager'); + $servicenowManager->runAllMigrations(); + } + } +} From 463f78e2af38105af1200122475fc35da5e896b2 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 11 Sep 2024 12:24:01 -0400 Subject: [PATCH 24/30] feat(YSP-593): use configurable endpoint for migration call --- ...servicenow_knowledge_base_article_block.yml | 3 ++- .../servicenow_knowledge_base_articles.yml | 3 ++- ...ervicenow_knowledge_base_layout_builder.yml | 3 ++- .../src/Form/ServiceNowSettings.php | 13 ++++++++++++- .../migrate/process/LayoutBuilderSections.php | 9 --------- .../custom/ys_servicenow/ys_servicenow.module | 18 ++++++++++++++++++ 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml index dd3412b22d..20d4459b56 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_article_block.yml @@ -10,7 +10,8 @@ source: authentication: plugin: servicenow_auth track_changes: true - urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category + urls: + callback: ys_servicenow_url_endpoint item_selector: result fields: - name: servicenow_number diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml index f9ab601d87..7079d9ae88 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml @@ -10,7 +10,8 @@ source: authentication: plugin: servicenow_auth track_changes: true - urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category + urls: + callback: ys_servicenow_url_endpoint item_selector: result fields: - name: servicenow_number diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml index 5a2a577b62..b9dd565276 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml @@ -10,7 +10,8 @@ source: authentication: plugin: servicenow_auth track_changes: true - urls: https://yaledevelopment.service-now.com/api/now/table/kb_knowledge?sysparm_query=workflow_state%3Dpublished%5Ekb_category.label!%3DNews%5Ecan_read_user_criteriaLIKEfd81a4dadbb6030043565bc0cf961905%5Eu_kb_ai_ready%3Dtrue&sysparm_display_value=true&sysparm_fields=sys_name%2Ctext%2Ctopic%2Cu_service_offering%2Cnumber%2Csys_created_on%2Ccan_read_user_criteria%2Cpublished%2Ckb_knowledge_base%2Cdescription%2Cvalid_to%2Csys_view_count%2Cshort_description%2Ckb_category + urls: + callback: ys_servicenow_url_endpoint item_selector: result fields: - name: servicenow_number diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php index f68b3af086..3a81b8d2df 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Form/ServiceNowSettings.php @@ -96,6 +96,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { if ( $config->get('enable_servicenow_sync') && + $config->get('servicenow_endpoint') && $config->get('servicenow_auth_key') ) { $form['sync_now_button'] = [ @@ -112,6 +113,12 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#disabled' => !$allowSecretItems, ]; + $form['servicenow_endpoint'] = [ + '#type' => 'textarea', + '#title' => $this->t('ServiceNow Endpoint'), + '#default_value' => $config->get('servicenow_endpoint') ?: '', + ]; + $form['servicenow_auth_key'] = [ '#type' => 'key_select', '#title' => $this->t('ServiceNow Authentication Credentials'), @@ -127,7 +134,10 @@ public function buildForm(array $form, FormStateInterface $form_state) { public function validateForm(array &$form, FormStateInterface $form_state) { $enabled = $form_state->getValue('enable_servicenow_sync'); if ($enabled) { - $requiredFields = []; + $requiredFields = [ + 'servicenow_auth_key', + 'servicenow_endpoint', + ]; foreach ($requiredFields as $field) { if (!$form_state->getValue($field)) { @@ -151,6 +161,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Set the submitted configuration setting. ->set('enable_servicenow_sync', $form_state->getValue('enable_servicenow_sync')) ->set('servicenow_auth_key', $form_state->getValue('servicenow_auth_key')) + ->set('servicenow_endpoint', $form_state->getValue('servicenow_endpoint')) ->save(); parent::submitForm($form, $form_state); diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php index e1cb2a34b3..a361b5b327 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/Plugin/migrate/process/LayoutBuilderSections.php @@ -26,10 +26,7 @@ class LayoutBuilderSections extends ProcessPluginBase { */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { - \Drupal::messenger()->addMessage("Value: " . $value, 'status', TRUE); - if ($value == NULL) { - \Drupal::messenger()->addError("value is NULL", 'status', TRUE); return NULL; } @@ -54,8 +51,6 @@ public function transform($value, MigrateExecutableInterface $migrate_executable return NULL; } - \Drupal::messenger()->addMessage("Got a block content"); - $config = [ 'id' => 'inline_block:text', 'label' => $block_content->label(), @@ -69,15 +64,11 @@ public function transform($value, MigrateExecutableInterface $migrate_executable $components[] = new SectionComponent($generator->generate(), 'content', $config); - \Drupal::messenger()->addMessage("Made a section component"); - // If you were doing multiple sections, you'd want this to be an array // somehow. @TODO figure out how to do that ;) // PARAMS: $layout_id, $layout_settings, $components. $sections = new Section('layout_onecol', [], $components); - \Drupal::messenger()->addMessage("Made a section"); - return $sections; } diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module index f0c6134097..b01c6f2710 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module @@ -5,6 +5,8 @@ * Primary module hooks for YS ServiceNow module. */ +use Drupal\migrate\Plugin\MigrationInterface; + /** * Implements hook_cron(). */ @@ -23,3 +25,19 @@ function ys_servicenow_cron() { } } } + +/** + * Provide the URL endpoint for migrations in servicenow from config. + */ +function ys_servicenow_url_endpoint(MigrationInterface $migration): array { + // Get the servicenow configuration. + $servicenow_config = \Drupal::config('ys_servicenow.settings'); + // Get the endpoint type from the migration. + $endpoint = $servicenow_config->get('servicenow_endpoint'); + + if ($endpoint) { + return [$endpoint]; + } + + return []; +} From bd825c62904f8b41121decb6ef199e10a33afd60 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 11 Sep 2024 16:04:06 -0400 Subject: [PATCH 25/30] fix(YSP-593): guard against invalid JSON --- ...rvicenow_knowledge_base_layout_builder.yml | 42 ------------------- .../ys_servicenow/src/BasicAuthWithKeys.php | 8 +++- 2 files changed, 7 insertions(+), 43 deletions(-) delete mode 100644 web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml deleted file mode 100644 index b9dd565276..0000000000 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_layout_builder.yml +++ /dev/null @@ -1,42 +0,0 @@ -id: servicenow_knowledge_base_layout_builder -label: 'ServiceNow knowledge base articles' -source: - plugin: url - data_fetcher_plugin: http - data_parser_plugin: json - headers: - Accept: 'application/json; charset=utf-8' - Content-Type: application/json - authentication: - plugin: servicenow_auth - track_changes: true - urls: - callback: ys_servicenow_url_endpoint - item_selector: result - fields: - - name: servicenow_number - label: 'ServiceNow number' - selector: number - ids: - servicenow_number: - type: string -process: - id: servicenow_number - field_text: servicenow_content - block: - plugin: migration_lookup - migration: servicenow_knowledge_base_article_block - source: servicenow_number - node: - plugin: migration_lookup - migration: servicenow_knowledge_base_articles - source: servicenow_number -destination: - plugin: append_block_to_node - source: servicenow_number -dependencies: - enforced: - module: - - migrate_plus - - migrate_tools - - layout_builder diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/BasicAuthWithKeys.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/BasicAuthWithKeys.php index cc8f66410b..3e3d72d3ad 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/BasicAuthWithKeys.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/BasicAuthWithKeys.php @@ -96,7 +96,13 @@ protected function getKeyValues($key) { throw new \Exception("Key has no value"); } - return json_decode($json_key); + $decoded_object = json_decode($json_key); + + if (!$decoded_object) { + throw new \Exception("Key value is not valid JSON. Could you have accidentally used single quotes vs double?"); + } + + return $decoded_object; } } From 5a2c43835430bdb6734ecd3e400022ea65b963cd Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Thu, 12 Sep 2024 15:00:26 -0400 Subject: [PATCH 26/30] feat(YSP-593): use workflow_state to drive publish status --- .../servicenow_knowledge_base_articles.yml | 8 ++++++-- .../custom/ys_servicenow/ys_servicenow.module | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml index 7079d9ae88..ebc6d2053e 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/migrations/servicenow_knowledge_base_articles.yml @@ -23,6 +23,9 @@ source: - name: servicenow_text label: 'ServiceNow text' selector: text + - name: servicenow_workflow_state + label: 'ServiceNow workflow state' + selector: workflow_state ids: servicenow_number: type: string @@ -36,8 +39,9 @@ process: source: servicenow_title plugin: layout_builder_sections moderation_state: - plugin: default_value - default_value: 'published' + plugin: callback + callable: ys_servicenow_moderation_state_transformation + source: servicenow_workflow_state destination: plugin: 'entity:node' default_bundle: page diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module index b01c6f2710..5609e3bc6a 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.module @@ -41,3 +41,16 @@ function ys_servicenow_url_endpoint(MigrationInterface $migration): array { return []; } + +/** + * Any state other than "Published" is unpublished. + */ +function ys_servicenow_moderation_state_transformation($value) { + $unpublished_state = 'archive'; + + $published_states = [ + 'Published' => 'published', + ]; + + return $published_states[$value] ?? $unpublished_state; +} From fd221db1f20512c579c06ed9f8fcc9d13248dccd Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Fri, 13 Sep 2024 11:42:25 -0400 Subject: [PATCH 27/30] docs(YSP-593): add supporting docs for usage --- .../modules/custom/ys_servicenow/README.md | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md index f8f9b83c98..e560f49ab6 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/README.md @@ -12,8 +12,29 @@ Features include: ## Usage 1. Install the module -2. Create a new key in the keys module with the ServiceNow endpoint username and password credentials +2. Create a new key in the keys module with the ServiceNow endpoint username and password credentials (see pantheon secrets below) 3. Visit the ServiceNow Settings under Configuration -4. Enable the module and select the key you created -5. Save -6. Upon reload, you'll notice a Sync button; click this button to do a manual sync +4. Enable the module +5. Select the key you created from the drop down +6. Enter the endpoint URL you were given by the ServiceNow Team + 1. Ensure that the following fields are present in the JSON output: + 1. number: The KB article number + 2. short_description: The title of the article + 3. text: The body of the article + 4. workflow_state: The state of the article (Published, etc) +7. Save +8. Upon reload, you'll notice a Sync button; click this button to do a manual sync + +The service once turned on will attempt to sync hourly. + +## Pantheon Secrets + +Pantheon secrets can be used with their Drupal module to interact with the keys module. To do this you'd want to add a pantheon secret at the site level first with empty data: + +`terminus secrets:site:set --scope web,user servicenow_auth ""` + +From there, you can then specify the multidev specific information. The key must ultimately be a JSON payload of the following: + +`terminus secrets:site:set . servicenow_auth '{"username":"username","password":"password"}'` + +Then simply sync pantheon secrets in the keys configuration to bring in the key; remember that there is a time delay on when that becomes available for sync. From 05623e09f0938d9738e998f2912485e9461b39a3 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Wed, 25 Sep 2024 15:03:40 -0400 Subject: [PATCH 28/30] fix(YSP-593): do not overwrite old data each time Marc has written about this, and it looks as if when an item is no longer present in the payload that it gets wiped, which we do not want. So we removed this; more testing needs to be done on the effects of changing the data and how it updates. --- .../custom/ys_servicenow/src/ServiceNowManager.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php index 23a60b549a..c2fe83ef3a 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/src/ServiceNowManager.php @@ -150,11 +150,11 @@ public function runMigration($migration) { // We choose to use syncSource since we want to recreate the block for // update. - if ($migration === 'servicenow_knowledge_base_article_block') { - $migrationInstance->set('syncSource', TRUE); - $migration_update = $migrationInstance->getIdMap(); - $migration_update->prepareUpdate(); - } + /*if ($migration === 'servicenow_knowledge_base_article_block') {*/ + /* $migrationInstance->set('syncSource', TRUE);*/ + /* $migration_update = $migrationInstance->getIdMap();*/ + /* $migration_update->prepareUpdate();*/ + /*}*/ $message = new MigrateMessage(); $executable = new MigrateExecutable($migrationInstance, $message); $executable->import(); From 3a1a597c83d92cac2bbe4e30d6fc74ff4563c2c6 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Fri, 27 Sep 2024 08:14:34 -0400 Subject: [PATCH 29/30] feat(YSP-593): move servicenow to web services configuration links --- .../modules/custom/ys_servicenow/ys_servicenow.links.menu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml index e8c0c1e650..c97fc72830 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_servicenow/ys_servicenow.links.menu.yml @@ -2,5 +2,5 @@ ys_servicenow.settings: title: 'ServiceNow settings' description: 'Configure ServiceNow sync settings' route_name: ys_servicenow.settings - parent: system.admin_config + parent: system.admin_config_services weight: 0 From 958e94f84ded7d329df770d8dc2c4ed7703a2ef9 Mon Sep 17 00:00:00 2001 From: David Blankenship Date: Fri, 27 Sep 2024 08:18:42 -0400 Subject: [PATCH 30/30] feat(YSP-593): add ys_servicenow to config ignore --- .../yalesites_profile/config/sync/config_ignore.settings.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml b/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml index 007ac237c4..50fe0d9570 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/config_ignore.settings.yml @@ -7,5 +7,4 @@ ignored_config_entities: - 'ys_core*' - ys_themes.theme_settings - 'ys_localist*' - - 'ai_engine*' - 'ys_servicenow*'