diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml new file mode 100644 index 0000000..8495e85 --- /dev/null +++ b/.github/workflows/laravel.yml @@ -0,0 +1,28 @@ +name: Laravel + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + laravel-tests: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Copy .env + run: php -r "file_exists('.env') || copy('.env.example', '.env');" + - name: Install Dependencies + run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist + - name: Create Database + run: | + mkdir -p database + touch database/database.sqlite + - name: Execute tests (Unit and Feature tests) via PHPUnit + env: + DB_CONNECTION: sqlite + DB_DATABASE: database/database.sqlite + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index cc5ef87..a333e12 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ Homestead.json # Rocketeer PHP task runner and deployment package. https://github.com/rocketeers/rocketeer .rocketeer/ +.phpunit.result.cache diff --git a/src/Models/Traits/HasEncryptedAttributes.php b/src/Models/Traits/HasEncryptedAttributes.php index 9eba47a..61ad35a 100644 --- a/src/Models/Traits/HasEncryptedAttributes.php +++ b/src/Models/Traits/HasEncryptedAttributes.php @@ -56,7 +56,6 @@ trait HasEncryptedAttributes */ public $hashAlg = 'sha256'; - /** * @var array */ @@ -68,8 +67,8 @@ trait HasEncryptedAttributes * @param $value * @return string */ - private function setEncryptedHashedBIAttributes($key, $value){ - + private function setEncryptedHashedBIAttributes($key, $value) + { if (array_key_exists($key, $this->encrypted)) { $this->checkTypes($key, $value); @@ -80,26 +79,25 @@ private function setEncryptedHashedBIAttributes($key, $value){ return $this->setHashed($key, $value); } - /** * @param $value * @return string */ - private function setEncrypted($value){ + private function setEncrypted($value) + { if (!is_null($value)) { $value = encrypt((string)$value); } return $value; } - /** * @param $key * @param $value * @return string */ - private function setHashed($key, $value){ - + private function setHashed($key, $value) + { if (in_array($key, $this->hashed??[]) && !is_null($value) && '' != $value) { $value = $this->getHash($value); } @@ -107,7 +105,6 @@ private function setHashed($key, $value){ return $value; } - /** * @param $key * @param $originalValue @@ -118,17 +115,14 @@ private function setBlindIndex($key, $originalValue) if (is_null($originalValue)) { $this->{$this->encrypted[$key]['hasBlindIndex']} = null; - - } else if ('' === $originalValue) { - $this->{$this->encrypted[$key]['hasBlindIndex']} = ''; - + } else if ('' === $originalValue) { // TODO: add config('ENCRYPT_EMPTY_STRING_BI') + $this->{$this->encrypted[$key]['hasBlindIndex']} = ''; } else { $this->{$this->encrypted[$key]['hasBlindIndex']} = $this->getHash($originalValue); } } } - /** * @param $key * @param $value @@ -137,7 +131,6 @@ private function setBlindIndex($key, $originalValue) private function getDecryptIfEncrypted($key, $value) { if (array_key_exists($key, $this->encrypted) && !empty($value)) { - $decryptionType = array_key_exists('type', $this->encrypted[$key]) ? $this->encrypted[$key]['type'] : 'string'; if ($decryptionType == 'date') { @@ -151,7 +144,6 @@ private function getDecryptIfEncrypted($key, $value) return $value; } - /** * @param $value * @param $type @@ -167,7 +159,6 @@ private function castPrimitive($value, $type) return (string)$value; } - /** * @param $value * @param null $format @@ -182,17 +173,15 @@ private function castDate($value, $format = null) } } - /** * @param $originalValue * @return string */ private function getHash($originalValue) { - return hash_hmac($this->hashAlg, (string)$originalValue, env('APP_KEY')); + return hash_hmac($this->hashAlg, (string)$originalValue, config('app.key')); } - /** * @param $key * @param $value @@ -206,7 +195,7 @@ private function checkTypes($key, $value) $type = array_key_exists('type', $this->encrypted[$key]) ? $this->encrypted[$key]['type'] : 'string'; $format = array_key_exists('dateFormat', $this->encrypted[$key]) ? $this->encrypted[$key]['dateFormat'] : null; - switch($type) { + switch ($type) { case 'date': $this->castDate($value, $format); break; @@ -217,7 +206,6 @@ private function checkTypes($key, $value) if(!in_array($type, $this->primitiveTypes)) throw new TypeError("Encryption error, $type not a supported type of 'integer', 'boolean', 'float', 'string', 'date'"); $this->checkType($key, $value, [$type]); } - } return true; @@ -229,25 +217,24 @@ private function checkTypes($key, $value) * @param array $types * @return bool */ - private function checkType($key, $value, array $types){ - + private function checkType($key, $value, array $types) + { $hasMatchedType = false; - foreach($types as $type){ - if (gettype($value) == $type){ + foreach ($types as $type) { + if (gettype($value) == $type) { $hasMatchedType = true; break; } } - if (!$hasMatchedType){ + if (!$hasMatchedType) { throw new TypeError("Encryption error, $key not of correct type or null. Type is: " . gettype($value)); } return true; } - /** * @param $query * @param array $blindIndexQuery @@ -271,7 +258,6 @@ public function scopeWhereBI($query, array $blindIndexQuery) throw new \Exception("Blind index column for " . key($blindIndexQuery) . " not found"); } - /** * @param $query * @param array $blindIndexQuery @@ -281,7 +267,6 @@ public function scopeWhereBI($query, array $blindIndexQuery) public function scopeOrWhereBI($query, array $blindIndexQuery) { if (array_key_exists(key($blindIndexQuery), $this->encrypted) && array_key_exists('hasBlindIndex', $this->encrypted[key($blindIndexQuery)])) { - $columnToSearch = $this->encrypted[key($blindIndexQuery)]['hasBlindIndex']; $unHashedValueToSearch = $blindIndexQuery[key($blindIndexQuery)]; @@ -295,22 +280,19 @@ public function scopeOrWhereBI($query, array $blindIndexQuery) throw new \Exception("Blind index column for " . key($blindIndexQuery) . " not found"); } - // //Eloquent Model method overrides below // - /** * @param $key * @return mixed */ - protected function getAttributeFromArray($key){ + protected function getAttributeFromArray($key) + { return $this->getDecryptIfEncrypted($key, parent::getAttributeFromArray($key)); } - - /** * @return array */ @@ -325,27 +307,24 @@ protected function getArrayableAttributes() return $array; } - - /** * @param $key * @param $value */ public function setAttribute($key, $value) { - if($value !== $this->$key){ + if ($value !== $this->$key) { parent::setAttribute($key, $this->setEncryptedHashedBIAttributes($key, $value)); } } - /** - * List all encripted columns so we can do some magic after + * List all encrypted columns so we can do some magic after * @return array */ - public function encriptedColumns() + public function encryptedColumns() { - return (!empty($this->encrypted))? $this->encrypted : []; + return (!empty($this->encrypted))? $this->encrypted : []; } } diff --git a/tests/Unit/Traits/Models/HasEncryptedAttributesTest.php b/tests/Unit/Traits/Models/HasEncryptedAttributesTest.php index d3b5afa..4cd894e 100644 --- a/tests/Unit/Traits/Models/HasEncryptedAttributesTest.php +++ b/tests/Unit/Traits/Models/HasEncryptedAttributesTest.php @@ -11,9 +11,9 @@ class HasEncryptedAttributesTest extends TestCase { /** - * + * @return void */ - public function setUp() + public function setUp() : void { parent::setUp(); @@ -45,19 +45,19 @@ public function testBulkSeedWithoutNulls_allTypesCorrectViaGetProperty_Test() foreach ($models as $model) { - $this->assertInternalType('string', $model->name); - $this->assertInternalType('string', $model->encrypt_string); - $this->assertInternalType('integer', $model->encrypt_integer); - $this->assertInternalType('boolean', $model->encrypt_boolean); - $this->assertInternalType('boolean', $model->encrypt_another_boolean); - $this->assertInternalType('float', $model->encrypt_float); + $this->assertIsString($model->name); + $this->assertIsString($model->encrypt_string); + $this->assertIsInt($model->encrypt_integer); + $this->assertIsBool($model->encrypt_boolean); + $this->assertIsBool($model->encrypt_another_boolean); + $this->assertIsFloat($model->encrypt_float); $this->assertInstanceOf(Carbon::class, $model->encrypt_date); - $this->assertInternalType('string', $model->encrypt_string_bi); - $this->assertInternalType('string', $model->encrypt_integer_bi); - $this->assertInternalType('string', $model->encrypt_boolean_bi); - $this->assertInternalType('string', $model->encrypt_float_bi); - $this->assertInternalType('string', $model->encrypt_date_bi); - $this->assertInternalType('string', $model->hash_string); + $this->assertIsString($model->encrypt_string_bi); + $this->assertIsString($model->encrypt_integer_bi); + $this->assertIsString($model->encrypt_boolean_bi); + $this->assertIsString($model->encrypt_float_bi); + $this->assertIsString($model->encrypt_date_bi); + $this->assertIsString($model->hash_string); } } @@ -98,18 +98,18 @@ public function testBulkSeedWithEmptyStrings_allTypesCorrectViaGetProperty_Test( foreach ($models as $model) { $this->assertEquals('', $model->encrypt_string); - $this->assertInternalType('string', $model->encrypt_string); + $this->assertIsString($model->encrypt_string); $this->assertTrue(is_null($model->encrypt_integer)); $this->assertTrue(is_null($model->encrypt_boolean)); $this->assertTrue(is_null($model->encrypt_another_boolean)); $this->assertTrue(is_null($model->encrypt_date)); - $this->assertInternalType('string', $model->encrypt_string_bi); + $this->assertIsString($model->encrypt_string_bi); $this->assertTrue(is_null($model->encrypt_integer_bi)); $this->assertTrue(is_null($model->encrypt_boolean_bi)); $this->assertTrue(is_null($model->encrypt_float_bi)); $this->assertTrue(is_null($model->encrypt_date_bi)); $this->assertEquals('', $model->hash_string); - $this->assertInternalType('string', $model->hash_string); + $this->assertIsString($model->hash_string); $this->assertTrue(is_null($model->encrypt_float)); } } @@ -128,19 +128,19 @@ public function testBulkSeedWithoutNulls_allTypesCorrectViaToArray_Test() $array = $model->toArray(); - $this->assertInternalType('string', $array['name']); - $this->assertInternalType('string', $array['encrypt_string']); - $this->assertInternalType('integer', $array['encrypt_integer']); - $this->assertInternalType('boolean', $array['encrypt_boolean']); - $this->assertInternalType('boolean', $array['encrypt_another_boolean']); - $this->assertInternalType('float', $array['encrypt_float']); + $this->assertIsString($array['name']); + $this->assertIsString($array['encrypt_string']); + $this->assertIsInt($array['encrypt_integer']); + $this->assertIsBool($array['encrypt_boolean']); + $this->assertIsBool($array['encrypt_another_boolean']); + $this->assertIsFloat($array['encrypt_float']); $this->assertInstanceOf(Carbon::class, $array['encrypt_date']); - $this->assertInternalType('string', $array['encrypt_string_bi']); - $this->assertInternalType('string', $array['encrypt_integer_bi']); - $this->assertInternalType('string', $array['encrypt_boolean_bi']); - $this->assertInternalType('string', $array['encrypt_float_bi']); - $this->assertInternalType('string', $array['encrypt_date_bi']); - $this->assertInternalType('string', $array['hash_string']); + $this->assertIsString($array['encrypt_string_bi']); + $this->assertIsString($array['encrypt_integer_bi']); + $this->assertIsString($array['encrypt_boolean_bi']); + $this->assertIsString($array['encrypt_float_bi']); + $this->assertIsString($array['encrypt_date_bi']); + $this->assertIsString($array['hash_string']); } } @@ -187,18 +187,18 @@ public function testBulkSeedWithEmptyStrings_allTypesCorrectViaToArray_Test() $array = $model->toArray(); $this->assertEquals('', $array['encrypt_string']); - $this->assertInternalType('string', $array['encrypt_string']); + $this->assertIsString($array['encrypt_string']); $this->assertTrue(is_null($array['encrypt_integer'])); $this->assertTrue(is_null($array['encrypt_boolean'])); $this->assertTrue(is_null($array['encrypt_another_boolean'])); $this->assertTrue(is_null($array['encrypt_date'])); - $this->assertInternalType('string', $array['encrypt_string_bi']); + $this->assertIsString($array['encrypt_string_bi']); $this->assertTrue(is_null($array['encrypt_integer_bi'])); $this->assertTrue(is_null($array['encrypt_boolean_bi'])); $this->assertTrue(is_null($array['encrypt_float_bi'])); $this->assertTrue(is_null($array['encrypt_date_bi'])); $this->assertEquals('', $array['hash_string']); - $this->assertInternalType('string', $array['hash_string']); + $this->assertIsString($array['hash_string']); $this->assertTrue(is_null($array['encrypt_float'])); } } @@ -221,7 +221,7 @@ public function testBulkSeed_localScopeForEachValueViaGetProperty_Test() $this->assertEquals(($models->get(0))->encrypt_date, '2043-12-23 23:59:59'); $this->assertEquals(($models->get(0))->hash_string, hash_hmac('sha256', 'A unqiue string that has not been generated', - env('APP_KEY'))); + config('app.key'))); } @@ -243,7 +243,7 @@ public function testBulkSeed_localScopeOrForEachValueViaGetProperty1_Test() $this->assertEquals(($models->get(0))->encrypt_date, '2043-12-23 23:59:59'); $this->assertEquals(($models->get(0))->hash_string, hash_hmac('sha256', 'A unqiue string that has not been generated', - env('APP_KEY'))); + config('app.key'))); } @@ -266,7 +266,7 @@ public function testBulkSeed_localScopeForEachValueViaToArray_Test() $this->assertEquals($array['encrypt_float'], 10.0001); $this->assertEquals($array['encrypt_date'], '2043-12-23 23:59:59'); $this->assertEquals($array['hash_string'], hash_hmac('sha256', 'A unqiue string that has not been generated', - env('APP_KEY'))); + config('app.key'))); } @@ -289,7 +289,7 @@ public function testBulkSeed_localScopeOrForEachValueViaToArray_Test() $this->assertEquals($array['encrypt_float'], 10.0001); $this->assertEquals($array['encrypt_date'], '2043-12-23 23:59:59'); $this->assertEquals($array['hash_string'], hash_hmac('sha256', 'A unqiue string that has not been generated', - env('APP_KEY'))); + config('app.key'))); } @@ -329,26 +329,26 @@ public function testSetProperty_existingValuesChanged_Test() $this->assertEquals($model->encrypt_date, '2012-12-13 13:39:29'); $this->assertEquals($model->hash_string, hash_hmac('sha256', 'Another unqiue string that has not been generated', - env('APP_KEY'))); + config('app.key'))); - $this->assertInternalType('string', $model->encrypt_string); - $this->assertInternalType('integer', $model->encrypt_integer); - $this->assertInternalType('boolean', $model->encrypt_boolean); - $this->assertInternalType('boolean', $model->encrypt_another_boolean); - $this->assertInternalType('float', $model->encrypt_float); + $this->assertIsString($model->encrypt_string); + $this->assertIsInt($model->encrypt_integer); + $this->assertIsBool($model->encrypt_boolean); + $this->assertIsBool($model->encrypt_another_boolean); + $this->assertIsFloat($model->encrypt_float); $this->assertInstanceOf(Carbon::class, $model->encrypt_date); - $this->assertInternalType('string', $model->hash_string); + $this->assertIsString($model->hash_string); $this->assertEquals($model->encrypt_string_bi, hash_hmac('sha256', (string)'newValue', - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_integer_bi, hash_hmac('sha256', (string)0, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_boolean_bi, hash_hmac('sha256', (string)false, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_float_bi, hash_hmac('sha256', (string)0.0, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_date_bi, hash_hmac('sha256', (string)'2012-12-13 13:39:29', - env('APP_KEY'))); + config('app.key'))); } /** @@ -429,23 +429,23 @@ public function testSetProperty_existingValuesChangedToEmptyString_Test() $this->assertEquals($model->encrypt_date, null); $this->assertEquals($model->hash_string, ''); - $this->assertInternalType('string', $model->encrypt_string); - $this->assertInternalType('integer', $model->encrypt_integer); - $this->assertInternalType('boolean', $model->encrypt_boolean); - $this->assertInternalType('boolean', $model->encrypt_another_boolean); - $this->assertInternalType('float', $model->encrypt_float); + $this->assertIsString($model->encrypt_string); + $this->assertIsInt($model->encrypt_integer); + $this->assertIsBool($model->encrypt_boolean); + $this->assertIsBool($model->encrypt_another_boolean); + $this->assertIsFloat($model->encrypt_float); $this->assertTrue(is_null($model->encrypt_date)); - $this->assertInternalType('null', $model->encrypt_date); - $this->assertInternalType('string', $model->hash_string); + $this->assertNull($model->encrypt_date); + $this->assertIsString($model->hash_string); $this->assertEquals($model->encrypt_string_bi, ''); - $this->assertInternalType('string', $model->encrypt_string_bi); + $this->assertIsString($model->encrypt_string_bi); $this->assertEquals($model->encrypt_integer_bi, hash_hmac('sha256', (string)0, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_boolean_bi, hash_hmac('sha256', (string)false, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_float_bi, hash_hmac('sha256', (string)0.0, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_date_bi, null); } @@ -485,26 +485,26 @@ public function testUpdate_existingValuesChanged_Test() $this->assertEquals($model->encrypt_date, '2012-12-13 13:39:29'); $this->assertEquals($model->hash_string, hash_hmac('sha256', 'Another unqiue string that has not been generated', - env('APP_KEY'))); + config('app.key'))); - $this->assertInternalType('string', $model->encrypt_string); - $this->assertInternalType('integer', $model->encrypt_integer); - $this->assertInternalType('boolean', $model->encrypt_boolean); - $this->assertInternalType('boolean', $model->encrypt_another_boolean); - $this->assertInternalType('float', $model->encrypt_float); + $this->assertIsString($model->encrypt_string); + $this->assertIsInt($model->encrypt_integer); + $this->assertIsBool($model->encrypt_boolean); + $this->assertIsBool($model->encrypt_another_boolean); + $this->assertIsFloat($model->encrypt_float); $this->assertInstanceOf(Carbon::class, $model->encrypt_date); - $this->assertInternalType('string', $model->hash_string); + $this->assertIsString($model->hash_string); $this->assertEquals($model->encrypt_string_bi, hash_hmac('sha256', (string)'newValue', - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_integer_bi, hash_hmac('sha256', (string)0, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_boolean_bi, hash_hmac('sha256', (string)false, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_float_bi, hash_hmac('sha256', (string)0.1, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_date_bi, hash_hmac('sha256', (string)'2012-12-13 13:39:29', - env('APP_KEY'))); + config('app.key'))); } /** @@ -585,23 +585,23 @@ public function testUpdate_existingValuesChangedToEmptyString_Test() $this->assertEquals($model->encrypt_date, null); $this->assertEquals($model->hash_string, ''); - $this->assertInternalType('string', $model->encrypt_string); - $this->assertInternalType('integer', $model->encrypt_integer); - $this->assertInternalType('boolean', $model->encrypt_boolean); - $this->assertInternalType('boolean', $model->encrypt_another_boolean); - $this->assertInternalType('float', $model->encrypt_float); + $this->assertIsString($model->encrypt_string); + $this->assertIsInt($model->encrypt_integer); + $this->assertIsBool($model->encrypt_boolean); + $this->assertIsBool($model->encrypt_another_boolean); + $this->assertIsFloat($model->encrypt_float); $this->assertTrue(is_null($model->encrypt_date)); - $this->assertInternalType('null', $model->encrypt_date); - $this->assertInternalType('string', $model->hash_string); + $this->assertNull($model->encrypt_date); + $this->assertIsString($model->hash_string); $this->assertEquals($model->encrypt_string_bi, ''); - $this->assertInternalType('string', $model->encrypt_string_bi); + $this->assertIsString($model->encrypt_string_bi); $this->assertEquals($model->encrypt_integer_bi, hash_hmac('sha256', (string)0, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_boolean_bi, hash_hmac('sha256', (string)false, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_float_bi, hash_hmac('sha256', (string)0.0, - env('APP_KEY'))); + config('app.key'))); $this->assertEquals($model->encrypt_date_bi, null); } @@ -939,7 +939,7 @@ public function testBulkSeed_localScopeBooleanSet_Test() $models = TestModel::whereBI(['encrypt_boolean' => true])->Get(); $total = DB::table('test_tables')->where('encrypt_boolean_bi', - hash_hmac('sha256', (string)true, env('APP_KEY')))->count(); + hash_hmac('sha256', (string)true, config('app.key')))->count(); $this->assertEquals($total, count($models)); @@ -953,7 +953,7 @@ public function testBulkSeed_localScopeOrBooleanSet_Test() $models = TestModel::where(1,2)->orWhereBI(['encrypt_boolean' => true])->Get(); $total = DB::table('test_tables')->where('encrypt_boolean_bi', - hash_hmac('sha256', (string)true, env('APP_KEY')))->count(); + hash_hmac('sha256', (string)true, config('app.key')))->count(); $this->assertEquals($total, count($models)); @@ -989,7 +989,6 @@ public function testBulkSeed_localScopeFloatSet_Test() $models = TestModel::whereBI(['encrypt_float' => 10.0001])->Get(); $this->assertEquals(1, count($models)); - } /** @@ -1026,7 +1025,7 @@ public function testConstruct_valuesAndTypesCorrectBeforeAndAfterSave_Test() $this->assertEquals($array['encrypt_float'], 9999.999); $this->assertEquals($array['encrypt_date'], '2043-12-23 23:59:59'); $this->assertEquals($array['hash_string'], hash_hmac('sha256', 'A unqiue string that has not been generated again', - env('APP_KEY'))); + config('app.key'))); $model->save(); @@ -1040,7 +1039,7 @@ public function testConstruct_valuesAndTypesCorrectBeforeAndAfterSave_Test() $this->assertEquals($array['encrypt_float'], 9999.999); $this->assertEquals($array['encrypt_date'], '2043-12-23 23:59:59'); $this->assertEquals($array['hash_string'], hash_hmac('sha256', 'A unqiue string that has not been generated again', - env('APP_KEY'))); + config('app.key'))); $models = TestModel::whereBI(['encrypt_float' => 9999.999])->Get(); $this->assertEquals(1, count($models));