I've got a Listener that decrypts certain fields at postLoad event. It's working great except for the issue that the related entities to the main one don't work.
I tried to edit my entities so the associations have the fetch="EAGER" but that only solves half of the issue, as if the app has to load two entities with the same relation, it fails again. Example:
Entity1 has id_company of 2. in this case, fetch EAGER works great.
Entity1 has id_company of 2 Entity2 has id_company of 2 in this case, the decryption fails.
Here's my relevant code of the Listener:
class EntityEncryptionListener implements EventSubscriber
{
private $secret;
private $secret_original;
private $request;
public function __construct($secret, RequestStack $request)
{
$this->secret = $secret;
$this->secret_original = $secret;
$this->request = $request;
}
public function getSubscribedEvents()
{
return [Events::prePersist, Events::preUpdate, Events::postLoad];
}
public function prePersist(LifecycleEventArgs $args)
{
$this->getSecret();
$this->encryptEntity($args);
}
public function preUpdate(LifecycleEventArgs $args)
{
$this->getSecret();
$this->encryptEntity($args);
}
public function postLoad(LifecycleEventArgs $args)
{
$this->getSecret();
$this->decryptEntity($args);
}
private function decryptEntity(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// Obtén el lector de anotaciones de Doctrine
$annotationReader = new AnnotationReader();
// Recorre todas las propiedades de la entidad
$reflectionClass = new \ReflectionClass(get_class($entity));
$properties = $reflectionClass->getProperties();
$unitOfWork = $args->getEntityManager()->getUnitOfWork();
$originalData = $unitOfWork->getOriginalEntityData($entity);
foreach ($properties as $property) {
$encriptado = false;
$annotationEnc = $annotationReader->getPropertyAnnotation($property, 'App\Annotation\Encrypted');
$annotationEncOrig = $annotationReader->getPropertyAnnotation($property, 'App\Annotation\EncryptedOriginal');
if ($annotationEnc !== null) {
$encriptado = true;
$secret = $this->secret;
}
if ($annotationEncOrig !== null){
$encriptado = true;
$secret = $this->secret_original;
}
$property->setAccessible(true);
if ($encriptado && $property->getValue($entity)){
$encryptedValue = $property->getValue($entity);
try{
$key = Key::loadFromAsciiSafeString($secret);
if ($encryptedValue && $key){
$decryptedValue = Crypto::decrypt($encryptedValue, $key);
}
$property->setValue($entity, $decryptedValue);
$originalData[$property->getName()] = $decryptedValue;
}catch(Exception $e){
}
}
}
$unitOfWork->setOriginalEntityData($entity, $originalData);
}