PHPackages                             dialect/laravel-gdpr-compliance - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. dialect/laravel-gdpr-compliance

ActiveLibrary

dialect/laravel-gdpr-compliance
===============================

GDPR compliant data portability and anonymization

1.4.7(6y ago)56117.2k↓24%5[4 issues](https://github.com/kfvit/laravel-gdpr-compliance/issues)MITPHPPHP &gt;=7.0

Since May 5Pushed 5y ago4 watchersCompare

[ Source](https://github.com/kfvit/laravel-gdpr-compliance)[ Packagist](https://packagist.org/packages/dialect/laravel-gdpr-compliance)[ Docs](https://github.com/dialect-katrineholm/laravel-gdpr-compliance)[ RSS](/packages/dialect-laravel-gdpr-compliance/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (2)Versions (21)Used By (0)

[![StyleCI](https://camo.githubusercontent.com/6ab9cc5a61bad123e10b0fe7658dd75a50db186632308c95786c2726aa7f03bb/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f3133333437343630332f736869656c643f6272616e63683d6d6173746572)](https://github.styleci.io/repos/133474603)

GDPR compliant data handling with ease
======================================

[](#gdpr-compliant-data-handling-with-ease)

This package helps you get compliant with GDPR;

Article **7**: Conditions for consent
Article **17**: Right to be forgotten
Article **20**: Right to data portability

Table of contents
=================

[](#table-of-contents)

- [Table of contents](#table-of-contents)
- [Dependencies](#dependencies)
- [Installation](#installation)
- [Configuration](#configuration)
    - [Consent](#gdpr-consent)
    - [Portability](#portability)
    - [Anonymizability](#anonymizability)
    - [Automatic anonymization](#automatic-anonymization-of-inactive-users)
    - [Configuring Anonymizable Data](#configuring-anonymizable-data)
    - [Recursive Anonymization](#recursive-anonymization)
    - [Configuring Portable Data](#configuring-portable-data)
    - [Lazy Eager Loading Relationships](#lazy-eager-loading-relationships)
    - [Hiding Attributes](#hiding-attributes)
- [Usage](#usage)
    - [Encryption](#encryption)
    - [Anonymization](#anonymization)
- [Tests](#tests)
- [Security Vulnerabilities](#security-vulnerabilities)
- [Credit](#credit)
- [License](#license)

Dependencies
------------

[](#dependencies)

- PHP &gt;= 7.0.0
- Laravel &gt;= 5.5

Installation
------------

[](#installation)

First, install the package via the Composer package manager:

```
$ composer require dialect/laravel-gdpr-compliance
```

After installing the package, you should publish the configuration file:

```
$ php artisan vendor:publish --provider="Dialect\Gdpr\GdprServiceProvider" --tag=gdpr-config
```

Configuration
-------------

[](#configuration)

#### GDPR Consent

[](#gdpr-consent)

The package includes a way for users to sign a GDPR-agreement. This will redirect the user to the agreement on the specified routes until the user has agreed to the new terms.

To add the agreement functionality:

1. Publish the middleware:
    `php artisan vendor:publish --provider="Dialect\Gdpr\GdprServiceProvider"`
2. Add `'gdpr.terms' => \App\Http\Middleware\RedirectIfUnansweredTerms::class`
    to the `$routeMiddleware` middlewaregroup in `app/Http/Kernel` like so:
    ```
        protected $routeMiddleware = [
            'gdpr.terms' => \App\Http\Middleware\RedirectIfUnansweredTerms::class,
        ];
    ```
3. Add the middleware to the routes that you want to check (normally the routes where auth is used): ```
        Route::group(['middleware' => ['auth', 'gdpr.terms']], function () {
           Route::get('/', 'HomeController@index');
        });
    ```
4. Add the fields to `$fillable` in the User model: ```
        protected $fillable = [
            'last_activity',
            'accepted_gdpr',
            'isAnonymized'
        ];
    ```
5. Change the Agreement text to your particular needs in `resources/views/gdpr/message.blade.php`

#### Portability

[](#portability)

Add the `Portable` trait to the model model you want to be able to port:

```
namespace App;

use Dialect\Gdpr\Portable;

class User extends Model
{
    use Portable;
}
```

#### Anonymizability

[](#anonymizability)

Add the `Anonymizable` trait to the model you want to be able to anonymize:

```
namespace App;

use Dialect\Gdpr\Anonymizable;

class User extends Model
{
    use Anonymizable;
}
```

#### Automatic Anonymization of inactive users

[](#automatic-anonymization-of-inactive-users)

The package adds a scheduled job intended to anonymize the `User` model automatically when the user has been inactive for a specific time. To specify the time, edit the `ttl` setting in the published config.
To activate this feature:

1. Add the command to the schedule function in `app/Console/Kernel.php` like so:

    ```
        protected function schedule(Schedule $schedule)
        {
            $schedule->command('gdpr:anonymizeInactiveUsers')->daily();
        }
    ```
2. Add the class to the `$commands` array in the same file like so:

```
```php
    protected $commands = [
        \Dialect\Gdpr\Commands\AnonymizeInactiveUsers::class,
    ];
```

```

### Configuring Anonymizable Data

[](#configuring-anonymizable-data)

On the model, set `gdprAnonymizableFields` by adding the fields you want to anonymize on the model, you can also set up attribute-like functions on your model to supply replacement data.
**If you have a unique-constraint on your model, you should use this.**If no value is supplied, a default string from settings will be used.

```
/**
 * Using the default string from config.
 */
protected $gdprAnonymizableFields = [
    'name',
    'email'
];
```

```
/**
 * Using replacement strings.
 */
protected $gdprAnonymizableFields = [
    'name' => 'Anonymized User',
    'email' => 'anonymous@mail.com'
];
```

```
namespace App;

use Dialect\Gdpr\Anonymizable;

class User extends Model
{
    use Anonymizable;

    protected $gdprAnonymizableFields = [
        'email'
    ];

    /**
    * Using getAnonymized{column} to return anonymizable data
    */
    public function getAnonymizedEmail()
    {
        return random_bytes(10);
    }
}
```

### Recursive Anonymization

[](#recursive-anonymization)

If the model has related models with fields that needs to be anonymized at the same time, add the related models to `$gdprWith`. On the related models. add the `Anonymizable` trait and specify the fields with `$gdprAnonymizableFields` like so:

```
class Order extends Model
{
    use Anonymizable;

	protected $guarded = [];
	protected $table = 'orders';
	protected $gdprWith = ['product'];
    protected $gdprAnonymizableFields = ['buyer' => 'Anonymized Buyer'];

	public function product()
	{
		return $this->belongsTo(Product::class);
	}
	public function customer()
	{
		return $this->belongsTo(Customer::class);
	}
}
```

```
class Customer extends Model
{
    use Anonymizable;
	protected $guarded = [];
	protected $table = 'customers';
	protected $gdprWith = ['orders'];

	protected $gdprAnonymizableFields = ['name' => 'Anonymized User'];

	public function orders()
	{
		return $this->hasMany(Order::class);
	}
}
```

Calling `$customer->anonymize();` will also change the `buyer`-field on the related orders.

### Configuring Portable Data

[](#configuring-portable-data)

By default, the entire `toArray` form of the `App\User` model will be made available for download. If you would like to customize the downloadable data, you may override the `toPortableArray()` method on the model:

```
use Dialect\Gdpr\Portable;

class User extends Model
{
    use Portable;

    /**
     * Get the GDPR compliant data portability array for the model.
     *
     * @return array
     */
    public function toPortableArray()
    {
        $array = $this->toArray();

        // Customize array...

        return $array;
    }
}
```

### Lazy Eager Loading Relationships

[](#lazy-eager-loading-relationships)

You may need to include a relationship in the data that will be made available for download. To do so, add a `$gdprWith` property to your `App\User` model:

```
use Dialect\Gdpr\Portable;

class User extends Model
{
    use Portable;

    /**
     * The relations to include in the downloadable data.
     *
     * @var array
     */
    protected $gdprWith = ['posts'];
}
```

### Hiding Attributes

[](#hiding-attributes)

You may wish to limit the attributes, such as passwords, that are included in the downloadable data. To do so, add a `$gdprHidden` property to your `App\User` model:

```
use Dialect\Gdpr\Portable;

class User extends Model
{
    use Portable;

    /**
     * The attributes that should be hidden for the downloadable data.
     *
     * @var array
     */
    protected $gdprHidden = ['password'];
}
```

Alternatively, you may use the `$gdprVisible` property to define a white-list of attributes that should be included in the data that will be made available for download. All other attributes will be hidden when the model is converted:

```
use Dialect\Gdpr\Portable;

class User extends Moeld
{
    use Portable;

    /**
     * The attributes that should be visible in the downloadable data.
     *
     * @var array
     */
    protected $gdprVisible = ['name', 'email'];
}
```

Usage
-----

[](#usage)

This package exposes an endpoint at `/gdpr/download`. Only authenticated users should be able to access the routes. Your application should make a POST call, containing the currently authenticated user's password, to this endpoint. The re-authentication is needed to prevent information leakage.

### Encryption

[](#encryption)

> Before using encryption, you must set a `key` option in your `config/app.php` configuration file. If this value is not properly set, all encrypted values will be insecure.

You may encrypt/decrypt attributes on the fly using the `EncryptsAttributes` trait on any model. The trait expects the `$encrypted` property to be filled with attribute keys:

```
use Dialect\Gdpr\EncryptsAttributes;

class User extends Model
{
    use EncryptsAttributes;

    /**
     * The attributes that should be encrypted and decrypted on the fly.
     *
     * @var array
     */
    protected $encrypted = ['ssnumber'];
}
```

If all fields are encrypted, the model can be returned in decrypted state as an array or collection:

```
$decryptedArray = $this->decryptToArray();

$decryptedCollection = $this->customer->decryptToCollection();
```

### Anonymization

[](#anonymization)

To anonymize a model you call `anonymize()` on it:

```
class SomeController extends Controller
{
    public function anonymizeAGroupOfUsers() {
    	$users = User::where('last_activity', '
