Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi server configuration #3

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
73 changes: 73 additions & 0 deletions includes/admin.form.inc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,44 @@ function islandora_pathauto_admin_settings(array $form, array &$form_state) {
'#default_value' => variable_get('islandora_pathauto_objects_query_solr', '*:*'),
);

$form['multi_server'] = array(
'#type' => 'fieldset',
'#title' => t('Multiple server configuration'),
'#description' => t('When using multiple servers, one might want to trigger the alias generation on a different server when an object is ingested.'),
);
$triggertype = variable_get('islandora_pathauto_trigger_type', NULL);
$triggerurl = variable_get('islandora_pathauto_trigger_url', NULL);
$triggersecret = variable_get('islandora_pathauto_trigger_secret', NULL);
$form['multi_server']['trigger_type'] = array(
'#type' => 'select',
'#title' => t('Trigger type'),
'#options' => array(
0 => t('Disabled'),
'receiving' => t('Trigger receiving server'),
'sending' => t('Trigger sending server'),
),
'#default_value' => $triggertype,
'#description' => t("Only enable for multi server configurations. For example: set the ingest server to 'trigger sending server' and the front-end server to 'trigger receiving server'.\nThe 'trigger sending server' will use the 'trigger URL' to send a trigger when an alias is created. The 'trigger receiving server' receives this trigger and creates an alias for the same object.\nDo not set both servers to 'trigger sending server' because this will create an endless loop."),
);
$form['multi_server']['trigger_url'] = array(
'#type' => 'textfield',
'#title' => t('Trigger URL'),
'#description' => t('The base URL of the server to send a trigger to.'),
'#states' => array(
'visible' => array(':input[name=trigger_type]' => array('value' => 'sending')),
),
'#default_value' => $triggerurl,
);
$form['multi_server']['trigger_secret'] = array(
'#type' => 'textfield',
'#title' => t('Trigger secret'),
'#description' => t('A secret that is shared between the sending and receiving server. Use the same secret for both sending and receiving servers.'),
'#states' => array(
'visible' => array(':input[name=trigger_type]' => array(array('value' => 'sending'), array('value' => 'receiving'))),
),
'#default_value' => $triggersecret,
);

$form['use_cron'] = array(
'#type' => 'checkbox',
'#title' => t('Use cron to automatically add / update aliases.'),
Expand All @@ -100,6 +138,38 @@ function islandora_pathauto_admin_settings(array $form, array &$form_state) {
return $form;
}

/**
* Validate handler for admin form.
*/
function islandora_pathauto_admin_settings_validate($form, &$form_state) {
$triggertype = $form_state['values']['trigger_type'];
if ($triggertype === 'receiving') {
if (empty($form_state['values']['trigger_secret'])) {
form_set_error('trigger_secret', t("Fill out a secret shared with the sending server."));
}
}
if ($triggertype === 'sending') {
if (empty($form_state['values']['trigger_secret'])) {
form_set_error('trigger_secret', t("Fill out a secret shared with the receiving server."));
}
if (empty($form_state['values']['trigger_url'])) {
form_set_error('trigger_url', t("Fill out the URL of the receiving server."));
}
else {
$response = islandora_pathauto_trigger_creation_on_server(NULL, 'insert', $form_state['values']['trigger_url'], $form_state['values']['trigger_secret']);
if ($response === NULL) {
form_set_error('trigger_url', t("The URL provided is not a valid receiving server. Make sure the URL contains only protocol and domain."));
}
elseif (isset($response['error'])) {
form_set_error('trigger_url', t("The URL provided gave the following error: %error", array('%error' => $response['error'])));
}
elseif (isset($response['success']) && !$response['success']) {
form_set_error('trigger_url', t("The URL provided is not valid and something unexpected happened"));
}
}
}
}

/**
* Submit handler for admin form.
*/
Expand All @@ -109,6 +179,9 @@ function islandora_pathauto_admin_settings_submit($form, &$form_state) {
variable_set('islandora_pathauto_use_cron', $form_state['values']['use_cron']);
variable_set('islandora_pathauto_objects_query_method', $form_state['values']['objects_query_method']);
variable_set('islandora_pathauto_objects_query_solr', $form_state['values']['objects_query_solr']);
variable_set('islandora_pathauto_trigger_type', $form_state['values']['trigger_type']);
variable_set('islandora_pathauto_trigger_url', $form_state['values']['trigger_url']);
variable_set('islandora_pathauto_trigger_secret', $form_state['values']['trigger_secret']);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions islandora_pathauto.install
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ function islandora_pathauto_uninstall() {
'islandora_pathauto_selected_cmodels',
'islandora_pathauto_objects_query_method',
'islandora_pathauto_objects_query_solr',
'islandora_pathauto_trigger_type',
'islandora_pathauto_trigger_url',
'islandora_pathauto_trigger_secret',
);
array_walk($variables, 'variable_del');
}
125 changes: 125 additions & 0 deletions islandora_pathauto.module
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ function islandora_pathauto_menu() {
'file' => 'includes/admin.form.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/islandora/tools/islandora-pathauto/trigger/%/%'] = array(
'page callback' => 'islandora_pathauto_triggered_create_alias',
'page arguments' => array(5, 6),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}

Expand Down Expand Up @@ -96,6 +102,7 @@ function islandora_pathauto_pathauto($op) {
* may be >1 if the object has multiple content models.
*/
function islandora_pathauto_create_alias($object, $op) {
module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('inc', 'pathauto');
$count = 0;
if (islandora_namespace_accessible($object->id)) {
Expand All @@ -114,6 +121,14 @@ function islandora_pathauto_create_alias($object, $op) {
}
}
}
if (variable_get('islandora_pathauto_trigger_type', '') === 'sending') {
$response = islandora_pathauto_trigger_creation_on_server($object, $op);
if ($response === NULL || isset($response['error'])) {
watchdog('islandora_pathauto', 'Unable to trigger creation of alias on remote server: @error', array(
'@error' => isset($response['error']) ? $response['error'] : 'Cannot read response',
), WATCHDOG_ERROR);
}
}

return $count;
}
Expand Down Expand Up @@ -593,3 +608,113 @@ function islandora_pathauto_cron() {
function islandora_pathauto_pathauto_bulkupdate(&$context) {
return islandora_pathauto_bulk_batch_process(FALSE, $context);
}

/**
* Fire a trigger to create aliases on other servers.
*/
function islandora_pathauto_trigger_creation_on_server($object, $op, $url = NULL, $secret = NULL) {
if ($url === NULL) {
$url = variable_get('islandora_pathauto_trigger_url', NULL);
}
if ($secret === NULL) {
$secret = variable_get('islandora_pathauto_trigger_secret', NULL);
}
if (isset($url, $secret)) {
$identifier = isset($object) ? $object->id : 'testing';
$time = time();
$url = rtrim($url, '/') . '/admin/islandora/tools/islandora-pathauto/trigger/' . $identifier . '/' . $op;
$hash = drupal_hash_base64("$secret $identifier $op $time");
$options = array(
'method' => 'POST',
'data' => array('hash' => $hash, 'time' => $time),
);
$result = drupal_http_request($url, $options);

if (isset($result->data, $result->code) && json_decode($result->data) !== NULL) {
return json_decode($result->data, TRUE);
}
else {
return array('success' => FALSE, 'error' => 'Cannot decode data');
}
}
}

/**
* Handle a received trigger from an other server.
*/
function islandora_pathauto_triggered_create_alias($objectid, $op) {
$input = file_get_contents("php://input");
parse_str($input, $vars);
$istest = ($objectid === 'testing');
$issuccess = TRUE;
$error = NULL;
$message = NULL;
$status = 200;

if (isset($vars['hash'], $vars['time'])) {
$receivedhash = $vars['hash'];
$receivedtime = $vars['time'];
$secret = variable_get('islandora_pathauto_trigger_secret', NULL);

$hash = drupal_hash_base64("$secret $objectid $op $receivedtime");
if ($hash !== $receivedhash) {
$issuccess = FALSE;
$error = 'Authentication failed';
$status = 401;
}
}
else {
$issuccess = FALSE;
$error = 'Authentication required';
$status = 401;
}

if ($success && ($op !== 'insert' && $op !== 'update')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$success -> $issuccess?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are a great code reviewer! Solved this in 24be51b

$issuccess = FALSE;
$error = 'Forbidden';
$status = 403;
}
if ($issuccess && variable_get('islandora_pathauto_trigger_type', '') !== 'receiving') {
$issuccess = FALSE;
$error = 'Forbidden';
$status = 403;
}
if ($issuccess && !$istest) {
$object = islandora_object_load($objectid);
if ($object) {
$result = islandora_pathauto_create_alias($object, $op);
if ($result == 0) {
$issuccess = FALSE;
$error = t('Could not !op alias for object !id.', array('!op' => $op, '!id' => $objectid));
$status = 400;
}
elseif ($result > 0) {
if ($op === 'insert') {
$message = t('Created new alias %alias for object %id.', array('%id' => $objectid, '%alias' => $result));
}
else {
$message = t('Updated alias %alias for object %id.', array('%id' => $objectid, '%alias' => $result));
}
}
}
else {
$issuccess = FALSE;
$error = t('Object "!id" not found', array('!id' => $objectid));
$status = 404;
}
}
$data = array('success' => $issuccess, 'test' => $istest);
if (isset($error)) {
$data['error'] = $error;
$data['success'] = FALSE;
}
elseif (isset($message)) {
$data['message'] = $message;
}
drupal_add_http_header('Status', $status);
drupal_add_http_header('Content-Type', 'application/json; utf-8');
if ($data !== NULL) {
print drupal_json_encode($data);
}
exit();
}