shuber-attr_encrypted 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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