shuber-attr_encrypted 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -7,6 +7,7 @@
7
7
  * Add ability to specify your own encoding directives
8
8
  * Update logic that evaluates symbol and proc options
9
9
  * Add support for :if and :unless options
10
+ * Add AttrEncrypted namespace
10
11
 
11
12
  2009-01-07 - Sean Huber (shuber@huberry.com)
12
13
  * Initial commit
data/README.markdown CHANGED
@@ -261,13 +261,18 @@ Then you'll have these two class methods available for each attribute: `User.enc
261
261
  be useful when you're using ActiveRecord (see below).
262
262
 
263
263
 
264
+ ### DataMapper ###
265
+
266
+ For your convenience, the `:encode` and `:marshal` options are set to true by default since you'll be storing everything in a database.
267
+
268
+
264
269
  ### ActiveRecord ###
265
270
 
266
271
  If you're using this gem with ActiveRecord, you get a few extra features:
267
272
 
268
273
  #### Default options ####
269
274
 
270
- For your convenience, the `:encode` and `:marshal` options are set to true by default since you'll be storing everything in a database.
275
+ Just like the default options for DataMapper, the `:encode` and `:marshal` options are set to true by default since you'll be storing everything in a database.
271
276
 
272
277
 
273
278
  #### Dynamic find\_by\_ and scoped\_by\_ methods ####
@@ -1,15 +1,15 @@
1
- require 'huberry/class'
2
- Class.send :include, Huberry::Class
1
+ require 'huberry/attr_encrypted/class'
2
+ Class.send :include, Huberry::AttrEncrypted::Class
3
3
 
4
- require 'huberry/object'
5
- Object.send :include, Huberry::Object
4
+ require 'huberry/attr_encrypted/object'
5
+ Object.send :include, Huberry::AttrEncrypted::Object
6
6
 
7
7
  if defined?(ActiveRecord)
8
- require 'huberry/active_record'
9
- ActiveRecord::Base.extend Huberry::ActiveRecord
8
+ require 'huberry/attr_encrypted/active_record'
9
+ ActiveRecord::Base.extend Huberry::AttrEncrypted::ActiveRecord
10
10
  end
11
11
 
12
12
  if defined?(DataMapper)
13
- require 'huberry/data_mapper'
14
- DataMapper::Resource.send :include, Huberry::DataMapper
13
+ require 'huberry/attr_encrypted/data_mapper'
14
+ DataMapper::Resource.send :include, Huberry::AttrEncrypted::DataMapper
15
15
  end
@@ -0,0 +1,50 @@
1
+ module Huberry
2
+ module AttrEncrypted
3
+ module ActiveRecord
4
+ def self.extended(base)
5
+ base.eigenclass_eval { alias_method_chain :method_missing, :attr_encrypted }
6
+ end
7
+
8
+ protected
9
+
10
+ # Calls attr_encrypted with the options <tt>:encode</tt> and <tt>:marshal</tt> set to true
11
+ # unless they've already been specified
12
+ def attr_encrypted(*attrs)
13
+ define_attribute_methods
14
+ options = { :encode => true, :marshal => true }.merge(attrs.last.is_a?(Hash) ? attrs.pop : {})
15
+ super *(attrs << options)
16
+ end
17
+
18
+ # Allows you to use dynamic methods like <tt>find_by_email</tt> or <tt>scoped_by_email</tt> for
19
+ # encrypted attributes
20
+ #
21
+ # NOTE: This only works when the <tt>:key</tt> option is specified as a string (see the README)
22
+ #
23
+ # This is useful for encrypting fields like email addresses. Your user's email addresses
24
+ # are encrypted in the database, but you can still look up a user by email for logging in
25
+ #
26
+ # Example
27
+ #
28
+ # class User < ActiveRecord::Base
29
+ # attr_encrypted :email, :key => 'secret key'
30
+ # end
31
+ #
32
+ # User.find_by_email_and_password('test@example.com', 'testing')
33
+ # # results in a call to
34
+ # User.find_by_encrypted_email_and_password('the_encrypted_version_of_test@example.com', 'testing')
35
+ def method_missing_with_attr_encrypted(method, *args, &block)
36
+ if match = /^(find|scoped)_(all_by|by)_([_a-zA-Z]\w*)$/.match(method.to_s)
37
+ attribute_names = match.captures.last.split('_and_')
38
+ attribute_names.each_with_index do |attribute, index|
39
+ if attr_encrypted?(attribute)
40
+ args[index] = send("encrypt_#{attribute}", args[index])
41
+ attribute_names[index] = encrypted_attributes[attribute]
42
+ end
43
+ end
44
+ method = "#{match.captures[0]}_#{match.captures[1]}_#{attribute_names.join('_and_')}".to_sym
45
+ end
46
+ method_missing_without_attr_encrypted(method, *args, &block)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,169 @@
1
+ module Huberry
2
+ module AttrEncrypted
3
+ module Class
4
+ protected
5
+ # Generates attr_accessors that encrypt and decrypt attributes transparently
6
+ #
7
+ # Options (any other options you specify are passed to the encryptor's encrypt and decrypt methods)
8
+ #
9
+ # :attribute => The name of the referenced encrypted attribute. For example
10
+ # <tt>attr_accessor :email, :attribute => :ee</tt> would generate an
11
+ # attribute named 'ee' to store the encrypted email. This is useful when defining
12
+ # one attribute to encrypt at a time or when the :prefix and :suffix options
13
+ # aren't enough. Defaults to nil.
14
+ #
15
+ # :prefix => A prefix used to generate the name of the referenced encrypted attributes.
16
+ # For example <tt>attr_accessor :email, :password, :prefix => 'crypted_'</tt> would
17
+ # generate attributes named 'crypted_email' and 'crypted_password' to store the
18
+ # encrypted email and password. Defaults to 'encrypted_'.
19
+ #
20
+ # :suffix => A suffix used to generate the name of the referenced encrypted attributes.
21
+ # For example <tt>attr_accessor :email, :password, :prefix => '', :suffix => '_encrypted'</tt>
22
+ # would generate attributes named 'email_encrypted' and 'password_encrypted' to store the
23
+ # encrypted email. Defaults to ''.
24
+ #
25
+ # :key => The encryption key. This option may not be required if you're using a custom encryptor. If you pass
26
+ # a symbol representing an instance method then the :key option will be replaced with the result of the
27
+ # method before being passed to the encryptor. Objects that respond to :call are evaluated as well (including procs).
28
+ # Any other key types will be passed directly to the encryptor.
29
+ #
30
+ # :encode => If set to true, attributes will be encoded as well as encrypted. This is useful if you're
31
+ # planning on storing the encrypted attributes in a database. The default encoding is 'm*' (base64),
32
+ # however this can be overwritten by setting the :encode option to some other encoding string instead of
33
+ # just 'true'. See http://www.ruby-doc.org/core/classes/Array.html#M002245 for more encoding directives.
34
+ # Defaults to false unless you're using it with ActiveRecord or DataMapper.
35
+ #
36
+ # :marshal => If set to true, attributes will be marshaled as well as encrypted. This is useful if you're planning
37
+ # on encrypting something other than a string. Defaults to false unless you're using it with ActiveRecord
38
+ # or DataMapper.
39
+ #
40
+ # :encryptor => The object to use for encrypting. Defaults to Huberry::Encryptor.
41
+ #
42
+ # :encrypt_method => The encrypt method name to call on the <tt>:encryptor</tt> object. Defaults to :encrypt.
43
+ #
44
+ # :decrypt_method => The decrypt method name to call on the <tt>:encryptor</tt> object. Defaults to :decrypt.
45
+ #
46
+ # :if => Attributes are only encrypted if this option evaluates to true. If you pass a symbol representing an instance
47
+ # method then the result of the method will be evaluated. Any objects that respond to :call are evaluated as well.
48
+ # Defaults to true.
49
+ #
50
+ # :unless => Attributes are only encrypted if this option evaluates to false. If you pass a symbol representing an instance
51
+ # method then the result of the method will be evaluated. Any objects that respond to :call are evaluated as well.
52
+ # Defaults to false.
53
+ #
54
+ # You can specify your own default options
55
+ #
56
+ # class User
57
+ # # now all attributes will be encoded and marshaled by default
58
+ # attr_encrypted_options.merge!(:encode => true, :marshal => true, :some_other_option => true)
59
+ # attr_encrypted :configuration
60
+ # end
61
+ #
62
+ #
63
+ # Example
64
+ #
65
+ # class User
66
+ # attr_encrypted :email, :credit_card, :key => 'some secret key'
67
+ # attr_encrypted :configuration, :key => 'some other secret key', :marshal => true
68
+ # end
69
+ #
70
+ # @user = User.new
71
+ # @user.encrypted_email # returns nil
72
+ # @user.email = 'test@example.com'
73
+ # @user.encrypted_email # returns the encrypted version of 'test@example.com'
74
+ #
75
+ # @user.configuration = { :time_zone => 'UTC' }
76
+ # @user.encrypted_configuration # returns the encrypted version of configuration
77
+ #
78
+ # See README for more examples
79
+ def attr_encrypted(*attrs)
80
+ options = {
81
+ :prefix => 'encrypted_',
82
+ :suffix => '',
83
+ :encryptor => Huberry::Encryptor,
84
+ :encrypt_method => :encrypt,
85
+ :decrypt_method => :decrypt,
86
+ :encode => false,
87
+ :marshal => false,
88
+ :if => true,
89
+ :unless => false
90
+ }.merge(attr_encrypted_options).merge(attrs.last.is_a?(Hash) ? attrs.pop : {})
91
+ options[:encode] = 'm*' if options[:encode] == true
92
+
93
+ attrs.each do |attribute|
94
+ encrypted_attribute_name = options[:attribute].nil? ? options[:prefix].to_s + attribute.to_s + options[:suffix].to_s : options[:attribute].to_s
95
+
96
+ encrypted_attributes[attribute.to_s] = encrypted_attribute_name
97
+
98
+ attr_accessor encrypted_attribute_name.to_sym unless instance_methods.include?(encrypted_attribute_name)
99
+
100
+ define_class_method "encrypt_#{attribute}" do |value|
101
+ if options[:if] && !options[:unless]
102
+ if value.nil?
103
+ encrypted_value = nil
104
+ else
105
+ value = Marshal.dump(value) if options[:marshal]
106
+ encrypted_value = options[:encryptor].send options[:encrypt_method], options.merge(:value => value)
107
+ encrypted_value = [encrypted_value].pack(options[:encode]) if options[:encode]
108
+ end
109
+ encrypted_value
110
+ else
111
+ value
112
+ end
113
+ end
114
+
115
+ define_class_method "decrypt_#{attribute}" do |encrypted_value|
116
+ if options[:if] && !options[:unless]
117
+ if encrypted_value.nil?
118
+ decrypted_value = nil
119
+ else
120
+ encrypted_value = encrypted_value.unpack(options[:encode]).to_s if options[:encode]
121
+ decrypted_value = options[:encryptor].send(options[:decrypt_method], options.merge(:value => encrypted_value))
122
+ decrypted_value = Marshal.load(decrypted_value) if options[:marshal]
123
+ end
124
+ decrypted_value
125
+ else
126
+ encrypted_value
127
+ end
128
+ end
129
+
130
+ define_method "#{attribute}" do
131
+ value = instance_variable_get("@#{attribute}")
132
+ encrypted_value = read_attribute(encrypted_attribute_name)
133
+ original_options = [:key, :if, :unless].inject({}) do |hash, option|
134
+ hash[option] = options[option]
135
+ options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
136
+ hash
137
+ end
138
+ value = instance_variable_set("@#{attribute}", self.class.send("decrypt_#{attribute}".to_sym, encrypted_value)) if value.nil? && !encrypted_value.nil?
139
+ options.merge!(original_options)
140
+ value
141
+ end
142
+
143
+ define_method "#{attribute}=" do |value|
144
+ original_options = [:key, :if, :unless].inject({}) do |hash, option|
145
+ hash[option] = options[option]
146
+ options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
147
+ hash
148
+ end
149
+ write_attribute(encrypted_attribute_name, self.class.send("encrypt_#{attribute}".to_sym, value))
150
+ options.merge!(original_options)
151
+ instance_variable_set("@#{attribute}", value)
152
+ end
153
+ end
154
+ end
155
+
156
+ # Evaluates an option specified as a symbol representing an instance method or a proc
157
+ # If the option is not a symbol or proc then the original option is returned
158
+ def evaluate_attr_encrypted_option(option, object)
159
+ if option.is_a?(Symbol) && object.respond_to?(option)
160
+ object.send(option)
161
+ elsif option.respond_to?(:call)
162
+ option.call(object)
163
+ else
164
+ option
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,23 @@
1
+ module Huberry
2
+ module AttrEncrypted
3
+ module DataMapper
4
+ def self.included(base)
5
+ base.class_eval do
6
+ extend ClassMethods
7
+ alias_method :read_attribute, :attribute_get
8
+ alias_method :write_attribute, :attribute_set
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ protected
14
+ # Calls attr_encrypted with the options <tt>:encode</tt> and <tt>:marshal</tt> set to true
15
+ # unless they've already been specified
16
+ def attr_encrypted(*attrs)
17
+ options = { :encode => true, :marshal => true }.merge(attrs.last.is_a?(Hash) ? attrs.pop : {})
18
+ super *(attrs << options)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ module Huberry
2
+ module AttrEncrypted
3
+ module Object
4
+ def self.included(base)
5
+ base.class_eval do
6
+ extend ClassMethods
7
+ eattr_accessor :attr_encrypted_options, :encrypted_attributes
8
+ attr_encrypted_options = {}
9
+ encrypted_attributes = {}
10
+ end
11
+ end
12
+
13
+ # Wraps instance_variable_get
14
+ def read_attribute(attribute)
15
+ instance_variable_get("@#{attribute}")
16
+ end
17
+
18
+ # Wraps instance_variable_set
19
+ def write_attribute(attribute, value)
20
+ instance_variable_set("@#{attribute}", value)
21
+ end
22
+
23
+ module ClassMethods
24
+ # Checks if an attribute has been configured to be encrypted
25
+ #
26
+ # Example
27
+ #
28
+ # class User
29
+ # attr_accessor :name
30
+ # attr_encrypted :email
31
+ # end
32
+ #
33
+ # User.attr_encrypted?(:name) # false
34
+ # User.attr_encrypted?(:email) # true
35
+ def attr_encrypted?(attribute)
36
+ encrypted_attributes.keys.include?(attribute.to_s)
37
+ end
38
+
39
+ # Copies existing encrypted attributes and options to the derived class
40
+ def inherited(base)
41
+ base.attr_encrypted_options = self.attr_encrypted_options.nil? ? {} : self.attr_encrypted_options.dup
42
+ base.encrypted_attributes = self.encrypted_attributes.nil? ? {} : self.encrypted_attributes.dup
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shuber-attr_encrypted
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Huber
@@ -41,10 +41,10 @@ extra_rdoc_files: []
41
41
  files:
42
42
  - CHANGELOG
43
43
  - lib/attr_encrypted.rb
44
- - lib/huberry/active_record.rb
45
- - lib/huberry/class.rb
46
- - lib/huberry/data_mapper.rb
47
- - lib/huberry/object.rb
44
+ - lib/huberry/attr_encrypted/active_record.rb
45
+ - lib/huberry/attr_encrypted/class.rb
46
+ - lib/huberry/attr_encrypted/data_mapper.rb
47
+ - lib/huberry/attr_encrypted/object.rb
48
48
  - MIT-LICENSE
49
49
  - Rakefile
50
50
  - README.markdown
@@ -1,48 +0,0 @@
1
- module Huberry
2
- module ActiveRecord
3
- def self.extended(base)
4
- base.eigenclass_eval { alias_method_chain :method_missing, :attr_encrypted }
5
- end
6
-
7
- protected
8
-
9
- # Calls attr_encrypted with the options <tt>:encode</tt> and <tt>:marshal</tt> set to true
10
- # unless they've already been specified
11
- def attr_encrypted(*attrs)
12
- define_attribute_methods
13
- options = { :encode => true, :marshal => true }.merge(attrs.last.is_a?(Hash) ? attrs.pop : {})
14
- super *(attrs << options)
15
- end
16
-
17
- # Allows you to use dynamic methods like <tt>find_by_email</tt> or <tt>scoped_by_email</tt> for
18
- # encrypted attributes
19
- #
20
- # NOTE: This only works when the <tt>:key</tt> option is specified as a string (see the README)
21
- #
22
- # This is useful for encrypting fields like email addresses. Your user's email addresses
23
- # are encrypted in the database, but you can still look up a user by email for logging in
24
- #
25
- # Example
26
- #
27
- # class User < ActiveRecord::Base
28
- # attr_encrypted :email, :key => 'secret key'
29
- # end
30
- #
31
- # User.find_by_email_and_password('test@example.com', 'testing')
32
- # # results in a call to
33
- # User.find_by_encrypted_email_and_password('the_encrypted_version_of_test@example.com', 'testing')
34
- def method_missing_with_attr_encrypted(method, *args, &block)
35
- if match = /^(find|scoped)_(all_by|by)_([_a-zA-Z]\w*)$/.match(method.to_s)
36
- attribute_names = match.captures.last.split('_and_')
37
- attribute_names.each_with_index do |attribute, index|
38
- if attr_encrypted?(attribute)
39
- args[index] = send("encrypt_#{attribute}", args[index])
40
- attribute_names[index] = encrypted_attributes[attribute]
41
- end
42
- end
43
- method = "#{match.captures[0]}_#{match.captures[1]}_#{attribute_names.join('_and_')}".to_sym
44
- end
45
- method_missing_without_attr_encrypted(method, *args, &block)
46
- end
47
- end
48
- end
data/lib/huberry/class.rb DELETED
@@ -1,167 +0,0 @@
1
- module Huberry
2
- module Class
3
- protected
4
- # Generates attr_accessors that encrypt and decrypt attributes transparently
5
- #
6
- # Options (any other options you specify are passed to the encryptor's encrypt and decrypt methods)
7
- #
8
- # :attribute => The name of the referenced encrypted attribute. For example
9
- # <tt>attr_accessor :email, :attribute => :ee</tt> would generate an
10
- # attribute named 'ee' to store the encrypted email. This is useful when defining
11
- # one attribute to encrypt at a time or when the :prefix and :suffix options
12
- # aren't enough. Defaults to nil.
13
- #
14
- # :prefix => A prefix used to generate the name of the referenced encrypted attributes.
15
- # For example <tt>attr_accessor :email, :password, :prefix => 'crypted_'</tt> would
16
- # generate attributes named 'crypted_email' and 'crypted_password' to store the
17
- # encrypted email and password. Defaults to 'encrypted_'.
18
- #
19
- # :suffix => A suffix used to generate the name of the referenced encrypted attributes.
20
- # For example <tt>attr_accessor :email, :password, :prefix => '', :suffix => '_encrypted'</tt>
21
- # would generate attributes named 'email_encrypted' and 'password_encrypted' to store the
22
- # encrypted email. Defaults to ''.
23
- #
24
- # :key => The encryption key. This option may not be required if you're using a custom encryptor. If you pass
25
- # a symbol representing an instance method then the :key option will be replaced with the result of the
26
- # method before being passed to the encryptor. Objects that respond to :call are evaluated as well (including procs).
27
- # Any other key types will be passed directly to the encryptor.
28
- #
29
- # :encode => If set to true, attributes will be encoded as well as encrypted. This is useful if you're
30
- # planning on storing the encrypted attributes in a database. The default encoding is 'm*' (base64),
31
- # however this can be overwritten by setting the :encode option to some other encoding string instead of
32
- # just 'true'. See http://www.ruby-doc.org/core/classes/Array.html#M002245 for more encoding directives.
33
- # Defaults to false unless you're using it with ActiveRecord or DataMapper.
34
- #
35
- # :marshal => If set to true, attributes will be marshaled as well as encrypted. This is useful if you're planning
36
- # on encrypting something other than a string. Defaults to false unless you're using it with ActiveRecord
37
- # or DataMapper.
38
- #
39
- # :encryptor => The object to use for encrypting. Defaults to Huberry::Encryptor.
40
- #
41
- # :encrypt_method => The encrypt method name to call on the <tt>:encryptor</tt> object. Defaults to :encrypt.
42
- #
43
- # :decrypt_method => The decrypt method name to call on the <tt>:encryptor</tt> object. Defaults to :decrypt.
44
- #
45
- # :if => Attributes are only encrypted if this option evaluates to true. If you pass a symbol representing an instance
46
- # method then the result of the method will be evaluated. Any objects that respond to :call are evaluated as well.
47
- # Defaults to true.
48
- #
49
- # :unless => Attributes are only encrypted if this option evaluates to false. If you pass a symbol representing an instance
50
- # method then the result of the method will be evaluated. Any objects that respond to :call are evaluated as well.
51
- # Defaults to false.
52
- #
53
- # You can specify your own default options
54
- #
55
- # class User
56
- # # now all attributes will be encoded and marshaled by default
57
- # attr_encrypted_options.merge!(:encode => true, :marshal => true, :some_other_option => true)
58
- # attr_encrypted :configuration
59
- # end
60
- #
61
- #
62
- # Example
63
- #
64
- # class User
65
- # attr_encrypted :email, :credit_card, :key => 'some secret key'
66
- # attr_encrypted :configuration, :key => 'some other secret key', :marshal => true
67
- # end
68
- #
69
- # @user = User.new
70
- # @user.encrypted_email # returns nil
71
- # @user.email = 'test@example.com'
72
- # @user.encrypted_email # returns the encrypted version of 'test@example.com'
73
- #
74
- # @user.configuration = { :time_zone => 'UTC' }
75
- # @user.encrypted_configuration # returns the encrypted version of configuration
76
- #
77
- # See README for more examples
78
- def attr_encrypted(*attrs)
79
- options = {
80
- :prefix => 'encrypted_',
81
- :suffix => '',
82
- :encryptor => Huberry::Encryptor,
83
- :encrypt_method => :encrypt,
84
- :decrypt_method => :decrypt,
85
- :encode => false,
86
- :marshal => false,
87
- :if => true,
88
- :unless => false
89
- }.merge(attr_encrypted_options).merge(attrs.last.is_a?(Hash) ? attrs.pop : {})
90
- options[:encode] = 'm*' if options[:encode] == true
91
-
92
- attrs.each do |attribute|
93
- encrypted_attribute_name = options[:attribute].nil? ? options[:prefix].to_s + attribute.to_s + options[:suffix].to_s : options[:attribute].to_s
94
-
95
- encrypted_attributes[attribute.to_s] = encrypted_attribute_name
96
-
97
- attr_accessor encrypted_attribute_name.to_sym unless instance_methods.include?(encrypted_attribute_name)
98
-
99
- define_class_method "encrypt_#{attribute}" do |value|
100
- if options[:if] && !options[:unless]
101
- if value.nil?
102
- encrypted_value = nil
103
- else
104
- value = Marshal.dump(value) if options[:marshal]
105
- encrypted_value = options[:encryptor].send options[:encrypt_method], options.merge(:value => value)
106
- encrypted_value = [encrypted_value].pack(options[:encode]) if options[:encode]
107
- end
108
- encrypted_value
109
- else
110
- value
111
- end
112
- end
113
-
114
- define_class_method "decrypt_#{attribute}" do |encrypted_value|
115
- if options[:if] && !options[:unless]
116
- if encrypted_value.nil?
117
- decrypted_value = nil
118
- else
119
- encrypted_value = encrypted_value.unpack(options[:encode]).to_s if options[:encode]
120
- decrypted_value = options[:encryptor].send(options[:decrypt_method], options.merge(:value => encrypted_value))
121
- decrypted_value = Marshal.load(decrypted_value) if options[:marshal]
122
- end
123
- decrypted_value
124
- else
125
- encrypted_value
126
- end
127
- end
128
-
129
- define_method "#{attribute}" do
130
- value = instance_variable_get("@#{attribute}")
131
- encrypted_value = read_attribute(encrypted_attribute_name)
132
- original_options = [:key, :if, :unless].inject({}) do |hash, option|
133
- hash[option] = options[option]
134
- options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
135
- hash
136
- end
137
- value = instance_variable_set("@#{attribute}", self.class.send("decrypt_#{attribute}".to_sym, encrypted_value)) if value.nil? && !encrypted_value.nil?
138
- options.merge!(original_options)
139
- value
140
- end
141
-
142
- define_method "#{attribute}=" do |value|
143
- original_options = [:key, :if, :unless].inject({}) do |hash, option|
144
- hash[option] = options[option]
145
- options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
146
- hash
147
- end
148
- write_attribute(encrypted_attribute_name, self.class.send("encrypt_#{attribute}".to_sym, value))
149
- options.merge!(original_options)
150
- instance_variable_set("@#{attribute}", value)
151
- end
152
- end
153
- end
154
-
155
- # Evaluates an option specified as a symbol representing an instance method or a proc
156
- # If the option is not a symbol or proc then the original option is returned
157
- def evaluate_attr_encrypted_option(option, object)
158
- if option.is_a?(Symbol) && object.respond_to?(option)
159
- object.send(option)
160
- elsif option.respond_to?(:call)
161
- option.call(object)
162
- else
163
- option
164
- end
165
- end
166
- end
167
- end
@@ -1,21 +0,0 @@
1
- module Huberry
2
- module DataMapper
3
- def self.included(base)
4
- base.class_eval do
5
- extend ClassMethods
6
- alias_method :read_attribute, :attribute_get
7
- alias_method :write_attribute, :attribute_set
8
- end
9
- end
10
-
11
- module ClassMethods
12
- protected
13
- # Calls attr_encrypted with the options <tt>:encode</tt> and <tt>:marshal</tt> set to true
14
- # unless they've already been specified
15
- def attr_encrypted(*attrs)
16
- options = { :encode => true, :marshal => true }.merge(attrs.last.is_a?(Hash) ? attrs.pop : {})
17
- super *(attrs << options)
18
- end
19
- end
20
- end
21
- end
@@ -1,45 +0,0 @@
1
- module Huberry
2
- module Object
3
- def self.included(base)
4
- base.class_eval do
5
- extend ClassMethods
6
- eattr_accessor :attr_encrypted_options, :encrypted_attributes
7
- attr_encrypted_options = {}
8
- encrypted_attributes = {}
9
- end
10
- end
11
-
12
- # Wraps instance_variable_get
13
- def read_attribute(attribute)
14
- instance_variable_get("@#{attribute}")
15
- end
16
-
17
- # Wraps instance_variable_set
18
- def write_attribute(attribute, value)
19
- instance_variable_set("@#{attribute}", value)
20
- end
21
-
22
- module ClassMethods
23
- # Checks if an attribute has been configured to be encrypted
24
- #
25
- # Example
26
- #
27
- # class User
28
- # attr_accessor :name
29
- # attr_encrypted :email
30
- # end
31
- #
32
- # User.attr_encrypted?(:name) # false
33
- # User.attr_encrypted?(:email) # true
34
- def attr_encrypted?(attribute)
35
- encrypted_attributes.keys.include?(attribute.to_s)
36
- end
37
-
38
- # Copies existing encrypted attributes and options to the derived class
39
- def inherited(base)
40
- base.attr_encrypted_options = self.attr_encrypted_options.nil? ? {} : self.attr_encrypted_options.dup
41
- base.encrypted_attributes = self.encrypted_attributes.nil? ? {} : self.encrypted_attributes.dup
42
- end
43
- end
44
- end
45
- end