Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
langcode: en
status: true
dependencies:
config:
- key.key.az_profiles_api_endpoint
- az_person_profiles_import.settings
id: az_profiles_api_endpoint
label: 'Profiles API Endpoint'
config_type: system.simple
config_prefix: ''
config_name: az_person_profiles_import.settings
config_item: endpoint
key_id: az_profiles_api_endpoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
langcode: en
status: true
dependencies:
config:
- key.key.az_profiles_api_key
- az_person_profiles_import.settings
id: az_profiles_api_key
label: 'Profiles API Key'
config_type: system.simple
config_prefix: ''
config_name: az_person_profiles_import.settings
config_item: apikey
key_id: az_profiles_api_key
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
langcode: en
status: true
dependencies: { }
id: az_profiles_api_endpoint
label: 'Profiles API Endpoint'
description: 'URL endpoint for the UA Profiles API service.'
key_type: authentication
key_type_settings: { }
key_provider: az_secrets
key_provider_settings:
secret_name: AZ_PROFILES_API_ENDPOINT
base64_encoded: false
key_input: none
key_input_settings: { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
langcode: en
status: true
dependencies: { }
id: az_profiles_api_key
label: 'Profiles API Key'
description: 'API key for the UA Profiles API service.'
key_type: authentication
key_type_settings: { }
key_provider: az_secrets
key_provider_settings:
secret_name: AZ_PROFILES_API_KEY
base64_encoded: false
key_input: none
key_input_settings: { }
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ final class AZPersonProfilesImportForm extends FormBase {
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->entityTypeManager = $container->get('entity_type.manager');

try {
// This service may not exist if ldap_query is not enabled.
$instance->ldapQueryController = $container->get('ldap.query');
Expand All @@ -71,7 +72,10 @@ public function getFormId(): string {
public function buildForm(array $form, FormStateInterface $form_state): array {

$config = $this->config('az_person_profiles_import.settings');

// Check if we have an API key from either config or secrets (via override).
$has_key = !empty(trim($config->get('apikey')));

if (!$has_key) {
$url = Url::fromRoute('az_person_profiles_import.settings_form')->toString();
$this->messenger->addWarning($this->t('You must first configure a Profiles API token <a href=":link">here</a>.', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,32 @@

namespace Drupal\az_person_profiles_import\Form;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Configure Quickstart Person Profiles Import settings for this site.
*/
final class AZPersonProfilesImportSettingsForm extends ConfigFormBase {

/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->entityTypeManager = $container->get('entity_type.manager');
return $instance;
}

/**
* {@inheritdoc}
*/
Expand All @@ -31,33 +49,97 @@ protected function getEditableConfigNames(): array {
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$config = $this->config('az_person_profiles_import.settings');

// Check if az_secrets integration is active by checking if keys exist and
// have values.
$using_secrets = $this->hasSecrets(['az_profiles_api_endpoint', 'az_profiles_api_key']);

if ($using_secrets) {
$form['secrets_status'] = [
'#type' => 'item',
'#markup' => new FormattableMarkup('<div class="messages messages--status">@message1<br>@message2</div>', [
'@message1' => $this->t('✓ API credentials are managed by Quickstart Secrets Management.'),
'@message2' => $this->t('Credentials are loaded from environment variables or Pantheon Secrets.'),
]),
];
}

$form['endpoint'] = [
'#type' => 'url',
'#title' => $this->t('Profiles API Endpoint'),
'#description' => $this->t('Enter a fully qualified URL for the endpoint of the profiles API service.'),
'#default_value' => $config->get('endpoint'),
'#required' => TRUE,
'#required' => !$using_secrets,
'#disabled' => $using_secrets,
];

if ($using_secrets) {
$form['endpoint']['#description'] = $this->t('This value is managed by Quickstart Secrets Management and cannot be edited here.');
}

$form['apikey'] = [
'#type' => 'password',
'#title' => $this->t('API Token'),
'#description' => $this->t('Enter an API Token for the profiles API service.'),
'#maxlength' => 128,
'#size' => 64,
'#default_value' => $config->get('apikey'),
'#disabled' => $using_secrets,
];

if ($using_secrets) {
$form['apikey']['#description'] = $this->t('This value is managed by Quickstart Secrets Management and cannot be edited here.');
}
return parent::buildForm($form, $form_state);
}

/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$this->config('az_person_profiles_import.settings')
->set('endpoint', $form_state->getValue('endpoint'))
->set('apikey', $form_state->getValue('apikey'))
->save();
// Only save to config if not using secrets.
if (!$this->hasSecrets(['az_profiles_api_endpoint', 'az_profiles_api_key'])) {
$this->config('az_person_profiles_import.settings')
->set('endpoint', $form_state->getValue('endpoint'))
->set('apikey', $form_state->getValue('apikey'))
->save();
}

parent::submitForm($form, $form_state);
}

/**
* Check if secrets are configured with values.
*
* @param array $key_ids
* Array of key entity IDs to check.
*
* @return bool
* TRUE if all keys exist and have values, FALSE otherwise.
*/
protected function hasSecrets(array $key_ids): bool {
try {
$key_storage = $this->entityTypeManager->getStorage('key');

foreach ($key_ids as $key_id) {
$key = $key_storage->load($key_id);

if (!$key || !method_exists($key, 'getKeyValue')) {
return FALSE;
}

$value = $key->getKeyValue();
if (empty($value)) {
return FALSE;
}
}

return TRUE;
}
catch (\Exception $e) {
// Key storage not available or error loading keys.
return FALSE;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public static function create(ContainerInterface $container, array $configuratio
*/
public function getResponseContent(string $url): string {
// Grab the profiles API settings from configuration.
// Note: If az_secrets is configured with key config overrides,
// these values will be automatically injected from secrets.
$config = $this->configFactory->get('az_person_profiles_import.settings');
$endpoint = $config->get('endpoint');
$apikey = $config->get('apikey');
Expand All @@ -78,7 +80,12 @@ public function getResponseContent(string $url): string {
try {
$body = (string) $this->getResponse($url)->getBody();
}
catch (MigrateException | RequestException $e) {
catch (RequestException $e) {
// Response from API had no data.
$json = ['Person' => ['netid' => $netid]];
$body = json_encode($json);
}
catch (MigrateException $e) {
// Response from API had no data.
$json = ['Person' => ['netid' => $netid]];
$body = json_encode($json);
Expand Down
Loading