Prevent "attr_encrypted" & "blind_index" from creating encrypted fields when original value is an empty strings

Viewed 201

I'm using attr_encrypted & blind_index Gems to save & search sensitive data securely.

Gemfile:

gem "attr_encrypted", "~> 3.0.0"  
gem "blind_index"

Model

attr_encrypted :email, :key => [ENV["DB_ENCRYPTED_KEY"]].pack("H*")
blind_index :email, :key => [ENV["BLIND_INDEX_KEY"]].pack("H*")

validates :email, :uniqueness => true, :allow_blank => true

Migration

add_column :users, :encrypted_email, :string
add_column :users, :encrypted_email_iv, :string
add_column :users, :encrypted_email_bidx, :string

add_index :users, :encrypted_email_bidx, :unique => true

Everything works fine except that when I try to add a user where email is blank (empty string), it still creates encrypted_email_iv and encrypted_email_bidx fields, and accordingly it raise a postgres 'PG::UniqueViolation' exception when I try to create another user with also a blank email. Here is the detailed error:

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_customers_on_encrypted_email_bidx" DETAIL: Key (encrypted_email_bidx)=(DuFZwCHck+O9kivr2J64r5Q9MJrGoP5P1U0ikIgyj7c= ) already exists.

When I try it from the rails console, I get the same error, however it works fine if the email is nil, not empty string.

So User.create(name: 'aaa', telephone: '1234-5678') won't create the encrypted fields While User.create(name: 'aaa', telephone: '1234-5678', email: '') will do !!

1 Answers

Both gems only produce NULL for nil values, you can patch them in controller:

params[:user][:email] = nil if params[:user][:email].empty?
@user = User.new(user_params)
...

or make your model convert empty strings to nils by overriding setter:

attr_encrypted :email, ...
...
old_setter = instance_method(:email=)
define_method(:email=) do |val|
  val = nil if val.blank?
  old_setter.bind(self).call(val)
end
Related