Skip to content

Commit

Permalink
poc personal data
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBadura committed Mar 20, 2024
1 parent 3b6277f commit 8f46d96
Show file tree
Hide file tree
Showing 60 changed files with 2,254 additions and 14 deletions.
51 changes: 49 additions & 2 deletions baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.22.2@d768d914152dbbf3486c36398802f74e80cfde48">
<files psalm-version="5.23.1@8471a896ccea3526b26d082f4461eeea467f10a4">
<file src="src/Aggregate/AggregateRootBehaviour.php">
<UnsafeInstantiation>
<code><![CDATA[new static()]]></code>
Expand All @@ -15,6 +15,28 @@
<code><![CDATA[class DoctrineHelper]]></code>
</ClassNotFinal>
</file>
<file src="src/Cryptography/Cipher/OpensslCipherKeyFactory.php">
<ArgumentTypeCoercion>
<code><![CDATA[openssl_random_pseudo_bytes($ivLength)]]></code>
<code><![CDATA[openssl_random_pseudo_bytes($this->length)]]></code>
</ArgumentTypeCoercion>
</file>
<file src="src/Cryptography/DefaultEventPayloadCryptographer.php">
<MixedArgument>
<code><![CDATA[$data[$propertyMetadata->fieldName]]]></code>
</MixedArgument>
<MixedAssignment>
<code><![CDATA[$data[$propertyMetadata->fieldName]]]></code>
<code><![CDATA[$data[$propertyMetadata->fieldName]]]></code>
<code><![CDATA[$data[$propertyMetadata->fieldName]]]></code>
</MixedAssignment>
</file>
<file src="src/Cryptography/Store/DoctrineCipherKeyStore.php">
<ArgumentTypeCoercion>
<code><![CDATA[base64_decode($result['crypto_iv'])]]></code>
<code><![CDATA[base64_decode($result['crypto_key'])]]></code>
</ArgumentTypeCoercion>
</file>
<file src="src/EventBus/AttributeListenerProvider.php">
<MixedMethodCall>
<code><![CDATA[$method->getName()]]></code>
Expand Down Expand Up @@ -88,12 +110,21 @@
<code><![CDATA[Closure(Message):void]]></code>
</MixedReturnTypeCoercion>
</file>
<file src="tests/Benchmark/BasicImplementation/Aggregate/Profile.php">
<file src="tests/Benchmark/BasicImplementation/Profile.php">
<PropertyNotSetInConstructor>
<code><![CDATA[$email]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$name]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Benchmark/PersonalDataBench.php">
<MissingConstructor>
<code><![CDATA[$bus]]></code>
<code><![CDATA[$id]]></code>
<code><![CDATA[$repository]]></code>
<code><![CDATA[$store]]></code>
</MissingConstructor>
</file>
<file src="tests/Benchmark/SimpleSetupBench.php">
<MissingConstructor>
<code><![CDATA[$bus]]></code>
Expand Down Expand Up @@ -145,6 +176,17 @@
<code><![CDATA[$name]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Integration/PersonalData/PersonalDataTest.php">
<MixedArgument>
<code><![CDATA[$row['payload']]]></code>
</MixedArgument>
</file>
<file src="tests/Integration/PersonalData/Profile.php">
<PropertyNotSetInConstructor>
<code><![CDATA[$id]]></code>
<code><![CDATA[$name]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Integration/Pipeline/Aggregate/Profile.php">
<PropertyNotSetInConstructor>
<code><![CDATA[$id]]></code>
Expand All @@ -164,6 +206,11 @@
<code><![CDATA[$name]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Unit/Cryptography/Cipher/OpensslCipherTest.php">
<MixedAssignment>
<code><![CDATA[$return]]></code>
</MixedAssignment>
</file>
<file src="tests/Unit/Fixture/MessageNormalizer.php">
<MixedArgumentTypeCoercion>
<code><![CDATA[$value]]></code>
Expand Down
8 changes: 8 additions & 0 deletions deptrac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ deptrac:
collectors:
- type: directory
value: src/Console/.*
- name: Cryptography
collectors:
- type: directory
value: src/Cryptography/.*
- name: Debug
collectors:
- type: directory
Expand Down Expand Up @@ -108,6 +112,9 @@ deptrac:
- Serializer
- Store
- Subscription
Cryptography:
- MetadataEvent
- Schema
Debug:
- Attribute
- Message
Expand Down Expand Up @@ -159,6 +166,7 @@ deptrac:
Schema:
Serializer:
- Aggregate
- Cryptography
- MetadataEvent
Snapshot:
- Aggregate
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ nav:
- Aggregate ID: aggregate_id.md
- Normalizer: normalizer.md
- Snapshots: snapshots.md
- Personal Data: personal_data.md
- Upcasting: upcasting.md
- Outbox: outbox.md
- Pipeline: pipeline.md
Expand Down
6 changes: 6 additions & 0 deletions docs/pages/personal_data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Personal Data




## Learn more
25 changes: 25 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ parameters:
count: 1
path: src/Console/DoctrineHelper.php

-
message: "#^Parameter \\#1 \\$key of class Patchlevel\\\\EventSourcing\\\\Cryptography\\\\Cipher\\\\CipherKey constructor expects non\\-empty\\-string, string given\\.$#"
count: 1
path: src/Cryptography/Cipher/OpensslCipherKeyFactory.php

-
message: "#^Parameter \\#3 \\$iv of class Patchlevel\\\\EventSourcing\\\\Cryptography\\\\Cipher\\\\CipherKey constructor expects non\\-empty\\-string, string given\\.$#"
count: 1
path: src/Cryptography/Cipher/OpensslCipherKeyFactory.php

-
message: "#^Parameter \\#2 \\$data of method Patchlevel\\\\EventSourcing\\\\Cryptography\\\\Cipher\\\\Cipher\\:\\:decrypt\\(\\) expects string, mixed given\\.$#"
count: 1
path: src/Cryptography/DefaultEventPayloadCryptographer.php

-
message: "#^Parameter \\#1 \\$key of class Patchlevel\\\\EventSourcing\\\\Cryptography\\\\Cipher\\\\CipherKey constructor expects non\\-empty\\-string, string given\\.$#"
count: 1
path: src/Cryptography/Store/DoctrineCipherKeyStore.php

-
message: "#^Parameter \\#3 \\$iv of class Patchlevel\\\\EventSourcing\\\\Cryptography\\\\Cipher\\\\CipherKey constructor expects non\\-empty\\-string, string given\\.$#"
count: 1
path: src/Cryptography/Store/DoctrineCipherKeyStore.php

-
message: "#^Parameter \\#2 \\$data of method Patchlevel\\\\Hydrator\\\\Hydrator\\:\\:hydrate\\(\\) expects array\\<string, mixed\\>, mixed given\\.$#"
count: 1
Expand Down
12 changes: 12 additions & 0 deletions src/Attribute/DataSubjectId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Attribute;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
final class DataSubjectId
{
}
16 changes: 16 additions & 0 deletions src/Attribute/PersonalData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Attribute;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
final class PersonalData
{
public function __construct(
public readonly mixed $fallback = null,
) {
}
}
14 changes: 14 additions & 0 deletions src/Cryptography/Cipher/Cipher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

interface Cipher
{
/** @throws EncryptionFailed */
public function encrypt(CipherKey $key, mixed $data): string;

/** @throws DecryptionFailed */
public function decrypt(CipherKey $key, string $data): mixed;
}
20 changes: 20 additions & 0 deletions src/Cryptography/Cipher/CipherKey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

final class CipherKey
{
/**
* @param non-empty-string $key
* @param non-empty-string $method
* @param non-empty-string $iv
*/
public function __construct(
public readonly string $key,
public readonly string $method,
public readonly string $iv,
) {
}
}
11 changes: 11 additions & 0 deletions src/Cryptography/Cipher/CipherKeyFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

interface CipherKeyFactory
{
/** @throws CreateCipherKeyFailed */
public function __invoke(): CipherKey;
}
15 changes: 15 additions & 0 deletions src/Cryptography/Cipher/CreateCipherKeyFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

use RuntimeException;

final class CreateCipherKeyFailed extends RuntimeException
{
public function __construct()
{
parent::__construct('Create cipher key failed.');
}
}
15 changes: 15 additions & 0 deletions src/Cryptography/Cipher/DecryptionFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

use RuntimeException;

final class DecryptionFailed extends RuntimeException
{
public function __construct()
{
parent::__construct('Decryption failed.');
}
}
15 changes: 15 additions & 0 deletions src/Cryptography/Cipher/EncryptionFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

use RuntimeException;

final class EncryptionFailed extends RuntimeException
{
public function __construct()
{
parent::__construct('Encryption failed.');
}
}
67 changes: 67 additions & 0 deletions src/Cryptography/Cipher/OpensslCipher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

use JsonException;

use function base64_decode;
use function base64_encode;
use function json_decode;
use function json_encode;
use function openssl_decrypt;
use function openssl_encrypt;

use const JSON_THROW_ON_ERROR;

final class OpensslCipher implements Cipher
{
public function encrypt(CipherKey $key, mixed $data): string
{
$encryptedData = @openssl_encrypt(
$this->dataEncode($data),
$key->method,
$key->key,
0,
$key->iv,
);

if ($encryptedData === false) {
throw new EncryptionFailed();
}

return base64_encode($encryptedData);
}

public function decrypt(CipherKey $key, string $data): mixed
{
$data = @openssl_decrypt(
base64_decode($data),
$key->method,
$key->key,
0,
$key->iv,
);

if ($data === false) {
throw new DecryptionFailed();
}

try {
return $this->dataDecode($data);
} catch (JsonException) {
throw new DecryptionFailed();
}
}

private function dataEncode(mixed $data): string
{
return json_encode($data, JSON_THROW_ON_ERROR);
}

private function dataDecode(string $data): mixed
{
return json_decode($data, true, 512, JSON_THROW_ON_ERROR);
}
}
40 changes: 40 additions & 0 deletions src/Cryptography/Cipher/OpensslCipherKeyFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Cryptography\Cipher;

use function openssl_cipher_iv_length;
use function openssl_random_pseudo_bytes;

final class OpensslCipherKeyFactory implements CipherKeyFactory
{
public const DEFAULT_LENGTH = 32;

public const DEFAULT_METHOD = 'aes128';

/**
* @param positive-int $length
* @param non-empty-string $method
*/
public function __construct(
private readonly int $length = self::DEFAULT_LENGTH,
private readonly string $method = self::DEFAULT_METHOD,
) {
}

public function __invoke(): CipherKey
{
$ivLength = @openssl_cipher_iv_length($this->method);

if ($ivLength === false) {
throw new CreateCipherKeyFailed();
}

return new CipherKey(
openssl_random_pseudo_bytes($this->length),
$this->method,
openssl_random_pseudo_bytes($ivLength),
);
}
}
Loading

0 comments on commit 8f46d96

Please sign in to comment.