From ecfc8ff52b56bb601f43751b851f89f5ec845a4b Mon Sep 17 00:00:00 2001
From: Bertrand Gauthier <bertrand.gauthier@unicaen.fr>
Date: Mon, 21 Jan 2019 09:28:48 +0100
Subject: [PATCH] Support de l'authentification locale.

---
 config/module.config.php                      | 12 +++
 config/unicaen-auth.global.php.dist           | 10 +++
 src/UnicaenAuth/Controller/AuthController.php | 22 ++++++
 src/UnicaenAuth/Options/ModuleOptions.php     | 26 +++++++
 src/UnicaenAuth/Service/ShibService.php       |  3 +
 .../View/Helper/LdapConnectViewHelper.php     |  4 +-
 .../View/Helper/LocalConnectViewHelper.php    | 76 +++++++++++++++++++
 .../Helper/LocalConnectViewHelperFactory.php  | 27 +++++++
 .../View/Helper/ShibConnectViewHelper.php     |  2 +-
 .../{ldap-connect.phtml => connect.phtml}     | 16 +++-
 .../View/Helper/partial/reset-password.phtml  | 39 ++++++++++
 view/zfc-user/user/login.phtml                | 25 +++++-
 12 files changed, 253 insertions(+), 9 deletions(-)
 create mode 100644 src/UnicaenAuth/View/Helper/LocalConnectViewHelper.php
 create mode 100644 src/UnicaenAuth/View/Helper/LocalConnectViewHelperFactory.php
 rename src/UnicaenAuth/View/Helper/partial/{ldap-connect.phtml => connect.phtml} (80%)
 create mode 100644 src/UnicaenAuth/View/Helper/partial/reset-password.phtml

diff --git a/config/module.config.php b/config/module.config.php
index 67fc886..f6ea7d6 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -6,11 +6,22 @@ use UnicaenAuth\Service\ShibService;
 use UnicaenAuth\Service\ShibServiceFactory;
 use UnicaenAuth\Service\UserContextFactory;
 use UnicaenAuth\View\Helper\LdapConnectViewHelperFactory;
+use UnicaenAuth\View\Helper\LocalConnectViewHelperFactory;
 use UnicaenAuth\View\Helper\ShibConnectViewHelperFactory;
 use UnicaenAuth\View\Helper\UserUsurpationHelperFactory;
 
 $settings = [
 
+    /**
+     * Configuration de l'authentification locale.
+     */
+    'local' => [
+        /**
+         * Possibilité ou non de s'authentifier à l'aide d'un compte local.
+         */
+        'enabled' => true,
+    ],
+
     /**
      * Configuration de l'authentification LDAP.
      */
@@ -453,6 +464,7 @@ return [
             'userProfileSelect'          => 'UnicaenAuth\View\Helper\UserProfileSelectFactory',
             'userProfileSelectRadioItem' => 'UnicaenAuth\View\Helper\UserProfileSelectRadioItemFactory',
             'userUsurpation'             => UserUsurpationHelperFactory::class,
+            'localConnect'               => LocalConnectViewHelperFactory::class,
             'ldapConnect'                => LdapConnectViewHelperFactory::class,
             'shibConnect'                => ShibConnectViewHelperFactory::class,
         ],
diff --git a/config/unicaen-auth.global.php.dist b/config/unicaen-auth.global.php.dist
index a703338..c6e7a2f 100644
--- a/config/unicaen-auth.global.php.dist
+++ b/config/unicaen-auth.global.php.dist
@@ -7,6 +7,16 @@
  */
 $settings = [
 
+    /**
+     * Configuration de l'authentification locale.
+     */
+    'local' => [
+        /**
+         * Possibilité ou non de s'authentifier à l'aide d'un compte local.
+         */
+        'enabled' => true,
+    ],
+
     /**
      * Configuration de l'authentification LDAP.
      */
diff --git a/src/UnicaenAuth/Controller/AuthController.php b/src/UnicaenAuth/Controller/AuthController.php
index 0451368..986c50e 100644
--- a/src/UnicaenAuth/Controller/AuthController.php
+++ b/src/UnicaenAuth/Controller/AuthController.php
@@ -107,4 +107,26 @@ class AuthController extends AbstractActionController
             throw new RuntimeException("Impossible d'écrire dans le storage");
         }
     }
+
+    public function sendPasswordRenewalMailAction()
+    {
+        // lecture email fourni
+
+        // tester email connu dans table utilisateur
+
+        // générer / enregistrer token dans table utilisateur
+
+        // envoyer mail avec lien/token
+    }
+
+    public function changePasswordAction()
+    {
+        // lecture token fourni
+
+        // test token fourni existe dans table utilisateur
+
+        // afficher formulaire de màj
+
+        // màj password
+    }
 }
\ No newline at end of file
diff --git a/src/UnicaenAuth/Options/ModuleOptions.php b/src/UnicaenAuth/Options/ModuleOptions.php
index 7939d37..7e76ac0 100644
--- a/src/UnicaenAuth/Options/ModuleOptions.php
+++ b/src/UnicaenAuth/Options/ModuleOptions.php
@@ -9,6 +9,13 @@ namespace UnicaenAuth\Options;
  */
 class ModuleOptions extends \ZfcUser\Options\ModuleOptions
 {
+    /**
+     * Paramètres concernant l'authentification locale.
+     *
+     * @var array
+     */
+    protected $local = [];
+
     /**
      * Paramètres concernant l'authentification LDAP.
      *
@@ -46,6 +53,25 @@ class ModuleOptions extends \ZfcUser\Options\ModuleOptions
      */
     protected $entityManagerName = 'doctrine.entitymanager.orm_default';
 
+    /**
+     * @return array
+     */
+    public function getLocal()
+    {
+        return $this->local;
+    }
+
+    /**
+     * @param array $local
+     * @return self
+     */
+    public function setLocal(array $local)
+    {
+        $this->local = $local;
+
+        return $this;
+    }
+
     /**
      * Retourne les paramètres concernant l'authentification LDAP.
      *
diff --git a/src/UnicaenAuth/Service/ShibService.php b/src/UnicaenAuth/Service/ShibService.php
index 96fe081..e0df741 100644
--- a/src/UnicaenAuth/Service/ShibService.php
+++ b/src/UnicaenAuth/Service/ShibService.php
@@ -327,6 +327,9 @@ EOS;
         if ($this->getShibbolethSimulate()) {
             return '/';
         }
+        if ($this->getAuthenticatedUser() === null) {
+            return '/';
+        }
 
         $logoutRelativeUrl = '/Shibboleth.sso/Logout?return='; // NB: '?return=' semble obligatoire!
 
diff --git a/src/UnicaenAuth/View/Helper/LdapConnectViewHelper.php b/src/UnicaenAuth/View/Helper/LdapConnectViewHelper.php
index ecee68d..42b1910 100644
--- a/src/UnicaenAuth/View/Helper/LdapConnectViewHelper.php
+++ b/src/UnicaenAuth/View/Helper/LdapConnectViewHelper.php
@@ -62,10 +62,12 @@ class LdapConnectViewHelper extends AbstractHelper
         }
 
         try {
-            return $this->getView()->render("ldap-connect", [
+            return $this->getView()->render("connect", [
+                'title' => null,
                 'enabled' => $this->enabled,
                 'form' => $this->form,
                 'redirect' => null,
+                'password_reset' => false,
             ]);
         } catch (\Exception $e) {
             return '<p>' . $e->getMessage() . '</p><p>' . $e->getTraceAsString() . '</p>';
diff --git a/src/UnicaenAuth/View/Helper/LocalConnectViewHelper.php b/src/UnicaenAuth/View/Helper/LocalConnectViewHelper.php
new file mode 100644
index 0000000..e6dd804
--- /dev/null
+++ b/src/UnicaenAuth/View/Helper/LocalConnectViewHelper.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace UnicaenAuth\View\Helper;
+
+use Zend\Form\Form;
+use Zend\View\Helper\AbstractHelper;
+use Zend\View\Renderer\PhpRenderer;
+use Zend\View\Resolver\TemplatePathStack;
+
+/**
+ * Aide de vue dessinant le formulaire d'authentification locale,
+ * si l'authentification locale est activée.
+ *
+ * @method PhpRenderer getView()
+ * @author Unicaen
+ */
+class LocalConnectViewHelper extends AbstractHelper
+{
+    /**
+     * @var bool
+     */
+    protected $enabled = true;
+
+    /**
+     * @var Form
+     */
+    protected $form;
+
+    /**
+     * @param bool $enabled
+     * @return $this
+     */
+    public function setEnabled($enabled = true)
+    {
+        $this->enabled = $enabled;
+
+        return $this;
+    }
+
+    /**
+     * @param Form $form
+     * @return $this
+     */
+    public function __invoke(Form $form)
+    {
+        $this->form = $form;
+
+        $this->getView()->resolver()->attach(
+            new TemplatePathStack(['script_paths' => [__DIR__ . "/partial"]])
+        );
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        if (! $this->enabled) {
+            return '';
+        }
+
+        try {
+            return $this->getView()->render("connect", [
+                'title' => "Avec un compte local",
+                'enabled' => $this->enabled,
+                'form' => $this->form,
+                'redirect' => null,
+                'password_reset' => true,
+            ]);
+        } catch (\Exception $e) {
+            return '<p>' . $e->getMessage() . '</p><p>' . $e->getTraceAsString() . '</p>';
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/View/Helper/LocalConnectViewHelperFactory.php b/src/UnicaenAuth/View/Helper/LocalConnectViewHelperFactory.php
new file mode 100644
index 0000000..092f0cc
--- /dev/null
+++ b/src/UnicaenAuth/View/Helper/LocalConnectViewHelperFactory.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace UnicaenAuth\View\Helper;
+
+use UnicaenAuth\Options\ModuleOptions;
+use Zend\View\HelperPluginManager;
+
+class LocalConnectViewHelperFactory
+{
+    /**
+     * @param HelperPluginManager $hpm
+     * @return LocalConnectViewHelper
+     */
+    public function __invoke(HelperPluginManager $hpm)
+    {
+        /** @var ModuleOptions $moduleOptions */
+        $moduleOptions = $hpm->getServiceLocator()->get('unicaen-auth_module_options');
+        $config = $moduleOptions->getLocal();
+
+        $enabled = isset($config['enabled']) && (bool) $config['enabled'];
+
+        $helper = new LocalConnectViewHelper();
+        $helper->setEnabled($enabled);
+
+        return $helper;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php b/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php
index 9a9751e..44669aa 100644
--- a/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php
+++ b/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php
@@ -41,7 +41,7 @@ class ShibConnectViewHelper extends AbstractHelper
         $shibUrl = $this->getView()->url('auth/shibboleth', [], ['query' => $this->getView()->queryParams()], true);
 
         return <<<EOS
-Se connecter via la 
+<h3 class="connect-title">Via la fédération d'identité</h3> 
 <a href="$shibUrl" class="btn btn-success btn-lg">Fédération d'identité Renater</a>
 EOS;
     }
diff --git a/src/UnicaenAuth/View/Helper/partial/ldap-connect.phtml b/src/UnicaenAuth/View/Helper/partial/connect.phtml
similarity index 80%
rename from src/UnicaenAuth/View/Helper/partial/ldap-connect.phtml
rename to src/UnicaenAuth/View/Helper/partial/connect.phtml
index 6fc01da..f216e21 100644
--- a/src/UnicaenAuth/View/Helper/partial/ldap-connect.phtml
+++ b/src/UnicaenAuth/View/Helper/partial/connect.phtml
@@ -5,22 +5,30 @@ use Zend\Form\Form;
 /**
  * @var bool   $enabled
  * @var Form   $form
+ * @var string $title
  * @var string $redirect
  */
 ?>
 
+<?php if ($title): ?>
+    <h3 class="connect-title">
+        <?php echo $title ?>
+    </h3>
+<?php endif ?>
+
 <?php echo $this->form()->openTag($form) ?>
+
 <?php if (($errors = $this->formErrors($form))): ?>
     <p><?php echo $errors ?></p>
 <?php endif ?>
-<p>
+<p class="connect-identity">
     <?php
     $identity = $form->get($name = 'identity')->setAttributes(['id' => $name, 'class' => 'form-control']);
     echo $this->formLabel($identity);
     echo $this->formInput($identity);
     ?>
 </p>
-<p>
+<p class="connect-credentials">
     <?php
     $identity = $form->get($name = 'credential')->setAttributes(['id' => $name, 'class' => 'form-control']);
     echo $this->formLabel($identity);
@@ -30,7 +38,9 @@ use Zend\Form\Form;
 <?php if ($redirect): ?>
     <input type="hidden" name="redirect" value="<?php echo $redirect ?>"/>
 <?php endif ?>
-<p>
+
+<p class="connect-submit">
     <?php echo $this->formButton($form->get('submit')->setAttribute('class', 'btn btn-primary')) ?>
 </p>
+
 <?php echo $this->form()->closeTag() ?>
diff --git a/src/UnicaenAuth/View/Helper/partial/reset-password.phtml b/src/UnicaenAuth/View/Helper/partial/reset-password.phtml
new file mode 100644
index 0000000..ef61977
--- /dev/null
+++ b/src/UnicaenAuth/View/Helper/partial/reset-password.phtml
@@ -0,0 +1,39 @@
+<?php
+
+use Zend\Form\Form;
+
+/**
+ * @var bool   $enabled
+ * @var Form   $form
+ * @var string $title
+ * @var string $redirect
+ */
+?>
+
+<?php if ($title): ?>
+    <h3 class="password-reset-title">
+        <?php echo $title ?>
+    </h3>
+<?php endif ?>
+
+<?php echo $this->form()->openTag($form) ?>
+
+<?php if (($errors = $this->formErrors($form))): ?>
+    <p><?php echo $errors ?></p>
+<?php endif ?>
+<p class="password-reset-identity">
+    <?php
+    $identity = $form->get($name = 'identity')->setAttributes(['id' => $name, 'class' => 'form-control']);
+    echo $this->formLabel($identity);
+    echo $this->formInput($identity);
+    ?>
+</p>
+<?php if ($redirect): ?>
+    <input type="hidden" name="redirect" value="<?php echo $redirect ?>"/>
+<?php endif ?>
+
+<p class="password-reset-submit">
+    <?php echo $this->formButton($form->get('submit')->setAttribute('class', 'btn btn-primary')) ?>
+</p>
+
+<?php echo $this->form()->closeTag() ?>
diff --git a/view/zfc-user/user/login.phtml b/view/zfc-user/user/login.phtml
index 51ba373..1f6e9a7 100644
--- a/view/zfc-user/user/login.phtml
+++ b/view/zfc-user/user/login.phtml
@@ -1,6 +1,22 @@
-<?php $this->headTitle("Connexion") ?>
+<?php
+/**
+ * @var PhpRenderer $this
+ *
+ * @method LocalConnectViewHelper localConnect()
+ * @method LdapConnectViewHelper ldapConnect()
+ * @method ShibConnectViewHelper shibConnect()
+ */
+
+use UnicaenAuth\View\Helper\LdapConnectViewHelper;
+use UnicaenAuth\View\Helper\LocalConnectViewHelper;
+use UnicaenAuth\View\Helper\ShibConnectViewHelper;
+use Zend\Form\Form;
+use Zend\View\Renderer\PhpRenderer;
+
+$this->headTitle("Connexion") ?>
 
 <?php
+/** @var Form $form */
 $form = $this->loginForm;
 $form->prepare();
 $form->setAttributes([
@@ -25,9 +41,10 @@ $form->setAttributes([
 
     <div class="panel-body">
         <?php
-        $ldapAuthHtml = (string) $this->ldapConnect($form);
-        $shibAuthHtml = (string) $this->shibConnect($form);
-        echo implode('<hr>', array_filter([$ldapAuthHtml, $shibAuthHtml]));
+        $localAuthHtml = (string) $this->localConnect($form);
+        $ldapAuthHtml  = (string) $this->ldapConnect($form);
+        $shibAuthHtml  = (string) $this->shibConnect($form);
+        echo implode('<hr>', array_filter([$ldapAuthHtml, $shibAuthHtml, $localAuthHtml]));
         ?>
     </div>
 </div>
-- 
GitLab