Problem:
When a user is invited, a hash url is generated and sent to their email address.
The user clicks this link and it sends them to the user/register interface.
The user fills out this form, and then has to go back to their email to confirm their email address again.
Isn't it enough to verify their email through the invite URL?

My suggested fix (and I'll be willing to submit a patch if there is agreement) that the invite URL should redirect to a custom menu callback to register the user.

This page would simply be a form asking the user to enter a username and password to continue. It would then create the account and log them in immediately using the hash verified email address, username, and password.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

smk-ka’s picture

Status: Active » Needs review
FileSize
936 bytes

Actually the user is already unblocked by the invite module, which would normally be done by clicking the activation link in the second email. So, if I'm not wrong, all we have do is to prevent getting the activation email sent. This could be done by temporarily switching email verification off in hook_user(). I've attached a patch but didn't test it for now.

zirafa’s picture

Patch works for me, I added an additional line that automatically logs the user in as well, redirects to user/$uid/edit with a message that they need to change their password.

Patched against 5.x-1.9, I can reroll against HEAD.

Farsheed

smk-ka’s picture

FileSize
2.14 KB

This doesn't work, as we're bailing out in the middle of user_save(). Look in user.module for user_module_invoke('insert', ...) -- everything after that line is lost because we'll never return...

The only real way seems to put the password field back in the register form. This is what I've tried in the new patch, email verification is now (temporarily) switched off before user_register_submit() is processed. Tricked this way, it stores the entered password, still sends the welcome email (which is good IMO) and finally logs the user in.

The only thing that bothers me is the way it's done: if a third party module also modifies the register form's #submit property and (for example) inserts its own handler (and therefore removes ours), then the user enters a password but it won't be saved -- which is bad.

An alternative (and possibly cleaner) way to achieve the same result could be checking in hook_init() if the session variable is set && we're at user/register then switch email verification off. That way we could get rid of the fragile #submit handler stuff.

Note: this is against DRUPAL-5 branch. Tested, seems to work.

smk-ka’s picture

FileSize
791 bytes

Just implemented the alternative way and it turns out to look like the very first patch, no more form_alter no submit handler fuzz. Seems to work fine, too. IMO this is the way to go, what do you think?

zirafa’s picture

Interesting. I don't quite understand what you mean by "This doesn't work, as we're bailing out in the middle of user_save(). Look in user.module for user_module_invoke('insert', ...) -- everything after that line is lost because we'll never return..."

How are we bailing out in the middle?

Haven't had a chance to test the other patches - but I think I see what you are saying by trying to change the email verification variable as early as possible.

Another possible option - create our own invite/register form that takes user's email, password, username and has our own submit handler? That way we can avoid other modules hijacking the submit handler.

smk-ka’s picture

Status: Needs review » Needs work

With "bail out" I meant drupal_goto() which will never return (issues a Location header and exits).

Creating our own register handler would mean lots of duplicated code, if we want to keep all the functionality that Drupal offers: third party modules hooking into the register form, for example (profile/nodeprofile asking for required extra fields). I doubt this will be possible without breaking something.

While discussing this issue with sun, he came up with another problem: this issue is essentially only true if the email address that the user enters on the registration page actually is the same as the email the invitation was initially sent to. So the latest patch still requires some additional checks that eventually switches email verification back on if the emails differ.

zirafa’s picture

I suspected you meant the drupal_goto. Probably changing the #redirect for the form could have that work, but it sounds like you'd like to have them enter in a password upon registration, which is friendlier anyway.

I was thinking too about the email verification - seems like a fair assumption that an invite only applies to a specific email. So we could just set that email form to disabled so they can't change it.

zacker’s picture

Sam-ka: I tested the latest patch and it seems to work as described. WRT checking to make sure the email address matches the one the user was invited with, I think there are a fair number of people who will want to use a different email address than the one someone invited them with I think we may want to support changing email addresses on registration even if it means sending out a confirm email address.

zirafa’s picture

Talking with Zacker, he explained the use case for changing your email upon being invited. Other modules can disable that form element later if they want to restrict it, so it's making sense to me now.

smk-ka’s picture

but it sounds like you'd like to have them enter in a password upon registration, which is friendlier anyway

It was may intention by then. In the meantime I'm a bit unsure, because it isn't as simple as I first thought. So, if we can move the drupal_goto() into the form's #destination, that is, choose the way of letting the user change its password right after registration, then this seems to me to be currently the cleanest solution (ie. the behavior is still similar to what would normally happen).

smk-ka’s picture

Version: 5.x-1.9 » 6.x-2.x-dev

Marked #313365: Logintoboggin and Invite module incompatibility as a duplicate of this issue.

IIRC, this issue was simply "too much" for D5 with its hardcoded execution flow. Let's see what's possible in D6.

benlotter’s picture

I'm also facing this issue. I'm assuming since it's been so long that we've moved on to other priorities.

YK85’s picture

+1 subscribing
To confirm, there is no patch to test for 6.x-2.x-dev correct?
Thanks!

Rhino’s picture

+subscribing as well.

YK85’s picture

Category: bug » feature

Hi smk-ka,

I use Logintoboggan module and from reading this thread I see a huge benefit of this new feature.
Changed Category to 'feature request' and hope to help out with testing.

Thanks!

hefox’s picture

What happens when the user doesn't want to use the invited email?

I'm doing something similair to the patch in a custom module, but with some additional handling for the case of users using different email addresses and decline the invite.

I'm good with the current patch (method works for me, haven't tested the actual patch, I think it needs to be updated for d6), but just putting it this here as consider.

/**
 * Implementation of hook_init().
 */
function mymodule_init() {
  // Change the form to not needing verifcation.
  // We could do this using a lot of ugly form_alters, but want the other email.
  if ($_GET['q'] == 'user/register' && !empty($_SESSION[INVITE_SESSION])) {
    global $conf;
    // Decline invite
    if ($_GET['decline']) {
      unset($_SESSION[INVITE_SESSION]);
    }
    else {
      if (!empty($_GET['different_email'])) {
        $conf['user_email_verification'] = 0;
      }
    }
  }
}

/**
 * Implementation of hook_form_alter() of user_register.
 */
function mymodule_form_user_register_alter(&$form, $form_state) {
  if ($invite = invite_load_from_session()) {
    if (empty($invite->data['different_email'])) {
      if (!empty($form['account'])) {
        $use = &$form['account'];
      }
      else {
        $use = &$form; 
      }
      $use['mail']['#access'] = FALSE;
      $use['email'] = array(
        '#type' => 'item',
        '#value' => $use['mail']['#default_value'],
        '#title' => $use['mail']['#title'],
        '#weight' => $use['mail']['#weight'],
        '#description' => t("<a href='!diff_url'>Change Email</a> If you use a different email address than the one you were invited with, you will have to verify this new address before you can log in.", 
          array(
            '!diff_url' => url('user/register', array(
              'query' => array(
                'different_email' => 1,
              ),
            )),
          )
        ),
      );
    }
    $form['cancel'] = array(
      '#type' => 'markup',
      '#value' => l(t('Decline Invite'), 'user/register', array(
        'title' => t('If you do not want to use this invite, click here.'),
        'query' => array(
          'decline' => 1
        ),
      )),
      '#weight' => $form['submit']['#weight'] - 2,
    );
  }
}

edit: oh and need to use the new variable in #651264: Path to the registration page configurable instead of 'user/register'.

ezheidtmann’s picture

Version: 6.x-2.x-dev » 7.x-2.1-beta2

I wanted similar behavior in 7.x. This is what I did:

function MYMODULE_form_user_register_form_alter(&$form, &$form_state, $form_id) {
  $invite = invite_load_from_context();
  if (!empty($invite) && invite_validate($invite) == INVITE_VALID) {    
    // Get selected email address
    if (isset($form_state['input']['mail'])) {
      $mail = $form_state['input']['mail'];
    }
    else {
      $mail = $form['account']['mail']['#default_value'];
    }
    
    if ($mail == $invite->email) {
      // Disable verification if they registered with the same address
      // as the invite
      $GLOBALS['conf']['user_email_verification'] = 0;
    }
  }
}
ckng’s picture

Title: Inviting a user requires two emails » Disable registration email verification when user registered using invited email
Version: 7.x-2.1-beta2 » 7.x-4.x-dev
Issue summary: View changes
ckng’s picture

Assigned: Unassigned » ckng