gmail 0.5.0 → 0.6.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.
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