Created
March 31, 2017 23:44
-
-
Save serundeputy/49310f7b51fde4b8d02ad89b342a0824 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/bakery.install b/bakery.install | |
index 8207f26..16610a3 100644 | |
--- a/bakery.install | |
+++ b/bakery.install | |
@@ -52,4 +52,13 @@ function bakery_uninstall() { | |
variable_del('bakery_help_text'); | |
variable_del('bakery_freshness'); | |
variable_del('bakery_cookie_extension'); | |
+ variable_del('bakery_subsite_login'); | |
+} | |
+ | |
+/** | |
+ * Keep legacy support for subsite log in & registration. Disabling this | |
+ * deprecated feature is recommended. | |
+ */ | |
+function bakery_update_7001() { | |
+ variable_set('bakery_subsite_login', 1); | |
} | |
diff --git a/bakery.module b/bakery.module | |
index f3688b4..de66a31 100644 | |
--- a/bakery.module | |
+++ b/bakery.module | |
@@ -20,24 +20,20 @@ function bakery_menu() { | |
); | |
if (variable_get('bakery_is_master', 0)) { | |
- $items['bakery'] = array( | |
- 'title' => 'Register', | |
- 'access callback' => 'user_is_anonymous', | |
- 'page callback' => 'bakery_register', | |
- 'type' => MENU_CALLBACK, | |
- ); | |
- $items['bakery/login'] = array( | |
- 'title' => 'Login', | |
- 'access callback' => 'user_is_anonymous', | |
- 'page callback' => 'bakery_login', | |
- 'type' => MENU_CALLBACK, | |
- ); | |
- $items['bakery/validate'] = array( | |
- 'title' => 'Validate', | |
- 'access callback' => 'bakery_taste_thinmint_cookie', | |
- 'page callback' => 'bakery_eat_thinmint_cookie', | |
- 'type' => MENU_CALLBACK, | |
- ); | |
+ if (variable_get('bakery_subsite_login', 0)) { | |
+ $items['bakery'] = array( | |
+ 'title' => 'Register', | |
+ 'access callback' => 'user_is_anonymous', | |
+ 'page callback' => 'bakery_register', | |
+ 'type' => MENU_CALLBACK, | |
+ ); | |
+ $items['bakery/login'] = array( | |
+ 'title' => 'Login', | |
+ 'access callback' => 'user_is_anonymous', | |
+ 'page callback' => 'bakery_login', | |
+ 'type' => MENU_CALLBACK, | |
+ ); | |
+ } | |
$items['bakery/create'] = array( | |
'title' => 'Bakery create', | |
'access callback' => 'bakery_taste_gingerbread_cookie', | |
@@ -46,18 +42,20 @@ function bakery_menu() { | |
); | |
} | |
else { | |
- $items['bakery'] = array( | |
- 'title' => 'Register', | |
- 'access callback' => TRUE, | |
- 'page callback' => 'bakery_register_return', | |
- 'type' => MENU_CALLBACK, | |
- ); | |
- $items['bakery/login'] = array( | |
- 'title' => 'Login', | |
- 'access callback' => TRUE, | |
- 'page callback' => 'bakery_login_return', | |
- 'type' => MENU_CALLBACK, | |
- ); | |
+ if (variable_get('bakery_subsite_login', 0)) { | |
+ $items['bakery'] = array( | |
+ 'title' => 'Register', | |
+ 'access callback' => TRUE, | |
+ 'page callback' => 'bakery_register_return', | |
+ 'type' => MENU_CALLBACK, | |
+ ); | |
+ $items['bakery/login'] = array( | |
+ 'title' => 'Login', | |
+ 'access callback' => TRUE, | |
+ 'page callback' => 'bakery_login_return', | |
+ 'type' => MENU_CALLBACK, | |
+ ); | |
+ } | |
$items['bakery/update'] = array( | |
'title' => 'Update', | |
'access callback' => 'bakery_taste_stroopwafel_cookie', | |
@@ -307,8 +305,11 @@ function bakery_form_alter(&$form, $form_state, $form_id) { | |
break; | |
case 'user_register_form': | |
- // Provide register ability on the slave sites. | |
- if (!variable_get('bakery_is_master', FALSE)) { | |
+ if (variable_get('bakery_is_master', FALSE)) { | |
+ $form['#submit'][] = '_bakery_login_redirect'; | |
+ } | |
+ else { | |
+ // Provide register ability on the slave sites. | |
if (arg(0) == 'admin') { | |
// Admin create user form. Add a note about account synchronization. | |
$form['account']['bakery_help'] = array( | |
@@ -319,7 +320,7 @@ function bakery_form_alter(&$form, $form_state, $form_id) { | |
'#weight' => -100, | |
); | |
} | |
- else { | |
+ elseif (variable_get('bakery_subsite_login', 0)) { | |
// Anonymous user registration form. | |
// Populate fields if set from previous attempt. | |
if (isset($_SESSION['bakery']['register'])) { | |
@@ -330,6 +331,15 @@ function bakery_form_alter(&$form, $form_state, $form_id) { | |
// Replace the submit handler with our own. | |
$form['#submit'] = array('_bakery_register_submit'); | |
} | |
+ else { | |
+ $query = array(); | |
+ if (isset($_GET['destination']) && !url_is_external($_GET['destination'])) { | |
+ $query['bd'] = url($_GET['destination'], array('absolute' => TRUE)); | |
+ // Do not let drupal_goto() use the destination. | |
+ unset($_GET['destination']); | |
+ } | |
+ drupal_goto(variable_get('bakery_master', 'http://drupal.org/') . 'user/register', array('query' => $query)); | |
+ } | |
} | |
break; | |
@@ -341,33 +351,61 @@ function bakery_form_alter(&$form, $form_state, $form_id) { | |
} | |
break; | |
- case 'user_pass_reset': | |
- // As part of the slave site registration we need to handle email | |
- // validation and password reset. | |
- if (!variable_get('bakery_is_master', FALSE)) { | |
- // Set a submit handler for the psuedo-reset form. | |
- $form['#submit'] = array('_bakery_reset_submit'); | |
- // Unset its custom action. | |
- unset($form['#action']); | |
- } | |
- break; | |
- | |
case 'user_login_block': | |
+ // If this is a subsite, and subsite login is disabled, remove the login | |
+ // form. | |
+ if (!variable_get('bakery_is_master', FALSE) && !variable_get('bakery_subsite_login', 0)) { | |
+ $form['name']['#access'] = FALSE; | |
+ $form['pass']['#access'] = FALSE; | |
+ $form['actions']['#access'] = FALSE; | |
+ break; | |
+ } | |
case 'user_login': | |
- // Provide login ability on the slave sites. | |
- if (!variable_get('bakery_is_master', FALSE)) { | |
- // Replace two validators from user module because they log the user in | |
- // and test if account exists. We want to check if the account exists on | |
- // the master instead. | |
- $form['#validate'] = array_diff($form['#validate'], array('user_login_authenticate_validate', 'user_login_final_validate')); | |
- // Replace the submit handler with our own to set a redirect cookie. | |
- $form['#submit'] = array('_bakery_login_submit'); | |
+ if (variable_get('bakery_is_master', FALSE)) { | |
+ // Use both validate and submit, in case other modules like TFA are | |
+ // also altering the login process. | |
+ $form['#validate'][] = '_bakery_login_redirect'; | |
+ $form['#submit'][] = '_bakery_login_redirect'; | |
+ } | |
+ else { | |
+ // Only process login on subsites if enabled, or if this is bakery | |
+ // logging the user in from bakery_user_external_login(). | |
+ if (variable_get('bakery_subsite_login', 0) || (isset($form_state['build_info']['args'][0]) && $form_state['build_info']['args'][0] === 'via_bakery')) { | |
+ // Replace two validators from user module because they log the user in | |
+ // and test if account exists. We want to check if the account exists on | |
+ // the master instead. | |
+ $form['#validate'] = array_diff($form['#validate'], array('user_login_authenticate_validate', 'user_login_final_validate')); | |
+ // Replace the submit handler with our own to set a redirect cookie. | |
+ $form['#submit'] = array('_bakery_login_submit'); | |
+ } | |
+ else { | |
+ $query = array(); | |
+ if (isset($_GET['destination']) && !url_is_external($_GET['destination'])) { | |
+ $query['bd'] = url($_GET['destination'], array('absolute' => TRUE)); | |
+ // Do not let drupal_goto() use the destination. | |
+ unset($_GET['destination']); | |
+ } | |
+ drupal_goto(variable_get('bakery_master', 'http://drupal.org/') . 'user', array('query' => $query)); | |
+ } | |
} | |
break; | |
+ } | |
+} | |
- default: | |
- break; | |
+/** | |
+ * Get the bakery destination from the bd query parameter, if set. | |
+ */ | |
+function bakery_get_destination() { | |
+ $parameters = drupal_get_query_parameters(); | |
+ | |
+ if (isset($parameters['bd']) && $parameters['bd'] === drupal_strip_dangerous_protocols($parameters['bd'])) { | |
+ foreach (variable_get('bakery_slaves', array()) as $subsite) { | |
+ if (strpos($parameters['bd'], $subsite) === 0) { | |
+ return $parameters['bd']; | |
+ } | |
+ } | |
} | |
+ return FALSE; | |
} | |
/** | |
@@ -391,63 +429,6 @@ function _bakery_pass_validate($form, &$form_state) { | |
} | |
/** | |
- * Submit handler for the password reset form. | |
- */ | |
-function _bakery_reset_submit($form, &$form_state) { | |
- global $base_url; | |
- | |
- // If we're here it means the user has validated their email correctly. | |
- $master = variable_get('bakery_master', 'http://drupal.org/'); | |
- $key = variable_get('bakery_key', ''); | |
- // It's safe to use arg(2) here to load the user and log in because the | |
- // callback has validated the request and Drupal's Form API protects us | |
- // against forgery. | |
- $account = user_load(arg(2)); | |
- // If they have not logged in before we need to update the master site. | |
- if ($account->login == 0) { | |
- $type = 'thinmint'; | |
- $payload = array(); | |
- $payload['name'] = $account->name; | |
- // Match how slaves are set on the master. | |
- $payload['slave'] = rtrim($base_url, '/') . '/'; | |
- $payload['uid'] = $account->uid; | |
- $payload['timestamp'] = $_SERVER['REQUEST_TIME']; | |
- $payload['type'] = $type; | |
- $data = bakery_bake_data($payload); | |
- $payload = drupal_http_build_query(array($type => $data)); | |
- // Push validation to master. | |
- $http_options = array( | |
- 'method' => 'POST', | |
- 'data' => $payload, | |
- 'headers' => array( | |
- 'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8', | |
- ), | |
- ); | |
- $result = drupal_http_request($master . 'bakery/validate', $http_options); | |
- } | |
- | |
- // If they have logged in before or the master updated correctly, log them in. | |
- if ($account->login > 0 || $result->code == 200) { | |
- // Log the user in. | |
- $init = _bakery_init_field($account->uid); | |
- _bakery_bake_chocolatechip_cookie($account->name, $account->mail, $init); | |
- global $user; | |
- $user = $account; | |
- $edit = array('name' => $user->name); | |
- bakery_user_authenticate_finalize($edit); | |
- // Inform them that they need to reset their password. | |
- drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password at <a href="!url">@master</a>.', array( | |
- '!url' => check_url(_bakery_init_field_url($user->init)), | |
- '@master' => variable_get('bakery_master', ''), | |
- ))); | |
- drupal_goto('user/' . $user->uid); | |
- } | |
- else { | |
- drupal_goto('user/login'); | |
- } | |
-} | |
- | |
-/** | |
* Check if a form destination is set and save it in $data array. | |
* | |
* Used to preserve destination in Bakery redirection to master and slave | |
@@ -526,6 +507,15 @@ function _bakery_login_submit($form, &$form_state) { | |
} | |
/** | |
+ * Redirect back to a subsite after login. | |
+ */ | |
+function _bakery_login_redirect($form, &$form_state) { | |
+ if ($bd = bakery_get_destination()) { | |
+ $form_state['redirect'] = $bd; | |
+ } | |
+} | |
+ | |
+/** | |
* Bakery settings form. | |
*/ | |
function bakery_settings($form, &$form_state) { | |
@@ -537,7 +527,18 @@ function bakery_settings($form, &$form_state) { | |
'#type' => 'checkbox', | |
'#title' => 'Is this the master site?', | |
'#default_value' => variable_get('bakery_is_master', 0), | |
- '#description' => t('On the master site, accounts need to be created by traditional processes, i.e by a user registering or an admin creating them.'), | |
+ '#description' => t('On the master site, accounts are created by traditional processes, i.e by a user registering or an admin creating them.'), | |
+ ); | |
+ | |
+ $form['bakery_subsite_login'] = array( | |
+ '#type' => 'radios', | |
+ '#title' => t('Subsite log in & registration'), | |
+ '#options' => array( | |
+ 0 => t('Only log in & register on master site'), | |
+ 1 => t('Allow log in & register on any site (deprecated)'), | |
+ ), | |
+ '#default_value' => variable_get('bakery_subsite_login', 0), | |
+ '#description' => t('Limiting log ins and registration to the master site gives users a consistent experience and reduces the surface area available to attackers.'), | |
); | |
$form['bakery_master'] = array( | |
@@ -1060,11 +1061,21 @@ function _bakery_taste_chocolatechip_cookie() { | |
} | |
if (variable_get('bakery_is_master', 0)) { | |
- // Bake a fresh cookie. Yum. | |
- _bakery_bake_chocolatechip_cookie($cookie['name'], $cookie['mail'], $cookie['init']); | |
+ if ($user->uid || variable_get('bakery_subsite_login', 0)) { | |
+ // User is logged in or acquired a chocolatechip cookie from a subsite. | |
+ // Bake a fresh cookie. Yum. | |
+ _bakery_bake_chocolatechip_cookie($cookie['name'], $cookie['mail'], $cookie['init']); | |
+ } | |
+ else { | |
+ // User is not logged in and couldn't have logged in from a subsite, | |
+ // destroy their cookie. | |
+ $destroy_cookie = TRUE; | |
+ } | |
} | |
- if (!$user->uid) { | |
+ // If the user is not logged in and their cookie is not marked for | |
+ // destruction. | |
+ if (!$user->uid && !$destroy_cookie) { | |
// Since this might happen in hook_boot we need to bootstrap first. | |
// Note that this only runs if they have a valid session on the master | |
// and do not have one on the slave so it only creates the extra load of | |
@@ -1385,45 +1396,6 @@ function bakery_eat_stroopwafel_cookie() { | |
} | |
/** | |
- * Verify the validation request. | |
- */ | |
-function bakery_taste_thinmint_cookie() { | |
- $type = 'thinmint'; | |
- if (empty($_POST[$type])) { | |
- return FALSE; | |
- } | |
- if (($cookie = bakery_validate_data($_POST[$type], $type)) === FALSE) { | |
- return FALSE; | |
- } | |
- $_SESSION['bakery']['name'] = $cookie['name']; | |
- $_SESSION['bakery']['slave'] = $cookie['slave']; | |
- $_SESSION['bakery']['uid'] = $cookie['uid']; | |
- return TRUE; | |
-} | |
- | |
-/** | |
- * Update the user's login time to reflect them validating their email address. | |
- */ | |
-function bakery_eat_thinmint_cookie() { | |
- // Session was set in validate. | |
- $name = $_SESSION['bakery']['name']; | |
- unset($_SESSION['bakery']['name']); | |
- $slave = $_SESSION['bakery']['slave']; | |
- unset($_SESSION['bakery']['slave']); | |
- $uid = $_SESSION['bakery']['uid']; | |
- unset($_SESSION['bakery']['uid']); | |
- | |
- $account = user_load_by_name($name); | |
- if ($account) { | |
- // @todo | |
- db_query("UPDATE {users} SET login = :login WHERE uid = :uid", array(':login' => $_SERVER['REQUEST_TIME'], ':uid' => $account->uid)); | |
- | |
- // Save UID provided by slave site. | |
- _bakery_save_slave_uid($account, $slave, $uid); | |
- } | |
-} | |
- | |
-/** | |
* Request account information from master to create account locally. | |
* | |
* @param string $name | |
@@ -1696,7 +1668,7 @@ function bakery_decrypt($text) { | |
* TRUE if the login succeeds, FALSE otherwise. | |
*/ | |
function bakery_user_external_login($account, $edit = array()) { | |
- $form = drupal_get_form('user_login'); | |
+ $form = drupal_get_form('user_login', 'via_bakery'); | |
$state['values'] = $edit; | |
if (empty($state['values']['name'])) { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment