Skip to content

Commit

Permalink
Update for 3.x behaviour changes available in Laravel 8.14
Browse files Browse the repository at this point in the history
  • Loading branch information
RichardStyles committed Nov 10, 2020
1 parent 77f774a commit cb6ca19
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 2 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

All notable changes to `eloquentencryption` will be documented in this file

## 3.0

- As of **Laravel 8.14** you can specify the built in Eloquent Encryption casting setting a model's encryptUsing in your app service provider. This allows for automatic separation of your APP_KEY, when using a different `Illuminate\Contracts\Encryption\Encrypter` class/instance.

```php
EncryptedCast::encryptUsing(new \RichardStyles\EloquentEncryption\EloquentEncryption);
```

Then simply define your casts in your model as you normally would.

```php
class EncryptedCast extends Model
{
public $casts = [
'secret' => 'encrypted',
'secret_array' => 'encrypted:array',
'secret_json' => 'encrypted:json',
'secret_object' => 'encrypted:object',
'secret_collection' => 'encrypted:collection',
];
}
```

## 2.0
- EloquentEncryption now uses `Illuminate\Contracts\Encryption\Encrypter` contract.
- **BC** If relying on 1.x use `encryptString()` or `decryptString()` functions **if you are using this encryption elsewhere in your application**. As the default encrypt/decrypt function now serialize values automatically, this may cause unexpected errors during decrypting.
Expand Down
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,37 @@ Schema::create('sales_notes', function (Blueprint $table) {

You can use any additional blueprint helpers, such as `->nullable()` if there is no initial data to encrypt. It is advised that `->index()` shouldn't normally be placed on these binary fields as you should not be querying against these, given they are encrypted.

## Usage
## Usage 3.x

As of version 3.x, the requirement for laravel is 8.14. This release added the `Model::encryptUsing()` static function to the base Eloquent Model.
This allows the built in process for encrypted casting to use any `Illuminate\Contracts\Encryption\Encrypter` class.

**Please test with any existing keys and data before upgrading**
Otherwise your data may not be decrypted as expected. If you are on 2.x you should not see any issues as this version follows the Encrypter Contract required by the encryptUsing static function.

In your AppServiceProvider
```php
EncryptedCast::encryptUsing(new \RichardStyles\EloquentEncryption\EloquentEncryption);
```

Then on your models, use the built in encrypted casts as needed.

```php
class EncryptedCast extends Model
{
public $casts = [
'secret' => 'encrypted',
'secret_array' => 'encrypted:array',
'secret_json' => 'encrypted:json',
'secret_object' => 'encrypted:object',
'secret_collection' => 'encrypted:collection',
];
}
```

This was made possible by a [PR](https://github.com/laravel/framework/pull/35080) to Laravel by [@hivokas](https://github.com/hivokas).

## Usage 2.x

This package leverages Laravel's own [custom casting](https://laravel.com/docs/8.x/eloquent-mutators#custom-casts) to encode/decode values.

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
"require": {
"php": "^7.3",
"illuminate/support": "^8.0",
"illuminate/database": "^8.14",
"phpseclib/phpseclib": "~2.0"
},
"require-dev": {
"orchestra/testbench": "^6.0",
"orchestra/testbench": "^6.4",
"phpunit/phpunit": "^8.0"
},
"autoload": {
Expand Down
8 changes: 8 additions & 0 deletions src/Casts/Encrypted.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class Encrypted implements CastsAttributes
*/
public function get($model, $key, $value, $attributes)
{
if(is_null($value)){
return null;
}

return EloquentEncryptionFacade::decryptString($value);
}

Expand All @@ -33,6 +37,10 @@ public function get($model, $key, $value, $attributes)
*/
public function set($model, $key, $value, $attributes)
{
if(is_null($value)){
return null;
}

return EloquentEncryptionFacade::encryptString($value);
}
}
110 changes: 110 additions & 0 deletions tests/Unit/ModelCustomEncryptorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php


namespace RichardStyles\EloquentEncryption\Tests\Unit;


use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Encryption\Encrypter;
use Illuminate\Support\Facades\Schema;
use RichardStyles\EloquentEncryption\EloquentEncryption;
use RichardStyles\EloquentEncryption\EloquentEncryptionFacade;
use RichardStyles\EloquentEncryption\Tests\TestCase;
use RichardStyles\EloquentEncryption\Tests\Traits\WithRSAHelpers;

class ModelCustomEncryptorTest extends TestCase
{
use WithRSAHelpers;

protected $eloquent_encryption;

protected function getPackageAliases($app)
{
return [
'EloquentEncryption' => EloquentEncryptionFacade::class
];
}

/**
* Define environment setup.
*
* @param \Illuminate\Foundation\Application $app
* @return void
*/
protected function getEnvironmentSetUp($app)
{
// Setup default database to use sqlite :memory:
$app['config']->set('database.default', 'testbench');
$app['config']->set('database.connections.testbench', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);
}

protected function setUp(): void
{
parent::setUp();

$this->eloquentEncryption = $this->mock(EloquentEncryption::class);

Schema::create('encrypted_casts', function (Blueprint $table) {
$table->increments('id');
$table->string('secret', 1000)->nullable();
$table->text('secret_array')->nullable();
$table->text('secret_json')->nullable();
$table->text('secret_object')->nullable();
$table->text('secret_collection')->nullable();
});

$this->assertNull(Model::$encrypter);

Model::encryptUsing($this->eloquentEncryption);
}

/** @test */
function a_model_can_encrypt_using_eloquent_encryption()
{

$this->eloquentEncryption->expects('encrypt')
->with('this is a secret string', false)
->andReturn('encrypted-secret-string');
$this->eloquentEncryption->expects('decrypt')
->with('encrypted-secret-string', false)
->andReturn('this is a secret string');


/** @var \Illuminate\Tests\Integration\Database\EncryptedCast $subject */
$subject = EncryptedCast::create([
'secret' => 'this is a secret string',
]);

$this->assertSame('this is a secret string', $subject->secret);
$this->assertDatabaseHas('encrypted_casts', [
'id' => $subject->id,
'secret' => 'encrypted-secret-string',
]);
}
}

/**
* @property $secret
* @property $secret_array
* @property $secret_json
* @property $secret_object
* @property $secret_collection
*/
class EncryptedCast extends Model
{
public $timestamps = false;
protected $guarded = [];

public $casts = [
'secret' => 'encrypted',
'secret_array' => 'encrypted:array',
'secret_json' => 'encrypted:json',
'secret_object' => 'encrypted:object',
'secret_collection' => 'encrypted:collection',
];
}

0 comments on commit cb6ca19

Please sign in to comment.