Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add configuration option for matching users with CiviCRM contacts on login #42

Merged
merged 1 commit into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions civiremote.module
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use Drupal\civiremote;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Url;
use Drupal\user\UserInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;

/**
* Implements hook_entity_insert().
Expand All @@ -22,19 +20,7 @@ function civiremote_entity_insert(EntityInterface $entity) {
* Implements hook_user_login().
*/
function civiremote_user_login(UserInterface $account) {
// Synchronise user roles with CiviRemote roles retrieved from CiviCRM.
try {
civiremote\User::synchroniseRoles($account);
}
catch (Exception $exception) {
user_logout();
Drupal::messenger()->addError(
t('Could not complete login. Please try again later or contact the site administrator.')
);
$url = Url::fromRoute('<front>')->toString();
$response = new RedirectResponse($url);
$response->send();
}
civiremote\User::login($account);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions config/install/civiremote.settings.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
cmrf_connector: civiremote
acquire_civiremote_id: false
match_blocked_users: false
match_on_login: false
match_on_login_exclude_roles: []
9 changes: 9 additions & 0 deletions config/schema/civiremote.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ civiremote.settings:
match_blocked_users:
type: boolean
label: 'Match blocked users'
match_on_login:
type: boolean
label: 'Acquire CiviRemote ID on login'
match_on_login_exclude_roles:
type: sequence
label: 'Roles to exclude when matching on login'
sequence:
type: string
label: 'Role'
match_contact_mapping:
type: sequence
label: 'Parameter mapping'
Expand Down
56 changes: 48 additions & 8 deletions src/Form/CiviRemoteConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,33 @@
namespace Drupal\CiviRemote\Form;

use Drupal;
use Drupal\Component\Utility\Html;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\user\RoleInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\cmrf_core;
use Drupal\user\RoleStorageInterface;

class CiviRemoteConfigForm extends ConfigFormBase {

/* @var cmrf_core\Core $cmrf_core */
public $cmrf_core;
public cmrf_core\Core $cmrf_core;

public RoleStorageInterface $roleStorage;

/**
* CiviRemoteConfigForm constructor.
*
* @param cmrf_core\Core $cmrf_core
* @param \Drupal\user\RoleStorageInterface $roleStorage
*/
public function __construct(cmrf_core\Core $cmrf_core) {
public function __construct(cmrf_core\Core $cmrf_core, RoleStorageInterface $roleStorage) {
$this->cmrf_core = $cmrf_core;
$this->roleStorage = $roleStorage;
}

/**
Expand All @@ -46,10 +52,13 @@ public static function create(ContainerInterface $container) {
/**
* Inject dependencies.
* @var cmrf_core\Core $cmrf
* @var \Drupal\user\RoleStorageInterface $roleStorage
*/
$cmrf = $container->get('cmrf_core.core');
$roleStorage = $container->get('entity_type.manager')->getStorage('user_role');
return new static(
$cmrf
$cmrf,
$roleStorage
);
}

Expand Down Expand Up @@ -84,14 +93,19 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#required' => TRUE,
];

$form['acquire_civiremote_id'] = [
$form['match_contacts'] = [
'#type' => 'fieldset',
'#title' => $this->t('CiviCRM Contact Matching'),
];

$form['match_contacts']['acquire_civiremote_id'] = [
'#type' => 'checkbox',
'#title' => $this->t('Acquire CiviRemote ID'),
'#description' => $this->t('Whether to match a new user to a CiviCRM contact and store the CiviRemote ID returned by CiviCRM.'),
'#default_value' => $config->get('acquire_civiremote_id'),
];

$form['match_blocked_users'] = [
$form['match_contacts']['match_blocked_users'] = [
'#type' => 'checkbox',
'#title' => $this->t('Match blocked users'),
'#description' => $this->t('Whether to match blocked users to a CiviCRM contact. If unchecked, only active users will be matched.'),
Expand All @@ -101,6 +115,30 @@ public function buildForm(array $form, FormStateInterface $form_state) {
],
];

$form['match_contacts']['match_on_login'] = [
'#type' => 'checkbox',
'#title' => $this->t('Acquire CiviRemote ID on login'),
'#description' => $this->t('Whether to match existing users without a CiviRemote ID when they log in.'),
'#default_value' => $config->get('match_on_login'),
'#states' => [
'visible' => [':input[name="acquire_civiremote_id"]' => ['checked' => TRUE]],
],
];

$form['match_contacts']['match_on_login_exclude_roles'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Roles to exclude when matching on login'),
'#description' => $this->t('Users with one of the selected roles will be excluded from acquiring a CiviCRM Contact ID during login.'),
'#options' => array_map(fn(RoleInterface $role) => Html::escape($role->label()), $this->roleStorage->loadMultiple()),
'#default_value' => $config->get('match_on_login_exclude_roles') ?? [],
'#states' => [
'visible' => [
':input[name="acquire_civiremote_id"]' => ['checked' => TRUE],
':input[name="match_on_login"]' => ['checked' => TRUE],
],
],
];

$form['match_contact_mapping'] = [
'#type' => 'fieldset',
'#title' => $this->t('Parameter mapping'),
Expand Down Expand Up @@ -207,8 +245,10 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
$form_state->cleanValues();
$config = $this->config('civiremote.settings');
$config->set('cmrf_connector', $form_state->getValue('cmrf_connector'));
$config->set('acquire_civiremote_id', $form_state->getValue('acquire_civiremote_id'));
$config->set('match_blocked_users', $form_state->getValue('match_blocked_users'));
$config->set('acquire_civiremote_id', (bool) $form_state->getValue('acquire_civiremote_id'));
$config->set('match_blocked_users', (bool) $form_state->getValue('match_blocked_users'));
$config->set('match_on_login', (bool) $form_state->getValue('match_on_login'));
$config->set('match_on_login_exclude_roles', $form_state->getValue('match_on_login_exclude_roles'));
$config->set('match_contact_mapping', $form_state->getValue('match_contact_mapping_table'));
$config->save();
parent::submitForm($form, $form_state);
Expand Down
36 changes: 33 additions & 3 deletions src/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ class User {
/**
* Act on User entity creation.
*
* @param UserInterface $user
* The User entity object.
*
* @throws Entity\EntityStorageException
*
* @see civiremote_entity_insert()
Expand All @@ -45,6 +42,39 @@ public static function create(UserInterface $user) {
}
}

/**
* Act on user login.
*
* @see civiremote_user_login()
*/
public static function login(UserInterface $user): void {
try {
// Acquire CiviRemote ID on login if configured.
if (!$civiremote_id = $user->get('civiremote_id')->getValue()) {
$config = Drupal::config('civiremote.settings');
if (
$config->get('acquire_civiremote_id')
&& ($config->get('match_on_login') ?? FALSE)
&& [] === array_intersect($user->getRoles(), $config->get('match_on_login_exclude_roles') ?? [])
) {
self::matchContact($user);
}
}

// Synchronise user roles with CiviRemote roles retrieved from CiviCRM.
self::synchroniseRoles($user);
}
catch (\Exception $exception) {
user_logout();
Drupal::messenger()->addError(
t('Could not complete login. Please try again later or contact the site administrator.')
);
$url = Url::fromRoute('<front>')->toString();
$response = new RedirectResponse($url);
$response->send();
}
}

/**
* Match a CiviCRM contact and set the returned CiviRemote ID on the user.
*
Expand Down
Loading