shuber-attr_encrypted 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ 2009-01-14 - Sean Huber (shuber@huberry.com)
2
+ * Move Class logic into Object
3
+
1
4
  2009-01-13 - Sean Huber (shuber@huberry.com)
2
5
  * :marshal no longer defaults to true in ORM adapters
3
6
  * Load gem dependencies
@@ -4,10 +4,223 @@ require 'eigenclass'
4
4
  gem 'shuber-encryptor'
5
5
  require 'encryptor'
6
6
 
7
- require 'huberry/attr_encrypted/class'
8
- Class.send :include, Huberry::AttrEncrypted::Class
7
+ module Huberry
8
+ module AttrEncrypted
9
+ def self.extended(base)
10
+ base.attr_encrypted_options = {}
11
+ base.instance_variable_set('@encrypted_attributes', {})
12
+ end
13
+
14
+ # Default options to use with calls to <tt>attr_encrypted</tt>.
15
+ #
16
+ # It will inherit existing options from its parent class
17
+ def attr_encrypted_options
18
+ @attr_encrypted_options ||= superclass.attr_encrypted_options.nil? ? {} : superclass.attr_encrypted_options.dup
19
+ end
20
+
21
+ # Sets default options to use with calls to <tt>attr_encrypted</tt>.
22
+ def attr_encrypted_options=(options)
23
+ @attr_encrypted_options = options
24
+ end
25
+
26
+ # Contains a hash of encrypted attributes with virtual attribute names as keys and real attribute
27
+ # names as values
28
+ #
29
+ # Example
30
+ #
31
+ # class User
32
+ # attr_encrypted :email
33
+ # end
34
+ #
35
+ # User.encrypted_attributes # { 'email' => 'encrypted_email' }
36
+ def encrypted_attributes
37
+ @encrypted_attributes ||= superclass.encrypted_attributes.nil? ? {} : superclass.encrypted_attributes.dup
38
+ end
39
+
40
+ # Checks if an attribute has been configured to be encrypted
41
+ #
42
+ # Example
43
+ #
44
+ # class User
45
+ # attr_accessor :name
46
+ # attr_encrypted :email
47
+ # end
48
+ #
49
+ # User.attr_encrypted?(:name) # false
50
+ # User.attr_encrypted?(:email) # true
51
+ def attr_encrypted?(attribute)
52
+ encrypted_attributes.keys.include?(attribute.to_s)
53
+ end
54
+
55
+ protected
56
+
57
+ # Generates attr_accessors that encrypt and decrypt attributes transparently
58
+ #
59
+ # Options (any other options you specify are passed to the encryptor's encrypt and decrypt methods)
60
+ #
61
+ # :attribute => The name of the referenced encrypted attribute. For example
62
+ # <tt>attr_accessor :email, :attribute => :ee</tt> would generate an
63
+ # attribute named 'ee' to store the encrypted email. This is useful when defining
64
+ # one attribute to encrypt at a time or when the :prefix and :suffix options
65
+ # aren't enough. Defaults to nil.
66
+ #
67
+ # :prefix => A prefix used to generate the name of the referenced encrypted attributes.
68
+ # For example <tt>attr_accessor :email, :password, :prefix => 'crypted_'</tt> would
69
+ # generate attributes named 'crypted_email' and 'crypted_password' to store the
70
+ # encrypted email and password. Defaults to 'encrypted_'.
71
+ #
72
+ # :suffix => A suffix used to generate the name of the referenced encrypted attributes.
73
+ # For example <tt>attr_accessor :email, :password, :prefix => '', :suffix => '_encrypted'</tt>
74
+ # would generate attributes named 'email_encrypted' and 'password_encrypted' to store the
75
+ # encrypted email. Defaults to ''.
76
+ #
77
+ # :key => The encryption key. This option may not be required if you're using a custom encryptor. If you pass
78
+ # a symbol representing an instance method then the :key option will be replaced with the result of the
79
+ # method before being passed to the encryptor. Objects that respond to :call are evaluated as well (including procs).
80
+ # Any other key types will be passed directly to the encryptor.
81
+ #
82
+ # :encode => If set to true, attributes will be encoded as well as encrypted. This is useful if you're
83
+ # planning on storing the encrypted attributes in a database. The default encoding is 'm*' (base64),
84
+ # however this can be overwritten by setting the :encode option to some other encoding string instead of
85
+ # just 'true'. See http://www.ruby-doc.org/core/classes/Array.html#M002245 for more encoding directives.
86
+ # Defaults to false unless you're using it with ActiveRecord or DataMapper.
87
+ #
88
+ # :marshal => If set to true, attributes will be marshaled as well as encrypted. This is useful if you're planning
89
+ # on encrypting something other than a string. Defaults to false unless you're using it with ActiveRecord
90
+ # or DataMapper.
91
+ #
92
+ # :encryptor => The object to use for encrypting. Defaults to Huberry::Encryptor.
93
+ #
94
+ # :encrypt_method => The encrypt method name to call on the <tt>:encryptor</tt> object. Defaults to :encrypt.
95
+ #
96
+ # :decrypt_method => The decrypt method name to call on the <tt>:encryptor</tt> object. Defaults to :decrypt.
97
+ #
98
+ # :if => Attributes are only encrypted if this option evaluates to true. If you pass a symbol representing an instance
99
+ # method then the result of the method will be evaluated. Any objects that respond to :call are evaluated as well.
100
+ # Defaults to true.
101
+ #
102
+ # :unless => Attributes are only encrypted if this option evaluates to false. If you pass a symbol representing an instance
103
+ # method then the result of the method will be evaluated. Any objects that respond to :call are evaluated as well.
104
+ # Defaults to false.
105
+ #
106
+ # You can specify your own default options
107
+ #
108
+ # class User
109
+ # # now all attributes will be encoded and marshaled by default
110
+ # attr_encrypted_options.merge!(:encode => true, :marshal => true, :some_other_option => true)
111
+ # attr_encrypted :configuration
112
+ # end
113
+ #
114
+ #
115
+ # Example
116
+ #
117
+ # class User
118
+ # attr_encrypted :email, :credit_card, :key => 'some secret key'
119
+ # attr_encrypted :configuration, :key => 'some other secret key', :marshal => true
120
+ # end
121
+ #
122
+ # @user = User.new
123
+ # @user.encrypted_email # returns nil
124
+ # @user.email = 'test@example.com'
125
+ # @user.encrypted_email # returns the encrypted version of 'test@example.com'
126
+ #
127
+ # @user.configuration = { :time_zone => 'UTC' }
128
+ # @user.encrypted_configuration # returns the encrypted version of configuration
129
+ #
130
+ # See README for more examples
131
+ def attr_encrypted(*attrs)
132
+ options = {
133
+ :prefix => 'encrypted_',
134
+ :suffix => '',
135
+ :encryptor => Huberry::Encryptor,
136
+ :encrypt_method => :encrypt,
137
+ :decrypt_method => :decrypt,
138
+ :encode => false,
139
+ :marshal => false,
140
+ :if => true,
141
+ :unless => false
142
+ }.merge(attr_encrypted_options).merge(attrs.last.is_a?(Hash) ? attrs.pop : {})
143
+ options[:encode] = 'm*' if options[:encode] == true
144
+
145
+ attrs.each do |attribute|
146
+ encrypted_attribute_name = options[:attribute].nil? ? options[:prefix].to_s + attribute.to_s + options[:suffix].to_s : options[:attribute].to_s
147
+
148
+ encrypted_attributes[attribute.to_s] = encrypted_attribute_name
149
+
150
+ attr_reader encrypted_attribute_name.to_sym unless instance_methods.include?(encrypted_attribute_name)
151
+ attr_writer encrypted_attribute_name.to_sym unless instance_methods.include?("#{encrypted_attribute_name}=")
152
+
153
+ define_class_method "encrypt_#{attribute}" do |value|
154
+ if options[:if] && !options[:unless]
155
+ if value.nil?
156
+ encrypted_value = nil
157
+ else
158
+ value = Marshal.dump(value) if options[:marshal]
159
+ encrypted_value = options[:encryptor].send options[:encrypt_method], options.merge(:value => value)
160
+ encrypted_value = [encrypted_value].pack(options[:encode]) if options[:encode]
161
+ end
162
+ encrypted_value
163
+ else
164
+ value
165
+ end
166
+ end
167
+
168
+ define_class_method "decrypt_#{attribute}" do |encrypted_value|
169
+ if options[:if] && !options[:unless]
170
+ if encrypted_value.nil?
171
+ decrypted_value = nil
172
+ else
173
+ encrypted_value = encrypted_value.unpack(options[:encode]).to_s if options[:encode]
174
+ decrypted_value = options[:encryptor].send(options[:decrypt_method], options.merge(:value => encrypted_value))
175
+ decrypted_value = Marshal.load(decrypted_value) if options[:marshal]
176
+ end
177
+ decrypted_value
178
+ else
179
+ encrypted_value
180
+ end
181
+ end
182
+
183
+ define_method "#{attribute}" do
184
+ value = instance_variable_get("@#{attribute}")
185
+ encrypted_value = send(encrypted_attribute_name.to_sym)
186
+ original_options = [:key, :if, :unless].inject({}) do |hash, option|
187
+ hash[option] = options[option]
188
+ options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
189
+ hash
190
+ end
191
+ value = instance_variable_set("@#{attribute}", self.class.send("decrypt_#{attribute}".to_sym, encrypted_value)) if value.nil? && !encrypted_value.nil?
192
+ options.merge!(original_options)
193
+ value
194
+ end
195
+
196
+ define_method "#{attribute}=" do |value|
197
+ original_options = [:key, :if, :unless].inject({}) do |hash, option|
198
+ hash[option] = options[option]
199
+ options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
200
+ hash
201
+ end
202
+ send("#{encrypted_attribute_name}=".to_sym, self.class.send("encrypt_#{attribute}".to_sym, value))
203
+ options.merge!(original_options)
204
+ instance_variable_set("@#{attribute}", value)
205
+ end
206
+ end
207
+ end
208
+
209
+ # Evaluates an option specified as a symbol representing an instance method or a proc
210
+ #
211
+ # If the option is not a symbol or proc then the original option is returned
212
+ def evaluate_attr_encrypted_option(option, object)
213
+ if option.is_a?(Symbol) && object.respond_to?(option)
214
+ object.send(option)
215
+ elsif option.respond_to?(:call)
216
+ option.call(object)
217
+ else
218
+ option
219
+ end
220
+ end
221
+ end
222
+ end
9
223
 
10
- require 'huberry/attr_encrypted/object'
11
- Object.extend Huberry::AttrEncrypted::Object
224
+ Object.extend Huberry::AttrEncrypted
12
225
 
13
226
  Dir[File.join(File.dirname(__FILE__), 'huberry', 'attr_encrypted', 'adapters', '*.rb')].each { |file| require file }
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.6
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Huber
@@ -44,8 +44,6 @@ files:
44
44
  - lib/huberry/attr_encrypted/adapters/active_record.rb
45
45
  - lib/huberry/attr_encrypted/adapters/data_mapper.rb
46
46
  - lib/huberry/attr_encrypted/adapters/sequel.rb
47
- - lib/huberry/attr_encrypted/class.rb
48
- - lib/huberry/attr_encrypted/object.rb
49
47
  - MIT-LICENSE
50
48
  - Rakefile
51
49
  - README.markdown
@@ -1,170 +0,0 @@
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_reader encrypted_attribute_name.to_sym unless instance_methods.include?(encrypted_attribute_name)
99
- attr_writer encrypted_attribute_name.to_sym unless instance_methods.include?("#{encrypted_attribute_name}=")
100
-
101
- define_class_method "encrypt_#{attribute}" do |value|
102
- if options[:if] && !options[:unless]
103
- if value.nil?
104
- encrypted_value = nil
105
- else
106
- value = Marshal.dump(value) if options[:marshal]
107
- encrypted_value = options[:encryptor].send options[:encrypt_method], options.merge(:value => value)
108
- encrypted_value = [encrypted_value].pack(options[:encode]) if options[:encode]
109
- end
110
- encrypted_value
111
- else
112
- value
113
- end
114
- end
115
-
116
- define_class_method "decrypt_#{attribute}" do |encrypted_value|
117
- if options[:if] && !options[:unless]
118
- if encrypted_value.nil?
119
- decrypted_value = nil
120
- else
121
- encrypted_value = encrypted_value.unpack(options[:encode]).to_s if options[:encode]
122
- decrypted_value = options[:encryptor].send(options[:decrypt_method], options.merge(:value => encrypted_value))
123
- decrypted_value = Marshal.load(decrypted_value) if options[:marshal]
124
- end
125
- decrypted_value
126
- else
127
- encrypted_value
128
- end
129
- end
130
-
131
- define_method "#{attribute}" do
132
- value = instance_variable_get("@#{attribute}")
133
- encrypted_value = send(encrypted_attribute_name.to_sym)
134
- original_options = [:key, :if, :unless].inject({}) do |hash, option|
135
- hash[option] = options[option]
136
- options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
137
- hash
138
- end
139
- value = instance_variable_set("@#{attribute}", self.class.send("decrypt_#{attribute}".to_sym, encrypted_value)) if value.nil? && !encrypted_value.nil?
140
- options.merge!(original_options)
141
- value
142
- end
143
-
144
- define_method "#{attribute}=" do |value|
145
- original_options = [:key, :if, :unless].inject({}) do |hash, option|
146
- hash[option] = options[option]
147
- options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self
148
- hash
149
- end
150
- send("#{encrypted_attribute_name}=".to_sym, self.class.send("encrypt_#{attribute}".to_sym, value))
151
- options.merge!(original_options)
152
- instance_variable_set("@#{attribute}", value)
153
- end
154
- end
155
- end
156
-
157
- # Evaluates an option specified as a symbol representing an instance method or a proc
158
- # If the option is not a symbol or proc then the original option is returned
159
- def evaluate_attr_encrypted_option(option, object)
160
- if option.is_a?(Symbol) && object.respond_to?(option)
161
- object.send(option)
162
- elsif option.respond_to?(:call)
163
- option.call(object)
164
- else
165
- option
166
- end
167
- end
168
- end
169
- end
170
- end
@@ -1,51 +0,0 @@
1
- module Huberry
2
- module AttrEncrypted
3
- module Object
4
- def self.extended(base)
5
- base.attr_encrypted_options = {}
6
- base.instance_variable_set('@encrypted_attributes', {})
7
- end
8
-
9
- # Default options to use with calls to <tt>attr_encrypted</tt>.
10
- #
11
- # It will inherit existing options from its parent class
12
- def attr_encrypted_options
13
- @attr_encrypted_options ||= superclass.attr_encrypted_options.nil? ? {} : superclass.attr_encrypted_options.dup
14
- end
15
-
16
- # Sets default options to use with calls to <tt>attr_encrypted</tt>.
17
- def attr_encrypted_options=(options)
18
- @attr_encrypted_options = options
19
- end
20
-
21
- # Contains a hash of encrypted attributes with virtual attribute names as keys and real attribute
22
- # names as values
23
- #
24
- # Example
25
- #
26
- # class User
27
- # attr_encrypted :email
28
- # end
29
- #
30
- # User.encrypted_attributes # { 'email' => 'encrypted_email' }
31
- def encrypted_attributes
32
- @encrypted_attributes ||= superclass.encrypted_attributes.nil? ? {} : superclass.encrypted_attributes.dup
33
- end
34
-
35
- # Checks if an attribute has been configured to be encrypted
36
- #
37
- # Example
38
- #
39
- # class User
40
- # attr_accessor :name
41
- # attr_encrypted :email
42
- # end
43
- #
44
- # User.attr_encrypted?(:name) # false
45
- # User.attr_encrypted?(:email) # true
46
- def attr_encrypted?(attribute)
47
- encrypted_attributes.keys.include?(attribute.to_s)
48
- end
49
- end
50
- end
51
- end