Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gems/attr_encrypted/test/active_record_test.rb')
-rw-r--r--vendor/gems/attr_encrypted/test/active_record_test.rb368
1 files changed, 368 insertions, 0 deletions
diff --git a/vendor/gems/attr_encrypted/test/active_record_test.rb b/vendor/gems/attr_encrypted/test/active_record_test.rb
new file mode 100644
index 00000000000..4c903bc3cd8
--- /dev/null
+++ b/vendor/gems/attr_encrypted/test/active_record_test.rb
@@ -0,0 +1,368 @@
+# frozen_string_literal: true
+
+require_relative 'test_helper'
+
+ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
+
+def create_tables
+ ActiveRecord::Schema.define(version: 1) do
+ self.verbose = false
+ create_table :people do |t|
+ t.string :encrypted_email
+ t.string :password
+ t.string :encrypted_credentials
+ t.binary :salt
+ t.binary :key_iv
+ t.string :encrypted_email_salt
+ t.string :encrypted_credentials_salt
+ t.string :encrypted_email_iv
+ t.string :encrypted_credentials_iv
+ end
+ create_table :accounts do |t|
+ t.string :encrypted_password
+ t.string :encrypted_password_iv
+ t.string :encrypted_password_salt
+ t.string :key
+ end
+ create_table :users do |t|
+ t.string :login
+ t.string :encrypted_password
+ t.string :encrypted_password_iv
+ t.boolean :is_admin
+ end
+ create_table :prime_ministers do |t|
+ t.string :encrypted_name
+ t.string :encrypted_name_iv
+ end
+ create_table :addresses do |t|
+ t.binary :encrypted_street
+ t.binary :encrypted_street_iv
+ t.binary :encrypted_zipcode
+ t.string :mode
+ end
+ end
+end
+
+ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
+
+if ::ActiveRecord::VERSION::STRING > "4.0"
+ module Rack
+ module Test
+ class UploadedFile; end
+ end
+ end
+
+ require 'action_controller/metal/strong_parameters'
+end
+
+class Person < ActiveRecord::Base
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
+ attr_encrypted :email, key: SECRET_KEY
+ attr_encrypted :credentials, key: Proc.new { |user| Encryptor.encrypt(value: user.salt, key: SECRET_KEY, iv: user.key_iv) }, marshal: true
+
+ after_initialize :initialize_salt_and_credentials
+
+ protected
+
+ def initialize_salt_and_credentials
+ self.key_iv ||= SecureRandom.random_bytes(12)
+ self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15]
+ self.credentials ||= { username: 'example', password: 'test' }
+ end
+end
+
+class PersonWithValidation < Person
+ validates_presence_of :email
+end
+
+class PersonWithProcMode < Person
+ attr_encrypted :email, key: SECRET_KEY, mode: Proc.new { :per_attribute_iv_and_salt }
+ attr_encrypted :credentials, key: SECRET_KEY, mode: Proc.new { :single_iv_and_salt }, insecure_mode: true
+end
+
+class PersonWithInstanceAttribute < Person
+ attr_encrypted :age
+end
+
+class Account < ActiveRecord::Base
+ ACCOUNT_ENCRYPTION_KEY = SecureRandom.urlsafe_base64(24)
+ attr_encrypted :password, key: :password_encryption_key
+
+ def encrypting?(attr)
+ encrypted_attributes[attr][:operation] == :encrypting
+ end
+
+ def password_encryption_key
+ if encrypting?(:password)
+ self.key = ACCOUNT_ENCRYPTION_KEY
+ else
+ self.key
+ end
+ end
+end
+
+class PersonWithSerialization < ActiveRecord::Base
+ self.table_name = 'people'
+ attr_encrypted :email, key: SECRET_KEY
+ serialize :password
+end
+
+class UserWithProtectedAttribute < ActiveRecord::Base
+ self.table_name = 'users'
+ attr_encrypted :password, key: SECRET_KEY
+ attr_protected :is_admin if ::ActiveRecord::VERSION::STRING < "4.0"
+end
+
+class PersonUsingAlias < ActiveRecord::Base
+ self.table_name = 'people'
+ attr_encryptor :email, key: SECRET_KEY
+end
+
+class PrimeMinister < ActiveRecord::Base
+ attr_encrypted :name, marshal: true, key: SECRET_KEY
+end
+
+class Address < ActiveRecord::Base
+ self.attr_encrypted_options[:marshal] = false
+ self.attr_encrypted_options[:encode] = false
+ attr_encrypted :street, encode_iv: false, key: SECRET_KEY
+ attr_encrypted :zipcode, key: SECRET_KEY, mode: Proc.new { |address| address.mode.to_sym }, insecure_mode: true
+end
+
+class ActiveRecordTest < Minitest::Test
+
+ def setup
+ drop_all_tables
+ create_tables
+ end
+
+ def test_should_encrypt_email
+ @person = Person.create(email: 'test@example.com')
+ refute_nil @person.encrypted_email
+ refute_equal @person.email, @person.encrypted_email
+ assert_equal @person.email, Person.first.email
+ end
+
+ def test_should_marshal_and_encrypt_credentials
+ @person = Person.create
+ refute_nil @person.encrypted_credentials
+ refute_equal @person.credentials, @person.encrypted_credentials
+ assert_equal @person.credentials, Person.first.credentials
+ end
+
+ def test_should_encode_by_default
+ assert Person.attr_encrypted_options[:encode]
+ end
+
+ def test_should_validate_presence_of_email
+ @person = PersonWithValidation.new
+ assert !@person.valid?
+ assert !@person.errors[:email].empty? || @person.errors.on(:email)
+ end
+
+ def test_should_encrypt_decrypt_with_iv
+ @person = Person.create(email: 'test@example.com')
+ @person2 = Person.find(@person.id)
+ refute_nil @person2.encrypted_email_iv
+ assert_equal 'test@example.com', @person2.email
+ end
+
+ def test_should_ensure_attributes_can_be_deserialized
+ @person = PersonWithSerialization.new(email: 'test@example.com', password: %w(an array of strings))
+ @person.save
+ assert_equal @person.password, %w(an array of strings)
+ end
+
+ def test_should_create_an_account_regardless_of_arguments_order
+ Account.create!(key: SECRET_KEY, password: "password")
+ Account.create!(password: "password" , key: SECRET_KEY)
+ end
+
+ def test_should_set_attributes_regardless_of_arguments_order
+ # minitest does not implement `assert_nothing_raised` https://github.com/seattlerb/minitest/issues/112
+ Account.new.attributes = { password: "password", key: SECRET_KEY }
+ end
+
+ def test_should_create_changed_predicate
+ person = Person.create!(email: 'test@example.com')
+ refute person.email_changed?
+ person.email = 'test@example.com'
+ refute person.email_changed?
+ person.email = nil
+ assert person.email_changed?
+ person.email = 'test2@example.com'
+ assert person.email_changed?
+ end
+
+ # PENDING - this test is failing because attr_encrypted does not adhere to the
+ # interface contract for ActiveModel::Dirty as of ActiveRecord 6.1:
+ # https://devdocs.io/rails~6.1/activemodel/dirty
+ def pending_test_should_create_was_predicate
+ original_email = 'test@example.com'
+ person = Person.create!(email: original_email)
+ assert_equal original_email, person.email_was
+ person.email = 'test2@example.com'
+ assert_equal original_email, person.email_was
+ old_pm_name = "Winston Churchill"
+ pm = PrimeMinister.create!(name: old_pm_name)
+ assert_equal old_pm_name, pm.name_was
+ old_zipcode = "90210"
+ address = Address.create!(zipcode: old_zipcode, mode: "single_iv_and_salt")
+ assert_equal old_zipcode, address.zipcode_was
+ end
+
+ # PENDING - this test is failing because attr_encrypted does not adhere to the
+ # interface contract for ActiveModel::Dirty as of ActiveRecord 6.1:
+ # https://devdocs.io/rails~6.1/activemodel/dirty
+ def pending_test_attribute_was_works_when_options_for_old_encrypted_value_are_different_than_options_for_new_encrypted_value
+ pw = 'password'
+ crypto_key = SecureRandom.urlsafe_base64(24)
+ old_iv = SecureRandom.random_bytes(12)
+ account = Account.create
+ encrypted_value = Encryptor.encrypt(value: pw, iv: old_iv, key: crypto_key)
+ Account.where(id: account.id).update_all(key: crypto_key, encrypted_password_iv: [old_iv].pack('m'), encrypted_password: [encrypted_value].pack('m'))
+ account = Account.find(account.id)
+ assert_equal pw, account.password
+ account.password = pw.reverse
+ assert_equal pw, account.password_was
+ account.save
+ account.reload
+ assert_equal Account::ACCOUNT_ENCRYPTION_KEY, account.key
+ assert_equal pw.reverse, account.password
+ end
+
+ if ::ActiveRecord::VERSION::STRING > "4.0"
+ def test_should_assign_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
+ assert_equal 'modified', @user.login
+ end
+
+ def test_should_not_assign_protected_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
+ assert !@user.is_admin?
+ end
+
+ def test_should_raise_exception_if_not_permitted
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ assert_raises ActiveModel::ForbiddenAttributesError do
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true)
+ end
+ end
+
+ def test_should_raise_exception_on_init_if_not_permitted
+ assert_raises ActiveModel::ForbiddenAttributesError do
+ @user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true)
+ end
+ end
+ else
+ def test_should_assign_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = { login: 'modified', is_admin: true }
+ assert_equal 'modified', @user.login
+ end
+
+ def test_should_not_assign_protected_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ @user.attributes = { login: 'modified', is_admin: true }
+ assert !@user.is_admin?
+ end
+
+ def test_should_assign_protected_attributes
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
+ if ::ActiveRecord::VERSION::STRING > "3.1"
+ @user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true)
+ else
+ @user.send(:attributes=, { login: 'modified', is_admin: true }, false)
+ end
+ assert @user.is_admin?
+ end
+ end
+
+ def test_should_allow_assignment_of_nil_attributes
+ @person = Person.new
+ assert_nil(@person.attributes = nil)
+ end
+
+ def test_should_allow_proc_based_mode
+ @person = PersonWithProcMode.create(email: 'test@example.com', credentials: 'password123')
+
+ # Email is :per_attribute_iv_and_salt
+ assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc
+ assert_equal @person.class.encrypted_attributes[:email][:mode].call, :per_attribute_iv_and_salt
+ refute_nil @person.encrypted_email_salt
+ refute_nil @person.encrypted_email_iv
+
+ # Credentials is :single_iv_and_salt
+ assert_equal @person.class.encrypted_attributes[:credentials][:mode].class, Proc
+ assert_equal @person.class.encrypted_attributes[:credentials][:mode].call, :single_iv_and_salt
+ assert_nil @person.encrypted_credentials_salt
+ assert_nil @person.encrypted_credentials_iv
+ end
+
+ if ::ActiveRecord::VERSION::STRING > "3.1"
+ def test_should_allow_assign_attributes_with_nil
+ @person = Person.new
+ assert_nil(@person.assign_attributes nil)
+ end
+ end
+
+ def test_that_alias_encrypts_column
+ user = PersonUsingAlias.new
+ user.email = 'test@example.com'
+ user.save
+
+ refute_nil user.encrypted_email
+ refute_equal user.email, user.encrypted_email
+ assert_equal user.email, PersonUsingAlias.first.email
+ end
+
+ # See https://github.com/attr-encrypted/attr_encrypted/issues/68
+ def test_should_invalidate_virtual_attributes_on_reload
+ old_pm_name = 'Winston Churchill'
+ new_pm_name = 'Neville Chamberlain'
+ pm = PrimeMinister.create!(name: old_pm_name)
+ assert_equal old_pm_name, pm.name
+ pm.name = new_pm_name
+ assert_equal new_pm_name, pm.name
+
+ result = pm.reload
+ assert_equal pm, result
+ assert_equal old_pm_name, pm.name
+ end
+
+ def test_should_save_encrypted_data_as_binary
+ street = '123 Elm'
+ address = Address.create!(street: street)
+ refute_equal address.encrypted_street, street
+ assert_equal Address.first.street, street
+ end
+
+ def test_should_evaluate_proc_based_mode
+ street = '123 Elm'
+ zipcode = '12345'
+ address = Address.create(street: street, zipcode: zipcode, mode: :single_iv_and_salt)
+ address.reload
+ refute_equal address.encrypted_zipcode, zipcode
+ assert_equal address.zipcode, zipcode
+ end
+
+ # See https://github.com/attr-encrypted/attr_encrypted/issues/332
+ def test_attribute_instance_methods_as_symbols_available_returns_false
+ assert_equal false, ActiveRecord::Base.__send__(:attribute_instance_methods_as_symbols_available?)
+ end
+
+ # See https://github.com/attr-encrypted/attr_encrypted/issues/332
+ def test_does_not_define_virtual_attributes
+ instance = Person.new
+
+ %w[
+ encrypted_age encrypted_age=
+ encrypted_age_iv encrypted_age_iv=
+ encrypted_age_salt encrypted_age_salt=
+ ].each do |method_name|
+ assert_equal false, instance.respond_to?(method_name), "should not define #{method_name}"
+ end
+ end
+end