diff --git a/acquia_agent/acquia_agent.module b/acquia_agent/acquia_agent.module index df9ad52..7ea8712 100644 --- a/acquia_agent/acquia_agent.module +++ b/acquia_agent/acquia_agent.module @@ -549,6 +549,8 @@ function acquia_agent_help($path, $arg) { } $output .= '
' . t('Receive updates from Acquia Network') . '
'; $output .= '
' . t('Receive dynamic updates on the Network Settings page from Acquia.com about your subscription and new features.') . '
'; + $output .= '
' . t('Allow Insight to update list of approved variables') . '
'; + $output .= '
' . t('As part of the Acquia Insight service, some variables can be corrected to their recommended settings from within the Insight system. The list of variables that can be corrected can also be updated at your discretion.') . '
'; $output .= ''; return $output; } @@ -756,8 +758,12 @@ function acquia_agent_stream_context_create($url, $module = 'acquia_agent') { /** * Determine if a response from the Acquia Network is valid. * - * @param $data - * The data array returned by acquia_agent_call(). + * @param $data The data array returned by acquia_agent_call(). Expected keys: + * 'authenticator' - request authenticator sent to server + * 'result' - response from server including keys + * 'authenticator' - server response authenticator + * 'body' - server response body + * * @return * TRUE or FALSE. */ diff --git a/acquia_agent/tests/acquia_connector_test.module b/acquia_agent/tests/acquia_connector_test.module index 1c7584e..5256af9 100644 --- a/acquia_agent/tests/acquia_connector_test.module +++ b/acquia_agent/tests/acquia_connector_test.module @@ -294,17 +294,25 @@ function acquia_connector_test_nspi_update($data) { return FALSE; } else { + $result = acquia_connector_test_validate_authenticator($data); $spi_data = $data['body']; - if (!isset($spi_data['spi_data_version'])) { - $return_result = TRUE; + $result->body = array('spi_data_received' => TRUE); + if (isset($spi_data['spi_def_update'])) { + $result->body['update_spi_definition'] = TRUE; } - else { - $return_result = array('result' => TRUE); - if (isset($spi_data['spi_def_update'])) { - $return_result['update_spi_definition'] = TRUE; - } + + // Reflect send_method as nspi_messages if set. + if (isset($spi_data['send_method'])) { + $result->body['nspi_messages'][] = $spi_data['send_method']; + } + + $result->authenticator['hash'] = _acquia_agent_hmac($result->secret['key'], $result->authenticator['time'], $result->authenticator['nonce'], $result->body); + + if (isset($spi_data['test_validation_error'])) { + $result->authenticator['nonce'] = 'TEST'; // Force a validation fail. } - return $return_result; + unset($result->secret); + return $result; } } else { @@ -384,6 +392,7 @@ function acquia_connector_test_validate_authenticator($data) { $result->is_error = TRUE; return $result; } + if ($key === ACQTEST_EXPIRED_KEY) { $result->code = ACQTEST_SUBSCRIPTION_EXPIRED; $result->message = t('Subscription expired.'); diff --git a/acquia_spi/acquia_spi.install b/acquia_spi/acquia_spi.install index af22339..652ef4a 100644 --- a/acquia_spi/acquia_spi.install +++ b/acquia_spi/acquia_spi.install @@ -24,6 +24,10 @@ function acquia_spi_uninstall() { variable_del('acquia_spi_server'); variable_del('acquia_spi_ssl_override'); variable_del('acquia_spi_module_rebuild'); + variable_del('acquia_spi_set_variables_automatic'); + variable_del('acquia_spi_ignored_set_variables'); + variable_del('acquia_spi_saved_variables'); + variable_del('acquia_spi_set_variables_override'); } /** diff --git a/acquia_spi/acquia_spi.module b/acquia_spi/acquia_spi.module index 33c0231..84a3cc8 100644 --- a/acquia_spi/acquia_spi.module +++ b/acquia_spi/acquia_spi.module @@ -6,7 +6,7 @@ */ // Version of SPI data format. -define('ACQUIA_SPI_DATA_VERSION', '2.0'); +define('ACQUIA_SPI_DATA_VERSION', 2.1); /** * Identifiers for the method of sending SPI data. @@ -15,6 +15,7 @@ define('ACQUIA_SPI_METHOD_CALLBACK', 'menu'); define('ACQUIA_SPI_METHOD_CRON', 'cron'); define('ACQUIA_SPI_METHOD_DRUSH', 'drush'); define('ACQUIA_SPI_METHOD_CREDS', 'creds'); +define('ACQUIA_SPI_METHOD_INSIGHT', 'insight'); /** * Implementation of hook_help() @@ -129,7 +130,7 @@ function _acquia_spi_send_access() { $acquia_key = acquia_agent_settings('acquia_key'); if (!empty($acquia_key) && isset($_GET['key'])) { $key = sha1(drupal_get_private_key()); - if ($key == $_GET['key']) { + if ($key === $_GET['key']) { return TRUE; } } @@ -140,21 +141,39 @@ function _acquia_spi_send_access() { * Callback for sending SPI data. */ function _acquia_spi_send() { - $ret = acquia_spi_send_full_spi(ACQUIA_SPI_METHOD_CALLBACK); + $method = ACQUIA_SPI_METHOD_CALLBACK; + // Insight's set variable feature will pass method insight. + if (isset($_GET['method']) && $_GET['method'] === ACQUIA_SPI_METHOD_INSIGHT) { + $method =ACQUIA_SPI_METHOD_INSIGHT; + } + + $response = acquia_spi_send_full_spi($method); if (isset($_GET['destination'])) { - if ($ret) { - drupal_set_message(t('SPI data sent.')); + if (!empty($response)) { + if (isset($response['spi_data_received']) && $response['spi_data_received'] === TRUE) { + $message = t('SPI data sent.'); + } + if (!empty($response['nspi_messages'])) { + $message .= t(' Acquia Network returned the following messages:
'); + foreach ($response['nspi_messages'] as $nspi_message) { + $message .= check_plain($nspi_message) . '
'; + } + } + drupal_set_message($message); } else { - drupal_set_message(t('There was an error sending SPI data. Check the logs for error messages or contact Acquia Support.'), 'error'); + drupal_set_message(t('Error sending SPI data. Consult the logs for more information.'), 'error'); } drupal_goto(); } + if (!empty($response)) { + if (!isset($response['spi_data_received']) || $response['spi_data_received'] !== TRUE) { + drupal_add_http_header('Status', '404 Not Found'); + } + } // If destination was not sent the call is via cron so close request and exit. - module_invoke_all('exit'); - print ''; - exit; + drupal_exit(); } /** @@ -261,6 +280,12 @@ function acquia_spi_form_acquia_agent_settings_form_alter(&$form) { '#description' => t('Source code analysis requires a SSL connection and for your site to be publicly accessible. Learn more.', array('!url' => $help_url)), '#disabled' => !$ssl_available, ); + $form['connection']['alter_variables'] = array( + '#type' => 'checkbox', + '#title' => t('Allow Insight to update list of approved variables'), + '#default_value' => (int) variable_get('acquia_spi_set_variables_override', 0), + '#description' => t('Insight can set variables on your site to recommended values at your approval, but only from a specific list of variables. Check this box to allow Insight to update the list of approved variables. Learn more.', array('!url' => $help_url)), + ); $use_cron = variable_get('acquia_spi_use_cron', 1); $form['connection']['spi_use_cron'] = array( @@ -308,6 +333,7 @@ function acquia_agent_spi_set_submit($form, &$form_state) { variable_set('acquia_spi_send_node_user', $form_state['values']['send_node_user']); variable_set('acquia_spi_send_watchdog', $form_state['values']['send_watchdog']); variable_set('acquia_spi_use_cron', $form_state['values']['spi_use_cron']); + variable_set('acquia_spi_set_variables_override', $form_state['values']['alter_variables']); } /** @@ -397,29 +423,39 @@ function acquia_spi_update_definition() { */ function acquia_spi_send_full_spi($method = '') { $spi = acquia_spi_get(); - if ($spi) { - if (!empty($method)) { - $spi['send_method'] = $method; - } - $result = acquia_spi_send_data($spi); - acquia_spi_handle_server_response($result); - variable_set('acquia_spi_cron_last', REQUEST_TIME); - return $result['result']; + if (!empty($method)) { + $spi['send_method'] = $method; } - return FALSE; + $result = acquia_spi_send_data($spi); + if ($result === FALSE) { + return FALSE; + } + acquia_spi_handle_server_response($result); + variable_set('acquia_spi_cron_last', REQUEST_TIME); + return $result; } /** - * Act on SPI update server response. + * Act on specific elements of SPI update server response. * * @param array $spi_response Array response from acquia_spi_send_data(). */ function acquia_spi_handle_server_response($spi_response) { // Check result for command to update SPI definition. - $update = isset($spi_response['result']['update_spi_definition']) ? $spi_response['result']['update_spi_definition'] : FALSE; + $update = isset($spi_response['update_spi_definition']) ? $spi_response['update_spi_definition'] : FALSE; if ($update === TRUE) { acquia_spi_update_definition(); } + // Check for set_variables command. + $set_variables = isset($spi_response['set_variables']) ? $spi_response['set_variables'] : FALSE; + if ($set_variables !== FALSE) { + acquia_spi_set_variables($set_variables); + } + // Log messages. + $messages = isset($spi_response['nspi_messages']) ? $spi_response['nspi_messages'] : FALSE; + if ($messages !== FALSE) { + watchdog('acquia spi', 'SPI update server response messages: @messages', array('@messages' => implode(', ', $messages))); + } } /** @@ -430,21 +466,31 @@ function acquia_spi_handle_server_response($spi_response) { * @param array $spi SPI data. Required parameters: * 'site_key' A SHA1 hash of the Drupal private key. * 'spi_data_version' + * @see acquia_spi_get(). * * Note, acquia_agent will add authenticator. - * @return mixed FALSE if no credentials to send else full NSPI response array. + * @return mixed FALSE if no credentials or validation error else full + * NSPI response array. */ function acquia_spi_send_data($spi) { // Do nothing unless we have credentials. - if (acquia_agent_has_credentials()) { - // acquia_agent_network_address() sets remote server protocol. - $nspi_server = variable_get('acquia_spi_server', 'https://nspi.acquia.com'); - // Specify version 3 of the RPC, which ommits request parameters in the HMAC. - $spi['rpc_version'] = 3; - $result = acquia_agent_call('acquia.nspi.update', $spi, NULL, NULL, $nspi_server); - return $result; + if (!acquia_agent_has_credentials()) { + watchdog('acquia spi', 'Connect your site to a valid subscription on the Acquia Network to send SPI data', array(), WATCHDOG_ERROR); + return FALSE; } - return FALSE; + // acquia_agent_network_address() sets remote server protocol. + $nspi_server = variable_get('acquia_spi_server', 'https://nspi.acquia.com'); + // Specify version 3 of the RPC, which ommits request parameters in the HMAC. + $spi['rpc_version'] = 3; + $response = acquia_agent_call('acquia.nspi.update', $spi, NULL, NULL, $nspi_server); + // Validate the server response. + if (!acquia_agent_valid_response($response, acquia_agent_settings('acquia_key'))) { + // Acquia Agent will have logged error. + return FALSE; + } + // $response contains request authenticator as well as server authenticator + // under 'result' element so return just the server response 'body' element. + return $response['result']['body']; } /** @@ -865,7 +911,7 @@ function acquai_spi_get_404s() { function acquia_spi_get_variables_data() { global $conf; $data = array(); - $variables = array('acquia_spi_send_node_user', 'acquia_spi_admin_priv', 'acquia_spi_module_diff_data', 'acquia_spi_send_watchdog', 'acquia_spi_use_cron', 'cache_backends', 'cache_default_class', 'cache_inc', 'cron_safe_threshold', 'googleanalytics_cache', 'error_level', 'preprocess_js', 'page_cache_maximum_age', 'block_cache', 'preprocess_css', 'page_compression', 'cache', 'cache_lifetime', 'cron_last', 'clean_url', 'redirect_global_clean', 'theme_zen_settings', 'site_offline', 'site_name', 'user_register', 'user_signatures', 'user_admin_role', 'user_email_verification', 'user_cancel_method', 'filter_fallback_format', 'dblog_row_limit', 'date_default_timezone', 'file_default_scheme', 'install_profile', 'maintenance_mode', 'update_last_check', 'site_default_country'); + $variables = array('acquia_spi_send_node_user', 'acquia_spi_admin_priv', 'acquia_spi_module_diff_data', 'acquia_spi_send_watchdog', 'acquia_spi_use_cron', 'cache_backends', 'cache_default_class', 'cache_inc', 'cron_safe_threshold', 'googleanalytics_cache', 'error_level', 'preprocess_js', 'page_cache_maximum_age', 'block_cache', 'preprocess_css', 'page_compression', 'cache', 'cache_lifetime', 'cron_last', 'clean_url', 'redirect_global_clean', 'theme_zen_settings', 'site_offline', 'site_name', 'user_register', 'user_signatures', 'user_admin_role', 'user_email_verification', 'user_cancel_method', 'filter_fallback_format', 'dblog_row_limit', 'date_default_timezone', 'file_default_scheme', 'install_profile', 'maintenance_mode', 'update_last_check', 'site_default_country', 'acquia_spi_saved_variables', 'acquia_spi_set_variables_automatic', 'acquia_spi_ignored_set_variables', 'acquia_spi_set_variables_override'); $spi_def_vars = variable_get('acquia_spi_def_vars', array()); $waived_spi_def_vars = variable_get('acquia_spi_def_waived_vars', array()); // Merge hard coded $variables with vars from SPI definition. @@ -1420,3 +1466,42 @@ function acquia_spi_hash_path($path = '') { } return $hash; } + +/** + * Set variables from NSPI response. + * + * @param array $set_variables Variables to be set. + * @return NULL + */ +function acquia_spi_set_variables($set_variables) { + if (empty($set_variables)) { + return; + } + $saved = array(); + $ignored = variable_get('acquia_spi_ignored_set_variables', array()); + + if (!variable_get('acquia_spi_set_variables_override', 0)) { + $ignored[] = 'acquia_spi_set_variables_automatic'; + } + // Some variables can never be set. + $ignored = array_merge($ignored, array('drupal_private_key', 'site_mail', 'site_name', 'maintenance_mode', 'user_register')); + // Variables that can be automatically set. + $whitelist = acquia_spi_approved_set_variables(); + foreach($set_variables as $key => $value) { + // Approved variables get set immediately unless ignored. + if (in_array($key, $whitelist) && !in_array($key, $ignored)) { + $saved[] = $key; + variable_set($key, $value); + } + } + variable_set('acquia_spi_saved_variables', array('variables' => $saved, 'time' => time())); +} + +/** + * Variables that can be automatically set by the NSPI set variables command. + * + * @return array Array of variable names. + */ +function acquia_spi_approved_set_variables() { + return variable_get('acquia_spi_set_variables_automatic', array('acquia_spi_set_variables_automatic', 'error_level', 'preprocess_js', 'page_cache_maximum_age', 'block_cache', 'preprocess_css', 'page_compression', 'cache', 'cache_lifetime')); +} diff --git a/acquia_spi/tests/acquia_spi.test b/acquia_spi/tests/acquia_spi.test index 6e9b4b8..0401fc2 100644 --- a/acquia_spi/tests/acquia_spi.test +++ b/acquia_spi/tests/acquia_spi.test @@ -80,13 +80,13 @@ class AcquiaSPITestCase extends DrupalWebTestCase { case 'spi-data-sent': return 'SPI data sent'; case 'spi-data-sent-error': - return 'There was an error sending SPI data'; + return 'Error sending SPI data. Consult the logs for more information.'; case 'spi-new-def': return 'There are new checks that will be performed on your site by the Acquia Network Connector'; } } - public function testAcquiaSPISendData() { + public function testAcquiaSPIUI() { $this->drupalGet($this->status_report_url); $this->assertNoText($this->acquiaSPIStrings('spi-status-text'), 'SPI send option does not exist when site is not connected'); // Connect site on key and id that will error. @@ -104,12 +104,7 @@ class AcquiaSPITestCase extends DrupalWebTestCase { $this->assertText($this->acquiaSPIStrings('spi-data-sent-error'), 'Page says there was an error sending data'); // Connect site on non-error key and id. - $this->drupalGet($this->credentials_path); - $edit_fields = array( - 'acquia_identifier' => ACQTEST_ID, - 'acquia_key' => ACQTEST_KEY, - ); - $this->drupalPost($this->credentials_path, $edit_fields, $submit_button); + $this->connectSite(); // Send SPI data. $this->drupalGet($this->status_report_url); $this->clickLink($this->acquiaSPIStrings('spi-send-text')); @@ -129,7 +124,6 @@ class AcquiaSPITestCase extends DrupalWebTestCase { $this->drupalGet('/node'); // Platform data should have been written. $stored = acquia_spi_data_store_get(array('platform')); - $this->pass(var_export($stored, TRUE)); $diff = array_diff(array_keys($stored['platform']), $this->platformKeys); $this->assertTrue(empty($diff), 'Platform element contains expected keys'); } @@ -170,52 +164,124 @@ class AcquiaSPITestCase extends DrupalWebTestCase { } } - public function testAcquiaSPIUpdateResponse() { - $this->drupalGet($this->credentials_path); + public function testAcquiaSPISend() { + // Connect site on invalid credentials. $edit_fields = array( - 'acquia_identifier' => ACQTEST_ID, - 'acquia_key' => ACQTEST_KEY, + 'acquia_identifier' => ACQTEST_ERROR_ID, + 'acquia_key' => ACQTEST_ERROR_KEY, ); $submit_button = 'Connect'; $this->drupalPost($this->credentials_path, $edit_fields, $submit_button); - $nspi_server = variable_get('acquia_spi_server', 'https://nspi.acquia.com'); + // Attempt to send something. + $result = acquia_spi_send_data(array()); + $this->assertFalse($result, 'acquia_spi_send_data returns false when not connected.'); + + // Connect site on valid credentials. + $this->connectSite(); + $spi_data = acquia_spi_get(); // Check that result is an array. - $result = acquia_agent_call('acquia.nspi.update', $spi_data, NULL, NULL, $nspi_server); - $this->assertTrue(is_array($result['result']), 'SPI update result is an array'); + $result = acquia_spi_send_data($spi_data); + $this->assertTrue(is_array($result), 'SPI update result is an array'); - // Check that result is a bool when spi_data_version is not sent. - $spi_data_version = $spi_data['spi_data_version']; - unset($spi_data['spi_data_version']); - $result = acquia_agent_call('acquia.nspi.update', $spi_data, NULL, NULL, $nspi_server); - $this->assertTrue(is_bool($result['result']), 'SPI update result is a boolean when not sending "spi_data_version"'); + // Trigger a validation error on response. + $spi_data['test_validation_error'] = TRUE; + $result = acquia_spi_send_data($spi_data); + $this->assertFalse($result, 'SPI result is false if validation error.'); + unset($spi_data['test_validation_error']); - $spi_data['spi_data_version'] = $spi_data_version; // Trigger a SPI definition update response. $spi_data['spi_def_update'] = TRUE; - $result = acquia_agent_call('acquia.nspi.update', $spi_data, NULL, NULL, $nspi_server); - $result = $result['result']; - $this->assertTrue(!empty($result['result']), 'SPI result array has expected "result" key.'); + $result = acquia_spi_send_data($spi_data); $this->assertTrue(!empty($result['update_spi_definition']), 'SPI result array has expected "update_spi_definition" key.'); + } + + public function testAcquiaSPIUpdateResponse() { $def_timestamp = variable_get('acquia_spi_def_timestamp', 0); $this->assertEqual($def_timestamp, 0, 'SPI definition has not been called before'); $def_vars = variable_get('acquia_spi_def_vars', array()); $this->assertTrue(empty($def_vars), 'SPI definition variables is empty'); $waived_vars = variable_get('acquia_spi_def_waived_vars', array()); $this->assertTrue(empty($waived_vars), 'SPI definition waived variables is empty'); - if (!empty($result['update_spi_definition']) && function_exists('acquia_spi_update_definition')) { - $update_res = acquia_spi_update_definition(); - $this->assertTrue($update_res, 'Update definition call returned true'); - $def_timestamp = variable_get('acquia_spi_def_timestamp', 0); - $this->assertNotEqual($def_timestamp, 0, 'SPI definition timestamp set'); - $def_vars = variable_get('acquia_spi_def_vars', array()); - $this->assertTrue(!empty($def_vars), 'SPI definition variable set'); - variable_set('acquia_spi_def_waived_vars', array('user_admin_role')); - // Test that new variables are in SPI data. - $spi_data = acquia_spi_get(); - $vars = drupal_json_decode($spi_data['system_vars']); - $this->assertTrue(!empty($vars['file_temporary_path']), 'New variables included in SPI data'); - $this->assertTrue(!isset($vars['user_admin_role']), 'user_admin_role not included in SPI data'); - } + $update_res = acquia_spi_update_definition(); + $this->assertTrue($update_res, 'Update definition call returned true'); + $def_timestamp = variable_get('acquia_spi_def_timestamp', 0); + $this->assertNotEqual($def_timestamp, 0, 'SPI definition timestamp set'); + $def_vars = variable_get('acquia_spi_def_vars', array()); + $this->assertTrue(!empty($def_vars), 'SPI definition variable set'); + variable_set('acquia_spi_def_waived_vars', array('user_admin_role')); + // Test that new variables are in SPI data. + $spi_data = acquia_spi_get(); + $vars = drupal_json_decode($spi_data['system_vars']); + $this->assertTrue(!empty($vars['file_temporary_path']), 'New variables included in SPI data'); + $this->assertTrue(!isset($vars['user_admin_role']), 'user_admin_role not included in SPI data'); + } + + public function testAcquiaSPIMessages() { + $this->connectSite(); + + $spi_data = acquia_spi_get(); + $response = acquia_spi_send_data($spi_data); + $this->assertTrue(!isset($response['nspi_messages']), 'No NSPI messages when send_method not set'); + + $method = $this->randomString(); + $spi_data['send_method'] = $method; + $response = acquia_spi_send_data($spi_data); + $this->assertIdentical($response['nspi_messages'][0], $method, 'NSPI messages when send_method is set'); + + $this->drupalGet($this->status_report_url); + $this->clickLink($this->acquiaSPIStrings('spi-send-text')); + $this->assertText(ACQUIA_SPI_METHOD_CALLBACK, 'NSPI messages printed on status page'); + } + + public function testAcquiaSPISetVariables() { + $spi_data = acquia_spi_get(); + $vars = drupal_json_decode($spi_data['system_vars']); + $this->assertTrue(empty($vars['acquia_spi_saved_variables']), 'Have not saved any variables'); + // Set error reporting so variable is saved. + $edit = array( + 'error_level' => 2, + ); + $this->drupalPost('admin/config/development/logging', $edit, 'Save configuration'); + + // Turn off error reporting. + $set_variables = array('error_level' => 0); + acquia_spi_set_variables($set_variables); + $new = variable_get('error_level', '2'); + $this->assertTrue($new === 0, 'Set error reporting to log only'); + $vars = drupal_json_decode(acquia_spi_get_variables_data()); + $this->assertTrue(in_array('error_level', $vars['acquia_spi_saved_variables']['variables']), 'SPI data reports error level was saved'); + $this->assertTrue(isset($vars['acquia_spi_saved_variables']['time']), 'Set time for saved variables'); + // Attemp to set variable that is not whitelisted. + $current = variable_get('clean_url', 'test'); + $set_variables = array('clean_url' => 0); + acquia_spi_set_variables($set_variables); + $after = variable_get('clean_url', 'set'); + $this->assertIdentical($current, $after, 'Non-whitelisted variable cannot be automatically set'); + $vars = drupal_json_decode(acquia_spi_get_variables_data()); + $this->assertFalse(in_array('clean_url', $vars['acquia_spi_saved_variables']['variables']), 'SPI data does not include anything about trying to save clean url'); + + // Test override of approved variable list. + $set_variables = array('acquia_spi_set_variables_automatic' => array('test_variable')); + acquia_spi_set_variables($set_variables); + $vars = drupal_json_decode(acquia_spi_get_variables_data()); + $this->assertFalse(isset($vars['acquia_spi_set_variables_automatic']), 'Using default list of approved list of variables'); + variable_set('acquia_spi_set_variables_override', 1); + $set_variables = array('acquia_spi_set_variables_automatic' => array('test_variable')); + acquia_spi_set_variables($set_variables); + $vars = drupal_json_decode(acquia_spi_get_variables_data()); + $this->assertIdentical($vars['acquia_spi_set_variables_automatic'], array('test_variable'), 'Altered approved list of variables that can be set'); + } + + /** + * Helper function connects to valid subscription. + */ + protected function connectSite() { + $edit_fields = array( + 'acquia_identifier' => ACQTEST_ID, + 'acquia_key' => ACQTEST_KEY, + ); + $submit_button = 'Connect'; + $this->drupalPost($this->credentials_path, $edit_fields, $submit_button); } }