diff --git a/VERSIONS_HOTLINE/157882 b/VERSIONS_HOTLINE/157882
new file mode 100644
index 0000000000000000000000000000000000000000..cdaf0f071ff513e80051191c2f1f5ba84aa410af
--- /dev/null
+++ b/VERSIONS_HOTLINE/157882
@@ -0,0 +1 @@
+ - correctif #157882 : Correction de la prise en compte du droit de groupe "Modification des bibliothèques" pour autoriser la modification de la fiche bibliothèque par les utilisateurs avec le rôle "Rédacteur bibliothèque" 
\ No newline at end of file
diff --git a/application/modules/admin/controllers/BibController.php b/application/modules/admin/controllers/BibController.php
index e32b344ea7957a1d2270dbe867ee41245c7107d6..8df7d192c09bcc46dd30ce3c2199fd38cfd41316 100644
--- a/application/modules/admin/controllers/BibController.php
+++ b/application/modules/admin/controllers/BibController.php
@@ -24,7 +24,8 @@ class Admin_BibController extends ZendAfi_Controller_Action {
 
   public function getPlugins() {
     return [ZendAfi_Controller_Plugin_ResourceDefinition_Library::class,
-            ZendAfi_Controller_Plugin_Manager_Library::class];
+            ZendAfi_Controller_Plugin_Manager_Library::class,
+            ZendAfi_Controller_Plugin_Rights_Library::class];
   }
 
 
@@ -41,11 +42,9 @@ class Admin_BibController extends ZendAfi_Controller_Action {
 
   public function indexAction() {
     $this->view->titre = $this->view->_('Gestion des bibliothèques');
-    if (!$this->canAccessToLibrary())
-      return $this->_redirect('admin/index');
 
     $user = Class_Users::getIdentity();
-    $this->view->libraries = $user->isAdminBib()
+    $this->view->libraries = $user->isRoleLibraryLimited()
       ? [$user->getBib()]
       : Class_Bib::findAllByIdZone($this->id_zone);
   }
@@ -387,22 +386,6 @@ class Admin_BibController extends ZendAfi_Controller_Action {
   }
 
 
-  public function canAccessToLibrary() {
-    $user = Class_Users::getIdentity();
-    if (!$user->hasRightsOnLibraries())
-      return false;
-
-    $id = (int)($this->_request->isPost()) ?
-      $this->_request->getPost('id_bib') :
-      $this->_request->getParam('id');
-
-    if(!$id)
-      return true;
-
-    return $user->hasRightsForLibrary($id);
-  }
-
-
   public function saveDefaultsAction() {
     if(!$widget = (new Class_Systeme_Widget_Widget())
        ->setId((int)$this->_getParam('id_module', 0))
diff --git a/application/modules/admin/controllers/CatalogueController.php b/application/modules/admin/controllers/CatalogueController.php
index afae82b52e6b7f45ced410538746e4f57258255d..2d53548456c68a0d35ed0657dc68e8cdfe4a8e57 100644
--- a/application/modules/admin/controllers/CatalogueController.php
+++ b/application/modules/admin/controllers/CatalogueController.php
@@ -44,16 +44,8 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action {
   }
 
 
-  protected function _findAccessibleLibrariesForDomainsListMode() {
-    $libraries = Class_Bib::findAllAccessibleToCurrentUser();
-    if (($this->_user->hasRightToAccess(Class_UserGroup::RIGHT_USER_DOMAINES_TOTAL_ACCESS)
-         ||
-         $this->_user->hasRightToAccess(Class_UserGroup::RIGHT_USER_DOMAINES_SUPPRESSION_LIMIT)
-         ||
-         !$this->_user->hasUserGroups()) && $this->_user->isRoleLibraryLimited()) {
-      $libraries []= Class_Bib::getPortail();
-    }
-    return $libraries;
+  protected function _findAccessibleLibrariesForDomainsListMode() : array {
+    return Class_Bib::findAllForCurrentUserAndPortal();
   }
 
 
@@ -64,7 +56,7 @@ class Admin_CatalogueController extends ZendAfi_Controller_Action {
 
     $library = ($id_bib = $this->_getParam('id_bib', null))
       ? Class_Bib::find($id_bib)
-      : Class_Bib::findForCurrentUser();
+      : Class_Bib::getPortail();
 
     if (!$domain = Class_Catalogue::find($this->_getParam('id', null)))
       $domain = Class_Catalogue::newInstanceWithId(null,
diff --git a/application/modules/admin/controllers/CmsController.php b/application/modules/admin/controllers/CmsController.php
index f2f56ca4b3b0de46f6929494b8e98e7c40e97410..2ef7edf2824679b1f3e8c76a35dd3c1a20e82aba 100644
--- a/application/modules/admin/controllers/CmsController.php
+++ b/application/modules/admin/controllers/CmsController.php
@@ -38,8 +38,10 @@ class Admin_CmsController extends ZendAfi_Controller_Action {
 
 
   protected function _renderList() {
-    $bibs = Class_Bib::findAllAccessibleToCurrentUser();
-    $current_library = Class_Bib::findForCurrentUser();
+    $bibs = Class_Bib::findAllForCurrentUserAndPortal();
+    $current_library = ($this->identity->isAdmin())
+      ? null
+      : $this->identity->getBib();
 
     $ids = array_map(function($model)
                      {
@@ -52,9 +54,9 @@ class Admin_CmsController extends ZendAfi_Controller_Action {
     $status = $this->_getParam(ZendAfi_Controller_Action_Helper_ListViewMode_Article::STATUS_SEARCH, '');
 
     $id_bib = $this->_getParam('id_bib',
-                               $this->identity->isRoleLibraryLimited()
-                               ? $current_library->getId()
-                               : null);
+                               ($current_library
+                                ? $current_library->getId()
+                                : null));
 
     $article = ($id_article = $this->_getParam('id', null))
       ? Class_Article::find($id_article)
@@ -99,7 +101,7 @@ class Admin_CmsController extends ZendAfi_Controller_Action {
     if (Class_AdminVar::isArticlesListMode())
       return $this->_renderList();
 
-    $bibs = Class_Bib::findAllAccessibleToCurrentUser();
+    $bibs = Class_Bib::findAllForCurrentUserAndPortal();
 
     $add_link_builder = function($bib) {
       $links = [];
diff --git a/application/modules/admin/controllers/OuverturesController.php b/application/modules/admin/controllers/OuverturesController.php
index cb3acc02480e74ffc156e5861de70aad4fd40b76..174539cefdeb8aa1beb757eae74c3b832fd21aea 100644
--- a/application/modules/admin/controllers/OuverturesController.php
+++ b/application/modules/admin/controllers/OuverturesController.php
@@ -20,11 +20,14 @@
  */
 
 class Admin_OuverturesController extends ZendAfi_Controller_Action {
+
   protected $_library, $_is_used_for = null;
 
+
   public function getPlugins() {
-    return ['ZendAfi_Controller_Plugin_ResourceDefinition_Opening',
-            'ZendAfi_Controller_Plugin_Manager_Opening'];
+    return [ZendAfi_Controller_Plugin_ResourceDefinition_Opening::class,
+            ZendAfi_Controller_Plugin_Manager_Opening::class,
+            ZendAfi_Controller_Plugin_Rights_Library::class];
   }
 
 
diff --git a/application/modules/admin/controllers/WidgetController.php b/application/modules/admin/controllers/WidgetController.php
index e6bb5627b3051c8ab4c9c9b6273f818d9edfad02..a23ed60aede2ecbe62a7562f3e655c5b5935170d 100644
--- a/application/modules/admin/controllers/WidgetController.php
+++ b/application/modules/admin/controllers/WidgetController.php
@@ -326,9 +326,6 @@ class Admin_WidgetController extends ZendAfi_Controller_Action {
   public function widgetActionAction() {
     $id_module = $this->_getParam('id_module');
 
-    if (Class_Profil::getCurrentProfil()->getId() !== (int)$this->_getParam('id_profil'))
-      throw new Zend_Controller_Action_Exception($this->view->_('Profil inexistant'), 404);
-
     if (!$config = Class_Profil::getCurrentProfil()->getLocalModuleAccueilConfig($id_module))
       throw new Zend_Controller_Action_Exception($this->view->_('Boite inexistante'), 404);
 
diff --git a/library/Class/Bib.php b/library/Class/Bib.php
index 61d924c4470d9d81284374d18ffd5e29df44f24e..c4249991999744dedaf7f7439b5551e91e6074ec 100644
--- a/library/Class/Bib.php
+++ b/library/Class/Bib.php
@@ -182,7 +182,7 @@ class BibLoader extends Storm_Model_Loader {
   }
 
 
-  public function getAvailableBibFor($user) {
+  public function canBeDeletedOrModifyByUser(Class_Users $user) : array {
     $portail = $this->_('Portail');
 
     if ($user->isSuperAdmin())
@@ -197,7 +197,12 @@ class BibLoader extends Storm_Model_Loader {
       return $labels;
     }
 
-    return [$portail];
+    $availables_libraries = [$portail];
+
+    if ($user === Class_Users::getIdentity() && $library = $user->getBib())
+      $availables_libraries [$library->getId()] = $library->getLabel();
+
+    return $availables_libraries;
   }
 
 
@@ -274,22 +279,15 @@ class BibLoader extends Storm_Model_Loader {
   }
 
 
-  public function findAllAccessibleToCurrentUser() {
-    $current_library = $this->findForCurrentUser();
-    if (!$current_library->isPortail())
-      return [$current_library];
-
-    $libraries = Class_Bib::findAllBy(['order' => 'libelle']);
-    array_unshift($libraries, $current_library);
-    return $libraries;
+  public function findAllForCurrentUserAndPortal() : array {
+    return ['0' => Class_Bib::getPortail(), ...$this->_findAllForCurrentUser()];
   }
 
 
-  public function findForCurrentUser() {
-    $current_user = Class_Users::getIdentity();
-    return $current_user->isRoleLibraryLimited()
-      ? $current_user->getBib()
-      : $this->getPortail();
+  protected function _findAllForCurrentUser() : array {
+    return (! Class_Users::isCurrentUserAdmin()) && ($user_library = Class_Users::getIdentity()->getBib())
+      ? [$user_library]
+      : Class_Bib::findAllBy(['order' => 'libelle']);
   }
 }
 
diff --git a/library/Class/Catalogue.php b/library/Class/Catalogue.php
index 002bd88085c9b8e81566e50c9f3c33ac34e80669..bd472abc7592116f5cc298b43cde52906db34ac7 100644
--- a/library/Class/Catalogue.php
+++ b/library/Class/Catalogue.php
@@ -569,15 +569,12 @@ class Class_Catalogue extends Storm_Model_Abstract {
 
 
   public function canBeDeletedOrModifyByUser($user) {
-    if ($user->isAdmin()) {
+    if ($user->isAdmin())
       return true;
-    }
 
     if (Class_AdminVar::isModuleEnabled('ENABLE_DOMAINS_PER_LIBRARIES')
-        && $user->isRoleLibraryLimited()
-        && (!in_array($this->getOwnOrParentLibraryId(), [0, $user->getIdSite()]))) {
+        && (!in_array($this->getOwnOrParentLibraryId(), [0, $user->getIdSite()])))
       return false;
-    }
 
     if ($user->hasRightToAccess(Class_UserGroup::RIGHT_USER_DOMAINES_TOTAL_ACCESS))
       return true;
diff --git a/library/Class/Profil.php b/library/Class/Profil.php
index 32c2ece5567af78639a594ff9e99010bcfa32a36..c2034d915d7b7dc2e14d95ffb0ebe208e3f17a68 100644
--- a/library/Class/Profil.php
+++ b/library/Class/Profil.php
@@ -96,18 +96,17 @@ class ProfilLoader extends Storm_Model_Loader {
   }
 
 
-  public function findTopForUser($user) {
-    if (!$user)
-      return [];
-
-    return ($user->isRoleLibraryLimited() && ($library = $user->getBib()))
-      ? Class_Profil::findTopForLibrary($library)
-      : Class_Profil::findTopProfils();
+  public function findTopForUser(Class_Users $user) : array {
+    return ($user->isAdmin() || ( ! $library = $user->getBib()))
+      ? Class_Profil::findTopProfils()
+      : Class_Profil::findTopForLibrary($library);
   }
 
 
-  public function findTopForCurrentUser() {
-    return Class_Profil::findTopForUser(Class_Users::getIdentity());
+  public function findTopForCurrentUser() : array {
+    return ($user = Class_Users::getIdentity())
+      ? Class_Profil::findTopForUser(Class_Users::getIdentity())
+      : [];
   }
 
 
diff --git a/library/Class/Users.php b/library/Class/Users.php
index 86e0a39cb12d3762efaf2feeaf0fd2c56fdaa5d5..142fb739071ed40ae1a95392c6dd0c17ccae9e95 100644
--- a/library/Class/Users.php
+++ b/library/Class/Users.php
@@ -193,9 +193,10 @@ class UsersLoader extends Storm_Model_Loader {
   }
 
 
-  public function isCurrentUserAllowedToEditLibrary($library) {
-    if(!$user = Class_Users::getIdentity())
+  public function hasCurrentUserRightsOnLibrary(Class_Bib $library) : bool {
+    if( ! $user = Class_Users::getIdentity())
       return false;
+
     return $user->hasRightsForLibrary($library->getId());
   }
 
@@ -552,6 +553,11 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
+  public function isRoleLibraryLimited() {
+    return $this->getRoleLevel() < ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL;
+  }
+
+
   public function getLibelleBib() {
     return ($library = $this->getLibrary()) ? $library->getLibelle() : '';
   }
@@ -645,11 +651,6 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
-  public function isRoleLibraryLimited() {
-    return ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB >= $this->getRoleLevel();
-  }
-
-
   public function setModeContact($mode_contact) {
     if (static::MODE_CONTACT_MAIL == $mode_contact)
       return $this->setIsContactMail(true)->setIsContactSms(false);
@@ -679,14 +680,17 @@ class Class_Users extends Storm_Model_Abstract {
 
 
   public function hasRightsOnLibraries() {
-    return $this->getRoleLevel() >= ZendAfi_Acl_AdminControllerRoles::ADMIN_BIB;
+    return (new ZendAfi_Acl_AdminControllerGroup)->isAllowed($this, 'bib', 'index');
   }
 
 
-  public function hasRightsForLibrary($id) {
-    if($this->isAdminBib() && ($this->getIdSite() != $id))
+  public function hasRightsForLibrary(string $id) : bool {
+    if ( ! $this->hasRightsOnLibraries())
       return false;
-    return $this->hasRightsOnLibraries();
+
+    return $this->getIdSite() == $id
+      ? true
+      : $this->isAdmin();
   }
 
 
@@ -1863,11 +1867,10 @@ class Class_Users extends Storm_Model_Abstract {
   }
 
 
-  public function getRedmineLibraries() {
-    if ($this->getRoleLevel() >= ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL)
-      return Class_Bib::findAllRedmineEnabled();
-
-    return [$this->getRedmineLibrary()];
+  public function getRedmineLibraries() : array {
+    return $this->isAdmin()
+      ? Class_Bib::findAllRedmineEnabled()
+      : [$this->getRedmineLibrary()];
   }
 
 
diff --git a/library/ZendAfi/Acl/AdminControllerGroup.php b/library/ZendAfi/Acl/AdminControllerGroup.php
index 0618ce8d0cce81f1562f2087052ebf350afbda0a..72fe1c455ebcaa87528631229dcdbb52fe33a4c5 100644
--- a/library/ZendAfi/Acl/AdminControllerGroup.php
+++ b/library/ZendAfi/Acl/AdminControllerGroup.php
@@ -81,7 +81,16 @@ class ZendAfi_Acl_AdminControllerGroup {
      'file-manager' => null,
      'bib/articles' => [Class_UserGroup::RIGHT_USER_CONFIG_FRONT,
                         Class_UserGroup::RIGHT_GERER_LETTRESINFO],
-     'bib' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/index' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/edit' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/localisations' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/plans' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/addplan' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/plansmaj' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/plansdelete' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/addlocalisation' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/localisationsmaj' => Class_UserGroup::RIGHT_EDITER_BIB,
+     'bib/localisationsdelete' => Class_UserGroup::RIGHT_EDITER_BIB,
      'lieu' => Class_UserGroup::RIGHT_EDITER_BIB,
      'ouvertures' => Class_UserGroup::RIGHT_EDITER_BIB,
     ],
diff --git a/library/ZendAfi/Controller/Action.php b/library/ZendAfi/Controller/Action.php
index b3e4007cd0cd69ff8034f8717fb53e57311995ba..0dfe1abecd0df82ccef18550fcf660df003fb09e 100644
--- a/library/ZendAfi/Controller/Action.php
+++ b/library/ZendAfi/Controller/Action.php
@@ -75,7 +75,6 @@ class ZendAfi_Controller_Action extends Zend_Controller_Action {
   public function init() {
     parent::init();
     $this->_helper = new ZendAfi_Controller_Action_Helper($this);
-    $this->_helper->redirector->setExit(false);
   }
 
 
@@ -118,7 +117,31 @@ class ZendAfi_Controller_Action extends Zend_Controller_Action {
   }
 
 
+  protected function _getRedirectUrl() : string {
+    return $this->_response->isRedirect()
+      ? (string) $this->_helper->redirector->getRedirectUrl()
+      : '';
+  }
+
+
+  public function dispatch($action) {
+    $this->_helper->notifyPreDispatch();
+    $this->preDispatch();
+
+    if ($redirect_url = $this->_getRedirectUrl())
+      return $this->_redirectClose($redirect_url);
+
+    if ( $this->_request->isDispatched()){
+      $this->$action();
+      $this->postDispatch();
+    }
+
+    $this->_helper->notifyPostDispatch();
+  }
+
+
   public function preDispatch() {
+    parent::preDispatch();
     $this->view->plugins = $this->_getActionPlugins();
 
     if ($this->isPopupRequest())
@@ -142,6 +165,7 @@ class ZendAfi_Controller_Action extends Zend_Controller_Action {
     $this->_helper->notify($this->_('Le profil %d n\'existe pas.',
                                     $this->_request->getParam('id_profil', 0)),
                            ['status' => 'error']);
+
     return $this->_redirectToIndex();
   }
 
diff --git a/library/ZendAfi/Controller/Action/Helper/Abstract.php b/library/ZendAfi/Controller/Action/Helper/Abstract.php
index 21c4def0edaaa46366cf6e3706da7f9f0c821ff5..ec69f60b21acffad58828585910ec63d121e8a92 100644
--- a/library/ZendAfi/Controller/Action/Helper/Abstract.php
+++ b/library/ZendAfi/Controller/Action/Helper/Abstract.php
@@ -39,6 +39,7 @@ class ZendAfi_Controller_Action_Helper_Abstract
     $this->_response = $this->getResponse();
     $this->_controller = $this->getActionController();
     $this->_view = $this->_controller->view;
+    return $this;
   }
 
 
diff --git a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Article.php b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Article.php
index 449d2e6a55caac045a5681e865a51bd247df8de0..f0a73a0930cf14b2f5ac2c895a9f8bf77df854b0 100644
--- a/library/ZendAfi/Controller/Action/Helper/ListViewMode/Article.php
+++ b/library/ZendAfi/Controller/Action/Helper/ListViewMode/Article.php
@@ -315,7 +315,7 @@ class ZendAfi_Controller_Action_Helper_ListViewMode_Article
                     'label' => $this->getBibLabel(),
                     'options' => []]];
 
-    if (Class_Users::getIdentity()->isRoleLibraryLimited())
+    if (!Class_Users::isCurrentUserAdmin())
       $breadcrumb = [['url' => ['module' => 'admin',
                                 'controller' => 'cms',
                                 'action' => 'index'],
diff --git a/library/ZendAfi/Controller/Plugin/AdminAuth.php b/library/ZendAfi/Controller/Plugin/AdminAuth.php
index b1771e1d8e51609d1fcd510dd0c0fd3d95f3ec4d..adbec4d2b1685d6db26b28210475211ac29f71bd 100644
--- a/library/ZendAfi/Controller/Plugin/AdminAuth.php
+++ b/library/ZendAfi/Controller/Plugin/AdminAuth.php
@@ -27,6 +27,8 @@
  */
 
 class ZendAfi_Controller_Plugin_AdminAuth extends Zend_Controller_Plugin_Abstract {
+
+
   public function preDispatch(Zend_Controller_Request_Abstract $request)   {
     $module = $this->_request->getModuleName();
     $controller = $this->_request->getControllerName();
diff --git a/library/ZendAfi/Controller/Plugin/Manager/Library.php b/library/ZendAfi/Controller/Plugin/Manager/Library.php
index 2bfba8dab47f6650c8ee84517ac6be3ff56044ab..f1f84ba593a88622584dc7a88010117d38a4e33d 100644
--- a/library/ZendAfi/Controller/Plugin/Manager/Library.php
+++ b/library/ZendAfi/Controller/Plugin/Manager/Library.php
@@ -21,16 +21,6 @@
 
 
 class ZendAfi_Controller_Plugin_Manager_Library extends ZendAfi_Controller_Plugin_Manager_Manager {
-  protected function _canEdit($model) {
-    return $this->_controller->canAccessToLibrary();
-  }
-
-
-  protected function _canAdd() {
-    return $this->_controller->canAccessToLibrary();
-  }
-
-
 
   protected function _doBeforeSave($model) {
     if ($location = $this->_controller->getOrCreateLocation($this->_getParam('id_lieu'), $model))
@@ -85,26 +75,14 @@ class ZendAfi_Controller_Plugin_Manager_Library extends ZendAfi_Controller_Plugi
 
 
   public function getActions($model) {
-    $is_allowed = function ($action) {
-      $user = Class_Users::getIdentity();
-      return (new ZendAfi_Acl_AdminControllerGroup)
-      ->isAllowed($user,'bib',$action);
-    };
-
     return [['url' => '/admin/bib/edit/id/%s',
              'icon' => 'edit',
-             'label' => $this->_('Modifier la bibliothèque'),
-             'condition' => function() use ($is_allowed) {
-               return $is_allowed('edit');
-             }],
+             'label' => $this->_('Modifier la bibliothèque')],
 
             ['url' => '/admin/bib/delete/id/%s',
              'icon' => 'delete',
              'label' => $this->_('Supprimer la bibliothèque'),
-             'condition' => function() use ($is_allowed) {
-                return $is_allowed('delete')
-                && !Class_Users::getIdentity()->isRoleLibraryLimited();
-             }],
+             'condition' => fn() => Class_Users::isCurrentUserAdmin()],
 
             ['url' => '/admin/bib/plans/id_bib/%s',
              'icon' => 'map',
diff --git a/library/ZendAfi/Controller/Plugin/Rights/Library.php b/library/ZendAfi/Controller/Plugin/Rights/Library.php
new file mode 100644
index 0000000000000000000000000000000000000000..358cb788a9c22b4bc82cb1ee0cb1624a9338e920
--- /dev/null
+++ b/library/ZendAfi/Controller/Plugin/Rights/Library.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright (c) 2012-2022, 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_Controller_Plugin_Rights_Library extends ZendAfi_Controller_Plugin_Abstract {
+
+  public function init() {
+    parent::init();
+
+    if ( ! $id_bib = $this->_getParam('id_bib', $this->_getParam('id', $this->_getParam('id_site', '0'))))
+      return;
+
+    if (!$library = Class_Bib::find($id_bib))
+      return;
+
+    if (Class_Users::hasCurrentUserRightsOnLibrary($library))
+      return;
+
+    $this->_helper->notify($this->_('Vous ne disposez pas des permissions suffisantes pour gérer la bibliothèque %s.',
+                                    $library->getLabel()));
+
+    $this->_redirectClose($this->_getReferer());
+  }
+}
diff --git a/library/ZendAfi/Form/Admin/User.php b/library/ZendAfi/Form/Admin/User.php
index c920872b710ec6dc43636bf5109eeb29081f2868..91c9bd6e7955e5819fda145f218beec08052d8c6 100644
--- a/library/ZendAfi/Form/Admin/User.php
+++ b/library/ZendAfi/Form/Admin/User.php
@@ -148,7 +148,7 @@ class ZendAfi_Form_Admin_User extends ZendAfi_Form {
       ->addElement('select',
                    'id_site',
                    ['label' => $this->_('Bibliothèque'),
-                    'multiOptions' => Class_Bib::getAvailableBibFor($this->_user)]);
+                    'multiOptions' => Class_Bib::canBeDeletedOrModifyByUser($this->_user)]);
 
     if (Class_Users::getIdentity()->isAdminBib() || Class_Users::getIdentity()->isAdmin())
       $this->addElement('userGroup',
diff --git a/library/ZendAfi/View/Helper/TagEditLibrary.php b/library/ZendAfi/View/Helper/TagEditLibrary.php
index d1d93672064ccf6d9e20beb04d18bcebe8c0de30..6b136966d37365a2edb918d3ba19d8911876138c 100644
--- a/library/ZendAfi/View/Helper/TagEditLibrary.php
+++ b/library/ZendAfi/View/Helper/TagEditLibrary.php
@@ -19,12 +19,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
-class ZendAfi_View_Helper_TagEditLibrary extends Zend_View_Helper_HtmlElement {
-  public function tagEditLibrary($library) {
-    if(!Class_Users::isCurrentUserAllowedToEditLibrary($library))
-      return '';
-
-    return $this->_renderEditLibrary($library);
+class ZendAfi_View_Helper_TagEditLibrary extends ZendAfi_View_Helper_BaseHelper {
+  public function tagEditLibrary(Class_Bib $library) : string {
+    return Class_Users::hasCurrentUserRightsOnLibrary($library)
+      ? $this->_renderEditLibrary($library)
+      : '';
   }
 
 
diff --git a/library/ZendAfi/View/Helper/TagEditOpenings.php b/library/ZendAfi/View/Helper/TagEditOpenings.php
index afb677fba11698aea5eaeabe7601f27565188496..3911d2ef676c2cf006e5cc558a66fd756e305a08 100644
--- a/library/ZendAfi/View/Helper/TagEditOpenings.php
+++ b/library/ZendAfi/View/Helper/TagEditOpenings.php
@@ -19,23 +19,22 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
-class ZendAfi_View_Helper_TagEditOpenings extends Zend_View_Helper_HtmlElement {
-  public function tagEditOpenings($library) {
-    if(!Class_Users::isCurrentUserAllowedToEditLibrary($library))
-      return '';
+class ZendAfi_View_Helper_TagEditOpenings extends ZendAfi_View_Helper_BaseHelper {
 
-    return $this->view->tagAnchor($this->view->url(['module' => 'admin',
-                                                    'controller' => 'ouvertures',
-                                                    'action' => 'index',
-                                                    'id_site' => $library->getId()], null, true),
-                                  Class_Admin_Skin::current()
-                                  ->renderActionIconOn('calendar',
-                                                       $this->view,
-                                                       ['class' => 'openings_edit',
-                                                        'alt' => $this->view->_('Modifier les ouvertures'),
-                                                        'title' => $this->view->_('Modifier les ouvertures')]),
-                                  ['class' => 'edit_openings',
-                                   'target' => '_blank']);
+  public function tagEditOpenings(Class_Bib $library) : string {
+    return Class_Users::hasCurrentUserRightsOnLibrary($library)
+      ? $this->view->tagAnchor($this->view->url(['module' => 'admin',
+                                                 'controller' => 'ouvertures',
+                                                 'action' => 'index',
+                                                 'id_site' => $library->getId()], null, true),
+                               Class_Admin_Skin::current()
+                               ->renderActionIconOn('calendar',
+                                                    $this->view,
+                                                    ['class' => 'openings_edit',
+                                                     'alt' => $this->view->_('Modifier les ouvertures'),
+                                                     'title' => $this->view->_('Modifier les ouvertures')]),
+                               ['class' => 'edit_openings',
+                                'target' => '_blank'])
+      : '';
   }
 }
-?>
diff --git a/tests/application/modules/admin/controllers/BibControllerTest.php b/tests/application/modules/admin/controllers/BibControllerTest.php
index aa03d92ff15c62ab0c6c0894973dc18250dd3731..aa38d94b174a8497dabd9e142f1ea0ab27df17e6 100644
--- a/tests/application/modules/admin/controllers/BibControllerTest.php
+++ b/tests/application/modules/admin/controllers/BibControllerTest.php
@@ -20,9 +20,7 @@
  */
 
 
-abstract class BibControllerTestCase extends AbstractControllerTestCase {
-  protected
-    $_storm_default_to_volatile = true;
+abstract class BibControllerTestCase extends Admin_AbstractControllerTestCase {
 
   public function setUp() {
     parent::setUp();
@@ -266,7 +264,6 @@ class BibControllerWithModerateurPortailWithoutRightEditBibTest
 
 
 
-
 class BibControllerWithModerateurPortailWithRightEditBibTest
   extends BibControllerTestCase {
   protected function _loginHook($account) {
@@ -303,8 +300,8 @@ class BibControllerWithModerateurPortailWithRightEditBibTest
 
 
   /** @test */
-  public function bibAnnecyShouldHaveActionToDelete() {
-    $this->assertXPath('//tr[1]//a[contains(@href, "bib/delete/id/2")]');
+  public function bibAnnecyShouldNotHaveDeleteLink() {
+    $this->assertNotXPath('//a[contains(@href, "bib/delete/id/2")]');
   }
 
 
@@ -358,6 +355,168 @@ class BibControllerWithModerateurBibTest extends BibControllerTestCase {
 
 
 
+abstract class BibControllerWithModerateurBibWithRightEditBibTestCase
+  extends BibControllerTestCase {
+
+  protected function _loginHook($account) {
+    $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::MODO_BIB;
+  }
+
+
+  public function setUp() {
+    parent::setUp();
+    Class_Users::getIdentity()
+      ->setPassword('toto')
+      ->setIdSite('2')
+      ->setUserGroups([$this->fixture(Class_UserGroup::class,
+                                      ['id' => 23])->addRightEditerBib()])
+      ->assertSave();
+  }
+}
+
+
+
+class BibControllerDispatchIndexWithModoTest
+  extends BibControllerWithModerateurBibWithRightEditBibTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/admin/bib/');
+  }
+
+  /** @test */
+  public function whenBibIndexShouldNotRedirectToAdminIndex() {
+    $this->assertNotRedirect('admin/index');
+  }
+
+
+
+  /** @test */
+  public function pageShouldContainsOnlyOneTr() {
+    $this->assertXPathCount('//table[@id="libraries"]//tbody//tr', 1);
+  }
+
+
+  /** @test */
+  public function pageShouldDisplayBibAnnecy() {
+    $this->assertXPathContentContains('//tr//td', 'Annecy');
+  }
+
+
+  /** @test */
+  public function bibAnnecyShouldHaveActionToEdit() {
+    $this->assertXPath('//tr//a[contains(@href, "bib/edit/id/2")]');
+  }
+
+
+  /** @test */
+  public function bibAnnecyShouldHaveActionToPlan() {
+    $this->assertXPath('//tr//a[contains(@href, "bib/plans/id_bib/2")]');
+  }
+
+
+  /** @test */
+  public function bibAnnecyShouldHaveActionToLocalisations() {
+    $this->assertXPath('//tr//a[contains(@href, "bib/localisations/id_bib/2")]');
+  }
+
+
+  /** @test */
+  public function bibAnnecyShouldHaveActionToOuvertures() {
+    $this->assertXPath('//tr//a[contains(@href, "ouvertures/index/id_site/2")]');
+  }
+}
+
+
+
+
+class BibControllerDispatchActionsWithModoTest
+  extends BibControllerWithModerateurBibWithRightEditBibTestCase {
+
+  public function urlsShouldDisplayHtml() : array {
+    return
+      [[ '/admin/bib/edit/id/2'],
+       [ '/admin/bib/localisations/id_bib/2'],
+       [ '/admin/bib/plans/id_bib/2'],
+       [ '/admin/bib/addplan/id_bib/2'],
+       [ '/admin/bib/addlocalisation/id_bib/2'],
+       [ '/admin/ouvertures/index/id_site/2']
+      ];
+  }
+
+
+  /**
+   * @test
+   * @dataProvider urlsShouldDisplayHtml
+   */
+  public function withGivenUrlShouldDisplayHtml($url) {
+    $this->dispatch($url);
+    $this->assertXPath('//div[@class="modules"]/h1');
+  }
+
+
+  public function urlsShouldRedirect() : array {
+    return
+      [[ '/admin/bib/delete/id/2'],
+       [ '/admin/bib/edit/id/3'],
+       [ '/admin/bib/localisations/id_bib/3'],
+       [ '/admin/bib/plans/id_bib/3'],
+       [ '/admin/ouvertures/index/id_site/3'],
+       [ '/admin/bib/delete/id/3']
+      ];
+  }
+
+
+  /**
+   * @test
+   * @dataProvider urlsShouldRedirect
+   */
+  public function withGivenUrlShouldRedirectToOpacIndex($url) {
+    $this->dispatch($url);
+    $this->assertRedirect();
+  }
+
+
+  /** @test */
+  public function dispatchPlansOfLibraryThreeShouldNotifyNoRightsMessage() {
+    $this->dispatch('/admin/bib/localisations/id_bib/3');
+    $this->assertFlashMessengerContentContains('Vous ne disposez pas des permissions suffisantes pour gérer la bibliothèque Cran-Gévrier.');
+  }
+
+
+  /** @test */
+  public function dispatchDeletePlansFourOfLibraryTwoShouldDeletePlanFour() {
+    $this->fixture(Class_Plan::class,
+                   ['id' => 4,
+                   ]);
+    $this->dispatch('/admin/bib/plansdelete/id_bib/2/id_plan/4');
+    $this->assertNull(Class_Plan::find('4'));
+  }
+
+
+  /** @test */
+  public function dispatchDeleteLocalisationFourOfLibraryTwoShouldDeleteLocalisationFour() {
+    $this->fixture(Class_Localisation::class,
+                   ['id' => 4,
+                   ]);
+    $this->dispatch('/admin/bib/localisationsdelete/id_bib/2/id_localisation/4');
+    $this->assertNull(Class_Localisation::find('4'));
+  }
+
+
+  /** @test */
+  public function dispatchDeleteLocalisationFourOfLibraryThreeShouldNotDeleteLocalisation() {
+    $this->fixture(Class_Localisation::class,
+                   ['id' => 4]);
+    $this->dispatch('/admin/bib/localisationsdelete/id_bib/3/id_localisation/4');
+    $this->assertNotNull(Class_Localisation::find(4));
+    $this->assertFlashMessengerContentContains('Vous ne disposez pas des permissions suffisantes pour gérer la bibliothèque Cran-Gévrier');
+  }
+}
+
+
+
+
 abstract class BibControllerWithAdminBibTestCase extends BibControllerTestCase {
 
   protected function _loginHook($account) {
@@ -370,17 +529,18 @@ abstract class BibControllerWithAdminBibTestCase extends BibControllerTestCase {
 
 
 class BibControllerWithAdminBibTest extends BibControllerWithAdminBibTestCase {
-  /** @test */
+
+/** @test */
   function responseToEditSiteTwoShouldBePageEdit() {
     $this->dispatch('admin/bib/edit/id/2');
-    $this->assertNotRedirect('admin/index');
+    $this->assertXPathContentContains('//h1', 'Modifier une bibliothèque');
   }
 
 
   /** @test */
-  function responseToEditSiteThreeShouldBePageEdit() {
+  function responseToEditSiteThreeShouldNotBeAllowed() {
     $this->dispatch('admin/bib/edit/id/3');
-    $this->assertRedirectTo('/admin/bib/index');
+    $this->assertRedirectTo('/');
   }
 }
 
@@ -1978,31 +2138,32 @@ class BibControllerWithRemineAPIPostDispatchTest extends BibControllerWithRedmin
 
 
 class BibControllerDispatchIndexWithLibraryAdmin extends AbstractControllerTestCase {
-  protected $_storm_default_to_volatile = true;
-
 
   public function setUp() {
     parent::setUp();
 
-    $hem = $this->fixture('Class_Bib',
-                          ['id' => 56,
-                           'libelle' => 'Hem']);
+    $hem =
+      $this->fixture(Class_Bib::class,
+                     ['id' => 56,
+                      'libelle' => 'Hem']);
 
-    $lille = $this->fixture('Class_Bib',
-                            ['id' => 89,
-                             'libelle' => 'Lille']);
+    $lille =
+      $this->fixture(Class_Bib::class,
+                     ['id' => 89,
+                      'libelle' => 'Lille']);
 
-    $monteux = $this->fixture('Class_Users',
-                              ['id' => 89,
-                               'login' => 'monteux',
-                               'password' => 'ishould',
-                               'id_site' => 56]);
+    $monteux =
+      $this->fixture(Class_Users::class,
+                     ['id' => 89,
+                      'login' => 'monteux',
+                      'password' => 'ishould',
+                      'id_site' => 56]);
 
     $monteux->beAdminBib()->save();
 
     ZendAfi_Auth::getInstance()->logUser($monteux);
 
-    $this->dispatch('admin/bib/index', true);
+    $this->dispatch('admin/bib/index');
   }
 
 
diff --git a/tests/application/modules/admin/controllers/CmsControllerListModeTest.php b/tests/application/modules/admin/controllers/CmsControllerListModeTest.php
index e1f94c12d3830231ff3689e139044ff5c3864bbe..b4679d9bd0058da48573c56be9ceaf0590e5312d 100644
--- a/tests/application/modules/admin/controllers/CmsControllerListModeTest.php
+++ b/tests/application/modules/admin/controllers/CmsControllerListModeTest.php
@@ -32,32 +32,29 @@ abstract class CmsControllerListModeTestCase extends CmsControllerWithPermission
 
 
 class CmsControllerListModeAdminRootTest extends CmsControllerListModeTestCase {
+
   public function setUp() {
     parent::setUp();
     ZendAfi_Auth::getInstance()->logUser($this->_bernard);
-    $this->dispatch('/admin/cms', true);
+    $this->dispatch('/admin/cms');
   }
 
 
   /** @test */
   public function shouldDisplayPortal() {
-    $this->assertXPathContentContains('//td/a[contains(@href, "cms/index/id_bib/0")]',
-                                      'Portail',
-                                      $this->_response->getBody());
+    $this->assertXPathContentContains('//td/a[contains(@href, "cms/index/id_bib/0")]', 'Portail');
   }
 
 
   /** @test */
   public function portalShouldHaveAddCategoryAction() {
-    $this->assertXPath('//td//a[contains(@href, "cms-category/add/id_bib/0")]',
-                       $this->_response->getBody());
+    $this->assertXPath('//td//a[contains(@href, "cms-category/add/id_bib/0")]');
   }
 
 
   /** @test */
   public function portalShouldHaveDefaultPermissionsAction() {
-    $this->assertXPath('//td//a[contains(@href, "bib/permissions/id/0")]',
-                       $this->_response->getBody());
+    $this->assertXPath('//td//a[contains(@href, "bib/permissions/id/0")]');
   }
 
 
@@ -291,35 +288,36 @@ class CmsControllerListModeAdminBibSubCategoryTest
 
 class CmsControllerListModeSearchTest
   extends CmsControllerListModeTestCase {
+
   public function setUp() {
     parent::setUp();
     ZendAfi_Auth::getInstance()->logUser($this->_bernard);
 
-    $this->fixture('Class_Article',
+    $this->fixture(Class_Article::class,
                    ['id' => 1,
                     'titre' => 'News from bib',
                     'contenu' => 'Welcome',
                     'categorie' => Class_ArticleCategorie::find(1)]);
 
-    $this->fixture('Class_Article',
+    $this->fixture(Class_Article::class,
                    ['id' => 2,
                     'titre' => 'News from portail',
                     'contenu' => 'Welcome',
                     'categorie' => Class_ArticleCategorie::find(23)]);
 
-    $this->fixture('Class_ArticleCategorie',
+    $this->fixture(Class_ArticleCategorie::class,
                    ['id' => 3400,
                     'libelle' => 'Racine CRan',
                     'parent_categorie' => Class_ArticleCategorie::find(340),
                     'sous_categories' => []]);
 
-    $this->fixture('Class_ArticleCategorie',
+    $this->fixture(Class_ArticleCategorie::class,
                    ['id' => 340,
                     'libelle' => 'first level',
                     'parent_categorie' => Class_ArticleCategorie::find(3400),
                     'sous_categories' => []]);
 
-    $this->fixture('Class_ArticleCategorie',
+    $this->fixture(Class_ArticleCategorie::class,
                    ['id' => 44,
                     'libelle' => 'second level',
                     'parent_categorie' => Class_ArticleCategorie::find(340),
@@ -327,14 +325,14 @@ class CmsControllerListModeSearchTest
 
     $this->annecy->setArticleCategories([Class_ArticleCategorie::find(3400)])->save();
 
-    $this->fixture('Class_Article',
+    $this->fixture(Class_Article::class,
                    ['id' => 3,
                     'titre' => 'News evenement',
                     'contenu' => 'Welcome',
                     'categorie' => Class_ArticleCategorie::find(44)]);
 
 
-    $this->fixture('Class_Article',
+    $this->fixture(Class_Article::class,
                    ['id' => 4,
                     'titre' => 'Top cat evenement',
                     'contenu' => 'Welcome',
@@ -342,7 +340,7 @@ class CmsControllerListModeSearchTest
 
     $this->fixture('Class_AdminVar', ['id' => 'WORKFLOW', 'valeur' => '1']);
 
-    $this->dispatch('/admin/cms/index/title_search/news', true);
+    $this->dispatch('/admin/cms/index/title_search/news');
   }
 
 
diff --git a/tests/application/modules/admin/controllers/ModulesControllerTest.php b/tests/application/modules/admin/controllers/ModulesControllerTest.php
index 08ec2300ecf084a38a276b189a4f84bdcfc6606e..040b553c73d0d66f5900c567ff25b8acdb49f0b4 100644
--- a/tests/application/modules/admin/controllers/ModulesControllerTest.php
+++ b/tests/application/modules/admin/controllers/ModulesControllerTest.php
@@ -1289,14 +1289,15 @@ class ModulesControllerNoticeApplyToActionTest extends Admin_AbstractControllerT
 
 abstract class ModulesControllerApplyToActionPostTestCase
   extends Admin_AbstractControllerTestCase {
+
   protected
-    $_storm_default_to_volatile = true,
     $_current_profil,
     $_other_profil,
     $_cfg_controller = '',
     $_cfg_action = '',
     $_cfg_sub_action = '';
 
+
   public function setUp() {
     parent::setUp();
     $this->_prepare_fixtures();
@@ -1304,30 +1305,31 @@ abstract class ModulesControllerApplyToActionPostTestCase
 
 
   protected function _prepare_fixtures() {
-    $this->_other_profil = $this->fixture('Class_Profil',
-                                          ['id' => 44,
-                                           'parent_id' => null,
-                                           'libelle' => 'Other Profile',
-                                           'titre_site' => 'Other Profile',
-                                           'cfg_site'  => ["largeur_site" => 1000,
-                                                           "nb_divisions" => 3,
-                                                           "menu_haut_on" => 0,
-                                                           "barre_nav_on" => 1,
-                                                           "accessibilite_on" => 0,
-                                                           "largeur_division1" => 250,
-                                                           "marge_division1" => 10,
-                                                           "largeur_division2" => 600,
-                                                           "marge_division2" => 10,
-                                                           "largeur_division3" => 150,
-                                                           "marge_division3" => 10,
-                                                           "ref_description" => '',
-                                                           "division_three_always_visible" => false,
-                                                           "ref_tags" => ''],
-                                           'skin' => 'original',
-                                           'ref_tags' => '',
-                                           'mail_site' => '',
-                                           'browser' => 'opac',
-                                           'cfg_modules' => []]);
+    $this->_other_profil =
+      $this->fixture(Class_Profil::class,
+                     ['id' => 44,
+                      'parent_id' => null,
+                      'libelle' => 'Other Profile',
+                      'titre_site' => 'Other Profile',
+                      'cfg_site'  => ["largeur_site" => 1000,
+                                      "nb_divisions" => 3,
+                                      "menu_haut_on" => 0,
+                                      "barre_nav_on" => 1,
+                                      "accessibilite_on" => 0,
+                                      "largeur_division1" => 250,
+                                      "marge_division1" => 10,
+                                      "largeur_division2" => 600,
+                                      "marge_division2" => 10,
+                                      "largeur_division3" => 150,
+                                      "marge_division3" => 10,
+                                      "ref_description" => '',
+                                      "division_three_always_visible" => false,
+                                      "ref_tags" => ''],
+                      'skin' => 'original',
+                      'ref_tags' => '',
+                      'mail_site' => '',
+                      'browser' => 'opac',
+                      'cfg_modules' => []]);
   }
 
 
@@ -1372,13 +1374,14 @@ abstract class ModulesControllerContactApplyToActionPostTestCase
     $_cfg_action = 'formulairecontact',
     $_cfg_sub_action = '';
 
+
   public function setUp() {
     parent::setUp();
-
     $this->postDispatch($this->_getDispatchUrl(),
                         ['profiles' => ['2', '44']]);
   }
 
+
   protected function _prepare_fixtures() {
     parent::_prepare_fixtures();
 
@@ -1415,7 +1418,7 @@ class ModulesControllerApplyToActionPostWithLimitedToLibraryUserTest
   protected function _prepare_fixtures() {
     parent::_prepare_fixtures();
 
-    $this->fixture('Class_Bib', ['id' => 74, 'libelle' => 'Annecy']);
+    $this->fixture(Class_Bib::class, ['id' => 74, 'libelle' => 'Annecy']);
 
     $this->_other_profil->setIdSite(74)->assertSave();
     $this->_other_profil->beCurrentProfil();
@@ -1444,6 +1447,7 @@ class ModulesControllerApplyToActionPostWithLimitedToLibraryUserTest
 
 
 
+
 class ModulesControllerNoticeApplyToActionPostTest
   extends ModulesControllerApplyToActionPostTestCase {
 
diff --git a/tests/application/modules/admin/controllers/UsersControllerTest.php b/tests/application/modules/admin/controllers/UsersControllerTest.php
index 753beafa2dce48c6c3f93c2796292afac5fa3352..4fa25af4181ce7fb6b7ce5b2243c8181a8d9c8d6 100644
--- a/tests/application/modules/admin/controllers/UsersControllerTest.php
+++ b/tests/application/modules/admin/controllers/UsersControllerTest.php
@@ -2421,3 +2421,53 @@ class Admin_UsersControllerIndexButtonTest extends Admin_AbstractControllerTestC
     $this->assertXPath('//div//table//a[@href="/admin/users/delete/id/123"][@onclick="return confirm(\'Supprimer Francis ?\');"]');
   }
 }
+
+
+
+
+class Admin_UsersControllerEditModoBibTest extends Admin_AbstractControllerTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    $this->fixture(Class_Bib::class,
+                   ['id' => 5,
+                    'libelle' => 'Jolieville'
+                   ]);
+
+    $this->fixture(Class_Bib::class,
+                   ['id' => 6,
+                    'libelle' => 'Wonderville'
+                   ]);
+
+
+    $redac = $this->fixture(Class_Users::class,
+                            ['id' => 5,
+                             'login' => 'rédacteur',
+                             'password' => 'msmdp',
+                             'id_site' => '5',
+                             'role_level' => ZendAfi_Acl_AdminControllerRoles::MODO_BIB,
+                             'last_login' => '']);
+
+    ZendAfi_Auth::getInstance()->logUser($redac);
+
+    $this->dispatch('admin/users/edit/id/5');
+  }
+
+
+  /** @test */
+  public function formShouldContainsIdSiteJolievilleSelected() {
+    $this->assertXPathContentContains('//form//select[@id="id_site"]/option[@value="5"][@selected]','Jolieville');
+  }
+
+
+  /** @test */
+  public function formShouldContainsIdSitePortail() {
+    $this->assertXPathContentContains('//form//select[@id="id_site"]/option[@value="0"]','Portail');
+  }
+
+
+  /** @test */
+  public function formIdSIteOptionsShouldNotContainsWonderVille() {
+    $this->assertXPathCount('//form//select[@id="id_site"]/option',2);
+  }
+}
\ No newline at end of file
diff --git a/tests/application/modules/admin/controllers/WidgetControllerTest.php b/tests/application/modules/admin/controllers/WidgetControllerTest.php
index 955f63d164b1b6672d18b3b4e6fe7785a520c724..0fe8bf97398a73082224c0739ff1d7e7efadf87c 100644
--- a/tests/application/modules/admin/controllers/WidgetControllerTest.php
+++ b/tests/application/modules/admin/controllers/WidgetControllerTest.php
@@ -1199,9 +1199,12 @@ class WidgetControllerTwoWidgetPostEditTest extends WidgetControllerPostDispatch
 
   /** @test */
   public function secondDispatchShouldCreateNewWidget() {
-    $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/5', ['col_gauche_type' => 'KIOSQUE',
-                                                                       'col_droite_type' => 'NEWS',
-                                                                       'titre' => 'Ce mois ci']);
+    // Reset response redirect status because of being after a postDispatch.
+    $this->_response->setHttpResponseCode(200);
+    $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/5',
+                        ['col_gauche_type' => 'KIOSQUE',
+                         'col_droite_type' => 'NEWS',
+                         'titre' => 'Ce mois ci']);
     Class_Profil::clearCache();
     $this->assertEquals(1002, Class_Profil::find(5)->getCfgAccueilAsArray()['modules'][6]['preferences']['col_droite_module_id']);
   }
diff --git a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php
index 25c6ff8d3c7fa2ced22290a84d71c0e39bf63532..d1a0ce782ab3dcf972e9f7d4d71f4e98a6818afa 100644
--- a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php
+++ b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php
@@ -792,10 +792,10 @@ class AbonneControllerPretsListReservationTest extends AbonneControllerPretsList
 
 
 abstract class AbonneControllerPretsRenewThreePretsTestCase extends AbonneControllerPretsListThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
     Class_CommSigb::setInstance($this->getSigbMock());
-    $this->dispatch('/opac/abonne/prolongerPret/render/popup', true);
   }
 
 
@@ -820,11 +820,13 @@ abstract class AbonneControllerPretsRenewThreePretsTestCase extends AbonneContro
 
 
 class AbonneControllerPretsRenewErrorThreePretsTest extends AbonneControllerPretsRenewThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12', true);
+    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12');
   }
 
+
   protected function getSigbMock() {
     return $this->mock()
                 ->whenCalled('prolongerPret')
@@ -833,21 +835,20 @@ class AbonneControllerPretsRenewErrorThreePretsTest extends AbonneControllerPret
   }
 
 
-
   /** @test */
   public function notificationPopupContentShouldContainsPatronNotFound() {
     $this->assertFlashMessengerContentContains('Patron not found');
   }
-
 }
 
 
 
 
 class AbonneControllerPretsRenewSuccessThreePretsTest extends AbonneControllerPretsRenewThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12', true);
+    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12');
   }
 
 
@@ -868,9 +869,10 @@ class AbonneControllerPretsRenewSuccessThreePretsTest extends AbonneControllerPr
 
 
 class AbonneControllerPretsWithoutLoanToExtendThreePretsTest extends AbonneControllerPretsRenewThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/prolongerPret/id_pret/', true);
+    $this->dispatch('/opac/abonne/prolongerPret/id_pret/');
   }
 
 
@@ -891,11 +893,13 @@ class AbonneControllerPretsWithoutLoanToExtendThreePretsTest extends AbonneContr
 
 
 class AbonneControllerPretsExtendAllLoansSuccessThreePretsTest extends AbonneControllerPretsRenewThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12;123456_13', true);
+    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12;123456_13');
   }
 
+
   protected function getSigbMock() {
     return $this->mock()
                 ->whenCalled('prolongerPret')
@@ -919,11 +923,13 @@ class AbonneControllerPretsExtendAllLoansSuccessThreePretsTest extends AbonneCon
 
 
 class AbonneControllerPretsExtendAllLoansErrorThreePretsTest extends AbonneControllerPretsRenewThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12;123456_13', true);
+    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12;123456_13');
   }
 
+
   protected function getSigbMock() {
     return $this->mock()
                 ->whenCalled('prolongerPret')
@@ -950,9 +956,10 @@ class AbonneControllerPretsExtendAllLoansErrorThreePretsTest extends AbonneContr
 
 
 class AbonneControllerPretsExtendAllLoansSuccessAndErrorThreePretsTest extends AbonneControllerPretsRenewThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12;123456_13', true);
+    $this->dispatch('/opac/abonne/prolongerPret/id_pret/123456_12;123456_13');
   }
 
 
@@ -988,9 +995,10 @@ class AbonneControllerPretsExtendAllLoansSuccessAndErrorThreePretsTest extends A
 
 
 class AbonneControllerPretsBadFormatExtendLoanThreePretsTest extends AbonneControllerPretsRenewThreePretsTestCase {
+
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/prolongerPret/id_pret/;123456_12;', true);
+    $this->dispatch('/opac/abonne/prolongerPret/id_pret/;123456_12;');
   }
 
 
diff --git a/tests/scenarios/AuthorPage/AuthorWidgetTest.php b/tests/scenarios/AuthorPage/AuthorWidgetTest.php
index de331220bab128577d5134106334d8312a00d135..2b3196e031c2f4b243682cf3b62649bee9c845ee 100644
--- a/tests/scenarios/AuthorPage/AuthorWidgetTest.php
+++ b/tests/scenarios/AuthorPage/AuthorWidgetTest.php
@@ -143,27 +143,27 @@ class AuthorWidgetActionRefreshThumbnailsTest extends AuthorWidgetOnPageTestCase
 
 
 class AuthorWidgetActionRefreshThumbnailsWithWrongParamsTest extends AuthorWidgetOnPageTestCase {
-  public function errors() {
-    return [
-            ['id_module/1/id_profil/66655',
-             [404, 'Profil inexistant']],
 
-            ['id_module/134245/id_profil/2',
-             [404, 'Boite inexistante']],
-    ];
+  /** @test */
+  public function withWrongIdProfilShouldRedirectToIndex() {
+    $this->dispatch('/admin/widget/widget-action/named/refresh/id_module/1/id_profil/66655');
+    $this->assertRedirectTo('/');
+  }
+
+
+  /** @test */
+  public function withWrongIdProfilShouldNotifyProfile66655DoesNotExists() {
+    $this->dispatch('/admin/widget/widget-action/named/refresh/id_module/1/id_profil/66655');
+    $this->assertFlashMessengerContentContains('Le profil 66655 n\'existe pas.');
   }
 
 
-  /**
-   * @dataProvider errors
-   * @test
-   */
-  public function withWrongIdProfilShouldAnswer404($url, $expected) {
+  /** @test */
+  public function withWrongIdModuleShouldRedirectToIndex() {
     try {
-      $this->dispatch('/admin/widget/widget-action/named/refresh/' . $url);
+      $this->dispatch('/admin/widget/widget-action/named/refresh/id_module/134245/id_profil/2');
     }  catch(Zend_Controller_Action_Exception $e) {
-      $this->assertEquals($expected,
-                          [$e->getCode(), $e->getMessage()]);
+      $this->assertEquals([404, 'Boite inexistante'], [$e->getCode(), $e->getMessage()]);
       return;
     }
     $this->fail('should raise error 404 not found');
diff --git a/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php b/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php
index dd89e9ba6ca23f465a6b1d23a1b408db8d9203c5..5c973f762d8a2ed35275cabbc1ab6e2aaaa7e07e 100644
--- a/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php
+++ b/tests/scenarios/DomainsPerLibraries/DomainsPerLibrariesTest.php
@@ -22,8 +22,6 @@
 
 abstract class DomainsPerLibrariesTestCase extends Admin_AbstractControllerTestCase {
 
-  protected $_storm_default_to_volatile = true;
-
 
   public function setUp() {
     parent::setUp();
diff --git a/tests/scenarios/Manager/ManagerTest.php b/tests/scenarios/Manager/ManagerTest.php
index b1d3d0eaa95b29807a61346421e4e8a123617cc7..15c7e1fa5fac557d8b65343992840c599642ab37 100644
--- a/tests/scenarios/Manager/ManagerTest.php
+++ b/tests/scenarios/Manager/ManagerTest.php
@@ -22,8 +22,6 @@
 
 class ManagerArticleTest extends Admin_AbstractControllerTestCase {
 
-  protected $_storm_default_to_volatile = true;
-
   public function setup() {
     parent::setUp();
     $this->fixture('Class_ArticleCategorie',
@@ -36,7 +34,7 @@ class ManagerArticleTest extends Admin_AbstractControllerTestCase {
                     'contenu' => 'Happy new Year 2017',
                     'id_cat' => 56]);
 
-    $this->dispatch('/admin/cms/index', true);
+    $this->dispatch('/admin/cms/index');
   }
 
 
diff --git a/tests/scenarios/MultiSelection/MultiSelectionTest.php b/tests/scenarios/MultiSelection/MultiSelectionTest.php
index 410dba2bbe2dfd2b7abde7dfd1ad36ceacd1798a..f782fe67b623f0c7beb6576e0e33b5258110fae3 100644
--- a/tests/scenarios/MultiSelection/MultiSelectionTest.php
+++ b/tests/scenarios/MultiSelection/MultiSelectionTest.php
@@ -339,17 +339,17 @@ class MultiSelectionArticleRemoveCategoryTest extends MultiSelectionArticlesTest
 
 
 class MultiSelectionArticleNoListViewModeTest extends MultiSelectionArticlesTestCase {
+
   public function setUp() {
     parent::setUp();
     Class_AdminVar::set('ARTICLES_LIST_MODE', '0');
     Zend_Registry::get('session')->selected_items = ['article' => [12,1301]];
 
     Class_Users::getIdentity()->beModoPortail();
-    $this->dispatch('admin/cms/index/id_bib/0', true);
+    $this->dispatch('admin/cms/index/id_bib/0');
   }
 
 
-
   /** @test */
   public function widgetMultipleArticlesShouldBeDisplay() {
     $this->assertXpath('//div[@class="selected_items_widget show"]');
diff --git a/tests/scenarios/SearchByWork/SearchResultByWorkTest.php b/tests/scenarios/SearchByWork/SearchResultByWorkTest.php
index 523f5371d01cec6337eda54f9fe0b8544ba8ea44..aa1739871bba47ddcc1a1390f4048c84742a4dcf 100644
--- a/tests/scenarios/SearchByWork/SearchResultByWorkTest.php
+++ b/tests/scenarios/SearchByWork/SearchResultByWorkTest.php
@@ -132,7 +132,7 @@ class SearchResultByWorkWithoutTemplatingTest extends SearchResultByWorkTestCase
   /** @test */
   public function workViewActionShouldRedirectToOpacIndex() {
     $this->dispatch('/opac/work/view/expressionRecherche/lapin/by_work/1/id/ACCROCDUROC-PRATCHETTT');
-    $this->assertRedirectContains('/opac/index/index');
+    $this->assertRedirectTo('/opac/index/index');
   }
 }
 
diff --git a/tests/scenarios/Versionning/VersionningArticleTest.php b/tests/scenarios/Versionning/VersionningArticleTest.php
index fca2519a83961eb79db9d2372d4546dec2d07999..488958a4c6865aa0297e8f0133421ef95a48580f 100644
--- a/tests/scenarios/Versionning/VersionningArticleTest.php
+++ b/tests/scenarios/Versionning/VersionningArticleTest.php
@@ -371,14 +371,13 @@ class VersionningArticleIndexTest extends VersionningAdminTestCase {
                                               'events_debut' => '23/03/2017 16:00',
                                               'events_fin' => '']));
 
-    $this->dispatch('/admin/cms/index/id_cat/33', true);
+    $this->dispatch('/admin/cms/index/id_cat/33');
   }
 
 
   /** @test */
   public function versionLinkOfArticleShouldBePresent() {
-    $this->assertXPath('//a[contains(@href, "/cms/version/id/27")]',
-                       $this->_response->getBody());
+    $this->assertXPath('//a[contains(@href, "/cms/version/id/27")]');
   }