attr-encrypted / attr_encrypted

Generates attr_accessors that encrypt and decrypt attributes
MIT License
2.01k stars 427 forks source link

Encrypted password doesn't save in MongoDB #51

Open macosgrove opened 11 years ago

macosgrove commented 11 years ago

Perhaps I'm setting up my class incorrectly, but I can't get my encrypted data to save to MongoDB. I'm using attr_encrypted (1.2.1) and mongoid (3.0.14).

My class looks like

class Participant
  include Mongoid::Document
  field :first_name, type: String
  field :last_name, type: String
  field :email, type: String
  attr_encrypted :password, :key => 'mykey', :encode => true
  field :password, type: String
  field :encrypted_password, type: String

  attr_accessible :first_name, :last_name, :email, :password

  auto_increment :user_id

  validates_presence_of :encrypted_password
  validates_length_of :password, minimum: 5
  validates :last_name, :presence => true, :if => "first_name.nil?"
  validates_uniqueness_of :email
  validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :allow_nil => true
end

My failing test is

 describe 'saving' do
    let!(:participant) { FactoryGirl.build(:participant)}
    it 'should save the encrypted password in the database' do
      participant.password = 'averyuniquepassword'
      participant.save
      puts participant.password
      puts participant.encrypted_password
      retrieved_participant = Participant.where(encrypted_password: participant.encrypted_password).first
      retrieved_participant.should_not be_nil
    end
end

and I can retrieve the values of encrypted_password and password from the instance in memory, but I can see they're not saved in MongoDB.

Thanks for your help!

macosgrove commented 11 years ago

This is probably the same as #49, however the fix listed there does not work for me for (at least) two reasons: 1) Mongoid has no after_find - I replaced with after_initialize 2) Then I started getting Encoding::UndefinedConversionError: "\x89" from ASCII-8BIT to UTF-8. Seems related to issue #35 but I haven't yet figured out how to fix this for Encryptor (since I can't use attr_encrypted due to #49)

schir1964 commented 11 years ago

Try this and see if it works (it contains the UTF-8 fix from attr_encrypted):

class DatabaseModelName < ActiveRecord::Base
  attr_accessible :data

  before_save :encrypt_data

  after_save :decrypt_data
  after_initialize :decrypt_data

  protected

  def encrypt_data
    self.data = [Encryptor.encrypt(:value => self.data, :key => CONFIG[:encryption_key])].pack('m') unless self.data.blank?
  end

  def decrypt_data
    self.data = Encryptor.decrypt(:value => self.data.unpack('m').first, :key => CONFIG[:encryption_key) unless self.data.blank?
  end
end
billymonk commented 11 years ago

Hi @macosgrove, sorry it has taken awhile to get back to you.

Move the call to attr_encrypted to after the calls to field :password and field :encrypted_password and your issue with persistence should be resolved. In the meantime I'll look into why order matters.

In regards to your Encoding::UndefinedConversion error: 1) When you were getting that error did you drop the ':encode => true' option? 2) Do you have an example of a string it chokes on?

billymonk commented 11 years ago

Hi @macosgrove,

I think I understand your issue above where you are getting the Encoding::UndefinedConversion error. When you use the attr_encrypted macro to define what columns you want you are explicitly calling :encode => true. However, if you are using the fix found in #49 and the only change your making is converting it to an after_initialize, you are losing the :encode => true part.

I'm working on a Mongoid adapter that will solve that problem as it will add attr_encrypted_options[:encode] = true to the base class but in the meantime if you do use the fix in #49 ensure that you are passing in the option :encode => true.

As for the ordering of macros, I looked into Mongoid for the first time today and I can see no easy way to allow attr_encrypted :field to come before field :field. At least not as easily as we can ignore order when using ActiveRecord. In the meantime I'm going to add documentation to the README for Mongoid and I'll make a point of mentioning the importance of order.

If all of that is satisfactory and you no longer have any issues please close this issue.

Thanks

sbfaulkner commented 11 years ago

I think changing the documentation is the right way to go... since the implementation of attr_encrypted depends on the columns/attributes/fields (depending on adapter) existing already in order to "do the right thing"