Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save serundeputy/49310f7b51fde4b8d02ad89b342a0824 to your computer and use it in GitHub Desktop.
Save serundeputy/49310f7b51fde4b8d02ad89b342a0824 to your computer and use it in GitHub Desktop.
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