File tree Expand file tree Collapse file tree 6 files changed +65
-12
lines changed Expand file tree Collapse file tree 6 files changed +65
-12
lines changed Original file line number Diff line number Diff line change 8
8
9
9
module ActiveSupport
10
10
class EncryptedConfiguration < EncryptedFile
11
+ class InvalidContentError < RuntimeError
12
+ def initialize ( content_path )
13
+ super "Invalid YAML in '#{ content_path } '."
14
+ end
15
+
16
+ def message
17
+ cause . is_a? ( Psych ::SyntaxError ) ? "#{ super } \n \n #{ cause . message } " : super
18
+ end
19
+ end
20
+
11
21
delegate :[] , :fetch , to : :config
12
22
delegate_missing_to :options
13
23
@@ -23,10 +33,8 @@ def read
23
33
""
24
34
end
25
35
26
- def write ( contents )
27
- deserialize ( contents )
28
-
29
- super
36
+ def validate! # :nodoc:
37
+ deserialize ( read )
30
38
end
31
39
32
40
def config
@@ -48,9 +56,14 @@ def options
48
56
@options ||= ActiveSupport ::InheritableOptions . new ( deep_transform ( config ) )
49
57
end
50
58
51
- def deserialize ( config )
52
- doc = YAML . respond_to? ( :unsafe_load ) ? YAML . unsafe_load ( config ) : YAML . load ( config )
53
- doc . presence || { }
59
+ def deserialize ( content )
60
+ config = YAML . respond_to? ( :unsafe_load ) ?
61
+ YAML . unsafe_load ( content , filename : content_path ) :
62
+ YAML . load ( content , filename : content_path )
63
+
64
+ config . presence || { }
65
+ rescue Psych ::SyntaxError
66
+ raise InvalidContentError . new ( content_path )
54
67
end
55
68
end
56
69
end
Original file line number Diff line number Diff line change @@ -66,11 +66,19 @@ class EncryptedConfigurationTest < ActiveSupport::TestCase
66
66
assert_equal "things" , @credentials [ :new ]
67
67
end
68
68
69
- test "raise error when writing an invalid format value" do
70
- assert_raise ( Psych ::SyntaxError ) do
71
- @credentials . change do |config_file |
72
- config_file . write "login: *login\n username: dummy"
73
- end
69
+ test "raises helpful error when loading invalid content" do
70
+ @credentials . write ( "key: value\n bad" )
71
+
72
+ assert_raise ( ActiveSupport ::EncryptedConfiguration ::InvalidContentError ) do
73
+ @credentials . config
74
+ end
75
+ end
76
+
77
+ test "raises helpful error when validating invalid content" do
78
+ @credentials . write ( "key: value\n bad" )
79
+
80
+ assert_raise ( ActiveSupport ::EncryptedConfiguration ::InvalidContentError ) do
81
+ @credentials . validate!
74
82
end
75
83
end
76
84
Original file line number Diff line number Diff line change @@ -41,6 +41,7 @@ def edit
41
41
end
42
42
43
43
say "File encrypted and saved."
44
+ warn_if_credentials_are_invalid
44
45
rescue ActiveSupport ::MessageEncryptor ::InvalidMessage
45
46
say "Couldn't decrypt #{ content_path } . Perhaps you passed the wrong key?"
46
47
end
@@ -103,6 +104,14 @@ def change_credentials_in_system_editor
103
104
end
104
105
end
105
106
107
+ def warn_if_credentials_are_invalid
108
+ credentials . validate!
109
+ rescue ActiveSupport ::EncryptedConfiguration ::InvalidContentError => error
110
+ say "WARNING: #{ error . message } " , :red
111
+ say ""
112
+ say "Your application will not be able to load '#{ content_path } ' until the error has been fixed." , :red
113
+ end
114
+
106
115
def missing_credentials_message
107
116
if !credentials . key?
108
117
"Missing '#{ key_path } ' to decrypt credentials. See `bin/rails credentials:help`"
Original file line number Diff line number Diff line change @@ -32,6 +32,7 @@ def edit(*)
32
32
end
33
33
34
34
say "File encrypted and saved."
35
+ warn_if_encrypted_configuration_is_invalid
35
36
rescue ActiveSupport ::MessageEncryptor ::InvalidMessage
36
37
say "Couldn't decrypt #{ content_path } . Perhaps you passed the wrong key?"
37
38
end
@@ -71,6 +72,13 @@ def change_encrypted_configuration_in_system_editor
71
72
end
72
73
end
73
74
75
+ def warn_if_encrypted_configuration_is_invalid
76
+ encrypted_configuration . validate!
77
+ rescue ActiveSupport ::EncryptedConfiguration ::InvalidContentError => error
78
+ say "WARNING: #{ error . message } " , :red
79
+ say ""
80
+ say "Your application will not be able to load '#{ content_path } ' until the error has been fixed." , :red
81
+ end
74
82
75
83
def encryption_key_file_generator
76
84
require "rails/generators"
Original file line number Diff line number Diff line change @@ -142,6 +142,13 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
142
142
assert_match %r/provides_secret_key_base: true/ , run_edit_command
143
143
end
144
144
145
+ test "edit command preserves user's content even if it contains invalid YAML" do
146
+ write_invalid_yaml = %(ruby -e "File.write ARGV[0], 'foo: bar: bad'")
147
+
148
+ assert_match %r/WARNING: Invalid YAML/ , run_edit_command ( editor : write_invalid_yaml )
149
+ assert_match %r/foo: bar: bad/ , run_edit_command
150
+ end
151
+
145
152
146
153
test "show credentials" do
147
154
assert_match DEFAULT_CREDENTIALS_PATTERN , run_show_command
Original file line number Diff line number Diff line change @@ -82,6 +82,14 @@ class Rails::Command::EncryptedCommandTest < ActiveSupport::TestCase
82
82
assert_match ( /access_key_id: 123/ , run_edit_command ( key : "config/tokens.key" ) )
83
83
end
84
84
85
+ test "edit command preserves user's content even if it contains invalid YAML" do
86
+ write_invalid_yaml = %(ruby -e "File.write ARGV[0], 'foo: bar: bad'")
87
+
88
+ assert_match %r/WARNING: Invalid YAML/ , run_edit_command ( editor : write_invalid_yaml )
89
+ assert_match %r/foo: bar: bad/ , run_edit_command
90
+ end
91
+
92
+
85
93
test "show encrypted file with custom key" do
86
94
run_edit_command ( key : "config/tokens.key" )
87
95
You can’t perform that action at this time.
0 commit comments