From 097d7f7686533e1c18c6ea672bc23e8c5bf42ca7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20L=C3=A9cluse?= <laurent.lecluse@unicaen.fr>
Date: Fri, 13 Apr 2018 11:23:00 +0200
Subject: [PATCH] =?UTF-8?q?Modification=20de=20la=20conf=20pour=20utiliser?=
 =?UTF-8?q?=20des=20liens=20symboliques=20plut=C3=B4t=20que=20des=20liens?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .gitignore                                    |   5 +-
 CHANGELOG                                     |  10 +-
 bin/ose                                       | 177 +++++++++++++++---
 bin/ose-deploy                                | 139 +++++++++++---
 composer.json                                 |   2 +-
 composer.lock                                 |   8 +-
 config/autoload/unicaen-app.global.php        |   2 +-
 "data/D\303\251ploiement/Changements.pdf"     | Bin 169020 -> 169020 bytes
 .../Proc\303\251dure d'installation.md"       |   5 -
 .../Proc\303\251dure d'installation.pdf"      | Bin 206899 -> 206899 bytes
 ...roc\303\251dure de mise \303\240 jour.pdf" | Bin 162098 -> 162098 bytes
 module/Application/Module.php                 |   3 +
 .../config/administration.config.php          |  17 ++
 .../Controller/AdministrationController.php   |  20 ++
 public/vendor/unicaen/apache-test             |   1 +
 15 files changed, 323 insertions(+), 66 deletions(-)
 create mode 100644 public/vendor/unicaen/apache-test

diff --git a/.gitignore b/.gitignore
index 10c2736d5d..e361fe5c89 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,7 @@ vendor/*
 data/cache/*
 .idea
 deploy.log
-VERSION
\ No newline at end of file
+VERSION
+public/vendor/unincaen/app
+public/vendor/unincaen/import
+public/vendor/unincaen/code
\ No newline at end of file
diff --git a/CHANGELOG b/CHANGELOG
index bf3aa27c6d..8e04a1faa5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -32,6 +32,8 @@ author: Laurent Lécluse - DSI - Unicaen
 L'apparence de l'application peut également être personnalisée en fournissant une URL qui
 pointe vers une feuille de style CSS propre à votre établissement.
 
+* Nouvel outil en ligne de comande permettant de piloter OSE ( `<dossier OSE>/bin/ose help` pour la liste des possibilités)
+
 * Nouvelle procédure d'installation (https://ose.unicaen.fr/deploiement)
 Le déploiement de OSE se fait désormais directement à partir de sa plateforme GitLab.
 
@@ -39,6 +41,8 @@ Le déploiement de OSE se fait désormais directement à partir de sa plateforme
 
 * Suppression des anciens Jobs Oracle et remplacement par des tâches CRON
 
+* Possibilité de changer le mot de passe d'un utilisateur local depuis la ligne de commande
+
 ## Procédure de mise à jour
 
 * Sauvegardez votre fichier de configuration local (`config/application.local.php`)
@@ -65,9 +69,9 @@ Le fichier n'est donc plus placé dans le répertoire `config`, mais à la **rac
 * Modifiez la structure de votre base de données en exécutant dans SQL developer le script de mise à jour suivant :
 `data/Mises à jour/06.3.sql`
 
-* Modifiez votre configuration Apache pour ajouter la ligne suivante :
-`Alias /ose/vendor/unicaen/import	/var/www/ose/vendor/unicaen/import/public`
-`/ose/` et `/var/www/ose/` sont à adapter à votre configuration.
+* Modifiez votre configuration Apache pour supprimer la ligne suivante, qui n'est plus nécessaire :
+`Alias /ose/vendor/unicaen/app	/var/www/ose/vendor/unicaen/app/public`
+`/ose/` et `/var/www/ose/` sont à adapter selon votre configuration.
 Pour plus d'informations, merci de vous reporter à la [procédure d'installation](https://ose.unicaen.fr/deploiement/install.html).
 
 * Créez les tâches CRON suivantes si elles n'existent pas déjà :
diff --git a/bin/ose b/bin/ose
index c4bbc712bd..237c849794 100755
--- a/bin/ose
+++ b/bin/ose
@@ -17,12 +17,12 @@ switch ($action) {
     break;
     case 'migration':
         $oldVersion = $c->getArg(2);
-        $version = $c->getArg(3);
+        $version    = $c->getArg(3);
         /* Action à effectuer */
     break;
     case 'synchronisation':
         $job = $c->getArg(2);
-        $oa->exec('UnicaenImport SyncJob '.$job);
+        $oa->exec('UnicaenImport SyncJob ' . $job);
     break;
     case 'chargens-calcul-effectifs':
         $oa->exec('chargens-calcul-effectifs');
@@ -33,13 +33,18 @@ switch ($action) {
     case 'formule-calcul':
         $oa->exec('formule-calcul');
     break;
+    case 'changement-mot-de-passe':
+        passwordChange($c, $oa);
+    break;
+    case 'maj-public-links':
+        majPublicLinks($c, $oa);
+    break;
     default:
         help($c, $oa);
     break;
 }
 
 
-
 function update(Console $c, OseAdmin $oa)
 {
     $osedir = dirname(__DIR__);
@@ -57,7 +62,7 @@ function update(Console $c, OseAdmin $oa)
     $oldVersion = $oa->currentVersion($osedir);
 
     $c->println("Sélection de la version à déployer", $c::COLOR_LIGHT_CYAN);
-    $c->println("La version actuellement installée est la ".$oldVersion);
+    $c->println("La version actuellement installée est la " . $oldVersion);
     $c->println("Voici la liste des versions de OSE disponibles:");
     $tags = $oa->getTags();
     foreach ($tags as $tag) {
@@ -96,9 +101,14 @@ function update(Console $c, OseAdmin $oa)
         "rm -Rf data/cache/*",
         "php vendor/bin/doctrine-module orm:generate-proxies",
         "chmod -R 777 data/cache/DoctrineProxy",
-        "php bin/ose migration $oldVersion $version"
+        "php bin/ose migration $oldVersion $version",
     ]);
 
+    // Mise à jour des liens vers les répertoires publics des dépendances
+    $c->println("\nMise à jour des liens vers les répertoires publics des dépendances", $c::COLOR_LIGHT_CYAN);
+    $res = $oa->majUnicaenSymLinks($osedir);
+    $c->println($res ? 'Liens mis à jour' : 'Liens déjà à jour', $c::COLOR_LIGHT_GREEN);
+
     // Conclusion
     $c->println("\nFin de la mise à jour des fichiers", $c::COLOR_LIGHT_GREEN);
     $c->println("Il reste encore votre base de données à mettre à jour.");
@@ -108,16 +118,64 @@ function update(Console $c, OseAdmin $oa)
 
 
 
+function passwordChange(Console $c, OseAdmin $oa)
+{
+    $c->println("Veuillez saisir un login :");
+    $login = $c->getInput();
+
+    $c->println("Veuillez maintenant saisir un mot de passe :");
+    $pwd1 = $c->getSilentInput();
+
+    $c->println("Veuillez saisir à nouveau le même mot de passe :");
+    $pwd2 = $c->getSilentInput();
+
+    if ($pwd1 <> $pwd2) {
+        $c->printDie('Les mots de passe saisis ne correspondent pas!');
+    }
+
+    $c->println('Application du changement de mot de pase ...');
+    $oa->exec("changement-mot-de-passe --utilisateur=$login --mot-de-passe=$pwd1");
+
+    $c->println('Mot de passe changé', $c::COLOR_LIGHT_GREEN);
+}
+
+
+
+function majPublicLinks(Console $c, OseAdmin $oa)
+{
+    $osedir = dirname(__DIR__);
+
+    $c->println("\nMise à jour des liens vers les répertoires publics des dépendances", $c::COLOR_LIGHT_CYAN);
+
+    $res = $oa->majUnicaenSymLinks($osedir);
+
+    if ($res){
+        $c->println('Liens mis à jour', $c::COLOR_LIGHT_GREEN);
+    }else{
+        $c->println('Liens déjà à jour', $c::COLOR_LIGHT_GREEN);
+    }
+}
+
+
+
 function help(Console $c, OseAdmin $oa)
 {
-    $c->println('Actions possibles :');
-    $c->println(" - update               : Mise à jour de l'application");
-    $c->println(" - notifier-indicateurs : Envoi des mails relatifs aux indicateurs");
-    $c->println(" - synchronisation <job> : Effectue la synchronisation des données pour le <job> transmis");
-    $c->println(" - chargens-calcul-effectifs : Calcul des effectifs du module Charges");
-    $c->println(" - calcul-tableaux-bord : Recalcule tous les tableaux de bord de calculs itermédiaires");
-    $c->println(" - formule-calcul : Calcul de toutes les heures complémentaires à l'aide de la formule");
+    $actions = [
+        "update"                    => "Mise à jour de l'application",
+        "notifier-indicateurs"      => "Envoi des mails relatifs aux indicateurs",
+        "synchronisation"           => "<job> : Effectue la synchronisation des données pour le <job> transmis",
+        "chargens-calcul-effectifs" => "Calcul des effectifs du module Charges",
+        "calcul-tableaux-bord"      => "Recalcule tous les tableaux de bord de calculs itermédiaires",
+        "formule-calcul"            => "Calcul de toutes les heures complémentaires à l'aide de la formule",
+        "changement-mot-de-passe"   => "Changement de mot de passe (pour un utilisateur local uniquement)",
+        "maj-public-links"          => "Mise à jour des liens vers les répertoires publics des dépendances",
+    ];
 
+    $c->println('Actions possibles :');
+    foreach ($actions as $a => $l) {
+        $c->print($a, $c::COLOR_BLACK, $c::BG_LIGHT_GRAY);
+        $c->println(" : " . $l);
+    }
 }
 
 
@@ -155,6 +213,49 @@ class OseAdmin
 
 
 
+    public function majUnicaenSymLinks($oseDir ): bool
+    {
+        if (substr($oseDir, -1) !== '/') {
+            $oseDir .= '/';
+        }
+
+        $publicDir  = $oseDir . 'public/vendor/unicaen/';
+        $unicaenDir = $oseDir . 'vendor/unicaen/';
+
+        $oldLibs = [];
+        $od      = array_filter(glob($publicDir . '*'), 'is_dir');
+        foreach ($od as $dir) {
+            $oldLibs[] = basename($dir);
+        }
+
+        $newLibs = [];
+        $nd      = array_filter(glob($unicaenDir . '*'), 'is_dir');
+        foreach ($nd as $dir) {
+            if (is_dir($dir . '/public')) {
+                $newLibs[] = basename($dir);
+            }
+        }
+
+        $deleteLibs = array_diff($oldLibs, $newLibs);
+        $createLibs = array_diff($newLibs, $oldLibs);
+
+        foreach ($deleteLibs as $lib) {
+            $command = "rm $publicDir$lib";
+            $this->console->print($command);
+            $this->console->exec($command);
+        }
+
+        foreach ($createLibs as $lib) {
+            $command = "ln -sf $unicaenDir$lib/public $publicDir$lib";
+            $this->console->print($command);
+            $this->console->exec($command);
+        }
+
+        return ! (empty($deleteLibs) && empty($createLibs));
+    }
+
+
+
     public function gitlabIsReachable(): bool
     {
         $gitCheck = $this->console->exec("git ls-remote --heads " . self::OSE_ORIGIN, false);
@@ -225,7 +326,7 @@ class OseAdmin
 
     public function exec($args)
     {
-        $this->console->exec("php ".dirname(__DIR__)."/public/index.php " . $args);
+        $this->console->exec("php " . dirname(__DIR__) . "/public/index.php " . $args);
     }
 }
 
@@ -272,11 +373,11 @@ class Console
         $this->println($this->strPad('Commande (description éventuelle)', $len) . "Résultat");
         $this->println($this->strPad('----------------------', $len) . "--------");
         foreach ($prerequis as $command => $desc) {
-            if (is_array($desc)){
+            if (is_array($desc)) {
                 extract($desc);
-            }else{
+            } else {
                 $description = $desc;
-                $facultatif = false;
+                $facultatif  = false;
             }
 
             $return = null;
@@ -286,15 +387,15 @@ class Console
             $this->print($this->strPad($command . ($description ? " ($description)" : ''), $len));
             if ($passed) {
                 $this->println('Commande trouvée', self::COLOR_LIGHT_GREEN);
-            } elseif($facultatif) {
+            } elseif ($facultatif) {
                 $this->println('Manquante, facultative', self::COLOR_LIGHT_PURPLE);
-            }else{
+            } else {
                 $this->println('Commande manquante', self::COLOR_LIGHT_RED);
                 $res = false;
             }
         }
 
-        if (!$res){
+        if (!$res) {
             $this->printDie('Un ou plusieurs prérequis nécessaires ne sont pas présents sur cette machine. Merci de les installer avant de poursuivre l\'installation.');
         }
 
@@ -358,15 +459,15 @@ class Console
 
 
 
-    public function getArg($index=null)
+    public function getArg($index = null)
     {
         $args = isset($_SERVER['argv']) ? $_SERVER['argv'] : [];
 
         if (null === $index) return $args;
 
-        if (isset($args[$index])){
+        if (isset($args[$index])) {
             return $args[$index];
-        }else{
+        } else {
             return null;
         }
     }
@@ -380,6 +481,38 @@ class Console
 
 
 
+    public function getSilentInput()
+    {
+        if (preg_match('/^win/i', PHP_OS)) {
+            $vbscript = sys_get_temp_dir() . 'prompt_password.vbs';
+            file_put_contents(
+                $vbscript, 'wscript.echo(InputBox("'
+                . addslashes('')
+                . '", "", "password here"))');
+            $command  = "cscript //nologo " . escapeshellarg($vbscript);
+            $password = rtrim(shell_exec($command));
+            unlink($vbscript);
+
+            return $password;
+        } else {
+            $command = "/usr/bin/env bash -c 'echo OK'";
+            if (rtrim(shell_exec($command)) !== 'OK') {
+                trigger_error("Can't invoke bash");
+
+                return;
+            }
+            $command  = "/usr/bin/env bash -c 'read -s -p \""
+                . addslashes('')
+                . "\" mypassword && echo \$mypassword'";
+            $password = rtrim(shell_exec($command));
+            echo "\n";
+
+            return $password;
+        }
+    }
+
+
+
     public function exec($command, $autoDisplay = true)
     {
         if (is_array($command)) {
diff --git a/bin/ose-deploy b/bin/ose-deploy
index 71bd9b39ca..0523ba709b 100644
--- a/bin/ose-deploy
+++ b/bin/ose-deploy
@@ -32,27 +32,29 @@ if (!$od->checkPhpModules([
 };
 
 // Mise en place de la clé SSH
-$c->println("\nMise en place de la clé SSH vers le GitLab hébergeant OSE", $c::COLOR_LIGHT_CYAN);
-$c->println("L'accès au serveur Gitlab doit se faire par SSH.");
-$c->print("Voulez-vous créer une clé SSH pour accéder au serveur Gitlab hébergeant OSE ? (o/n, n par défaut) ");
-$needKey = $c->getInput();
-if (in_array($needKey, ["o", "O"])) {
-    $c->println("Génération de la clé SSH...");
-    $c->print("Veuillez préciser l'adresse mail du compte utilisé pour accéder au Gitlab de OSE: ");
-    $gitlabMail = $c->getInput();
-    $c->passthru("ssh-keygen -t rsa -C $gitlabMail -b 4096");
-    $c->println("Intégrez ensuite votre clé SSH dans Gitlab.");
-    $c->println("Le serveur GitLab est accessible à l'adresse suivante : https://git.unicaen.fr/dsi/OSE");
-    $c->println("Ensuite, appuyez sur \"Entrée\" pour continuer...");
-    $c->getInput();
-    if ($od->gitlabIsReachable()) {
-        $c->println("Votre clé SSH a bien été déployée et est fonctionnelle.", $c::COLOR_LIGHT_GREEN);
+if (!$od->gitlabIsReachable()) {
+    $c->println("\nMise en place de la clé SSH vers le GitLab hébergeant OSE", $c::COLOR_LIGHT_CYAN);
+    $c->println("L'accès au serveur Gitlab doit se faire par SSH.");
+    $c->print("Voulez-vous créer une clé SSH pour accéder au serveur Gitlab hébergeant OSE ? (o/n, n par défaut) ");
+    $needKey = $c->getInput();
+    if (in_array($needKey, ["o", "O"])) {
+        $c->println("Génération de la clé SSH...");
+        $c->print("Veuillez préciser l'adresse mail du compte utilisé pour accéder au Gitlab de OSE: ");
+        $gitlabMail = $c->getInput();
+        $c->passthru("ssh-keygen -t rsa -C $gitlabMail -b 4096");
+        $c->println("Intégrez ensuite votre clé SSH dans Gitlab.");
+        $c->println("Le serveur GitLab est accessible à l'adresse suivante : https://git.unicaen.fr/dsi/OSE");
+        $c->println("Ensuite, appuyez sur \"Entrée\" pour continuer...");
+        $c->getInput();
+        if ($od->gitlabIsReachable()) {
+            $c->println("Votre clé SSH a bien été déployée et est fonctionnelle.", $c::COLOR_LIGHT_GREEN);
+        } else {
+            $c->printDie("L'accès par SSH au serveur GitLab de OSE ne fonctionne pas. Merci de déployer par vous-même une clé, car vous en aurez besoin pour la suite de la procédure.");
+        }
     } else {
-        $c->printDie("L'accès par SSH au serveur GitLab de OSE ne fonctionne pas. Merci de déployer par vous-même une clé, car vous en aurez besoin pour la suite de la procédure.");
-    }
-} else {
-    if (!$od->gitlabIsReachable()) {
-        $c->printDie("L'accès par SSH au serveur GitLab de OSE ne fonctionne pas. Merci de déployer par vous-même une clé, car vous en aurez besoin pour la suite de la procédure.");
+        if (!$od->gitlabIsReachable()) {
+            $c->printDie("L'accès par SSH au serveur GitLab de OSE ne fonctionne pas. Merci de déployer par vous-même une clé, car vous en aurez besoin pour la suite de la procédure.");
+        }
     }
 }
 
@@ -123,6 +125,11 @@ $c->exec([
     "cp config/application.local.php.dist config.local.php",
 ]);
 
+// Mise à jour des liens vers les répertoires publics des dépendances
+$c->println("\nMise à jour des liens vers les répertoires publics des dépendances", $c::COLOR_LIGHT_CYAN);
+$od->majUnicaenSymLinks($osedir);
+$c->println('Liens mis en place', $c::COLOR_LIGHT_GREEN);
+
 // Mise en place des tâches CRON ??
 
 
@@ -133,11 +140,10 @@ $c->println(" 1 - Configurez votre serveur Apache");
 $c->println(" 2 - Initialisez la base de données de OSE avec le script prévu à cet effet");
 $c->println(" 3 - Mettez en place la configuration locale de l'application");
 $c->println(" 4 - Une fois bien connecté, configurez vos connecteurs en vous appuyant\n     le cas échéant sur ceux qui vous sont fournis");
-$c->println(" 5 - Mettez en place les tâches CRON et les JOBS Oracle nécessaires (envoi de mails pour les infdicateurs, Synchronisatio automatique, etc.");
+$c->println(" 5 - Mettez en place les tâches CRON nécessaires (envoi de mails pour les indicateurs, Synchronisation automatique, etc.");
 $c->println(" 6 - Paramétrez l'application pour l'adapter à vos besoins");
 $c->println('');
-$c->println("Pour la suite, merci de vous reporter sur la procédure d'installation de OSE (https://ose.unicaen.fr/deploiement/install)");
-$c->println("OSE possède également un guide de l'administrateur pour vous aider à configurer l'application");
+$c->println("Pour la suite, merci de vous reporter au guide de l'administrateur pour vous aider à configurer l'application");
 $c->println('');
 
 
@@ -175,6 +181,49 @@ class OseDeploy
 
 
 
+    public function majUnicaenSymLinks($oseDir ): bool
+    {
+        if (substr($oseDir, -1) !== '/') {
+            $oseDir .= '/';
+        }
+
+        $publicDir  = $oseDir . 'public/vendor/unicaen/';
+        $unicaenDir = $oseDir . 'vendor/unicaen/';
+
+        $oldLibs = [];
+        $od      = array_filter(glob($publicDir . '*'), 'is_dir');
+        foreach ($od as $dir) {
+            $oldLibs[] = basename($dir);
+        }
+
+        $newLibs = [];
+        $nd      = array_filter(glob($unicaenDir . '*'), 'is_dir');
+        foreach ($nd as $dir) {
+            if (is_dir($dir . '/public')) {
+                $newLibs[] = basename($dir);
+            }
+        }
+
+        $deleteLibs = array_diff($oldLibs, $newLibs);
+        $createLibs = array_diff($newLibs, $oldLibs);
+
+        foreach ($deleteLibs as $lib) {
+            $command = "rm $publicDir$lib";
+            $this->console->print($command);
+            $this->console->exec($command);
+        }
+
+        foreach ($createLibs as $lib) {
+            $command = "ln -sf $unicaenDir$lib/public $publicDir$lib";
+            $this->console->print($command);
+            $this->console->exec($command);
+        }
+
+        return ! (empty($deleteLibs) && empty($createLibs));
+    }
+
+
+
     public function checkPhpModules(array $modules)
     {
         $len = 60;
@@ -312,11 +361,11 @@ class Console
         $this->println($this->strPad('Commande (description éventuelle)', $len) . "Résultat");
         $this->println($this->strPad('----------------------', $len) . "--------");
         foreach ($prerequis as $command => $desc) {
-            if (is_array($desc)){
+            if (is_array($desc)) {
                 extract($desc);
-            }else{
+            } else {
                 $description = $desc;
-                $facultatif = false;
+                $facultatif  = false;
             }
 
             $return = null;
@@ -326,15 +375,15 @@ class Console
             $this->print($this->strPad($command . ($description ? " ($description)" : ''), $len));
             if ($passed) {
                 $this->println('Commande trouvée', self::COLOR_LIGHT_GREEN);
-            } elseif($facultatif) {
+            } elseif ($facultatif) {
                 $this->println('Manquante, facultative', self::COLOR_LIGHT_PURPLE);
-            }else{
+            } else {
                 $this->println('Commande manquante', self::COLOR_LIGHT_RED);
                 $res = false;
             }
         }
 
-        if (!$res){
+        if (!$res) {
             $this->printDie('Un ou plusieurs prérequis nécessaires ne sont pas présents sur cette machine. Merci de les installer avant de poursuivre l\'installation.');
         }
 
@@ -420,6 +469,38 @@ class Console
 
 
 
+    public function getSilentInput()
+    {
+        if (preg_match('/^win/i', PHP_OS)) {
+            $vbscript = sys_get_temp_dir() . 'prompt_password.vbs';
+            file_put_contents(
+                $vbscript, 'wscript.echo(InputBox("'
+                . addslashes('')
+                . '", "", "password here"))');
+            $command  = "cscript //nologo " . escapeshellarg($vbscript);
+            $password = rtrim(shell_exec($command));
+            unlink($vbscript);
+
+            return $password;
+        } else {
+            $command = "/usr/bin/env bash -c 'echo OK'";
+            if (rtrim(shell_exec($command)) !== 'OK') {
+                trigger_error("Can't invoke bash");
+
+                return;
+            }
+            $command  = "/usr/bin/env bash -c 'read -s -p \""
+                . addslashes('')
+                . "\" mypassword && echo \$mypassword'";
+            $password = rtrim(shell_exec($command));
+            echo "\n";
+
+            return $password;
+        }
+    }
+
+
+
     public function exec($command, $autoDisplay = true)
     {
         if (is_array($command)) {
diff --git a/composer.json b/composer.json
index ec3ba225fc..323ccc42d5 100755
--- a/composer.json
+++ b/composer.json
@@ -15,7 +15,7 @@
         "bjyoungblood/bjy-authorize":   "dev-master",
         "zf-commons/zfc-user":          "0.1.3",
         "zendframework/zend-file":      "^2.4",
-        "unicaen/code":                 "1.1.5",
+        "unicaen/code":                 "1.1.6",
         "unicaen/import":               "1.1.6",
         "unicaen/tbl":                  "1.0.3"
     }
diff --git a/composer.lock b/composer.lock
index e5ae04b7f4..68dcdf1eea 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "d1c736056c2956117533af943f5a0618",
+    "content-hash": "a0650787c87b941797d1f4e117fc7145",
     "packages": [
         {
             "name": "bjyoungblood/bjy-authorize",
@@ -1529,11 +1529,11 @@
         },
         {
             "name": "unicaen/code",
-            "version": "1.1.5",
+            "version": "1.1.6",
             "source": {
                 "type": "git",
                 "url": "https://git.unicaen.fr/lib/unicaen/code.git",
-                "reference": "2890c341e174c6212b873e10649d7603a2f0abd4"
+                "reference": "607fe27c60c3c90a6c953cf2b16bfdbdc8b54d17"
             },
             "require": {
                 "doctrine/dbal": "^2.5",
@@ -1551,7 +1551,7 @@
                 ]
             },
             "description": "Boite à outils pour la programmation avec la bibliothèque Unicaen",
-            "time": "2018-04-04T14:06:04+00:00"
+            "time": "2018-04-12T15:24:29+00:00"
         },
         {
             "name": "unicaen/import",
diff --git a/config/autoload/unicaen-app.global.php b/config/autoload/unicaen-app.global.php
index b37e8544b5..1c4ca0b05a 100644
--- a/config/autoload/unicaen-app.global.php
+++ b/config/autoload/unicaen-app.global.php
@@ -5,7 +5,7 @@ if (file_exists($versionFile)){
 }else{
     $version = 'inconnue';
 }
-$dateVersion = '12/04/2018';
+$dateVersion = '13/04/2018';
 
 return [
     'unicaen-app' => [
diff --git "a/data/D\303\251ploiement/Changements.pdf" "b/data/D\303\251ploiement/Changements.pdf"
index 170d6983eba0924dd39dc4eaf44a0e7f3eec456d..3bd5deea2250ff70c77265ffd685e1cd4f1994e0 100644
GIT binary patch
delta 133
zcmdn9f@{wTu7(!IEldsV8s^3(h6dUOM(PFz>Y7~ozWFIGi6yBD8ZK5w28I>}CWc0a
zU?tmEv@=C=JG&UUIJub`JDR!~n7Em_SQwi*S~^=88M&F6nYvh-I@&4N5K=PTWirzb
E0BYDG)&Kwi

delta 133
zcmdn9f@{wTu7(!IEldsV8fHeO2A0|eM(PFz>Y7~ozWFIGi6yBD8ZK5w28I>}CWc0a
zU?tmEv@=C=J3Bc$IvSgsyBeFDJGz(}x>~rJnY$PpSvnh-nYtO9n%gPZ5K=PTWirzb
E0Br&y!T<mO

diff --git "a/data/D\303\251ploiement/Proc\303\251dure d'installation.md" "b/data/D\303\251ploiement/Proc\303\251dure d'installation.md"
index f3d6d47909..243af27ba5 100644
--- "a/data/D\303\251ploiement/Proc\303\251dure d'installation.md"	
+++ "b/data/D\303\251ploiement/Proc\303\251dure d'installation.md"	
@@ -65,9 +65,6 @@ A adapter à vos besoins.
 	ServerName ose.unicaen.fr
 	DocumentRoot /var/www/ose/public
 
-	Alias /vendor/unicaen/app       /var/www/ose/vendor/unicaen/app/public
-	Alias /vendor/unicaen/import    /var/www/ose/vendor/unicaen/import/public
-
 	RewriteEngine On
 	RewriteBase /
 
@@ -95,8 +92,6 @@ A adapter à vos besoins.
 Exemple pris avec /var/www/ose en répertoire d'installation et /ose en Alias.
 A adapter à vos besoins.
 ```apache
-Alias /ose/vendor/unicaen/app	    /var/www/ose/vendor/unicaen/app/public
-Alias /ose/vendor/unicaen/import	/var/www/ose/vendor/unicaen/import/public
 Alias /ose			                /var/www/ose/public
 
 <Directory /var/www/ose/public>
diff --git "a/data/D\303\251ploiement/Proc\303\251dure d'installation.pdf" "b/data/D\303\251ploiement/Proc\303\251dure d'installation.pdf"
index 8c5da9e2c5aa52921782c4bdc6151f738d054ea5..26fe5564e70b14026c0cb7c2dba357ce59938ec7 100644
GIT binary patch
delta 111
zcmdmdfoJmto`x327N#xCUSh1~#wG^l)BVMm<si)MMPkfx{7z0TrY^>Y&aRfmmX;>Y
iZU*M2rshT_#?Houj&2r)W-fLLHUyMx7gA$ZWC8$S92&j=

delta 111
zcmdmdfoJmto`x327N#xCUSh0fMy3X4)BVMm<si)MMPkfx{7$AOCYBb?F6L&2#;z_-
i7OpO4M&_<Y#zv+l7M8|_7A|%QHUyMx7gA$ZWC8$Kff|?q

diff --git "a/data/D\303\251ploiement/Proc\303\251dure de mise \303\240 jour.pdf" "b/data/D\303\251ploiement/Proc\303\251dure de mise \303\240 jour.pdf"
index c4be40231e8600502bd81d33b88deb4871782190..08b3e6e2b8c00f54f7c708fccf54ee48ba113dbd 100644
GIT binary patch
delta 105
zcmdn=iF4B@&W0AoElkC^%;v@>)5~(16hMsaGjo|Dxtt9wjE#&<4P0F<T@8#)Oe|cD
dEDhZp&5bPGj7^*@Or7i$YzQftZd$?g7XU`v97X^D

delta 105
zcmdn=iF4B@&W0AoElkC^%w|TW)5~(16hMsaGjo|DxtxtnoLw!9jf_lOO^jR&j7%)u
dEFH})oea!ejf`BK-7M`CYzQftZd$?g7XVM@9E1P>

diff --git a/module/Application/Module.php b/module/Application/Module.php
index e08855cfc3..ccd62d49a6 100755
--- a/module/Application/Module.php
+++ b/module/Application/Module.php
@@ -167,6 +167,9 @@ class Module implements ConsoleUsageProviderInterface, ConsoleBannerProviderInte
             'calcul-tableaux-bord' => "Calcul de tous les tableaux de bord (sauf la formule qui est à part)",
             "Formule de calcul",
             'formule-calcul' => "Calcul de toutes les heures complémentaires à l'aide de la formule",
+
+            "Administration : Changement de mot de passe",
+            'changement-mot-de-passe' => "Paramètres : --utilisateur, --mot-de-passe",
         ];
     }
 
diff --git a/module/Application/config/administration.config.php b/module/Application/config/administration.config.php
index 743da826ee..09877f67bb 100644
--- a/module/Application/config/administration.config.php
+++ b/module/Application/config/administration.config.php
@@ -21,6 +21,23 @@ return [
             ],
         ],
     ],
+
+    'console' => [
+        'router' => [
+            'routes' => [
+                'changement-mot-de-passe' => [
+                    'options' => [
+                        'route'    => 'changement-mot-de-passe [--utilisateur=] [--mot-de-passe=]',
+                        'defaults' => [
+                            'controller' => 'Application\Controller\Administration',
+                            'action'     => 'changement-mot-de-passe',
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
     'navigation'      => [
         'default' => [
             'home' => [
diff --git a/module/Application/src/Application/Controller/AdministrationController.php b/module/Application/src/Application/Controller/AdministrationController.php
index 627bab418c..a14d877c10 100644
--- a/module/Application/src/Application/Controller/AdministrationController.php
+++ b/module/Application/src/Application/Controller/AdministrationController.php
@@ -2,6 +2,8 @@
 
 namespace Application\Controller;
 
+use Application\Service\Traits\UtilisateurServiceAwareTrait;
+
 
 /**
  * Description of AdministrationController
@@ -11,6 +13,9 @@ namespace Application\Controller;
  */
 class AdministrationController extends AbstractController
 {
+    use UtilisateurServiceAwareTrait;
+
+
 
     /**
      *
@@ -21,4 +26,19 @@ class AdministrationController extends AbstractController
         return [];
     }
 
+
+
+    public function changementMotDePasseAction()
+    {
+        $utilisateur = $this->getRequest()->getParam('utilisateur');
+        $motDePasse  = $this->getRequest()->getParam('mot-de-passe');
+
+        $userObject = $this->getServiceUtilisateur()->getByUsername($utilisateur);
+        if (!$userObject) {
+            throw new \Exception("Utilisateur $utilisateur non trouvé");
+        }
+
+        $userObject->setPassword($motDePasse, true);
+        $this->getServiceUtilisateur()->save($userObject);
+    }
 }
\ No newline at end of file
diff --git a/public/vendor/unicaen/apache-test b/public/vendor/unicaen/apache-test
new file mode 100644
index 0000000000..a37e3be172
--- /dev/null
+++ b/public/vendor/unicaen/apache-test
@@ -0,0 +1 @@
+APACHE TEST OK 
\ No newline at end of file
-- 
GitLab