mournful_settings 0.0.6 → 0.1.0
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/README.rdoc +79 -36
- data/lib/active_record/acts/mournful_setting.rb +22 -0
- data/lib/mournful_settings/setting.rb +1 -110
- data/lib/mournful_settings/{setting → setting_methods}/cipher.rb +1 -1
- data/lib/mournful_settings/setting_methods.rb +120 -0
- data/lib/mournful_settings/version.rb +9 -1
- data/lib/mournful_settings.rb +2 -1
- data/test/dummy/db/test.sqlite3.db +0 -0
- data/test/dummy/lib/setting.rb +1 -1
- data/test/dummy/lib/setting_actor.rb +9 -0
- data/test/dummy/test/setting_actor_test.rb +155 -0
- data/test/dummy/test/setting_test.rb +1 -0
- data/test/test_helper.rb +1 -0
- metadata +9 -3
data/README.rdoc
CHANGED
@@ -7,48 +7,54 @@ they can be stored encrypted. Aren't puns wonderful.
|
|
7
7
|
|
8
8
|
gem mournful_settings
|
9
9
|
|
10
|
-
Setting are stored in a database table 'mournful_settings_settings'. To add
|
11
|
-
mournful_settings migrations to the host app run this rake task:
|
12
|
-
|
13
|
-
rake mournful_settings:install:migrations
|
14
|
-
|
15
|
-
Then run 'rake db:migrate' to create the 'mournful_settings_settings' table
|
16
|
-
|
17
10
|
== Usage
|
18
11
|
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
class MySetting < ActiveRecord::Base
|
13
|
+
|
14
|
+
acts_as_mournful_setting
|
22
15
|
|
23
|
-
class Setting < MournfulSettings::Setting
|
24
16
|
end
|
25
17
|
|
26
18
|
=== Fields
|
27
|
-
Each setting has five fields:
|
28
19
|
|
29
|
-
|
20
|
+
Each setting should have five fields:
|
30
21
|
|
31
|
-
[
|
22
|
+
[name] String: Identifies the setting. Used in 'for' (see below)
|
32
23
|
|
33
|
-
[
|
34
|
-
should be presented. For example, '1.23' with value_type 'number'
|
35
|
-
will be presented as numeric 1.23. If the value_type was 'text'
|
36
|
-
the value returned would be '1.23'.
|
24
|
+
[value] String: The value being stored.
|
37
25
|
|
38
|
-
[
|
26
|
+
[value_type] String: defines how that string should be presented. For example,
|
27
|
+
'1.23' with value_type 'number' will be presented as numeric 1.23.
|
28
|
+
If the value_type was 'text' the value returned would be '1.23'.
|
29
|
+
|
30
|
+
[description] String or Text: Information about the setting being stored
|
39
31
|
|
40
32
|
[encrypted] Boolean: If set to true, the value will be stored in an encrypted
|
41
33
|
format. Otherwise the value will be stored as plain text.
|
42
34
|
|
35
|
+
See db/migrate/001_create_settings.rb for an example migration.
|
36
|
+
|
37
|
+
=== Forcing encryption
|
38
|
+
|
39
|
+
If you wish to force all settings to be either encrypted or not, you can
|
40
|
+
overwrite the encrypted? method. For example, if you wanted all settings to
|
41
|
+
be encrypted:
|
42
|
+
|
43
|
+
def encrypted?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
If you use this option, you do not need an encrypted field in the database
|
48
|
+
|
43
49
|
=== Retrieving a setting
|
44
50
|
|
45
51
|
To use a stored setting, use the 'for' class method:
|
46
52
|
|
47
|
-
|
53
|
+
MySetting.create(:name => 'pi', :value => '3.14159', :value_type => 'number')
|
48
54
|
|
49
|
-
|
55
|
+
MySetting.for(:pi) --> 3.14159
|
50
56
|
|
51
|
-
In this example,
|
57
|
+
In this example, MySetting.for(:pi) will return nil if there is no MySetting
|
52
58
|
with a name of 'pi' in the database.
|
53
59
|
|
54
60
|
=== Supplying a default
|
@@ -56,18 +62,16 @@ with a name of 'pi' in the database.
|
|
56
62
|
If you wish an alternative value to be returned if no matching setting has been
|
57
63
|
defined, you can add a default to the for declaration.
|
58
64
|
|
59
|
-
|
65
|
+
MySetting.for(:pi, 3.14)
|
60
66
|
|
61
67
|
This will return 3.14 until a 'pi' setting has been created.
|
62
68
|
|
63
|
-
The
|
64
|
-
|
65
69
|
== Encryption
|
66
70
|
|
67
71
|
By default mournful settings are encrypted. You can choose not to encrypt a
|
68
72
|
setting, by setting :encrypted => false.
|
69
73
|
|
70
|
-
|
74
|
+
MySetting.create(
|
71
75
|
:name => 'pi',
|
72
76
|
:value => '3.14159',
|
73
77
|
:value_type => 'number',
|
@@ -80,12 +84,12 @@ Out of the box, encryption uses a blowfish cipher, and a generic key string.
|
|
80
84
|
|
81
85
|
If you wish to use your own encryption key, you can define the key like this:
|
82
86
|
|
83
|
-
|
87
|
+
MySetting::Cipher.key = 'your key'
|
84
88
|
|
85
89
|
Mournful settings uses Ruby's OpenSSL::Cipher. If you wish to change
|
86
90
|
the cipher from blowfish, you can alter it like this:
|
87
91
|
|
88
|
-
|
92
|
+
MySetting::Cipher.config = 'aes-128-cbc'
|
89
93
|
|
90
94
|
To see a list of the available options use:
|
91
95
|
|
@@ -107,7 +111,7 @@ config/application:
|
|
107
111
|
.....
|
108
112
|
|
109
113
|
config.before_initialize do
|
110
|
-
|
114
|
+
MySetting::Cipher.key = 'your key'
|
111
115
|
end
|
112
116
|
end
|
113
117
|
end
|
@@ -119,9 +123,9 @@ See: http://guides.rubyonrails.org/configuring.html#initialization-events
|
|
119
123
|
If you change the cipher configuration, existing encrypted settings will break.
|
120
124
|
Therefore, to make the change after you have started using encrypted settings,
|
121
125
|
you must decrypt your settings, make the change and then re-encrypt the settings
|
122
|
-
again. To ease this task, use the
|
126
|
+
again. To ease this task, use the MySetting.recrypt_all method:
|
123
127
|
|
124
|
-
|
128
|
+
MySetting.recrypt_all { MySetting::Cipher.key = 'your key' }
|
125
129
|
|
126
130
|
So the process would be:
|
127
131
|
|
@@ -130,6 +134,45 @@ So the process would be:
|
|
130
134
|
- Add/Update the configuration code in the app
|
131
135
|
- Start the server
|
132
136
|
|
137
|
+
== Add functionality by inheritance
|
138
|
+
|
139
|
+
The original design for mournful settings relied on the class in the hosting
|
140
|
+
app, inheriting its functionality from MournfulSettings::Setting. This
|
141
|
+
functionality is still supported.
|
142
|
+
|
143
|
+
For example
|
144
|
+
(/app/models/settings.rb)
|
145
|
+
|
146
|
+
class Setting < MournfulSettings::Setting
|
147
|
+
end
|
148
|
+
|
149
|
+
=== Database
|
150
|
+
|
151
|
+
When inheriting MournfulSettings::Setting, settings are stored in a database
|
152
|
+
table 'mournful_settings_settings'. This table can be configured via migrations.
|
153
|
+
To add mournful_settings migrations to the host app run this rake task:
|
154
|
+
|
155
|
+
rake mournful_settings:install:migrations
|
156
|
+
|
157
|
+
Then run 'rake db:migrate' to create the 'mournful_settings_settings' table.
|
158
|
+
|
159
|
+
=== Updating inherited Setting to use acts_as_mournful_setting
|
160
|
+
|
161
|
+
The class Setting above could be modified to work with acts_as_mournful_setting,
|
162
|
+
like this:
|
163
|
+
|
164
|
+
class Setting < ActiveRecord::Base
|
165
|
+
|
166
|
+
self.table_name = 'mournful_settings_settings'
|
167
|
+
|
168
|
+
acts_as_mournful_setting
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
This demonstrates the main advantage of using acts_as_mounful_settings, in that
|
173
|
+
you are not restricted as to the table name you wish to use, and it is easier
|
174
|
+
to extend the functionality of the setting class.
|
175
|
+
|
133
176
|
== Integration with ActiveAdmin
|
134
177
|
|
135
178
|
Mournful settings contains an ActiveAdmin register file, that allows settings to
|
@@ -137,11 +180,11 @@ be managed from within the parent app's active_admin space. Of course
|
|
137
180
|
ActiveAdmin needs to be installed and working in the parent rails application,
|
138
181
|
for this to work.
|
139
182
|
|
140
|
-
|
141
|
-
active_admin initializer in your
|
183
|
+
If your host class is Settings, you can use the Mournful settings' ActiveAdmin
|
184
|
+
register files by adding this to the active_admin initializer in your
|
185
|
+
application.
|
142
186
|
|
143
187
|
config.load_paths << MournfulSettings.active_admin_load_path
|
144
188
|
|
145
|
-
Alternatively,
|
146
|
-
|
147
|
-
|
189
|
+
Alternatively, use lib/active_admin/admin/setting.rb as a template for your
|
190
|
+
own register file.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'mournful_settings/setting_methods'
|
2
|
+
module ActiveRecord
|
3
|
+
module Acts
|
4
|
+
module MournfulSetting
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.send :extend, ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def acts_as_mournful_setting
|
12
|
+
include MournfulSettings::SettingMethods
|
13
|
+
extend MournfulSettings::SettingMethods::ClassMethods
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
ActiveRecord::Base.send(:include, ActiveRecord::Acts::MournfulSetting)
|
@@ -1,118 +1,9 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require_relative 'setting/cipher'
|
3
1
|
module MournfulSettings
|
4
2
|
class Setting < ActiveRecord::Base
|
5
3
|
|
6
4
|
self.table_name = 'mournful_settings_settings'
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
before_save :set_encrypted_true_unless_false
|
11
|
-
before_save :encrypt_value
|
12
|
-
|
13
|
-
validates :value_type, :presence => true, :inclusion => {:in => VALUE_TYPES}
|
14
|
-
validates :value, :presence => true
|
15
|
-
validates :name, :uniqueness => true, :presence => true
|
16
|
-
|
17
|
-
def self.value_types
|
18
|
-
VALUE_TYPES
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.for(name, default = nil)
|
22
|
-
setting = find_by_name(name)
|
23
|
-
setting ? setting.value : default
|
24
|
-
end
|
25
|
-
|
26
|
-
def value
|
27
|
-
if value_type.present?
|
28
|
-
parent_value = encrypted? ? decrypt(super) : super
|
29
|
-
|
30
|
-
case value_type.to_s
|
31
|
-
when 'number'
|
32
|
-
parent_value.to_f
|
33
|
-
when 'decimal'
|
34
|
-
BigDecimal.new(parent_value.to_s)
|
35
|
-
else
|
36
|
-
parent_value
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.recrypt_all &do_while_unencrypted
|
42
|
-
encrypted = where(:encrypted => true)
|
43
|
-
encrypted.each {|s| s.encrypted = false; s.save}
|
44
|
-
do_while_unencrypted.call if do_while_unencrypted
|
45
|
-
encrypted.each {|s| s.encrypted = true; s.save}
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
def encrypt(text)
|
50
|
-
add_separators Base64.encode64 Cipher.encrypt text.to_s
|
51
|
-
end
|
52
|
-
|
53
|
-
def decrypt(text)
|
54
|
-
if is_encrypted?(text)
|
55
|
-
Cipher.decrypt Base64.decode64 remove_separators text
|
56
|
-
else
|
57
|
-
text
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def is_encrypted?(text)
|
62
|
-
inside_separators_and_is_base64_encoded?(text)
|
63
|
-
end
|
64
|
-
|
65
|
-
def inside_separators_and_is_base64_encoded?(text)
|
66
|
-
return unless text.kind_of? String
|
67
|
-
bytes = text.bytes.to_a
|
68
|
-
return unless bytes[0] == separator_byte
|
69
|
-
return unless bytes[-1] == separator_byte
|
70
|
-
return unless bytes[-2] == last_byte_of_base_64_encoded_text
|
71
|
-
non_white_space_with_equal_sign_packing =~ text[1..-3]
|
72
|
-
end
|
73
|
-
|
74
|
-
def non_white_space_with_equal_sign_packing
|
75
|
-
/\S+=*/
|
76
|
-
end
|
77
|
-
|
78
|
-
def set_encrypted_true_unless_false
|
79
|
-
self.encrypted = true unless self.encrypted == false
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
def encrypt_value
|
84
|
-
if encrypted?
|
85
|
-
self.value = encrypt(self.value)
|
86
|
-
else
|
87
|
-
self.value = decrypt(self.value)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def add_separators(text)
|
92
|
-
[separator, text, separator].join
|
93
|
-
end
|
94
|
-
|
95
|
-
def remove_separators(text)
|
96
|
-
text.gsub(separator, "")
|
97
|
-
end
|
98
|
-
|
99
|
-
# Used to delimit encrypted values to make identification more reliable
|
100
|
-
def separator
|
101
|
-
separator_byte.chr
|
102
|
-
end
|
103
|
-
|
104
|
-
|
105
|
-
def separator_byte
|
106
|
-
31 # ASCII unit separator
|
107
|
-
end
|
108
|
-
|
109
|
-
def last_byte_of_base_64_encoded_text
|
110
|
-
line_feed_byte
|
111
|
-
end
|
112
|
-
|
113
|
-
def line_feed_byte
|
114
|
-
10
|
115
|
-
end
|
6
|
+
acts_as_mournful_setting
|
116
7
|
|
117
8
|
end
|
118
9
|
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require_relative 'setting_methods/cipher'
|
3
|
+
module MournfulSettings
|
4
|
+
module SettingMethods
|
5
|
+
|
6
|
+
VALUE_TYPES = ['text', 'number', 'decimal']
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.before_save :set_encrypted_true_unless_false
|
10
|
+
base.before_save :encrypt_value
|
11
|
+
|
12
|
+
base.validates :value_type, :presence => true, :inclusion => {:in => VALUE_TYPES}
|
13
|
+
base.validates :value, :presence => true
|
14
|
+
base.validates :name, :uniqueness => true, :presence => true
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def value_types
|
19
|
+
VALUE_TYPES
|
20
|
+
end
|
21
|
+
|
22
|
+
def for(name, default = nil)
|
23
|
+
setting = find_by_name(name)
|
24
|
+
setting ? setting.value : default
|
25
|
+
end
|
26
|
+
|
27
|
+
def recrypt_all &do_while_unencrypted
|
28
|
+
encrypted = where(:encrypted => true)
|
29
|
+
encrypted.each {|s| s.encrypted = false; s.save}
|
30
|
+
do_while_unencrypted.call if do_while_unencrypted
|
31
|
+
encrypted.each {|s| s.encrypted = true; s.save}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def value
|
36
|
+
if value_type.present?
|
37
|
+
parent_value = encrypted? ? decrypt(super) : super
|
38
|
+
|
39
|
+
case value_type.to_s
|
40
|
+
when 'number'
|
41
|
+
parent_value.to_f
|
42
|
+
when 'decimal'
|
43
|
+
BigDecimal.new(parent_value.to_s)
|
44
|
+
else
|
45
|
+
parent_value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def encrypt(text)
|
52
|
+
add_separators Base64.encode64 Cipher.encrypt text.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
def decrypt(text)
|
56
|
+
if is_encrypted?(text)
|
57
|
+
Cipher.decrypt Base64.decode64 remove_separators text
|
58
|
+
else
|
59
|
+
text
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def is_encrypted?(text)
|
64
|
+
inside_separators_and_is_base64_encoded?(text)
|
65
|
+
end
|
66
|
+
|
67
|
+
def inside_separators_and_is_base64_encoded?(text)
|
68
|
+
return unless text.kind_of? String
|
69
|
+
bytes = text.bytes.to_a
|
70
|
+
return unless bytes[0] == separator_byte
|
71
|
+
return unless bytes[-1] == separator_byte
|
72
|
+
return unless bytes[-2] == last_byte_of_base_64_encoded_text
|
73
|
+
non_white_space_with_equal_sign_packing =~ text[1..-3]
|
74
|
+
end
|
75
|
+
|
76
|
+
def non_white_space_with_equal_sign_packing
|
77
|
+
/\S+=*/
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_encrypted_true_unless_false
|
81
|
+
self.encrypted = true unless self.encrypted == false
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def encrypt_value
|
86
|
+
if encrypted?
|
87
|
+
self.value = encrypt(self.value)
|
88
|
+
else
|
89
|
+
self.value = decrypt(self.value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def add_separators(text)
|
94
|
+
[separator, text, separator].join
|
95
|
+
end
|
96
|
+
|
97
|
+
def remove_separators(text)
|
98
|
+
text.gsub(separator, "")
|
99
|
+
end
|
100
|
+
|
101
|
+
# Used to delimit encrypted values to make identification more reliable
|
102
|
+
def separator
|
103
|
+
separator_byte.chr
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def separator_byte
|
108
|
+
31 # ASCII unit separator
|
109
|
+
end
|
110
|
+
|
111
|
+
def last_byte_of_base_64_encoded_text
|
112
|
+
line_feed_byte
|
113
|
+
end
|
114
|
+
|
115
|
+
def line_feed_byte
|
116
|
+
10
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
@@ -1,14 +1,22 @@
|
|
1
1
|
module MournfulSettings
|
2
|
-
VERSION = "0.0
|
2
|
+
VERSION = "0.1.0"
|
3
3
|
end
|
4
4
|
|
5
5
|
# History
|
6
6
|
# =======
|
7
7
|
#
|
8
|
+
# 0.1.0: Acts As Mournful Setting
|
9
|
+
# -------------------------------
|
10
|
+
# Changes the way Mournful settings are used. Settings can now be defined via
|
11
|
+
# an acts_as_mournful_setting declaration rather than inheriting from
|
12
|
+
# MournfulSettings::Setting. Inheritance is still supported
|
13
|
+
#
|
14
|
+
#
|
8
15
|
# 0.0.6: Adds default option
|
9
16
|
# --------------------------
|
10
17
|
# Allows alternative to be set, that will be used until setting defined
|
11
18
|
#
|
19
|
+
#
|
12
20
|
# 0.0.5: Corrects gem description
|
13
21
|
# -------------------------------
|
14
22
|
# No functional change.
|
data/lib/mournful_settings.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_record'
|
2
|
-
require_relative 'mournful_settings/setting'
|
3
2
|
require_relative "mournful_settings/railtie" if defined?(Rails) # needed for rake tasks to be loaded into host app
|
3
|
+
require_relative 'active_record/acts/mournful_setting'
|
4
|
+
require_relative 'mournful_settings/setting'
|
4
5
|
|
5
6
|
module MournfulSettings
|
6
7
|
|
Binary file
|
data/test/dummy/lib/setting.rb
CHANGED
@@ -0,0 +1,155 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
require 'setting_actor'
|
3
|
+
|
4
|
+
class SettingActorTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@value = 'A secret'
|
8
|
+
SettingActor::Cipher.config = 'aes-128-cbc'
|
9
|
+
SettingActor::Cipher.key = 'something else'
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
SettingActor.delete_all
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_inheritence
|
17
|
+
assert_not_kind_of(MournfulSettings::Setting, text_setting)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_number_value
|
21
|
+
assert_kind_of(Float, number_setting.value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_text_value
|
25
|
+
assert_kind_of(String, text_setting.value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_decimal_value
|
29
|
+
assert_kind_of(BigDecimal, decimal_setting.value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_encrypted_value
|
33
|
+
assert_kind_of(String, encrypted_setting.reload.value)
|
34
|
+
assert_equal(@value, encrypted_setting.value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_encrypted_value_is_encrypted_in_database
|
38
|
+
database_value = database_value_for(encrypted_setting)
|
39
|
+
assert_not_equal(database_value, encrypted_setting.value)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_encrypted_with_different_value_types
|
43
|
+
{
|
44
|
+
'text' => 'this is a load of text',
|
45
|
+
'number' => 1.33333333,
|
46
|
+
'decimal' => 1.44
|
47
|
+
}.each do |value_type, value|
|
48
|
+
setting = SettingActor.create(:name => value_type, :value => value, :value_type => value_type)
|
49
|
+
assert_equal(value, setting.value)
|
50
|
+
assert_not_equal(database_value_for(setting), setting.value)
|
51
|
+
assert_not_equal(database_value_for(setting).to_s, setting.value.to_s)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_encrypting_an_existing_setting
|
56
|
+
value = number_setting.value
|
57
|
+
number_setting.encrypted = true
|
58
|
+
assert number_setting.save, "Should be able to save a setting after changing it to encrypted"
|
59
|
+
assert_equal(value, number_setting.value)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_unencrypting_an_encrypted_setting
|
63
|
+
encrypted_setting.encrypted = false
|
64
|
+
assert encrypted_setting.save, "Should be able to save a setting after changing it to unencrypted"
|
65
|
+
assert_equal(@value, encrypted_setting.value)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_valid_types
|
69
|
+
SettingActor::VALUE_TYPES.each do |valid_type|
|
70
|
+
number_setting.value_type = valid_type
|
71
|
+
assert(number_setting.valid?, "number_setting should be valid when value_type = #{valid_type}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_invalid_type
|
76
|
+
number_setting.value_type = 'invalid'
|
77
|
+
assert(number_setting.invalid?, "number_setting should be invalid")
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_for
|
81
|
+
[number_setting, text_setting, decimal_setting, encrypted_setting].each do |setting|
|
82
|
+
assert_equal(setting.value, SettingActor.for(setting.name.to_sym))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_for_when_no_matching_setting
|
87
|
+
assert_nil(SettingActor.for(:nothing), "Should return nil when setting doesn't exist")
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_for_with_default_provided
|
91
|
+
default = 'Something else'
|
92
|
+
assert_equal(default, SettingActor.for(:nothing, default))
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_setting_an_invalid_cipher_config
|
96
|
+
assert_raises RuntimeError do
|
97
|
+
SettingActor::Cipher.config = 'invalid'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_changing_cipher
|
102
|
+
cipher = 'bf-cbc'
|
103
|
+
assert_not_equal(cipher, SettingActor::Cipher.config)
|
104
|
+
test_encrypted_value
|
105
|
+
SettingActor::Cipher.config = cipher
|
106
|
+
assert_equal(cipher, SettingActor::Cipher.config)
|
107
|
+
assert_raise OpenSSL::Cipher::CipherError do
|
108
|
+
test_encrypted_value
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_changing_key
|
113
|
+
key = 'Some new key'
|
114
|
+
assert_not_equal(key, SettingActor::Cipher.key)
|
115
|
+
test_encrypted_value
|
116
|
+
SettingActor::Cipher.key = key
|
117
|
+
assert_equal(key, SettingActor::Cipher.key)
|
118
|
+
assert_raise OpenSSL::Cipher::CipherError do
|
119
|
+
test_encrypted_value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_recrypt_all
|
124
|
+
key = 'Some new key'
|
125
|
+
assert_not_equal(key, SettingActor::Cipher.key)
|
126
|
+
test_encrypted_value
|
127
|
+
SettingActor.recrypt_all { SettingActor::Cipher.key = key }
|
128
|
+
assert_equal(key, SettingActor::Cipher.key)
|
129
|
+
test_encrypted_value
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
def text_setting
|
134
|
+
@text_setting ||= SettingActor.create(:name => 'text_setting', :value => 'foo', :value_type => 'text', :encrypted => false)
|
135
|
+
end
|
136
|
+
|
137
|
+
def number_setting
|
138
|
+
@number_setting ||= SettingActor.create(:name => 'number_setting', :value => '1.33333333333333', :value_type => 'number', :encrypted => false)
|
139
|
+
end
|
140
|
+
|
141
|
+
def decimal_setting
|
142
|
+
@decimal_setting ||= SettingActor.create(:name => 'decimal_setting', :value => '4.55', :value_type => 'decimal', :encrypted => false)
|
143
|
+
end
|
144
|
+
|
145
|
+
def encrypted_setting
|
146
|
+
@encrypted_setting ||= SettingActor.create(:name => 'encrypted_setting', :value => @value, :value_type => 'text')
|
147
|
+
end
|
148
|
+
|
149
|
+
def database_value_for(setting)
|
150
|
+
sql = "SELECT value FROM mournful_settings_settings WHERE id = #{setting.id}"
|
151
|
+
SettingActor.connection.select_value(sql)
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mournful_settings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -51,9 +51,11 @@ executables: []
|
|
51
51
|
extensions: []
|
52
52
|
extra_rdoc_files: []
|
53
53
|
files:
|
54
|
+
- lib/active_record/acts/mournful_setting.rb
|
54
55
|
- lib/mournful_settings/version.rb
|
55
|
-
- lib/mournful_settings/setting/cipher.rb
|
56
56
|
- lib/mournful_settings/setting.rb
|
57
|
+
- lib/mournful_settings/setting_methods/cipher.rb
|
58
|
+
- lib/mournful_settings/setting_methods.rb
|
57
59
|
- lib/mournful_settings/railtie.rb
|
58
60
|
- lib/mournful_settings.rb
|
59
61
|
- lib/active_admin/admin/settings.rb
|
@@ -61,9 +63,11 @@ files:
|
|
61
63
|
- MIT-LICENSE
|
62
64
|
- Rakefile
|
63
65
|
- README.rdoc
|
66
|
+
- test/dummy/lib/setting_actor.rb
|
64
67
|
- test/dummy/lib/setting.rb
|
65
68
|
- test/dummy/db/development.sqlite3.db
|
66
69
|
- test/dummy/db/test.sqlite3.db
|
70
|
+
- test/dummy/test/setting_actor_test.rb
|
67
71
|
- test/dummy/test/setting_test.rb
|
68
72
|
- test/test_helper.rb
|
69
73
|
homepage: https://github.com/reggieb/mournful_settings
|
@@ -91,8 +95,10 @@ signing_key:
|
|
91
95
|
specification_version: 3
|
92
96
|
summary: Tool for adding encrypted settings to an app.
|
93
97
|
test_files:
|
98
|
+
- test/dummy/lib/setting_actor.rb
|
94
99
|
- test/dummy/lib/setting.rb
|
95
100
|
- test/dummy/db/development.sqlite3.db
|
96
101
|
- test/dummy/db/test.sqlite3.db
|
102
|
+
- test/dummy/test/setting_actor_test.rb
|
97
103
|
- test/dummy/test/setting_test.rb
|
98
104
|
- test/test_helper.rb
|