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