shuber-attr_encrypted 1.0.6 → 1.0.7

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
@@ -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