Planète Kgaut

Par kgaut
Kevin Gautreau

Drupal 8 - Créer la traduction d'une chaine de caractère dans le code

Dans un processus de déploiement, il est utile de gérer les traductions de chaînes de caractères dans le code, afin de pouvoir les déployer plus facilement.

Exemple avec cette fonction d'update à adapter en fonction de vos besoins :

  1. /**
  2.  * Création d'une traduction
  3.  */
  4. function mespronos_tweaks_update_8005() {
  5. $chaine = 'Forgotten password';
  6. $traduction = 'Mot de passe oublié';
  7. $storage = \Drupal::service('locale.storage');
  8. $string = $storage->findString(['source' => $chaine]);
  9. if ($string === NULL) {
  10. $string = new \Drupal\locale\SourceString();
  11. $string->setString($chaine);
  12. $string->setStorage($storage);
  13. $string->save();
  14. }
  15.  
  16. $translation = $storage->createTranslation(array(
  17. 'lid' => $string->lid,
  18. 'language' => 'fr',
  19. 'translation' => $traduction,
  20. ))->save();
  21. }

Pour un exemple réel, il sera plus pratique de passer par un tableau associatif (à deux dimensions si l'on veut importer plusieurs langues) qui sera parcouru par un ou deux foreach.

Par kgaut
Kevin Gautreau

Drupal 8 - Ajouter une restriction par ip sur une route

Dans le fichier MODULE.routing.yml on va utiliser le requirement « _custom_access »

  1. module.ma_methode:
  2.   path: 'mon-module/mon-chemin'
  3.   defaults:
  4.   _controller: '\Drupal\module\Controller\monController::maMethode'
  5.   requirements:
  6.   _custom_access: '\Drupal\module\Controller\monController::maMethodeAccess'

Que l'on va implémenter dans notre contrôleur, ici monController.php :

  1. public function maMethodeAccess() {
  2. /** @var Request $request */
  3. $request = \Drupal::request();
  4. $ipAutorisees = \Drupal::config('iamyourstory.checkcard_api')->get('allowed_ips')
  5. $ipAutorisees = explode(',', $ipAutorisees);
  6. $ipAutorisees = array_map('trim', $ipAutorisees);
  7. return AccessResult::allowedIf(\in_array($request->server->get('REMOTE_ADDR'), $ipAutorisees));
  8. }

à noter :

  • Les ip autorisées sont stockées en configuration via un formulaire de config, les ip sont séparées par une virgule, d'où le explode.
  • J'utilise ensuite la fonction array_map('trim', $ipAutorisees) pour supprimer les éventuels espaces. Si la personne avait saisi « 127.0.0.1, 192.168.0.2 », mon tableau sans le trim sera ['127.0.0.1', ' 192.168.0.2'] (espace au départ de la seconde ip.)
Par kgaut
Kevin Gautreau

Drupal 8 - Entité - Champ de base Fichier (File)

Voici comment créer un champ « fichier » au sein d'un type d'entité custom dans drupal 8 :

  1. $fields['programme_pdf'] = BaseFieldDefinition::create('file')
  2. ->setLabel(t('Programme PDF'))
  3. ->setSetting('file_directory', 'formations/programme') // dossier d'upload
  4. ->setSetting('max_filesize', '10MB') // taille max du fichier
  5. ->setSetting('file_extensions', 'pdf') // extensions autorisées, à séparer par un espace
  6. ->setSetting('description_field', FALSE) // si on veut activer un champ « description »
  7. ->setDisplayOptions('form', [
  8. 'label' => 'hidden',
  9. 'type' => 'file_generic',
  10. 'weight' => 4,
  11. ])
  12. ->setDisplayConfigurable('form', TRUE)
  13. ->setDisplayConfigurable('view', TRUE);

 

Par kgaut
Kevin Gautreau

Drupal 8 - Entitée & Views - Créer une relations inverse

Prenons deux types d'entités custom : « Bière » et « Brasserie » avec une relation 1-n entre les deux dans le sens :

  • Une bière provient d'une et d'une seule brasserie
  • Une brasserie peut proposer N bières

 Ainsi :

drupal-views-relations.png

En drupalisme, on aurait une propriété « entity_reference » au niveau de notre bière qui fera référence à la brasserie.

Dans views, si on fait un listing des bières, pas de soucis pour accéder au contenu de la brasserie depuis la bière, par contre l'inverse n'est pas possible.

Depuis un listing de brasserie, il n'est pas possible d’accéder aux bières de la brasserie.

Pour cela il faut utiliser la classe en charge de views_data, définie dans l'annotation de notre type d'entité brasserie :

drupal-entitee-annotation.png

Et voila le contenu de ce fichier

  1.  
  2. namespace Drupal\mon_module\Entity\ViewsData;
  3.  
  4. use Drupal\views\EntityViewsData;
  5.  
  6. class BrasserieViewsData extends EntityViewsData {
  7.  
  8. /**
  9.   * {@inheritdoc}
  10.   */
  11. public function getViewsData() {
  12. $data = parent::getViewsData();
  13. $data['brasserie']['bieres'] = [
  14. 'title' => t('Bieres'),
  15. 'help' => t('Lie la brasserie aux bières produites'),
  16. 'relationship' => [
  17. 'group' => t('bieres'), // Affiché en information dans la partie « relationship » de views
  18. 'label' => t('Actions de formation'), // Affiché en information dans la partie « relationship » de views
  19. 'base' => 'biere', // Table de base de l'entitée cible
  20. 'field table' => 'biere', // Table contenant le champ de l'entitée cible sur lequel on fera la jointure
  21. 'base field' => 'brasserie',// Champ de l'entité cible Champ sur lequel on fera la jointure
  22. 'relationship field' => 'brasserie_id', // Champ de l'entité source sur lequel on fera la jointure
  23. 'id' => 'standard',
  24. ],
  25. ];
  26. return $data;
  27. }
  28. }

Et voila le travail !

views-relationship.png

Par kgaut
Kevin Gautreau

Drupal - PSA-2018-001 - Patch de sécurité déployé le 28/03/2018

Mise à jour du 29 mars 2018 :

Patchez votre site

Si vous n'avez pas encore patché / mis à jour votre site, faite le ! Téléchargement des nouvelles versions ou des patchs à cette adresse : https://www.drupal.org/sa-core-2018-002.

Si vous utilisez composer, la commande pour mettre à jour le core est :

  1. composer update drupal/core

Si vous utilisez drush

  1. drush rf
  2. drush up

La faille

Il s'agit de variables get / post / cookies / pouvant contenir des « # » dans leurs noms et potentiellement déclencher des injections sql ? Je n'ai pas encore vu d'exploit mais les implications données sur la FAQ de la faille sont violente :

 

  • How difficult is it for the attacker to leverage the vulnerability? None (user visits page).
  • What privilege level is required for an exploit to be successful? None (all/anonymous users).
  • Does this vulnerability cause non-public data to be accessible? All non-public data is accessible.
  • Can this exploit allow system data (or data handled by the system) to be compromised? All data can be modified or deleted.
  • Does a known exploit exist? Theoretical or white-hat (no public exploit code or documentation on development exists)
  • What percentage of users are affected? Default or common module configurations are exploitable, but a config change can disable the exploit.

Source : https://groups.drupal.org/security/faq-2018-002

En tout cas le patch permet de filtrer ces tableaux et enlever toutes les éléments pouvant être dangereux.

Il est possible d'avoir une whitelist des paramètres à ne pas supprimer dans le cas où vous utilisez des noms de cookies, paramètres GET ou POST commençant par des « # ».

Pour cela, sous drupal 7, dans le fichier settings.php

  1. $conf['sanitize_input_whitelist'] = ['#clee_1', '#clee_2'];

Sous drupal 8, dans le fichier settings.php aussi :

  1. $settings['sanitize_input_whitelist'] = ['#clee_1', '#clee_2'];

Il y a aussi un système pour enregistrer à chaque fois que des paramètres sont supprimés.

Pour l'activer sous drupal 7 :

  1. $conf['sanitize_input_logging'] = TRUE;

Sous drupal 8 :

  1. $settings['sanitize_input_logging'] = TRUE;

Post original du 21/03/2018

Il vient d'être annoncé par l'équipe gérant la sécurité du CMS drupal qu'un gros correctif de sécurité pour drupal 7 et drupal 8 sera déployé mercredi 28/03/2018 entre 20h et 21h30 (heures Françaises). [Edit du 27/03/2018 : j'avais oublié le paramètre « heure d'été » dans mes conversions de timezones...]

On ne sait pas encore où se situe la faille. On sait seulement qu'elle semble (très) importante et qu'il est recommandé d'appliquer le patch immédiatement.

La dernière fois qu'un cas similaire s'est présenté, une fois le correctif disponible, les sites non patchés ont été très rapidement piratés. En effet : une fois que l'on a accès au patch, il est facile de trouver la faille corrigée et ainsi de l'exploiter sur des sites non protégés.

Si vous êtes développeur ou si vous gérez vos propres sites drupal, prévoyez une permanence mercredi soir pour vous occuper de ça.

Si vous avez un site drupal qui est géré par un tiers, assurez-vous qu'il soit au courant et qu'il s'en occupera au plus tôt.

Ce que l'on sait :

  1. Les versions 7 et 8 de drupal sont concernées. Potentiellement aussi la version 6 (pour plus d'informations spécifiques sur la version 6 : https://www.drupal.org/project/d6lts)
  2. Des patchs seront disponible en plus des nouvelles versions de drupal 7, 8.3, 8.4 et 8.5, la mise à disposition d'un patch permet une application du correctif plus rapide et moins risquée qu'une mise à jour complète d'un drupal.
  3. Le correctif ne nécessitera pas de mise à jour de la base de données.
  4. Il faudra aller vite, très vite : lors d'un précédent en 2015 (drupageddon) les premiers sites hackés l'avaient étés moins de 6h après la mise à disposition du patch.
  5. Le patch sera disponible à cette adresse : https://www.drupal.org/psa-2018-001 entre 20H et 21H30 ce mercredi.

 

Plus d'informations : https://www.drupal.org/psa-2018-001

Par kgaut
Kevin Gautreau

Drupal 8 - Créer la traduction d'une chaine de caractère dans le code

Dans un processus de déploiement, il est utile de gérer les traductions de chaînes de caractères dans le code, afin de pouvoir les déployer plus facilement.

Exemple avec cette fonction d'update à adapter en fonction de vos besoins :

  1. /**
  2.  * Création d'une traduction
  3.  */
  4. function mespronos_tweaks_update_8005() {
  5. $chaine = 'Forgotten password';
  6. $traduction = 'Mot de passe oublié';
  7. $storage = \Drupal::service('locale.storage');
  8. $string = $storage->findString(['source' => $chaine]);
  9. if ($string === NULL) {
  10. $string = new \Drupal\locale\SourceString();
  11. $string->setString($chaine);
  12. $string->setStorage($storage);
  13. $string->save();
  14. }
  15.  
  16. $translation = $storage->createTranslation(array(
  17. 'lid' => $string->lid,
  18. 'language' => 'fr',
  19. 'translation' => $traduction,
  20. ))->save();
  21. }

Pour un exemple réel, il sera plus pratique de passer par un tableau associatif (à deux dimensions si l'on veut importer plusieurs langues) qui sera parcouru par un ou deux foreach.

Par kgaut
Kevin Gautreau

Drupal 8 - Ajouter une restriction par ip sur une route

Dans le fichier MODULE.routing.yml on va utiliser le requirement « _custom_access »

  1. module.ma_methode:
  2.   path: 'mon-module/mon-chemin'
  3.   defaults:
  4.   _controller: '\Drupal\module\Controller\monController::maMethode'
  5.   requirements:
  6.   _custom_access: '\Drupal\module\Controller\monController::maMethodeAccess'

Que l'on va implémenter dans notre contrôleur, ici monController.php :

à noter : les ip autorisées sont stockées en configuration via un formulaire de config, les ip sont séparées par une virgule, d'où le explode.

  1. public function maMethodeAccess() {
  2. /** @var Request $request */
  3. $request = \Drupal::request();
  4. $ipAutorisees = explode(',', \Drupal::config('module.methode')->get('allowed_ips'));
  5. return AccessResult::allowedIf(\in_array($request->server->get('REMOTE_ADDR'), $ipAutorisees));
  6. }

 

Par kgaut
Kevin Gautreau

Drupal 8 - Entité - Champ de base Fichier (File)

Voici comment créer un champ « fichier » au sein d'un type d'entité custom dans drupal 8 :

  1. $fields['programme_pdf'] = BaseFieldDefinition::create('file')
  2. ->setLabel(t('Programme PDF'))
  3. ->setSetting('file_directory', 'formations/programme') // dossier d'upload
  4. ->setSetting('max_filesize', '10MB') // taille max du fichier
  5. ->setSetting('file_extensions', 'pdf') // extensions autorisées, à séparer par un espace
  6. ->setSetting('description_field', FALSE) // si on veut activer un champ « description »
  7. ->setDisplayOptions('form', [
  8. 'label' => 'hidden',
  9. 'type' => 'file_generic',
  10. 'weight' => 4,
  11. ])
  12. ->setDisplayConfigurable('form', TRUE)
  13. ->setDisplayConfigurable('view', TRUE);

 

Par kgaut
Kevin Gautreau

Drupal 8 - Entitée & Views - Créer une relations inverse

Prenons deux types d'entités custom : « Bière » et « Brasserie » avec une relation 1-n entre les deux dans le sens :

  • Une bière provient d'une et d'une seule brasserie
  • Une brasserie peut proposer N bières

 Ainsi :

drupal-views-relations.png

En drupalisme, on aurait une propriété « entity_reference » au niveau de notre bière qui fera référence à la brasserie.

Dans views, si on fait un listing des bières, pas de soucis pour accéder au contenu de la brasserie depuis la bière, par contre l'inverse n'est pas possible.

Depuis un listing de brasserie, il n'est pas possible d’accéder aux bières de la brasserie.

Pour cela il faut utiliser la classe en charge de views_data, définie dans l'annotation de notre type d'entité brasserie :

drupal-entitee-annotation.png

Et voila le contenu de ce fichier

  1.  
  2. namespace Drupal\mon_module\Entity\ViewsData;
  3.  
  4. use Drupal\views\EntityViewsData;
  5.  
  6. class BrasserieViewsData extends EntityViewsData {
  7.  
  8. /**
  9.   * {@inheritdoc}
  10.   */
  11. public function getViewsData() {
  12. $data = parent::getViewsData();
  13. $data['brasserie']['bieres'] = [
  14. 'title' => t('Bieres'),
  15. 'help' => t('Lie la brasserie aux bières produites'),
  16. 'relationship' => [
  17. 'group' => t('bieres'), // Affiché en information dans la partie « relationship » de views
  18. 'label' => t('Actions de formation'), // Affiché en information dans la partie « relationship » de views
  19. 'base' => 'biere', // Table de base de l'entitée cible
  20. 'field table' => 'biere', // Table contenant le champ de l'entitée cible sur lequel on fera la jointure
  21. 'base field' => 'brasserie',// Champ de l'entité cible Champ sur lequel on fera la jointure
  22. 'relationship field' => 'brasserie_id', // Champ de l'entité source sur lequel on fera la jointure
  23. 'id' => 'standard',
  24. ],
  25. ];
  26. return $data;
  27. }
  28. }

Et voila le travail !

views-relationship.png

Par kgaut
Kevin Gautreau

Drupal - PSA-2018-001 - Patch de sécurité déployé le 28/03/2018

Il vient d'être annoncé par l'équipe gérant la sécurité du CMS drupal qu'un gros correctif de sécurité pour drupal 7 et drupal 8 sera déployé mercredi 28/03/2018 entre 19h et 20h30 (heures Françaises).

On ne sait pas encore où se situe la faille. On sait seulement qu'elle semble (très) importante et qu'il est recommandé d'appliquer le patch immédiatement.

La dernière fois qu'un cas similaire s'est présenté, une fois le correctif disponible, les sites non patchés ont été très rapidement piratés. En effet : une fois que l'on a accès au patch, il est facile de trouver la faille corrigée et ainsi de l'exploiter sur des sites non protégés.

Si vous êtes développeur ou si vous gérez vos propres sites drupal, prévoyez une permanence mercredi soir pour vous occuper de ça.

Si vous avez un site drupal qui est géré par un tiers, assurez-vous qu'il soit au courant et qu'il s'en occupera au plus tôt.

Encore une fois, les versions 7 et 8 de drupal sont concernées.

Plus d'informations : https://www.drupal.org/psa-2018-001

 

 

Pages