From e3a8af979250b7a89f57207d09aa9bd0295aa868 Mon Sep 17 00:00:00 2001
From: Laurent Laffont <llaffont@afi-sa.fr>
Date: Tue, 6 Apr 2021 15:54:41 +0200
Subject: [PATCH] dev #132024 Identity providers : pre-registration

* Add option to redirect guests to ILS pre-registration on login
* Auto-complete pre-registration form
* Adds auth pre-registration action configuration
---
 VERSIONS_WIP/132024                           |   1 +
 .../opac/controllers/AuthController.php       |  25 +++-
 .../views/scripts/auth/pre-registration.phtml |  10 +-
 library/Class/IdentityProvider.php            |   5 +
 .../ModulesAccueil/Action/AuthPreRegister.php |  28 ++++
 .../Systeme/Widget/Action/AuthPreRegister.php |  32 +++++
 .../Systeme/Widget/Action/AuthRegister.php    |   2 +-
 library/Class/Systeme/Widget/ActionLoader.php |   3 +-
 library/Class/User/PreRegistration.php        |   7 +-
 .../Class/WebService/SIGB/Nanook/Service.php  |  11 +-
 .../Class/WebService/SIGB/PreRegistration.php |  45 ++++--
 .../ZendAfi/Form/Admin/IdentityProvider.php   |   5 +
 .../Widget/Action/AuthPreRegister.php         |  37 +++++
 .../ZendAfi/Form/PreRegistration/Nanook.php   |   6 +-
 .../AuthControllerPreRegistrationTest.php     | 131 +++++++++++++++++-
 .../IdentityProviderAdminTest.php             |   6 +
 ...roviderAuthenticationOpenIdConnectTest.php |  65 +++++++++
 .../TemplatesAuthPreRegisterTest.php          |  55 ++++++++
 18 files changed, 441 insertions(+), 33 deletions(-)
 create mode 100644 VERSIONS_WIP/132024
 create mode 100644 library/Class/Systeme/ModulesAccueil/Action/AuthPreRegister.php
 create mode 100644 library/Class/Systeme/Widget/Action/AuthPreRegister.php
 create mode 100644 library/ZendAfi/Form/Configuration/Widget/Action/AuthPreRegister.php
 create mode 100644 tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php

diff --git a/VERSIONS_WIP/132024 b/VERSIONS_WIP/132024
new file mode 100644
index 00000000000..992ce8d4299
--- /dev/null
+++ b/VERSIONS_WIP/132024
@@ -0,0 +1 @@
+ - ticket #132024 : Fournisseurs identité : ajout de l'option "redirection des invités vers la pré-inscription"
\ No newline at end of file
diff --git a/application/modules/opac/controllers/AuthController.php b/application/modules/opac/controllers/AuthController.php
index f654ebd31cd..fd812ccfc45 100644
--- a/application/modules/opac/controllers/AuthController.php
+++ b/application/modules/opac/controllers/AuthController.php
@@ -551,9 +551,10 @@ class AuthController extends ZendAfi_Controller_Action {
 
   public function preRegistrationAction() {
     $this->view->titre = $this->_('Demande de préinscription');
-
+    $this->view->help_message = nl2br(Class_Profil::getCurrentProfil()->getModulePreference('auth', 'pre-registration', 'help_message'));
     $registration = new Class_User_PreRegistration($this->view,
-                                                   function ($message) { $this->_helper->notify($message); });
+                                                   function ($message) {
+                                                     $this->_helper->notify($message); });
 
     if (!$form = $registration->getForm()) {
       $this->_helper->notify($this->_('Cette fonctionnalité n\'est pas activée.'));
@@ -564,6 +565,18 @@ class AuthController extends ZendAfi_Controller_Action {
       return $this->_redirect('/');
 
     $form = $registration->getForm();
+
+    if ($user = Class_Users::getIdentity()) {
+      $form->populate(['birthDate' => $user->getNaissance(),
+                       'mail' => $user->getMail(),
+                       'mail2' => $user->getMail(),
+                       'lastName' => $user->getNom(),
+                       'firstName' => $user->getPrenom(),
+                       'town' => $user->getVille(),
+                       'zipcode' => $user->getCodePostal(),
+                       'address' => $user->getAdresse()]);
+    }
+
     $this->view->form = $form->populate(ZendAfi_Filters_Post::filterStatic($this->_request->getParams()));
 
     if (!$this->_request->isPost())
@@ -575,9 +588,11 @@ class AuthController extends ZendAfi_Controller_Action {
     if (!$form->isValid($data))
       return;
 
-    $registration->send($data)
-      ? $this->_preRegistrationRedirect('pre-registration-success', $registration->getLibrary())
-      : $this->_preRegistrationRedirect('pre-registration', $registration->getLibrary());
+    $registration->send($data, $user)
+      ? $this->_preRegistrationRedirect('pre-registration-success',
+                                        $registration->getLibrary())
+      : $this->_preRegistrationRedirect('pre-registration',
+                                        $registration->getLibrary());
   }
 
 
diff --git a/application/modules/opac/views/scripts/auth/pre-registration.phtml b/application/modules/opac/views/scripts/auth/pre-registration.phtml
index fe6e94f481f..21ba203e0c6 100644
--- a/application/modules/opac/views/scripts/auth/pre-registration.phtml
+++ b/application/modules/opac/views/scripts/auth/pre-registration.phtml
@@ -1,5 +1,7 @@
 <?php
-$this->openBoite($this->titre);
-echo $this->renderForm($this->form);
-$this->closeBoite();
-?>
+echo $this->openCloseBoite($this->titre,
+                           $this->tag('p',
+                                      $this->help_message,
+                                      ['class' => 'help_message'])
+                           .
+                           $this->renderForm($this->form));
diff --git a/library/Class/IdentityProvider.php b/library/Class/IdentityProvider.php
index ef72b573af3..3084cb6a5b3 100644
--- a/library/Class/IdentityProvider.php
+++ b/library/Class/IdentityProvider.php
@@ -75,6 +75,7 @@ class Class_IdentityProvider extends Storm_Model_Abstract{
                        'prod_url',
                        'associate_on_login',
                        'auto_create_users',
+                       'redirect_to_preregistration',
                        'disable_nonce_check',
                        'scope'],
 
@@ -263,6 +264,10 @@ class Class_IdentityProvider extends Storm_Model_Abstract{
 
 
   public function loginSuccessRedirectUrl() {
+    if ($this->getRedirectToPreregistration()
+        && Class_Users::getIdentity()->isInvite())
+      return '/auth/pre-registration';
+
     return $this->getConnector()->loginSuccessRedirectUrl();
   }
 
diff --git a/library/Class/Systeme/ModulesAccueil/Action/AuthPreRegister.php b/library/Class/Systeme/ModulesAccueil/Action/AuthPreRegister.php
new file mode 100644
index 00000000000..9cc05e5e40c
--- /dev/null
+++ b/library/Class/Systeme/ModulesAccueil/Action/AuthPreRegister.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (c) 2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+class Class_Systeme_ModulesAccueil_Action_AuthPreRegister extends Class_Systeme_ModulesAccueil_Action {
+
+  public function __construct() {
+    parent::__construct();
+    $this->_form = ZendAfi_Form_Configuration_Widget_Action_AuthPreRegister::class;
+  }
+}
diff --git a/library/Class/Systeme/Widget/Action/AuthPreRegister.php b/library/Class/Systeme/Widget/Action/AuthPreRegister.php
new file mode 100644
index 00000000000..d1aafdfd21f
--- /dev/null
+++ b/library/Class/Systeme/Widget/Action/AuthPreRegister.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Systeme_Widget_Action_AuthPreRegister extends Class_Systeme_Widget_Action {
+  public function getResourcesDefinition() {
+    return (new Class_Systeme_ModulesAccueil_Action_AuthPreRegister);
+  }
+
+
+  public function _getTitle() {
+    return  $this->_('Configuration de la page de pré-inscription');
+  }
+}
diff --git a/library/Class/Systeme/Widget/Action/AuthRegister.php b/library/Class/Systeme/Widget/Action/AuthRegister.php
index 8f321d48459..f07f853bbd3 100644
--- a/library/Class/Systeme/Widget/Action/AuthRegister.php
+++ b/library/Class/Systeme/Widget/Action/AuthRegister.php
@@ -27,6 +27,6 @@ class Class_Systeme_Widget_Action_AuthRegister extends Class_Systeme_Widget_Acti
 
 
   public function _getTitle() {
-    return  $this->_('Configuration de la page de demande d\'inscrption');
+    return  $this->_('Configuration de la page de demande d\'inscription');
   }
 }
diff --git a/library/Class/Systeme/Widget/ActionLoader.php b/library/Class/Systeme/Widget/ActionLoader.php
index 1b54e57f8d5..cf5475b0cc6 100644
--- a/library/Class/Systeme/Widget/ActionLoader.php
+++ b/library/Class/Systeme/Widget/ActionLoader.php
@@ -55,7 +55,8 @@ class Class_Systeme_Widget_ActionLoader {
                 'abonne_fiche' => Class_Systeme_Widget_Action_User::class,
                 'author_view' => Class_Systeme_Widget_Action_Author::class,
                 'bib_en-lire-plus' => Class_Systeme_Widget_Action_Library::class,
-                'auth_register' => Class_Systeme_Widget_Action_AuthRegister::class
+                'auth_register' => Class_Systeme_Widget_Action_AuthRegister::class,
+                'auth_pre-registration' => Class_Systeme_Widget_Action_AuthPreRegister::class
     ];
 
     foreach (Class_TypeDoc::findAll() as $doc_type)
diff --git a/library/Class/User/PreRegistration.php b/library/Class/User/PreRegistration.php
index fc9ae7add38..e2618601b2d 100644
--- a/library/Class/User/PreRegistration.php
+++ b/library/Class/User/PreRegistration.php
@@ -46,10 +46,10 @@ class Class_User_PreRegistration {
   /**
    * @param $data array
    *
-   * @return boolean wether preregistration to ILS is done
+   * @return bool true when successful, otherwise false
    */
-  public function send($data) {
-    $this->_webservice->send($data);
+  public function send($data, $user) {
+    $this->_webservice->send($data, $user);
     $this->_library = $this->_webservice->getBib($data);
 
     if ($this->_webservice->hasError()) {
@@ -57,6 +57,7 @@ class Class_User_PreRegistration {
       return false;
     }
 
+
     if ($this->_email = $this->_webservice->getEmail($data))
       $this->_sendEmailNotification($data);
 
diff --git a/library/Class/WebService/SIGB/Nanook/Service.php b/library/Class/WebService/SIGB/Nanook/Service.php
index f4f71da4e88..06bd387f131 100644
--- a/library/Class/WebService/SIGB/Nanook/Service.php
+++ b/library/Class/WebService/SIGB/Nanook/Service.php
@@ -386,9 +386,12 @@ class Class_Webservice_SIGB_Nanook_Service extends Class_WebService_SIGB_Abstrac
     $url = $this->buildQueryURL(['service' => 'pre-register']);
     $xml = $this->getWebClient()->postData($url, $data);
 
-    return $this->ilsdiCheckXml($xml,
-                                'error',
-                                $this->_('Échec de la préinscription, une erreur est survenue'));
+    $status = $this->ilsdiCheckXml($xml,
+                                   'error',
+                                   $this->_('Échec de la préinscription, une erreur est survenue'));
+
+    $status['patron_id'] = $this->_getTagData($xml, 'patronId');
+    return $status;
   }
 
 
@@ -481,4 +484,4 @@ class PickupLocationsParamsWithSiteId extends PickupLocationsParams {
     $params['siteId'] = $item->getCodifAnnexe()->getIdOrigine();
     return $params;
   }
-}
\ No newline at end of file
+}
diff --git a/library/Class/WebService/SIGB/PreRegistration.php b/library/Class/WebService/SIGB/PreRegistration.php
index 2b2fd7ceae8..7a42688212c 100644
--- a/library/Class/WebService/SIGB/PreRegistration.php
+++ b/library/Class/WebService/SIGB/PreRegistration.php
@@ -86,10 +86,10 @@ class Class_WebService_SIGB_PreRegistration {
   }
 
 
-  public function send($data) {
+  public function send($data, $user) {
     if (isset($data[ static::REQUIRED_CHECKBOX_NAME ]))
       unset($data[ static::REQUIRED_CHECKBOX_NAME ]);
-    return $this->getStrategy()->send($data);
+    return $this->getStrategy()->send($data, $user);
   }
 
 
@@ -139,7 +139,7 @@ class Class_WebService_SIGB_PreRegistrationAbstract {
   public function getForm() {}
 
 
-  public function send($data) {}
+  public function send($data, $user) {}
 
 
   public function getBranchCode($data) {}
@@ -157,15 +157,16 @@ class Class_WebService_SIGB_PreRegistrationNanook extends Class_WebService_SIGB_
   }
 
 
-  public function send($data) {
+  public function send($data, $user) {
     if(!$int_bib = Class_IntBib::find($this->getBranchCode($data)))
       return $this->_pre_registration->addError($this->_('Échec de la préinscription, la médiathèque sélectionnée n\'existe pas.'));
 
     $response = $int_bib->getSIGBComm()->preRegistration($data);
 
-    if(!$response['statut'])
-      $this->_pre_registration->addError($response['erreur']);
+    if (!$response['statut'])
+      return $this->_pre_registration->addError($response['erreur']);
 
+    return $this->_updateUser($user, $int_bib, $response);
   }
 
 
@@ -181,6 +182,23 @@ class Class_WebService_SIGB_PreRegistrationNanook extends Class_WebService_SIGB_
       ? $data['mail']
       : '';
   }
+
+
+  protected function _updateUser($user, $int_bib, $response) {
+    if (!$user)
+      return $this;
+
+    $user->beAbonneSIGB()
+         ->setIdSite($int_bib->getId())
+         ->setIntBib($int_bib)
+         ->setIdabon($user->getLogin());
+
+    if (isset($response['patron_id']))
+      $user->setIdSigb($response['patron_id']);
+
+    $user->save();
+    return $this;
+  }
 }
 
 
@@ -193,9 +211,9 @@ class Class_WebService_SIGB_PreRegistrationKoha extends Class_WebService_SIGB_Pr
   }
 
 
-  public function send($data) {
+  public function send($data, $user) {
     $int_bib = $this->_extractIntBibFrom($data);
-    $this->_preRegistrationWithKoha($int_bib, $data);
+    return $this->_preRegistrationWithKoha($int_bib, $data);
   }
 
 
@@ -203,7 +221,6 @@ class Class_WebService_SIGB_PreRegistrationKoha extends Class_WebService_SIGB_Pr
     if(!isset($data['branchcode']))
       return 0;
     return explode('|', $data['branchcode'])[1];
-
   }
 
 
@@ -227,8 +244,10 @@ class Class_WebService_SIGB_PreRegistrationKoha extends Class_WebService_SIGB_Pr
 
 
   protected function _preRegistrationWithKoha($int_bib, $data) {
-    if(!$int_bib = Class_IntBib::find($int_bib))
-      return $this->_pre_registration->addError($this->_('Échec de la préinscription, les informations saisies sont invalides.'));
+    if(!$int_bib = Class_IntBib::find($int_bib)) {
+     $this->_pre_registration->addError($this->_('Échec de la préinscription, les informations saisies sont invalides.'));
+     return $this;
+    }
 
     $data['branchcode'] = $this->getBranchCode($data);
 
@@ -239,6 +258,8 @@ class Class_WebService_SIGB_PreRegistrationKoha extends Class_WebService_SIGB_Pr
 
     if(!$response['statut'])
       $this->_pre_registration->addError($response['erreur']);
+
+    return $this;
   }
 
 
@@ -247,4 +268,4 @@ class Class_WebService_SIGB_PreRegistrationKoha extends Class_WebService_SIGB_Pr
       return 0;
     return explode('|', $data['branchcode'])[0];
   }
-}
\ No newline at end of file
+}
diff --git a/library/ZendAfi/Form/Admin/IdentityProvider.php b/library/ZendAfi/Form/Admin/IdentityProvider.php
index 8a387752452..1cbfd8ecfc1 100644
--- a/library/ZendAfi/Form/Admin/IdentityProvider.php
+++ b/library/ZendAfi/Form/Admin/IdentityProvider.php
@@ -96,6 +96,11 @@ class ZendAfi_Form_Admin_IdentityProvider extends ZendAfi_Form {
                    'auto_create_users',
                    ['label' => $this->_('Création automatique des comptes')])
 
+
+      ->addElement('checkbox',
+                   'redirect_to_preregistration',
+                   ['label' => $this->_('Redirection des invités sur la pré-inscription')])
+
       ->addElement('multiInput', 'scopes',
                    ['label' => $this->_('Scopes à transmettre'),
                     'fields' => [['name' => 'scope']]])
diff --git a/library/ZendAfi/Form/Configuration/Widget/Action/AuthPreRegister.php b/library/ZendAfi/Form/Configuration/Widget/Action/AuthPreRegister.php
new file mode 100644
index 00000000000..afcd2c5a92b
--- /dev/null
+++ b/library/ZendAfi/Form/Configuration/Widget/Action/AuthPreRegister.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_Form_Configuration_Widget_Action_AuthPreRegister extends ZendAfi_Form_Configuration_Widget_Action {
+
+  public function init() {
+    parent::init();
+    $this
+      ->setAttrib('id', 'auth_pre_register')
+
+      ->addElement('ckeditor', 'help_message', ['label' => $this->_('Texte d\'aide'),
+                                                'cols' => 70,
+                                                'rows' => 5])
+      ->addDisplayGroup(['help_message'],
+                        'prefs',
+                        ['legend' => $this->_('Préférences')]);
+  }
+}
diff --git a/library/ZendAfi/Form/PreRegistration/Nanook.php b/library/ZendAfi/Form/PreRegistration/Nanook.php
index 56e8b0dcb9d..b0d41d17fb4 100644
--- a/library/ZendAfi/Form/PreRegistration/Nanook.php
+++ b/library/ZendAfi/Form/PreRegistration/Nanook.php
@@ -64,14 +64,16 @@ class ZendAfi_Form_PreRegistration_Nanook extends ZendAfi_Form {
                     'min' => 6,
                     'required' => true,
                     'allowEmpty' => false,
-                    'autocomplete' => 'mew-password',
+                    'autocomplete' => 'new-password',
+                    'renderPassword' => 'true',
                     'validators' => [(new Zend_Validate_StringLength())->setMin(6)]])
 
       ->addElement('password',
                    'password2',
                    ['label' => $this->_('Confirmer votre mot de passe'),
                     'placeholder' => $this->_('lettres + chiffres min 6'),
-                    'autocomplete' => 'mew-password',
+                    'autocomplete' => 'new-password',
+                    'renderPassword' => 'true',
                     'validators' => [new ZendAfi_Validate_PasswordEquals('password')]])
 
       ->addElement('date',
diff --git a/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php b/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php
index 2737b4b9500..1b9a738e1b0 100644
--- a/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php
+++ b/tests/application/modules/opac/controllers/AuthControllerPreRegistrationTest.php
@@ -729,7 +729,7 @@ class AuthControllerPreRegistrationSettingsTest extends AuthControllerPreRegistr
                                                          'password' => 'um',
                                                          'role_level' => ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN]));
 
-    $this->dispatch('/admin/modules/auth/config/site/type_module/auth/id_profil/1/action1/pre-registration/action2/', true);
+    $this->dispatch('/admin/modules/auth/config/site/type_module/auth/id_profil/1/action1/pre-registration/action2/');
   }
 
 
@@ -738,3 +738,132 @@ class AuthControllerPreRegistrationSettingsTest extends AuthControllerPreRegistr
     $this->assertXPath('//form//select[@name="boite"]');
   }
 }
+
+
+
+
+abstract class AuthControllerPreRegistrationNanookAsInviteTestCase extends AuthControllerPreRegistrationNanookTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $totoro = $this->fixture(Class_Users::class,
+                             ['id' => 19,
+                              'nom' => 'Ro',
+                              'prenom' => 'Toto',
+                              'naissance' => '1988-04-16',
+                              'login' => 'totoro',
+                              'password' => 'secret',
+                              'mail' => 'to@to.ro',
+                              'adresse' => '1 rue Ghibli',
+                              'code_postal' => '74000',
+                              'ville' => 'Annecy',
+                              'role_level' => ZendAfi_Acl_AdminControllerRoles::INVITE]);
+
+    ZendAfi_Auth::getInstance()->logUser($totoro);
+  }
+}
+
+
+
+
+class AuthControllerPreRegistrationNanookDispatchAsInviteTest extends AuthControllerPreRegistrationNanookAsInviteTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/opac/auth/pre-registration');
+  }
+
+
+  public function expectedInputValues() {
+    return [
+            ['birthDate', '1988-04-16'],
+            ['mail', 'to@to.ro'],
+            ['mail2', 'to@to.ro'],
+            ['lastName', 'Ro'],
+            ['firstName', 'Toto'],
+            ['town', 'Annecy'],
+            ['zipcode', '74000'],
+            ['address', '1 rue Ghibli']
+    ];
+  }
+
+
+  /**
+   * @dataProvider expectedInputValues
+   * @test
+   */
+  public function inputValueShouldBe($input_name, $expected_value) {
+    $this->assertXPath(sprintf('//input[@name="%s"][@value="%s"]',
+                               $input_name,
+                               $expected_value));
+  }
+}
+
+
+
+
+class AuthControllerPreRegistrationNanookDispatchAsInviteAndPostDispatchTest extends AuthControllerPreRegistrationNanookAsInviteTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    $this->mock_web_client
+      ->whenCalled('postData')
+      ->answers('<?xml version="1.0" encoding="UTF-8"?>
+<GetPatronInfo><patronId>5352</patronId><barcode></barcode><lastName>Ro</lastName><firstName>Toto</firstName><siteId>1</siteId></GetPatronInfo>');
+
+    $this->postDispatch('/opac/auth/pre-registration', ['site' => '1',
+                                                        'lastName' => 'Ro',
+                                                        'firstName' => 'Toto',
+                                                        'mail' => 'to@to.ro',
+                                                        'mail2' => 'to@to.ro',
+                                                        'password' => 'pwd123456',
+                                                        'password2' => 'pwd123456',
+                                                        'birthDate' => '1988-04-16',
+                                                        'town' => 'Annecy',
+                                                        'zipcode' => '74000',
+                                                        'address' => '11 bd du Fier',
+                                                        'website' => '']);
+  }
+
+
+  /** @test */
+  public function userTotoroShouldBePromotedToAbonneSIGB() {
+    $this->assertTrue(Class_Users::find(19)->isAbonne());
+  }
+
+
+  /** @test */
+  public function userTotoroIdSIGBShouldEquals5352() {
+    $this->assertEquals(5352,
+                        Class_Users::find(19)->getIdSigb());
+  }
+
+
+  /** @test */
+  public function userTotoroIdSiteShouldEqualsOne() {
+    $this->assertEquals(1,
+                        Class_Users::find(19)->getIdSite());
+  }
+
+
+  /** @test */
+  public function userTotoroIdIntBibShouldEqualsOne() {
+    $this->assertEquals(1,
+                        Class_Users::find(19)->getIdIntBib());
+  }
+
+
+  /** @test */
+  public function userTotoroIdAbonShouldBeTotoro() {
+    $this->assertEquals('totoro',
+                        Class_Users::find(19)->getIdabon());
+  }
+
+
+  /** @test */
+  public function userTotoroShouldBeValid() {
+    $totoro = Class_Users::find(19);
+    $this->assertTrue($totoro->isValid(),
+                      implode(';', $totoro->getErrors()));
+  }
+}
diff --git a/tests/scenarios/IdentityProvider/IdentityProviderAdminTest.php b/tests/scenarios/IdentityProvider/IdentityProviderAdminTest.php
index 0cb3b599454..d976cfd4df6 100644
--- a/tests/scenarios/IdentityProvider/IdentityProviderAdminTest.php
+++ b/tests/scenarios/IdentityProvider/IdentityProviderAdminTest.php
@@ -247,6 +247,12 @@ class IdentityProviderAdminEditTest extends IdentityProviderAdminTestCase {
   }
 
 
+  /** @test */
+  public function formShouldContainsCheckboxRedirectToPregistrationCheck() {
+    $this->assertXPath('//input[@type="checkbox"][@name="redirect_to_preregistration"][not(@checked)]');
+  }
+
+
 
   /** @test */
   public function tableShouldContainsCheckboxCreateAutoAccounts() {
diff --git a/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationOpenIdConnectTest.php b/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationOpenIdConnectTest.php
index e73331d3084..7531c716d05 100644
--- a/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationOpenIdConnectTest.php
+++ b/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationOpenIdConnectTest.php
@@ -265,3 +265,68 @@ class IdentityProviderOpenIdConnectGitlabTest extends IdentityProviderOpenIdConn
     $this->assertSame('', $user->getMail());
   }
 }
+
+
+
+
+class IdentityProviderOpenIdConnectAuthLoginWithRedirectPreregistrationTest extends IdentityProviderOpenIdConnectTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->_provider
+      ->setConfigValue('redirect_to_preregistration', 1);
+  }
+
+
+  protected function _loginAndAssertRedirectTo($location) {
+    $this->_setupRequests($code = 'code1234', $state = 'state1234');
+    $this->dispatch('/auth/login/provider/1?code=' . $code . '&state=' . $state);
+    $this->assertRedirectTo($location);
+  }
+
+
+  /** @test */
+  public function withAutoCreateUsersResponseShouldRedirectToPreRegistration() {
+    $this->_provider->setConfigValue('auto_create_users', 1);
+    $this->_loginAndAssertRedirectTo('/auth/pre-registration');
+  }
+
+
+
+  /** @test */
+  public function withExistingInviteResponseShouldRedirectToPreRegistration() {
+    $this->fixture(Class_Users::class,
+                   ['id' => 33,
+                    'login' => 'captainflam',
+                    'password' => 'secret',
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::INVITE
+                   ]);
+
+    $this->fixture(Class_User_Identity::class,
+                   ['id' => 1,
+                    'provider_id' => 1,
+                    'user_id' => 33,
+                    'identifier' => 2]);
+    $this->_loginAndAssertRedirectTo('/auth/pre-registration');
+  }
+
+
+  /** @test */
+  public function withExistingAbonneResponseShouldNotRedirectToPreRegistrationButRoot() {
+    $this->fixture(Class_Users::class,
+                   ['id' => 33,
+                    'login' => 'captainflam',
+                    'password' => 'secret',
+                    'id_site' => 3,
+                    'idabon' => 'abcd123',
+                    'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                   ]);
+
+    $this->fixture(Class_User_Identity::class,
+                   ['id' => 1,
+                    'provider_id' => 1,
+                    'user_id' => 33,
+                    'identifier' => 2]);
+
+    $this->_loginAndAssertRedirectTo('/');
+  }
+}
diff --git a/tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php b/tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php
new file mode 100644
index 00000000000..01096e6f166
--- /dev/null
+++ b/tests/scenarios/Templates/TemplatesAuthPreRegisterTest.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class TemplatesAuthPreRegisterTest extends Admin_AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->fixture('Class_IntBib',
+                   ['id' => 1,
+                    'comm_params' => ['url_serveur' => 'http://super.nano.ok/ilsdi/arcadia',
+                                      'pre-registration' => 1],
+                    'comm_sigb' => Class_IntBib::COM_NANOOK]);
+
+    $this->_buildTemplateProfil(['id' => 1,
+                                 'libelle' => 'Somewhere in time'])
+         ->setCfgModulesPreferences(['help_message' => "Go and register to<br>my library"],
+                                    'auth',
+                                    'pre-registration');
+  }
+
+
+  /** @test */
+  public function configFormShouldContainsTextAreaHelpMessage() {
+    $this->dispatch('/admin/widget/edit-action/id/auth_pre-registration/id_profil/1');
+    $this->assertXPath('//form//textarea[@name="help_message"]');
+  }
+
+
+  /** @test */
+  public function pageShouldContainsParagrahWithGoAndRegisterToMyLibrary() {
+    $this->dispatch('/auth/pre-registration');
+    $this->assertXPath('//p[@class="help_message"][contains(text(), "Go and register")]/br');
+  }
+}
-- 
GitLab