lib/encrypt_attr/base.rb
module EncryptAttr
module Base
def self.included(target)
target.extend(ClassMethods)
end
class << self
# Define the object that will encrypt/decrypt values.
# By default, it's EncryptAttr::Encryptor
attr_accessor :encryptor
end
def self.secret_token
@secret_token
end
def self.secret_token=(secret_token)
encryptor.validate_secret_token(secret_token.to_s) if encryptor.respond_to?(:validate_secret_token)
@secret_token = secret_token.to_s
end
# Set initial token value to empty string.
# Cannot assign through writer method because of size warning.
@secret_token = ""
# Set initial encryptor engine.
self.encryptor = Encryptor
module ClassMethods
def encrypt_attr(*args, secret_token: EncryptAttr.secret_token, encryptor: EncryptAttr.encryptor)
encryptor.validate_secret_token(secret_token) if encryptor.respond_to?(:validate_secret_token)
args.each do |attribute|
define_encrypted_attribute(attribute, secret_token, encryptor)
end
end
alias_method :attr_encrypt, :encrypt_attr
alias_method :attr_encrypted, :encrypt_attr
alias_method :attr_vault, :encrypt_attr
alias_method :encrypt_attr, :encrypt_attr
alias_method :encrypt_attribute, :encrypt_attr
alias_method :encrypted_attr, :encrypt_attr
alias_method :encrypted_attribute, :encrypt_attr
private
def define_encrypted_attribute(attribute, secret_token, encryptor)
define_method attribute do
value = instance_variable_get("@#{attribute}")
encrypted_value = send("encrypted_#{attribute}") unless value
value = encryptor.decrypt(secret_token, encrypted_value) if encrypted_value
instance_variable_set("@#{attribute}", value)
end
define_method "#{attribute}=" do |value|
instance_variable_set("@#{attribute}", value)
send("encrypted_#{attribute}=", nil)
send("encrypted_#{attribute}=", encryptor.encrypt(secret_token, value)) if value && value != ""
end
end
end
end
end