gmail 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +27 -27
  3. data/.rspec +1 -1
  4. data/.rubocop.yml +13 -13
  5. data/.rubocop_todo.yml +239 -239
  6. data/.travis.yml +19 -19
  7. data/CHANGELOG.md +145 -139
  8. data/Gemfile +3 -3
  9. data/LICENSE +21 -21
  10. data/README.md +355 -354
  11. data/Rakefile +46 -46
  12. data/gmail.gemspec +34 -34
  13. data/lib/gmail.rb +78 -78
  14. data/lib/gmail/client.rb +34 -34
  15. data/lib/gmail/client/base.rb +229 -229
  16. data/lib/gmail/client/plain.rb +24 -24
  17. data/lib/gmail/client/xoauth.rb +68 -68
  18. data/lib/gmail/client/xoauth2.rb +39 -39
  19. data/lib/gmail/imap_extensions.rb +159 -150
  20. data/lib/gmail/labels.rb +79 -79
  21. data/lib/gmail/mailbox.rb +175 -135
  22. data/lib/gmail/message.rb +207 -207
  23. data/lib/gmail/version.rb +3 -3
  24. data/spec/account.yml.example +1 -1
  25. data/spec/account.yml.obfus +2 -2
  26. data/spec/gmail/client/base_spec.rb +5 -5
  27. data/spec/gmail/client/plain_spec.rb +169 -168
  28. data/spec/gmail/client/xoauth2_spec.rb +186 -186
  29. data/spec/gmail/client/xoauth_spec.rb +5 -5
  30. data/spec/gmail/client_spec.rb +5 -5
  31. data/spec/gmail/imap_extensions_spec.rb +47 -12
  32. data/spec/gmail/labels_spec.rb +27 -18
  33. data/spec/gmail/mailbox_spec.rb +84 -47
  34. data/spec/gmail/message_spec.rb +181 -181
  35. data/spec/gmail_spec.rb +39 -39
  36. data/spec/recordings/gmail/_new_connects_with_client_and_give_it_context_when_block_given.yml +28 -28
  37. data/spec/recordings/gmail/_new_connects_with_gmail_service_and_return_valid_connection_object.yml +28 -28
  38. data/spec/recordings/gmail/_new_does_not_raise_error_when_couldn_t_connect_with_given_account.yml +13 -13
  39. data/spec/recordings/gmail/_new_raises_error_when_couldn_t_connect_with_given_account.yml +13 -13
  40. data/spec/recordings/gmail_client_plain/instance/_connection_automatically_logs_in_to_gmail_account_when_it_s_called.yml +42 -42
  41. data/spec/recordings/gmail_client_plain/instance/delivers_inline_composed_email.yml +42 -42
  42. data/spec/recordings/gmail_client_plain/instance/does_not_log_in_when_given_gmail_account_is_invalid.yml +13 -13
  43. data/spec/recordings/gmail_client_plain/instance/does_not_raise_error_even_though_gmail_account_is_invalid.yml +13 -13
  44. data/spec/recordings/gmail_client_plain/instance/labels/checks_if_there_is_given_label_defined.yml +196 -196
  45. data/spec/recordings/gmail_client_plain/instance/labels/creates_given_label.yml +151 -151
  46. data/spec/recordings/gmail_client_plain/instance/labels/removes_existing_label.yml +146 -146
  47. data/spec/recordings/gmail_client_plain/instance/labels/returns_list_of_all_available_labels.yml +113 -113
  48. data/spec/recordings/gmail_client_plain/instance/properly_logs_in_to_valid_gmail_account.yml +42 -42
  49. data/spec/recordings/gmail_client_plain/instance/properly_logs_out_from_gmail.yml +42 -42
  50. data/spec/recordings/gmail_client_plain/instance/properly_switches_to_given_mailbox.yml +109 -109
  51. data/spec/recordings/gmail_client_plain/instance/properly_switches_to_given_mailbox_using_block_style.yml +109 -109
  52. data/spec/recordings/gmail_client_plain/instance/raises_error_when_given_gmail_account_is_invalid_and_errors_enabled.yml +13 -13
  53. data/spec/recordings/gmail_client_xo_auth2/instance/does_not_log_in_when_given_gmail_account_is_invalid.yml +13 -13
  54. data/spec/recordings/gmail_client_xo_auth2/instance/labels/checks_if_there_is_given_label_defined.yml +27 -27
  55. data/spec/recordings/gmail_client_xo_auth2/instance/labels/creates_given_label.yml +39 -39
  56. data/spec/recordings/gmail_client_xo_auth2/instance/labels/removes_existing_label.yml +39 -39
  57. data/spec/recordings/gmail_client_xo_auth2/instance/labels/returns_list_of_all_available_labels.yml +27 -27
  58. data/spec/recordings/gmail_client_xo_auth2/instance/properly_logs_in_to_valid_gmail_account.yml +15 -15
  59. data/spec/recordings/gmail_client_xo_auth2/instance/properly_logs_out_from_gmail.yml +15 -15
  60. data/spec/recordings/gmail_client_xo_auth2/instance/properly_switches_to_given_mailbox.yml +40 -40
  61. data/spec/recordings/gmail_client_xo_auth2/instance/properly_switches_to_given_mailbox_using_block_style.yml +40 -40
  62. data/spec/recordings/gmail_client_xo_auth2/instance/raises_error_when_given_gmail_account_is_invalid_and_errors_enabled.yml +13 -13
  63. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/all/localizes_into_the_appropriate_label.yml +116 -116
  64. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/and_the_mailbox_does_not_exist/returns_the_mailbox_name_as_a_string.yml +110 -0
  65. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/drafts/localizes_into_the_appropriate_label.yml +116 -116
  66. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/flagged/localizes_into_the_appropriate_label.yml +116 -116
  67. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/important/localizes_into_the_appropriate_label.yml +116 -116
  68. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/inbox/localizes_into_the_appropriate_label.yml +42 -42
  69. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/junk/localizes_into_the_appropriate_label.yml +116 -116
  70. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/sent/localizes_into_the_appropriate_label.yml +116 -116
  71. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/trash/localizes_into_the_appropriate_label.yml +116 -116
  72. data/spec/recordings/gmail_mailbox/instance/counts_all_emails.yml +277 -277
  73. data/spec/recordings/gmail_mailbox/instance/finds_messages.yml +586 -586
  74. data/spec/recordings/gmail_mailbox/instance/waits_once.yml +136 -0
  75. data/spec/recordings/gmail_mailbox/instance/waits_repeatedly.yml +141 -0
  76. data/spec/recordings/gmail_mailbox/instance/waits_with_29-minute_re-issue.yml +136 -0
  77. data/spec/recordings/gmail_mailbox/instance/waits_with_an_unblocked_connection.yml +207 -0
  78. data/spec/recordings/gmail_mailbox/on_initialize/sets_client_and_name.yml +42 -42
  79. data/spec/recordings/gmail_mailbox/on_initialize/works_in_inbox_by_default.yml +42 -42
  80. data/spec/recordings/gmail_message/initialize/sets_prefetch_attrs.yml +578 -578
  81. data/spec/recordings/gmail_message/initialize/sets_uid_and_mailbox.yml +580 -580
  82. data/spec/recordings/gmail_message/instance_methods/deletes_itself.yml +637 -637
  83. data/spec/recordings/gmail_message/instance_methods/marks_itself_read.yml +682 -682
  84. data/spec/recordings/gmail_message/instance_methods/marks_itself_unread.yml +686 -686
  85. data/spec/recordings/gmail_message/instance_methods/moves_from_one_tag_to_other.yml +862 -862
  86. data/spec/recordings/gmail_message/instance_methods/removes_a_given_label.yml +776 -776
  87. data/spec/recordings/gmail_message/instance_methods/removes_a_given_label_with_old_method.yml +776 -776
  88. data/spec/recordings/gmail_message/instance_methods/sets_given_label.yml +690 -690
  89. data/spec/recordings/gmail_message/instance_methods/sets_given_label_with_old_method.yml +691 -691
  90. data/spec/spec_helper.rb +53 -53
  91. data/spec/support/imap_mock.rb +181 -129
  92. data/spec/support/obfuscation.rb +52 -52
  93. metadata +78 -5
@@ -1,53 +1,53 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
-
3
- require 'rubygems'
4
- require 'rspec'
5
- require 'yaml'
6
- require 'gmail'
7
-
8
- # require_support_files
9
- Dir[File.join(File.dirname(__FILE__), 'support', '*.rb')].each { |f| require f }
10
-
11
- RSpec.configure do |config|
12
- Spec::ImapMock.configure_rspec!(config)
13
- end
14
-
15
- def within_gmail(&block)
16
- Gmail.connect!(*TEST_ACCOUNT) do |gmail|
17
- yield(gmail)
18
- end
19
- end
20
-
21
- def mock_client(&block)
22
- client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
23
- client.connect
24
-
25
- if block_given?
26
- client.login
27
- yield client
28
- client.logout
29
- end
30
-
31
- client
32
- end
33
-
34
- def mock_mailbox(box = "INBOX", &block)
35
- within_gmail do |gmail|
36
- mailbox = gmail.mailbox(box)
37
- yield(mailbox) if block_given?
38
- mailbox
39
- end
40
- end
41
-
42
- # TODO: move this to it's own dir; get rid of global variable
43
- # Run test by creating your own test account with credentials in account.yml
44
- # Otherwise default credentials from an obfuscated file are used.
45
- clear_file = File.join(File.dirname(__FILE__), 'account.yml')
46
- obfus_file = File.join(File.dirname(__FILE__), 'account.yml.obfus')
47
- if File.exist?(clear_file)
48
- TEST_ACCOUNT = YAML.load_file(clear_file)
49
- elsif File.exist?(obfus_file)
50
- TEST_ACCOUNT = Spec::Obfuscation.decrypt_file(obfus_file)
51
- else
52
- raise 'account.yml file not found'
53
- end
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'rubygems'
4
+ require 'rspec'
5
+ require 'yaml'
6
+ require 'gmail'
7
+
8
+ # require_support_files
9
+ Dir[File.join(File.dirname(__FILE__), 'support', '*.rb')].each { |f| require f }
10
+
11
+ RSpec.configure do |config|
12
+ Spec::ImapMock.configure_rspec!(config)
13
+ end
14
+
15
+ def within_gmail(&block)
16
+ Gmail.connect!(*TEST_ACCOUNT) do |gmail|
17
+ yield(gmail)
18
+ end
19
+ end
20
+
21
+ def mock_client(&block)
22
+ client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
23
+ client.connect
24
+
25
+ if block_given?
26
+ client.login
27
+ yield client
28
+ client.logout
29
+ end
30
+
31
+ client
32
+ end
33
+
34
+ def mock_mailbox(box = "INBOX", &block)
35
+ within_gmail do |gmail|
36
+ mailbox = gmail.mailbox(box)
37
+ yield(mailbox) if block_given?
38
+ mailbox
39
+ end
40
+ end
41
+
42
+ # TODO: move this to it's own dir; get rid of global variable
43
+ # Run test by creating your own test account with credentials in account.yml
44
+ # Otherwise default credentials from an obfuscated file are used.
45
+ clear_file = File.join(File.dirname(__FILE__), 'account.yml')
46
+ obfus_file = File.join(File.dirname(__FILE__), 'account.yml.obfus')
47
+ if File.exist?(clear_file)
48
+ TEST_ACCOUNT = YAML.load_file(clear_file)
49
+ elsif File.exist?(obfus_file)
50
+ TEST_ACCOUNT = Spec::Obfuscation.decrypt_file(obfus_file)
51
+ else
52
+ raise 'account.yml file not found'
53
+ end
@@ -1,129 +1,181 @@
1
- module Net
2
- class IMAP
3
- class << self
4
- def recordings=(value)
5
- @replaying = !value.nil?
6
- @recordings = value
7
- end
8
-
9
- def recordings
10
- @recordings ||= {}
11
- end
12
-
13
- def replaying?
14
- @replaying
15
- end
16
- end
17
-
18
- private
19
-
20
- alias_method :_send_command, :send_command
21
-
22
- def self.force_utf8(data)
23
- case data.class.to_s
24
- when /String/
25
- data.force_encoding('utf-8')
26
- when /Hash/
27
- data.each { |k, v| data[k] = force_utf8(v) }
28
- when /Array/
29
- data.map { |s| force_utf8(s) }
30
- end
31
- end
32
-
33
- def send_command(cmd, *args, &block)
34
- # In Ruby 1.9.x, strings default to binary which causes the digest to be
35
- # different.
36
- clean_args = args.dup.each do |s|
37
- Net::IMAP.force_utf8(s)
38
- end
39
-
40
- yaml_dump = YAML.dump([cmd] + clean_args)
41
-
42
- if RUBY_VERSION =~ /^(1.9|2.0)/
43
- # From 1.9 to 2.0 to 2.1, the way YAML encodes special characters changed.
44
- # Here's what each returns for: YAML.dump(["", "%"])
45
- # 1.9.x: "---\n- ''\n- ! '%'\n"
46
- # 2.0.x: "---\n- ''\n- '%'\n"
47
- # 2.1.x: "---\n- ''\n- \"%\"\n"
48
- # The `gsub` here converts the older format into the 2.1.x.
49
- yaml_dump.gsub!(/(?:! )?'(.+)'/, '"\1"')
50
-
51
- # In 1.9 and 2.0 strings starting with `+` or `-` are not escaped in quotes, but
52
- # they are in 2.1+. This addresses that.
53
- yaml_dump.gsub!(/ ([+-](?:X-GM-\w+|FLAGS))/, ' "\1"')
54
-
55
- # In 1.9 and 2.0 strings starting with `\` are not escaped in quotes, but
56
- # they are in 2.1+. This addresses that. Yes we need all those backslashes :|
57
- yaml_dump.gsub!(/ \\(\w+)/, ' "\\\\\\\\\1"')
58
- end
59
-
60
- digest = "#{cmd}-#{Digest::MD5.hexdigest(yaml_dump)}"
61
-
62
- if Net::IMAP.replaying?
63
- recordings = Net::IMAP.recordings[digest] || []
64
- if recordings.empty?
65
- # Be lenient if LOGOUT is called but wasn't explicitly recorded. This
66
- # comes up often when called from `at_exit`.
67
- cmd == 'LOGOUT' ? return : raise('Could not find recording')
68
- end
69
-
70
- action, response, @responses = recordings.shift
71
- else
72
- action = :return
73
- begin
74
- response = _send_command(cmd, *args, &block)
75
- rescue => e
76
- action = :raise
77
- response = e
78
- end
79
-
80
- # @responses (the third argument here) contains untagged responses captured
81
- # via the Net::IMAP#record_response method.
82
- Net::IMAP.recordings[digest] ||= []
83
- Net::IMAP.recordings[digest] << [action, response.dup, @responses ? @responses.dup : nil]
84
- end
85
-
86
- raise(response) if action == :raise
87
-
88
- response
89
- end
90
- end
91
- end
92
-
93
- module Spec
94
- module ImapMock
95
- # Configures RSpec with an around(:each) block to use IMAP mocks
96
- def self.configure_rspec!(config)
97
- config.around(:each) do |example|
98
- Spec::ImapMock.run_rspec_example(example)
99
- end
100
- end
101
-
102
- # Run an RSpec example using IMAP mocks
103
- def self.run_rspec_example(example)
104
- # The path is determined by the rspec `describe`s and `context`s
105
- mock_path = example.example_group.to_s
106
- .gsub(/RSpec::ExampleGroups::/, '')
107
- .gsub(/(\w)([A-Z])/, '\1_\2')
108
- .gsub(/::/, '/')
109
- .downcase
110
-
111
- # The name is determined by the description of the example.
112
- mock_name = example.description.gsub(/[^\w\-\/]+/, '_').downcase
113
-
114
- filename = File.join('spec/recordings/', mock_path, "#{mock_name}.yml")
115
-
116
- # If we've already recorded this spec load the recordings
117
- Net::IMAP.recordings = File.exist?(filename) ? YAML.load_file(filename) : nil
118
-
119
- example.run
120
-
121
- # If we haven't yet recorded the spec and there were some recordings,
122
- # write them to a file.
123
- unless File.exist?(filename) or Net::IMAP.recordings.empty?
124
- FileUtils.mkdir_p(File.dirname(filename))
125
- File.open(filename, 'w') { |f| YAML.dump(Net::IMAP.recordings, f) }
126
- end
127
- end
128
- end
129
- end
1
+ module Net
2
+ class IMAP
3
+ class << self
4
+ def recordings=(value)
5
+ @replaying = !value.nil?
6
+ @recordings = value
7
+ end
8
+
9
+ def recordings
10
+ @recordings ||= {}
11
+ end
12
+
13
+ def replaying?
14
+ @replaying
15
+ end
16
+ end
17
+
18
+ alias_method :_idle, :idle
19
+ alias_method :_idle_done, :idle_done
20
+
21
+ def idle(&response_handler)
22
+ if Net::IMAP.replaying?
23
+ @idle_done_cond = new_cond
24
+ @idle_done = false
25
+ end
26
+
27
+ response = mock_command(:_idle, 'IDLE', &response_handler)
28
+
29
+ if Net::IMAP.replaying?
30
+ synchronize do
31
+ unless @idle_done
32
+ @idle_done_cond.wait(0.1)
33
+ raise('The IDLE has not done') unless @idle_done
34
+ end
35
+ @idle_done_cond = nil
36
+ end
37
+ end
38
+
39
+ response
40
+ end
41
+
42
+ def idle_done
43
+ if Net::IMAP.replaying?
44
+ synchronize do
45
+ if @idle_done_cond.nil?
46
+ raise Net::IMAP::Error, 'not during IDLE'
47
+ end
48
+ @idle_done = true
49
+ idle_done_cond.signal
50
+ end
51
+ else
52
+ _idle_done
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ alias_method :_send_command, :send_command
59
+
60
+ def self.force_utf8(data)
61
+ case data.class.to_s
62
+ when /String/
63
+ data.force_encoding('utf-8')
64
+ when /Hash/
65
+ data.each { |k, v| data[k] = force_utf8(v) }
66
+ when /Array/
67
+ data.map { |s| force_utf8(s) }
68
+ end
69
+ end
70
+
71
+ def send_command(cmd, *args, &block)
72
+ mock_command(:_send_command, cmd, *args, &block)
73
+ end
74
+
75
+ def mock_command(method, cmd, *args, &block)
76
+ # In Ruby 1.9.x, strings default to binary which causes the digest to be
77
+ # different.
78
+ clean_args = args.dup.each do |s|
79
+ Net::IMAP.force_utf8(s)
80
+ end
81
+
82
+ yaml_dump = YAML.dump([cmd] + clean_args)
83
+
84
+ if RUBY_VERSION =~ /^(1.9|2.0)/
85
+ # From 1.9 to 2.0 to 2.1, the way YAML encodes special characters changed.
86
+ # Here's what each returns for: YAML.dump(["", "%"])
87
+ # 1.9.x: "---\n- ''\n- ! '%'\n"
88
+ # 2.0.x: "---\n- ''\n- '%'\n"
89
+ # 2.1.x: "---\n- ''\n- \"%\"\n"
90
+ # The `gsub` here converts the older format into the 2.1.x.
91
+ yaml_dump.gsub!(/(?:! )?'(.+)'/, '"\1"')
92
+
93
+ # In 1.9 and 2.0 strings starting with `+` or `-` are not escaped in quotes, but
94
+ # they are in 2.1+. This addresses that.
95
+ yaml_dump.gsub!(/ ([+-](?:X-GM-\w+|FLAGS))/, ' "\1"')
96
+
97
+ # In 1.9 and 2.0 strings starting with `\` are not escaped in quotes, but
98
+ # they are in 2.1+. This addresses that. Yes we need all those backslashes :|
99
+ yaml_dump.gsub!(/ \\(\w+)/, ' "\\\\\\\\\1"')
100
+ end
101
+
102
+ digest = "#{cmd}-#{Digest::MD5.hexdigest(yaml_dump)}"
103
+
104
+ if Net::IMAP.replaying?
105
+ recordings = Net::IMAP.recordings[digest] || []
106
+ if recordings.empty?
107
+ # Be lenient if LOGOUT is called but wasn't explicitly recorded. This
108
+ # comes up often when called from `at_exit`.
109
+ cmd == 'LOGOUT' ? return : raise('Could not find recording')
110
+ end
111
+
112
+ action, response, @responses, all_responses = recordings.shift
113
+
114
+ if block && all_responses
115
+ all_responses.each do |resp|
116
+ block.call(resp)
117
+ end
118
+ end
119
+ else
120
+ action = :return
121
+ all_responses = []
122
+ begin
123
+ response = send(method, cmd, *args) do |resp|
124
+ all_responses << resp
125
+ block.call(resp)
126
+ end
127
+ rescue => e
128
+ action = :raise
129
+ response = e
130
+ end
131
+
132
+ # @responses (the third argument here) contains untagged responses captured
133
+ # via the Net::IMAP#record_response method.
134
+ Net::IMAP.recordings[digest] ||= []
135
+ Net::IMAP.recordings[digest] << [action, response.dup, @responses ? @responses.dup : nil, all_responses]
136
+ end
137
+
138
+ raise(response) if action == :raise
139
+
140
+ response
141
+ end
142
+ end
143
+ end
144
+
145
+ module Spec
146
+ module ImapMock
147
+ # Configures RSpec with an around(:each) block to use IMAP mocks
148
+ def self.configure_rspec!(config)
149
+ config.around(:each) do |example|
150
+ Spec::ImapMock.run_rspec_example(example)
151
+ end
152
+ end
153
+
154
+ # Run an RSpec example using IMAP mocks
155
+ def self.run_rspec_example(example)
156
+ # The path is determined by the rspec `describe`s and `context`s
157
+ mock_path = example.example_group.to_s
158
+ .gsub(/RSpec::ExampleGroups::/, '')
159
+ .gsub(/(\w)([A-Z])/, '\1_\2')
160
+ .gsub(/::/, '/')
161
+ .downcase
162
+
163
+ # The name is determined by the description of the example.
164
+ mock_name = example.description.gsub(/[^\w\-\/]+/, '_').downcase
165
+
166
+ filename = File.join('spec/recordings/', mock_path, "#{mock_name}.yml")
167
+
168
+ # If we've already recorded this spec load the recordings
169
+ Net::IMAP.recordings = File.exist?(filename) ? YAML.load_file(filename) : nil
170
+
171
+ example.run
172
+
173
+ # If we haven't yet recorded the spec and there were some recordings,
174
+ # write them to a file.
175
+ unless File.exist?(filename) or Net::IMAP.recordings.empty?
176
+ FileUtils.mkdir_p(File.dirname(filename))
177
+ File.open(filename, 'w') { |f| YAML.dump(Net::IMAP.recordings, f) }
178
+ end
179
+ end
180
+ end
181
+ end
@@ -1,52 +1,52 @@
1
- require 'base64'
2
- require 'yaml'
3
-
4
- # Lightweight obfuscation wrapper used to obfuscate account.yml file.
5
- #
6
- # CAUTION; this is not intended to be a robust security mechanism. It is simple
7
- # obfuscation (security through obscurity). There's no strong reason why we couldn't
8
- # store the credentials in clear text, but just taking an extra step to prevent trouble.
9
-
10
- module Spec
11
- module Obfuscation
12
- def encrypt(data)
13
- rot13(Base64.encode64(data))
14
- end
15
-
16
- def decrypt(data)
17
- Base64.decode64(rot13(data))
18
- end
19
-
20
- def rot13(data)
21
- data.tr!("A-Za-z", "N-ZA-Mn-za-m")
22
- end
23
-
24
- def encrypt_file(file)
25
- data = read_if_exist!(file)
26
- begin
27
- File.open("#{file}.obfus", 'w') { |file| file.write(encrypt(data)) }
28
- rescue Exception => e
29
- raise "Unable to encrypt #{file}"
30
- end
31
- end
32
-
33
- def decrypt_file(file)
34
- data = read_if_exist!(file)
35
- begin
36
- return ::YAML::load(decrypt(data))
37
- rescue Exception => e
38
- raise "Unable to decrypt #{file}"
39
- end
40
- end
41
-
42
- def read_if_exist!(file)
43
- if File.exist?(file)
44
- IO.read(file)
45
- else
46
- raise "File not found #{file}"
47
- end
48
- end
49
-
50
- extend self
51
- end
52
- end
1
+ require 'base64'
2
+ require 'yaml'
3
+
4
+ # Lightweight obfuscation wrapper used to obfuscate account.yml file.
5
+ #
6
+ # CAUTION; this is not intended to be a robust security mechanism. It is simple
7
+ # obfuscation (security through obscurity). There's no strong reason why we couldn't
8
+ # store the credentials in clear text, but just taking an extra step to prevent trouble.
9
+
10
+ module Spec
11
+ module Obfuscation
12
+ def encrypt(data)
13
+ rot13(Base64.encode64(data))
14
+ end
15
+
16
+ def decrypt(data)
17
+ Base64.decode64(rot13(data))
18
+ end
19
+
20
+ def rot13(data)
21
+ data.tr!("A-Za-z", "N-ZA-Mn-za-m")
22
+ end
23
+
24
+ def encrypt_file(file)
25
+ data = read_if_exist!(file)
26
+ begin
27
+ File.open("#{file}.obfus", 'w') { |file| file.write(encrypt(data)) }
28
+ rescue Exception => e
29
+ raise "Unable to encrypt #{file}"
30
+ end
31
+ end
32
+
33
+ def decrypt_file(file)
34
+ data = read_if_exist!(file)
35
+ begin
36
+ return ::YAML::load(decrypt(data))
37
+ rescue Exception => e
38
+ raise "Unable to decrypt #{file}"
39
+ end
40
+ end
41
+
42
+ def read_if_exist!(file)
43
+ if File.exist?(file)
44
+ IO.read(file)
45
+ else
46
+ raise "File not found #{file}"
47
+ end
48
+ end
49
+
50
+ extend self
51
+ end
52
+ end