Uploaded image for project: 'CiviCRM'
  1. CiviCRM
  2. CRM-13401

UF match fails on login if no existing civicrm_uf_match record

    Details

    • Type: Bug
    • Status: Done/Fixed
    • Priority: Minor
    • Resolution: Cannot Reproduce
    • Affects Version/s: 4.3.5
    • Fix Version/s: 4.4.0
    • Component/s: Core CiviCRM
    • Labels:
      None

      Description

      See http://forum.civicrm.org/index.php/topic,29979.0.html

      • Scenario: existing Drupal user, existing Civi contact with matching email. I deleted civicrm_uf_match records because the Civi database had been copied from a live environment to a test environment where some of the Drupal users did not coincide.

      What I did:
      Logged in as the Drupal user mentioned above.

      Expected behaviour:
      The existing Drupal user is matched to the existing Civi contact on email. A civicrm_uf_match record is created to link them.

      Actual behaviour:
      The existing Drupal user is not matched to the existing Civi contact, instead a new contact is created. A civicrm_uf_match record is created to link the user to the new contact.

      I tracked down the cause...

      civicrm_user_login() calls:
      return CRM_Core_BAO_UFMatch::synchronize($user, FALSE, 'Drupal',
      civicrm_get_ctype('Individual')
      );

      CRM_Core_BAO_UFMatch::synchronize() calls CRM_Core_BAO_UFMatch::synchronizeUFMatch()

      CRM_Core_BAO_UFMatch::synchronizeUFMatch() finds no existing civicrm_uf_match record and runs the following code...

      if (!empty($_POST) && !$isLogin) {
      $params = $_POST;
      $params['email'] = $uniqId;

      $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual');
      $dedupeParams['check_permission'] = FALSE;
      $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual');

      dupesByParams() returns nothing. Because $dedupeParams contains:

      Array
      (
      [civicrm_address] => Array
      (
      [name] => some-username
      )

      [civicrm_email] => Array
      (
      [email] => some@e.mail
      )

      [civicrm_im] => Array
      (
      [name] => some-username
      )

      [check_permission] =>
      )

      Hang on, why are civicrm_address and civicrm_im there and why do they contain the username? It looks like CRM_Dedupe_Finder::formatParams() iterates through CRM_Dedupe_BAO_RuleGroup::supportedFields(), including tables civicrm_address and civicrm_im, and because $_POST contains field 'name' (Drupal username) and those two tables contain a 'name' field, the username is interpreted as being both an address name and an IM name.

      If you're thinking, "ah, but this is a login, so $isLogin will be true, so this code won't run" - that's what I assumed at first, but $isLogin is actually false. It's passed through to CRM_Core_BAO_UFMatch::synchronizeUFMatch() from CRM_Core_BAO_UFMatch::synchronize() , where it defaults to FALSE.

      The call to CRM_Core_BAO_UFMatch::synchronize() from civicrm_user_login() does not specify the $isLogin parameter. Amending the call in civicrm_user_login() to:

      return CRM_Core_BAO_UFMatch::synchronize($user, FALSE, 'Drupal',
      civicrm_get_ctype('Individual'), TRUE
      );

      fixed the problem, because this bypasses the CRM_Dedupe_Finder::dupesByParams() route and instead does a good old-fashioned CRM_Contact_BAO_Contact::matchContactOnEmail().

      Does this seem the right solution - should $isLogin be TRUE here and so using CRM_Contact_BAO_Contact::matchContactOnEmail() ?

      Cheers,

      Dave

        Attachments

          Activity

            People

            • Assignee:
              davej Dave Jenkins
              Reporter:
              davej Dave Jenkins
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: