
Créer un blog – le RGPD
Nous avons dans le précédent article codé le profil de l’utilisateur. Dans un commentaire récent Braice m’a proposé de traiter le sujet du RGPD. C’est un sujet qu’il est nécessaire de prendre en compte dès qu’on doit recueillir et mémoriser des données personnelles. Le RGPD (Règlement Général sur la Protection des Données, mais ça fait GDPR en anglais) est une réglementation européenne qui a pour but d’encadrer strictement le traitement des données des personnes physiques. On peut se demander ce qu’est une donnée personnelle, et en fait c’est assez vaste : nom, adresse, email, téléphone, en fait toute donnée susceptible d’identifier une personne directement ou indirectement (par exemple le fait de croiser deux informations non pertinentes peut le devenir). Pour tout savoir sur le sujet je ne peux que vous conseiller le site officiel de la CNIL.
On peut se demander dans le cas de notre blog ce qu’il convient de mettre en place pour respecter ce règlement. » Le règlement général sur la protection des données (RGPD) impose une information concise, transparente, compréhensible et aisément accessible des personnes concernées. « . On doit donc faire preuve de transparence : pourquoi on collecte des données, ce qu’on va en faire, combien de temps on les conserve, qui y a accès, et seront-elles accessibles ? Lorsqu’une personne s’inscrit sur le blog on a une collecte directe de données et on doit donc fournir toutes les informations nécessaires lors de cette collecte. Le plus simple est de créer une page spécifique qui explique tout (responsable du traitement, finalité, base légale, durée de conservation, droit d’accès et de modification…) mais on doit en faire référence dans le formulaire, ce que nous n’avons pas fait.
Quand on recueille des informations personnelles il faut le consentement de la personne, et celui-ci doit être « libre, spécifique, éclairé et univoque ». Comment y parvenir ? Lisons le texte officiel : « Le consentement devrait être donné par un acte positif clair par lequel la personne concernée manifeste de façon libre, spécifique, éclairée et univoque son accord au traitement des données à caractère personnel la concernant, … Cela pourrait se faire notamment en cochant une case lors de la consultation d’un site internet« . Dans la pratique j’ai opté pour une case à cocher. La soumission d’un formulaire est impossible tant que la case n’est pas cochée. Le texte associé à la case exprime clairement la nature du consentement et renvoie à une page qui explicite tout.
Pour ce qui concerne les cookies ceux utilisés pour le blog sont exemptés de consentement parce qu’ils sont « destinés à l’authentification auprès d’un service, y compris ceux visant à assurer la sécurité du mécanisme d’authentification, par exemple en limitant les tentatives d’accès robotisées ou inattendues « . On n’a donc pas à mettre en place une alerte spécifique.
Vous pouvez télécharger le code final de cet article ici.
L’enregistrement
Pour le moment notre formulaire d’enregistrement se présente ainsi :
Un composant pour la case à cocher
On va ajouter une case à cocher pour le consentement. Comme on aura aussi à traiter le formulaire de contact on crée un composant pour la case à cocher :
On le code ainsi :
<label class="h-add-bottom"> <input id="rgpd" type="checkbox" name="rgpd" {{ old('rgpd') ? 'checked' : '' }}> <span class="label-text">@lang("I have read and accept the site's privacy policy.")</span> </label>
On ajoute la traduction dans resources/lang/fr.json :
"I have read and accept the site's privacy policy.": "J’ai lu et accepte la politique de confidentialité du site.",
On doit insérer ce composant dans la vue auth.register juste avant le bouton de soumission :
<!-- RGPD --> <x-auth.rgpd-checkbox /> <x-auth.submit title="Register" />
Il ne reste plus qu’à le faire fonctionner…
Un composant pour le script
Là aussi pour rendre le script facilement réutilisable on crée un autre composant :
Avec un peu de Javascript :
<script> const change = () => { if(rgpd.checked) { submit.removeAttribute('disabled'); submit.style.cursor = 'pointer'; } else { submit.setAttribute('disabled', true); submit.style.cursor = 'not-allowed'; } } document.addEventListener('DOMContentLoaded', () => { const rgpd = document.getElementById('rgpd'); const submit = document.getElementById('submit'); change(); rgpd.addEventListener('click', () => change()); }); </script>
On l’ajoute en bas de la vue auth.register :
@section('scripts') <x-auth.rgpd-script /> @endsection
Pour facilement accéder au bouton de soumission on ajoute un identifiant dans le composant auth.submit :
@props(['title']) <input id="submit" class="btn--primary h-full-width" type="submit" value="@lang($title)">
Fonctionnement
Au chargement le bouton est inactif (l’icône de la souris a été adapté) :
Quand on coche la case le bouton devient actif et l’icône change :
Le contact
Pour le moment notre formulaire de contact se présente ainsi pour un utilisateur non authentifié :
On ajoute les composants qu’on a créé précédemment dans la vue front.contact :
<br> @if(Auth::guest()) <x-auth.rgpd-checkbox /> @endif <x-auth.submit title="Send" /> </fieldset> </form> </div> </div> </div> </div> @endsection @section('scripts') @if(Auth::guest()) <x-auth.rgpd-script /> @endif @endsection
On introduit cette fonctionnalité que si on a affaire à un utilisateur non authentifié, sinon on a déjà les données personnelles. On bénéficie maintenant exactement du même fonctionnement que pour le formulaire d’enregistrement :
Le profil
On a déjà créé un formulaire de profil où l’utilisateur authentifié peut lire et modifier ses données personnelles. On va ajouter la possibilité de supprimer le compte. Évidemment ça aura pour conséquence la suppression corrélative des éventuelles données liées : articles et commentaires.
Le contrôleur RegisteredUserController
On ajoute une méthode dans le contrôleur RegisteredUserController :
public function destroy(Request $request) { $request->user()->delete(); return response()->json(); }
On va y accéder en Ajax, on se contente de supprimer le compte et de renvoyer un réponse JSON.
La route
On ajoute une route :
// Profile Route::middleware(['auth', 'password.confirm'])->group(function () { ... Route::name('deleteAccount')->delete('profile/delete', [RegisteredUserController::class, 'destroy']); });
On la prévoit dans le groupe protégé du profil.
La vue auth.profile
Dans la vue auth.profile on ajoute la bouton et le script :
<x-auth.submit title="Save" /> <a id="delete" href="{{ route('deleteAccount') }}" class="btn btn--primary h-full-width" style="background: crimson;">@lang('Delete account')</a> </form> </div> </div> @endsection @section('scripts') <script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script> <script> // Variables const headers = { 'X-CSRF-TOKEN': '{{ csrf_token() }}', 'Content-Type': 'application/json', 'Accept': 'application/json' } // Delete account const deleteAccount = async e => { e.preventDefault(); Swal.fire({ title: '@lang('Really delete your account?')', icon: 'warning', showCancelButton: true, confirmButtonColor: '#DD6B55', confirmButtonText: '@lang('Yes')', cancelButtonText: '@lang('No')', preConfirm: () => { return fetch(e.target.getAttribute('href'), { method: 'DELETE', headers: headers }) .then(response => { if (response.ok) { document.location.reload(); } else { Swal.fire({ icon: 'error', title: '@lang('Whoops!')', text: '@lang('Something went wrong!')' }); } }); } }); } document.getElementById('delete').addEventListener('click', e => deleteAccount(e)); </script> @endsection
On ajoute les traductions dans resources/lang/fr.json :
"Delete account": "Supprimer mon compte", ... "Really delete your account?": "Vraiment supprimer votre compte ?",
On se retrouve avec un bouton supplémentaire :
Par sécurité on présente une fenêtre de confirmation :
En cas de suppression effective on recharge la page et, comme l’utilisateur n’est plus authentifié, le middleware renvoie sur la page de connexion.
Conclusion
Voilà maintenant on devrait être en conformité avec le RGPD !


7 commentaires
fabBlab
Bonjour,
Ma question n’est pas directement liée au RGPD, mais pas sans rapport, puisque nous sommes censés sécuriser nos applications traitant des données personnelles : est-ce qu’il y a une protection par défaut bloquant un certain temps la connexion à un compte suite à un certain nombre d’échecs ?
Je m’attendais à trouver le nombre d’échecs autorisés et la durée de blocage dans le fichier .env ou encore dans config/auth.php, mais je n’ai rien vu qui y ressemble.
Cela peut être utile pour se protéger des attaques « brute force ».
En général, je bloque une heure au bout de 10 échecs.
ronald169
Salut Best serait-il possible d’ajouter une fonctionnalité d’archivage ?
bestmomo
Salut,
Archivage de quoi ?
ronald169
L’archivage des post mais bon je vois comment le gerer.
oksam
Bonjour Best! c’est possible d’ajouter une file d’actualitée et des carrousel d’image sur le côté gauche par exemple des Posts en espérant que ça ne change la règle des gestions du départ pour t’éviter trop de travail!
bestmomo
Salut,
Pour la file d’actualité je ne sais pas trop, je n’ai jamais fait ça, il faudrait que je fouille un peu la question. Par contre pour un diaporama ça ferait pas mal modifier le thème en place et donc ça serait surtout du travail frontend sans trop de lien avec Laravel.
oksam
D’accord je verrai dans qu’elle mesure je pourrai en ajouter