Commit 9cfa0495 authored by Christian BUFFIN's avatar Christian BUFFIN

Améioration de la gestion des exceptions pour l'expérience utilisateur,...

Améioration de la gestion des exceptions pour l'expérience utilisateur, corrections diverses liées aux tests (d'intégraton d'accès et fonctionnels automatisés)
parent d4dbbc5a
......@@ -141,6 +141,10 @@ require ROOT . DS . 'vendors'. DS .'autoload.php';
spl_autoload_unregister(['App', 'load']);
spl_autoload_register(['App', 'load'], true, true);
// Gestion spéciale des exceptions pour qu'elles deviennent des messages flash dans l'interface
App::uses('UserFriendlyExceptionHandler', 'Lib');
UserFriendlyExceptionHandler::setUp();
//Configuration du plugin Cakeflow
Configure::write('Cakeflow.app', 'webdelib');
......
......@@ -54,7 +54,7 @@ class ReferersComponent extends Component {
$sessionKey = "{$this->settings['sessionKeyPrefix']}.{$here}";
$stored = $this->Session->read($sessionKey);
if (('/' !== $referer || null === $stored) && $stored !== $referer && $here !== $referer) {
if (('/' !== $referer || null === $stored) && $stored !== $referer && $here !== $referer && $controller->request->param('requested') === false) {
$this->Session->write($sessionKey, $referer);
}
......
......@@ -93,6 +93,8 @@ class FichesController extends AppController
} elseif ($action === 'ajax_update_listing_soustraitant') {
$this->Droits->assertAuthorized([ListeDroit::GESTION_SOUSTRAITANT_TRAITEMENT]);
$this->Droits->assertNotSu();
} elseif ($action === 'show') {
$this->Droits->assertNotSu();
}
/*elseif (in_array($action, $anyone) === false) {
throw new ForbiddenException(__d('default', 'default.flasherrorPasDroitPage'));
......@@ -1094,15 +1096,7 @@ class FichesController extends AppController
*/
public function show($id)
{
$findTraitement = $this->Fiche->find('count',[
'conditions' => [
'id' => $id
]
]);
if (!$id || $findTraitement != 1) {
$this->Session->setFlash(__d('default', 'default.flasherrorTraitementInexistant'), 'flasherror');
$this->redirect($this->Referers->get());
}
$this->Droits->assertRecordAuthorized('Fiche', $id);
$this->requestAction([
'controller' => 'pannel',
......@@ -1119,7 +1113,7 @@ class FichesController extends AppController
'valeur'
]
]);
$this->set('title', __d('fiche', 'fiche.titreApercuFiche') . $nameTraitement['Valeur']['valeur']);
$this->set('title', __d('fiche', 'fiche.titreApercuFiche') . Hash::get($nameTraitement, 'Valeur.valeur'));
$fiche = $this->Fiche->find('first', [
'conditions' => [
......
......@@ -587,8 +587,6 @@ class PannelController extends AppController {
* @version V1.0.0
*/
public function supprimerLaNotif($idFiche) {
$this->Droits->assertRecordAuthorized('Fiche', $idFiche);
$success = true;
$this->Notification->begin();
......
......@@ -39,8 +39,8 @@ class RecettesController extends AppController {
'order' => ['Service.libelle']
],
'Soustraitant' => [
'fields' => ['Soustraitant.raisonsociale'],
'order' => ['Soustraitant.raisonsociale']
'fields' => ['Soustraitant.raisonsocialestructure'],
'order' => ['Soustraitant.raisonsocialestructure']
],
'Typage' => [
'fields' => ['Typage.libelle'],
......
......@@ -97,6 +97,7 @@ class RolesController extends AppController {
]
]);
$roleDPO_id = null;
foreach ($roles as $role) {
if ($this->_roleIsDpoRole($role['Role']['id']) === true) {
$roleDPO_id = $role['Role']['id'];
......
......@@ -1138,7 +1138,7 @@ class UsersController extends AppController {
public function ajax_password() {
// @fixme: vérifier que l'on soit en ajax
$this->autoRender = false;
$password = $this->request->data['password'];
$password = Hash::get($this->request->data, 'password');
$json = [
'entropie' => PasswordStrengthMeterAnssi::entropy($password),
'force' => PasswordStrengthMeterAnssi::strength($password),
......
<?php
App::uses('CakeRequest', 'Network');
App::uses('CakeResponse', 'Network');
App::uses('CakeSession', 'Model/Datasource');
App::uses('Configure', 'Core');
/**
* La classe UserFriendlyExceptionHandler permet de remplacer le gestionnaire d'exceptions pour transformer celles-ci
* en messages flash lorsque l'exception est de type 403 (ForbiddenException) ou 404 (MissingActionException,
* MissingControllerException, MissingPluginException ou NotFoundException).
*
* Usage, dans le fichier bootstrap.php:
* App::uses('UserFriendlyExceptionHandler', 'Lib');
* UserFriendlyExceptionHandler::setUp();
*/
class UserFriendlyExceptionHandler
{
public static function setUp() {
$originalExceptionHandler = Configure::read('Exception.handler');
Configure::write('Exception.handler', function ($exception) use ($originalExceptionHandler) {
static::customExceptionHandler($exception, $originalExceptionHandler);
});
}
public static function customExceptionHandler($exception, $originalExceptionHandler) {
$request = new CakeRequest();
if ($request->is('ajax') === true) {
$originalExceptionHandler($exception);
}
$message = $exception->getMessage();
if ($exception instanceof ForbiddenException) {
if ($message === 'Forbidden') {
$message = 'Vous n\'avez pas le droit d\'acceder à cette page';
}
} elseif ($exception instanceof MissingActionException) {
if (preg_match('/^Action .* could not be found/', $message) === 1) {
$message = 'Page non trouvée';
}
} elseif ($exception instanceof MissingControllerException) {
if (preg_match('/^Controller class .* could not be found/', $message) === 1) {
$message = 'Page non trouvée';
}
} elseif ($exception instanceof MissingPluginException) {
if (preg_match('/^Plugin .* could not be found/', $message) === 1) {
$message = 'Page non trouvée';
}
} elseif ($exception instanceof NotFoundException) {
if ($message === 'Not Found') {
$message = 'Enregistrement non trouvé';
}
} else {
$originalExceptionHandler($exception);
}
$connected = empty(CakeSession::read('Auth.User.id')) === false;
$superadmin = $connected && CakeSession::read('Su');
$current = Router::url(null, false);
$redirect = CakeSession::read('Auth.redirect');
if ($connected === false) {
$redirect = '/users/login';
} elseif ($redirect === null) {
$redirect = $request->referer(true);
}
// @see app/Config/routes.php et app/Controller/PannelController.php
if ($connected === true && $redirect === null && in_array($current, ['/', '/pannel', '/pannel/index']) === false) {
if ($superadmin === true) {
$redirect = '/pannel/superadmin';
} else {
$redirect = '/pannel/index';
}
}
if ($redirect !== null && $redirect !== $current) {
$count = count(Hash::extract((array)CakeSession::read(), 'Message.flash.{n}'));
//$exceptions = Hash::extract(CakeSession::read(), 'Message.flash.{n}[element=/error/]');
$flash = ['message' => $message, 'element' => 'flasherror'];
CakeSession::write(sprintf("Message.flash.%d", $count), $flash);
$response = new CakeResponse();
$response->header('Location', Router::url($redirect, true));
$response->statusCode(302);
$response->send();
} else {
$originalExceptionHandler($exception);
}
}
}
......@@ -591,21 +591,6 @@ msgstr "Ajout d'un sous-traitant"
msgid "fiche.emptySelectTypeFile"
msgstr "Séléctionnez un type pour le fichier"
###############################################################################
msgid ""
msgstr ""
"Project-Id-Version: web-DPO 1.2\n"
"PO-Revision-Date: 2020-04-03 12:00+0100\n"
"Last-Translator: Théo GUILLON <theo.guillon@libriciel.coop>\n"
"Language-Team: Théo GUILLON <theo.guillon@libriciel.coop>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n>1);\n"
# ======================================================================================================================
msgid "fiche.champRt_structure_raisonsociale"
......
......@@ -572,7 +572,7 @@ class Fiche extends AppModel implements LinkedOrganisationInterface {
* l'organisation + champ propre au formulaire + informations du DPO +
* information sur le déclarant au moment de la création du traitement
*/
foreach (json_decode($tabId, true) as $key => $id) {
foreach ((array)json_decode($tabId, true) as $key => $id) {
$donnees['traitement'][$key] = $this->_preparationGenerationValeurTraitement($id, $donnees['traitement'][$key], $historique);
}
......
......@@ -383,15 +383,15 @@ class PannelControllerTest extends ControllerTestCase
[200, 'Rédacteur.rjaune', '/pannel/supprimerLaNotif/1'],
[200, 'Valideur.cnoir', '/pannel/supprimerLaNotif/1'],
[200, 'Consultant.mrose', '/pannel/supprimerLaNotif/1'],
// Un utilisateur mono-collectivité ne peut pas accéder à l'enregistrement d'une autre collectivité
[403, 'Administrateur.findigo', '/pannel/supprimerLaNotif/1'],
[403, 'DPO.hvermeil', '/pannel/supprimerLaNotif/1'],
// Un utilisateur mono-collectivité peut accéder à l'enregistrement d'une autre collectivité
[200, 'Administrateur.findigo', '/pannel/supprimerLaNotif/1'],
[200, 'DPO.hvermeil', '/pannel/supprimerLaNotif/1'],
// 1.2. Enregistrement inexistant
[404, 'Administrateur.ibleu', '/pannel/supprimerLaNotif/666'],
[404, 'DPO.nroux', '/pannel/supprimerLaNotif/666'],
[404, 'Rédacteur.rjaune', '/pannel/supprimerLaNotif/666'],
[404, 'Valideur.cnoir', '/pannel/supprimerLaNotif/666'],
[404, 'Consultant.mrose', '/pannel/supprimerLaNotif/666'],
[200, 'Administrateur.ibleu', '/pannel/supprimerLaNotif/666'],
[200, 'DPO.nroux', '/pannel/supprimerLaNotif/666'],
[200, 'Rédacteur.rjaune', '/pannel/supprimerLaNotif/666'],
[200, 'Valideur.cnoir', '/pannel/supprimerLaNotif/666'],
[200, 'Consultant.mrose', '/pannel/supprimerLaNotif/666'],
// 2. Utilisateurs ne pouvant pas accéder à la fonctionnalité
// 1.1. Enregistrement existant
[403, 'Superadministrateur.superadmin', '/pannel/supprimerLaNotif/1'],
......
......@@ -30,6 +30,7 @@ class RegistresControllerTest extends ControllerTestCase
'app.Service',
'app.Soustraitant',
'app.TraitementRegistre',
'app.Typage',
'app.User',
'app.Valeur',
];
......@@ -162,13 +163,14 @@ class RegistresControllerTest extends ControllerTestCase
public function dataAccessRegistreActivite() {
return [
// Tous les utilisateurs peuvent accéder à la fonctionnalité
[302, 'Superadministrateur.superadmin', '/registres/registreActivite'],
// Utilisateurs pouvant accéder à la fonctionnalité
[302, 'Administrateur.ibleu', '/registres/registreActivite'],
[302, 'DPO.nroux', '/registres/registreActivite'],
[302, 'Rédacteur.rjaune', '/registres/registreActivite'],
[302, 'Valideur.cnoir', '/registres/registreActivite'],
[302, 'Consultant.mrose', '/registres/registreActivite'],
// Utilisateurs ne pouvant pas accéder à la fonctionnalité
[403, 'Superadministrateur.superadmin', '/registres/registreActivite'],
];
}
......@@ -181,13 +183,14 @@ class RegistresControllerTest extends ControllerTestCase
public function dataAccessRegistreSoustraitance() {
return [
// Tous les utilisateurs peuvent accéder à la fonctionnalité
[302, 'Superadministrateur.superadmin', '/registres/registreSoustraitance'],
// Utilisateurs pouvant accéder à la fonctionnalité
[302, 'Administrateur.ibleu', '/registres/registreSoustraitance'],
[302, 'DPO.nroux', '/registres/registreSoustraitance'],
[302, 'Rédacteur.rjaune', '/registres/registreSoustraitance'],
[302, 'Valideur.cnoir', '/registres/registreSoustraitance'],
[302, 'Consultant.mrose', '/registres/registreSoustraitance'],
// Utilisateurs ne pouvant pas accéder à la fonctionnalité
[403, 'Superadministrateur.superadmin', '/registres/registreSoustraitance'],
];
}
......
......@@ -241,6 +241,27 @@ class ListeDroitFixture extends CakeTestFixture {
'created' => '2020-06-10 00:15:34.567556',
'modified' => '2020-06-10 00:15:34.567556'
),
array(
'id' => 33,
'libelle' => 'Consulter tous les traitements dans l\'entité',
'value' => 33,
'created' => '2020-06-10 00:15:34.567556',
'modified' => '2020-06-10 00:15:34.567556'
),
array(
'id' => 34,
'libelle' => 'Gestion des co-responsables lors de la déclaration d\'un traitement',
'value' => 34,
'created' => '2020-06-10 00:15:34.567556',
'modified' => '2020-06-10 00:15:34.567556'
),
array(
'id' => 35,
'libelle' => 'Gestion des sous-traitants lors de la déclaration d\'un traitement',
'value' => 35,
'created' => '2020-06-10 00:15:34.567556',
'modified' => '2020-06-10 00:15:34.567556'
),
);
}
......@@ -1817,6 +1817,51 @@ class RoleDroitFixture extends CakeTestFixture {
'role_id' => 25,
'liste_droit_id' => 32
),
array(
'id' => 361,
'role_id' => 5,
'liste_droit_id' => 33
),
array(
'id' => 362,
'role_id' => 5,
'liste_droit_id' => 34
),
array(
'id' => 363,
'role_id' => 5,
'liste_droit_id' => 35
),
array(
'id' => 364,
'role_id' => 10,
'liste_droit_id' => 33
),
array(
'id' => 365,
'role_id' => 10,
'liste_droit_id' => 34
),
array(
'id' => 366,
'role_id' => 10,
'liste_droit_id' => 35
),
array(
'id' => 367,
'role_id' => 15,
'liste_droit_id' => 33
),
array(
'id' => 368,
'role_id' => 15,
'liste_droit_id' => 34
),
array(
'id' => 369,
'role_id' => 15,
'liste_droit_id' => 35
),
);
}
......@@ -19,79 +19,157 @@ class SoustraitantFixture extends CakeTestFixture {
public $records = array(
array(
'id' => 1,
'raisonsociale' => 'Commission nationale de l\'informatique et des libertés',
'siret' => '75000000000000',
'ape' => '8411Z',
'telephone' => null,
'fax' => null,
'adresse' => null,
'email' => null,
'raisonsocialestructure' => 'Commission nationale de l\'informatique et des libertés',
'siretstructure' => '75000000000000',
'apestructure' => '8411Z',
'telephonestructure' => null,
'faxstructure' => null,
'adressestructure' => null,
'emailstructure' => null,
'civiliteresponsable' => null,
'prenomresponsable' => null,
'nomresponsable' => null,
'emailresponsable' => null,
'telephoneresponsable' => null,
'fonctionresponsable' => null,
'civility_dpo' => null,
'prenom_dpo' => null,
'nom_dpo' => null,
'numerocnil_dpo' => null,
'email_dpo' => null,
'telephonefixe_dpo' => null,
'telephoneportable_dpo' => null,
'createdbyorganisation' => null,
'created' => '2020-06-10 00:20:42',
'modified' => '2020-06-10 00:21:14'
),
array(
'id' => 2,
'raisonsociale' => 'Commission nationale de concertation',
'siret' => '83000000000000',
'ape' => '8411Z',
'telephone' => null,
'fax' => null,
'adresse' => null,
'email' => null,
'raisonsocialestructure' => 'Commission nationale de concertation',
'siretstructure' => '83000000000000',
'apestructure' => '8411Z',
'telephonestructure' => null,
'faxstructure' => null,
'adressestructure' => null,
'emailstructure' => null,
'civiliteresponsable' => null,
'prenomresponsable' => null,
'nomresponsable' => null,
'emailresponsable' => null,
'telephoneresponsable' => null,
'fonctionresponsable' => null,
'civility_dpo' => null,
'prenom_dpo' => null,
'nom_dpo' => null,
'numerocnil_dpo' => null,
'email_dpo' => null,
'telephonefixe_dpo' => null,
'telephoneportable_dpo' => null,
'createdbyorganisation' => null,
'created' => '2020-06-10 00:20:45',
'modified' => '2020-06-10 00:21:16'
),
array(
'id' => 4,
'raisonsociale' => 'Commission nationale du débat public',
'siret' => '08100000000000',
'ape' => '8411Z',
'telephone' => null,
'fax' => null,
'adresse' => null,
'email' => null,
'raisonsocialestructure' => 'Commission nationale du débat public',
'siretstructure' => '08100000000000',
'apestructure' => '8411Z',
'telephonestructure' => null,
'faxstructure' => null,
'adressestructure' => null,
'emailstructure' => null,
'civiliteresponsable' => null,
'prenomresponsable' => null,
'nomresponsable' => null,
'emailresponsable' => null,
'telephoneresponsable' => null,
'fonctionresponsable' => null,
'civility_dpo' => null,
'prenom_dpo' => null,
'nom_dpo' => null,
'numerocnil_dpo' => null,
'email_dpo' => null,
'telephonefixe_dpo' => null,
'telephoneportable_dpo' => null,
'createdbyorganisation' => null,
'created' => '2020-06-10 00:20:50',
'modified' => '2020-06-10 00:20:50'
),
array(
'id' => 5,
'raisonsociale' => 'Commune d\'Assas',
'siret' => '16100000000000',
'ape' => '8411Z',
'telephone' => null,
'fax' => null,
'adresse' => null,
'email' => null,
'raisonsocialestructure' => 'Commune d\'Assas',
'siretstructure' => '16100000000000',
'apestructure' => '8411Z',
'telephonestructure' => null,
'faxstructure' => null,
'adressestructure' => null,
'emailstructure' => null,
'createdbyorganisation' => 1,
'civiliteresponsable' => null,
'prenomresponsable' => null,
'nomresponsable' => null,
'emailresponsable' => null,
'telephoneresponsable' => null,
'fonctionresponsable' => null,
'civility_dpo' => null,
'prenom_dpo' => null,
'nom_dpo' => null,
'numerocnil_dpo' => null,
'email_dpo' => null,
'telephonefixe_dpo' => null,
'telephoneportable_dpo' => null,
'created' => '2020-06-10 00:21:02',
'modified' => '2020-06-10 00:21:30'
),
array(
'id' => 6,
'raisonsociale' => 'Commune de Castelnau-le-Lez',
'siret' => '24100000000000',
'ape' => '8411Z',
'telephone' => null,
'fax' => null,
'adresse' => null,
'email' => null,
'raisonsocialestructure' => 'Commune de Castelnau-le-Lez',
'siretstructure' => '24100000000000',
'apestructure' => '8411Z',
'telephonestructure' => null,
'faxstructure' => null,
'adressestructure' => null,
'emailstructure' => null,
'createdbyorganisation' => 1,
'civiliteresponsable' => null,
'prenomresponsable' => null,
'nomresponsable' => null,
'emailresponsable' => null,
'telephoneresponsable' => null,
'fonctionresponsable' => null,
'civility_dpo' => null,
'prenom_dpo' => null,
'nom_dpo' => null,
'numerocnil_dpo' => null,
'email_dpo' => null,
'telephonefixe_dpo' => null,
'telephoneportable_dpo' => null,
'created' => '2020-06-10 00:21:05',
'modified' => '2020-06-10 00:21:33'
),
array(
'id' => 8,
'raisonsociale' => 'Commune du Crès',
'siret' => '40100000000000',
'ape' => '8411Z',
'telephone' => null,
'fax' => null,
'adresse' => null,
'email' => null,
'raisonsocialestructure' => 'Commune du Crès',
'siretstructure' => '40100000000000',
'apestructure' => '8411Z',
'telephonestructure' => null,
'faxstructure' => null,
'adressestructure' => null,
'emailstructure' => null,
'createdbyorganisation' => 1,
'civiliteresponsable' => null,
'prenomresponsable' => null,
'nomresponsable' => null,
'emailresponsable' => null,
'telephoneresponsable' => null,
'fonctionresponsable' => null,
'civility_dpo' => null,
'prenom_dpo' => null,
'nom_dpo' => null,
'numerocnil_dpo' => null,
'email_dpo' => null,
'telephonefixe_dpo' => null,
'telephoneportable_dpo' => null,
'created' => '2020-06-10 00:21:12',
'modified' => '2020-06-10 00:21:12'
),
......
......@@ -202,7 +202,7 @@ $line = 1;
$checked = $val == $this->request->data("{$modelName}.{$fieldName}") ? ' checked="checked"' : '';
echo '<div class="radio">
<input type="radio" id="'.$options['name'].$key.'" name="data['.$modelName.']['.$fieldName.']" value="'.$val.'" '.$checked.'>
'.$val.'
<label for="'.$options['name'].$key.'">'.$val.'</label>
</div>';
}
?>
......
......@@ -551,9 +551,9 @@
}
} else {
if ($this->here === '/organisations/administrer') {
$userEntiteEnCours = sprintf("%s - %s", $userCo['User']['nom_complet'], $this->Session->read('Organisation.raisonsociale'));
$userEntiteEnCours = sprintf("%s - %s", $this->Session->read('Auth.User.nom_complet'), $this->Session->read('Organisation.raisonsociale'));
} else {
$userEntiteEnCours = sprintf("%s", $userCo['User']['nom_complet']);
$userEntiteEnCours = $this->Session->read('Auth.User.nom_complet');
}