Как вы используете фикстуры с attr_encrypted

Я хочу протестировать модель, использующую attr_encrypted для шифрования секрета в базе данных.

class Thing
  attr_encrypted :secret, encode: true
end

Но когда я определяю секрет в приспособлении, закодированный символ новой строки экранируется.

one:
  encrypted_secret: '<%= Thing.encrypt_secret(SecureRandom.uuid) %>'

То есть:

'axZFZEknxUSYdUlPhwLBbj8CwSeCW5at2INA98EcCcY7MVFdmXvk7Sb4DZhC\nm6qD\n'

Хранится в базе данных как:

'axZFZEknxUSYdUlPhwLBbj8CwSeCW5at2INA98EcCcY7MVFdmXvk7Sb4DZhC
 m6qD'

Проблема в том, что это не удается:

thing = things(:one)
assert_equal thing, Thing.find_by_secret(thing.secret)

Thing.find_by_secret(thing.secret) возвращает nil, поскольку результирующий SQL-запрос пытается сопоставить две версии зашифрованного секрета и не может найти совпадение.

Я пытался:

one:
  encrypted_secret: 'axZFZEknxUSYdUlPhwLBbj8CwSeCW5at2INA98EcCcY7MVFdmXvk7Sb4DZhC\nm6qD\n'

но получить тот же результат.

Как я могу настроить свои приборы для работы с attr_encrypted?


person ReggieB    schedule 10.07.2014    source источник


Ответы (2)


Решение, которое работает, состоит в том, чтобы заменить все '\n' на '\\n' и использовать двойные кавычки. Это работает:

one:
  encryped_secret: "<%= Thing.encrypt_secret(SecureRandom.uuid).gsub(/\n/, '\\\\n') %>"

Есть ли более аккуратный способ сделать это?

person ReggieB    schedule 10.07.2014

Я столкнулся с той же ситуацией в среде Rails4 + attr_encrypted + приспособление + Minitest, и вот мой обходной путь.

В общем, у меня были следующие шаги:

  1. записать простой (= незашифрованный) текстовый файл с определенным расширением файла (в моем случае это *.yml.noenc).
  2. напишите rake-task для преобразования простого фикста (.yml.noenc) в зашифрованный фикстур (.yml).

Позвольте мне объяснить детали ниже.

Например, модель «Сообщение» имеет два атрибута «имя» и «тело», которые необходимо зашифровать следующим образом:

class Message < ActiveRecord::Base
  attr_encrypted :name, key: ...
  attr_encrypted :body, key: ...
  ...
end
  1. напишите test/fixtures/messages.yml.noenc следующим образом, который имеет простое имя и основной текст:
msg1:
  name: Hello
  body: Hello, I am here...
msg2:
  name: How are you
  body: Good morning, ...
  1. напишите следующую rake-задачу (например, lib/tasks/encrypt_fixture.rake), чтобы преобразовать messages.yml.noenc в messages.yml:
require 'active_record/fixtures'

src_yml   = 'test/fixtures/messages.yml.noenc'
dest_yml  = 'test/fixtures/messages.yml'

task 'test'   => dest_yml

namespace :[MY_APP] do
  desc "generate encrypted fixture"
  file dest_yml => src_yml do |t|
    require Rails.root + 'config/environment'

    encrypted_hash  = {}
    for k, v in YAML.load(ERB.new(File.read(Rails.root + src_yml)).result) do
      msg = Message.new(v.merge([ANY ADDITIONAL ATTRS]))
      encrypted_hash[k] = {
        'encrypted_name'    => msg.encrypted_name,
        'encrypted_name_iv' => msg.encrypted_name_iv,
        'encrypted_body'    => msg.encrypted_body,
        'encrypted_body_iv' => msg.encrypted_body_iv,
        [ANY ADDITIONAL KEY_N_VALUE]
      }
    end

    File.open(Rails.root + t.name, 'w') do |f|
      f.write(<<EOH)
    #----------------------------------------------------------------------
    # DO NOT MODIFY THIS FILE!!
    #
    # This file is generated from #{src_yml} by:
    #
    #   (edit #{src_yml})
    #   $ rake [MY_APP]:generate_fixture, or
    #   $ rake
    #----------------------------------------------------------------------
EOH
      f.write(encrypted_hash.to_yaml)
    end
  end
end

Пожалуйста, замените [MY_APP], [ЛЮБЫЕ ДОПОЛНИТЕЛЬНЫЕ ATTRS] и [ЛЮБЫЕ ДОПОЛНИТЕЛЬНЫЕ KEY_N_VALUE] фактическими значениями.

Затем «рейк» или «рейк-тест» проверяет файловую зависимость между messages.yml.noenc и messages.yml и генерирует messages.yml при необходимости перед «рейк-тестом».

person Fumisky Wells    schedule 15.05.2016