Laravel GDPR Consent
Light-weight Laravel 5 package
for user's consents and data processing records., (*1)
Install
Via composer, (*2)
composer require foothing/laravel-gdpr-consent
, (*3)
Add service provider in config/app.php
, (*4)
'providers' => [
// omitted
Foothing\Laravel\Consent\ConsentServiceProvider::class
]
Add alias in config/app.php
if you want to use the facade, (*5)
'aliases' => [
// omitted
'Consent' => Foothing\Laravel\Consent\Facades\Consent::class
]
Publish config and migrations, (*6)
php artisan vendor:publish --tag=config
, (*7)
php artisan vendor:publish --tag=migrations
, (*8)
Configure as needed, then run the migration
php artisan migrate
, (*9)
Setup the treatments table
php artisan consent
, (*10)
Quick start
First you need to configure which treatments
are required by your site.
You can do so in config/consent.php
, like the following example:, (*11)
'treatments' => [
[
// A logical name for your treatment.
'name' => 'gdpr.privacy',
// You can specify which document
// describes the treatment type
// with a document version and url.
// This part is optional.
'documentVersion' => '1.0',
'documentUrl' => env('PRIVACY_POLICY'),
// Whether this treatment is active or not.
// The reason why this flag is here is to
// allow for progressive modifications, so you
// can keep track of what the end user gave
// consent to. So if you are upgrading or
// changing the treatment the recommended
// process is to deactivate the current one
// then add a new record.
'active' => true,
// Set if this treatment is mandatory or optional.
'required' => true,
// A description text to be shown near a checkbox
// or anywhere in your UI.
'description' => 'gdpr.privacy.text',
// UI weight, use this to choose what should be
// listed first.
'weight' => 0,
],
[
'name' => 'gdpr.marketing',
'documentVersion' => '1.0',
'documentUrl' => env('PRIVACY_POLICY'),
'active' => true,
'required' => false,
'description' => 'gdpr.marketing.text',
'weight' => 1,
],
]
Once you are done with the configuration you can run php artisan consent:setup
to update your treatments database., (*12)
Then make your User
model implement the
ConsentSubject
Contract and use the HasConsents
trait., (*13)
class User extends Model implements ConsentSubject
{
// This trait will implement the relation to the consent table.
use HasConsents;
/**
* Returns the subject id.
*
* @return mixed
*/
public function getSubjectId()
{
return $this->id;
}
}
Now you will be able to use the package API to register user's consent and
data processing events like in the following example., (*14)
Display consent checkboxes in register page
@foreach(Consent::treatments() as $treatment)
<div class="checkbox">
<label>
<input name="consent_{{ $treatment->id }}" type="checkbox">
{{ trans($treatment->description) }}
</label>
</div>
@endforeach
Note that your checkbox
name must match consent_TREATMENTID
, (*15)
Validate checkboxes in your controller
public function postRegister(Request $request)
{
if (! $treatments = Consent::validate($request->all()) {
// User didn't accept all the mandatory checkboxes.
throw new \Exception("Consent is mandatory in order to proceed.");
}
}
Register the consent
public function postRegister(Request $request)
{
// omitted
// This will register a record with the
// user's consent along with an event log.
Facade::grant($treatments, Auth::user());
}
Show consent in a user's settings page
<!-- Cycle through active treatments, just like the register page. -->
@foreach(Consent::treatments() as $treatment)
<div class="checkbox">
<label>
<input {{ Consent::exists($user, $treatment) ? 'checked' : '' }} name="{{ $treatment->id }}" type="checkbox">
{{ trans($treatment->description) }}
</label>
</div>
@endforeach
Note that for the update handler the checkbox name should be the treatment id., (*16)
Save user's consent changes
public function postUpdateConsent(Request $request)
{
// You should pass only the checkboxes as the first argument.
Consent::update($request->except('_token'), Auth::user());
// redirect as you like.
}
Note that those are just examples to show the Consent API,
though i wouldn't recommend using the facade inside the views
and you can replicate the same feature manipulating data in
a controller, before the view is being rendered., (*17)
Log the "right to erasure"
In your delete user
controller or service:, (*18)
public function deleteIndex(Request $request)
{
\DB::transaction(function() use($user)
{
// Delete the user first.
// i.e. $user->delete();
// This will remove consents and log the erasure request.
Consent::erase($user);
});
}
Events
It's not completely clear yet how anyone will approach logs
or data processing records, which should anyway be stored and
maintained. In order to provide a better flexibility an API
for events has been added aswell., (*19)
The events API is implicitly used within the only hardcoded
actions (grant, revoke, erasure) but you can use it
how you like to track meaningful data processing records., (*20)
$event = new Event([
// The subject id.
'subject_id' => $user->id,
// A string describing what has been done with subject's data.
'action' => $action,
// Optional, consent record id.
'consent_id' => $consentId,
]);
Consent::log($event);
// Retrieving subject's logs
Consent::events($subject);
"Pseudonymization" in event records
Since each event record stores subject's ip and the request payload,
those fields are encrypted with a 2-way algorithm., (*21)
Keep in mind that Laravel uses the config/app.php
key to encrypt and decrypt, so if you change
that your data won't be decryptable anymore., (*22)
Project status
This package is under active development and needs work,
but it got to the point where i had the features i need
at the moment., (*23)
What is needed yet
- api refactor
- test coverage to 100%
- test with every 5.x minor release
- travis integration
- style fixes, (*24)
so feel free to drop a line if you'd like to contribute., (*25)
License
MIT, (*26)