I'm working a project based on Symfony 4. I'm trying to make the @UniqueEntity works on an @Encrypted field, and I can't figure out how.
- Without the
@Encryptedannotation, the@UniqueEntityannotation prevents the duplication - With the
@Encryptedannotation, the@UniqueEntityannotation allows the duplication
/**
* @ORM\Entity(repositoryClass="App\Repository\DemoRepository")
* @ORM\HasLifecycleCallbacks()
* @UniqueEntity(
* fields={"example"},
* ignoreNull=true,
* )
*
*/
class Demo implements LoggableEntityInterface
{
/**
* @ORM\Column(type="text", nullable=true)
* @Encrypted
*/
private $example;
First, I have no clue how that
Encryptedpackage works, but if the content of the fields are encrypted it could be hard or impossible for the framework to check if the new value matches the the old one.It would depend on how the field was encrypted, and how the check is made. The
UniqueEntityis a validation check, so it's performed before the value is saved. It should first encrypt the value, and compare against the encrypted value. The Symfony annotation does not support that workflow.You could store a hash for the field, the set the
Uniquecheck on the hash, not on the field. It would add quite a bit of storage to your table, though.A naive implementation:
Now the check will be made against the hash, which won't be encrypted but should be relatively safe to store. Note that I'm also using the classname as a "salt", so the hash is slightly more secure.
Alternatively, you could use the
repositoryMethodkey of the annotation, and create a custom repository method that takes a raw value, encrypts it, and performs the search by the encrypted value. That would imply that you understand how to use whatever facility your encryption package is using, so you could use it in your new repository method.