4me-sdk 1.1.4 → 1.2.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.
@@ -59,6 +59,11 @@ module Sdk4me
59
59
  end
60
60
  alias_method :success?, :valid?
61
61
 
62
+ # +true+ in case of a HTTP 5xx error
63
+ def failure?
64
+ !success? && (@response.code.to_s.blank? || @response.code.to_s =~ /5\d\d/)
65
+ end
66
+
62
67
  # retrieve a value from the resource
63
68
  # if the JSON value is an Array a array with the value for each resource will be given
64
69
  # @param keys: a single key or a key-path separated by comma
@@ -111,6 +116,10 @@ module Sdk4me
111
116
  !!(@response.code.to_s == '429' || (message && message =~ /Too Many Requests/))
112
117
  end
113
118
 
119
+ def retry_after
120
+ @current_page ||= @response.header['Retry-After'].to_i
121
+ end
122
+
114
123
  def to_s
115
124
  valid? ? json.to_s : message
116
125
  end
@@ -1,5 +1,5 @@
1
1
  module Sdk4me
2
2
  class Client
3
- VERSION = '1.1.4'
3
+ VERSION = '1.2.0'
4
4
  end
5
5
  end
@@ -2,177 +2,262 @@ require 'spec_helper'
2
2
 
3
3
  describe Sdk4me::Attachments do
4
4
 
5
- before(:each) do
6
- @client = Sdk4me::Client.new(api_token: 'secret', max_retry_time: -1)
7
- @attachments = Sdk4me::Attachments.new(@client)
5
+ def attachments(authentication)
6
+ (@attachments ||= {})[authentication] ||= begin
7
+ client = if authentication == :api_token
8
+ Sdk4me::Client.new(api_token: 'secret', max_retry_time: -1)
9
+ else
10
+ Sdk4me::Client.new(access_token: 'secret', max_retry_time: -1)
11
+ end
12
+ Sdk4me::Attachments.new(client)
13
+ end
8
14
  end
9
15
 
10
- context 'upload_attachments!' do
11
- it 'should not do anything when no :attachments are present' do
12
- expect(@attachments.upload_attachments!('/requests', {status: :in_progress})).to be_nil
16
+ def credentials(authentication)
17
+ if authentication == :api_token
18
+ { basic_auth: ['secret', 'x'] }
19
+ else
20
+ { headers: {'Authorization' => 'Bearer secret'} }
13
21
  end
22
+ end
14
23
 
15
- it 'should not do anything when :attachments is nil' do
16
- expect(@attachments.upload_attachments!('/requests', {attachments: nil})).to be_nil
17
- end
24
+ [:api_token, :access_token].each do |authentication|
18
25
 
19
- it 'should not do anything when :attachments is empty' do
20
- expect(@attachments.upload_attachments!('/requests', {attachments: []})).to be_nil
21
- expect(@attachments.upload_attachments!('/requests', {attachments: [nil]})).to be_nil
22
- end
26
+ context "#{authentication} - " do
27
+ context 'upload_attachments!' do
28
+ context 'normal' do
29
+ it 'should not do anything when no :attachments are present' do
30
+ expect(attachments(authentication).upload_attachments!('/requests', {status: :in_progress})).to be_nil
31
+ end
23
32
 
24
- it 'should show a error if no attachment may be uploaded' do
25
- stub_request(:get, 'https://api.4me.com/v1/sites/1?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {name: 'site 1'}.to_json)
26
- expect_log('Attachments not allowed for /sites/1', :error)
27
- expect(@attachments.upload_attachments!('/sites/1', {attachments: ['file1.png']})).to be_nil
28
- end
33
+ it 'should not do anything when :attachments is nil' do
34
+ expect(attachments(authentication).upload_attachments!('/requests', {attachments: nil})).to be_nil
35
+ end
29
36
 
30
- it 'should raise an exception if no attachment may be uploaded' do
31
- stub_request(:get, 'https://api.4me.com/v1/sites/1?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {name: 'site 1'}.to_json)
32
- message = 'Attachments not allowed for /sites/1'
33
- expect{ @attachments.upload_attachments!('/sites/1', {attachments: ['file1.png'], attachments_exception: true}) }.to raise_error(::Sdk4me::UploadFailed, message)
34
- end
37
+ it 'should not do anything when :attachments is empty' do
38
+ expect(attachments(authentication).upload_attachments!('/requests', {attachments: []})).to be_nil
39
+ expect(attachments(authentication).upload_attachments!('/requests', {attachments: [nil]})).to be_nil
40
+ end
35
41
 
36
- it 'should add /new to the path for new records' do
37
- stub_request(:get, 'https://api.4me.com/v1/sites/new?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {missing: 'storage'}.to_json)
38
- expect_log('Attachments not allowed for /sites', :error)
39
- expect(@attachments.upload_attachments!('/sites', {attachments: ['file1.png']})).to be_nil
40
- end
42
+ it 'should show a error if no attachment may be uploaded' do
43
+ stub_request(:get, 'https://api.4me.com/v1/sites/1?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {name: 'site 1'}.to_json)
44
+ expect_log('Attachments not allowed for /sites/1', :error)
45
+ expect(attachments(authentication).upload_attachments!('/sites/1', {attachments: ['file1.png']})).to be_nil
46
+ end
41
47
 
42
- [ [:requests, :note],
43
- [:problems, :note],
44
- [:contracts, :remarks],
45
- [:cis, :remarks],
46
- [:flsas, :remarks],
47
- [:slas, :remarks],
48
- [:service_instances, :remarks],
49
- [:service_offerings, :summary],
50
- [:any_other_model, :note]].each do |model, attribute|
51
-
52
- it "should replace :attachments with :#{attribute}_attachments after upload at /#{model}" do
53
- stub_request(:get, "https://api.4me.com/v1/#{model}/new?attachment_upload_token=true").with(basic_auth: ['secret', 'x']).to_return(body: {storage_upload: 'conf'}.to_json)
54
- expect(@attachments).to receive(:upload_attachment).with('conf', 'file1.png', false).ordered{ 'uploaded file1.png' }
55
- expect(@attachments).to receive(:upload_attachment).with('conf', 'file2.zip', false).ordered{ 'uploaded file2.zip' }
56
- data = {leave: 'me alone', attachments: %w(file1.png file2.zip)}
57
- @attachments.upload_attachments!("/#{model}", data)
58
- expect(data[:attachments]).to be_nil
59
- expect(data[:leave]).to eq('me alone')
60
- expect(data[:"#{attribute}_attachments"]).to eq(['uploaded file1.png', 'uploaded file2.zip'].to_json)
61
- end
62
- end
48
+ it 'should raise an exception if no attachment may be uploaded' do
49
+ stub_request(:get, 'https://api.4me.com/v1/sites/1?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {name: 'site 1'}.to_json)
50
+ message = 'Attachments not allowed for /sites/1'
51
+ expect{ attachments(authentication).upload_attachments!('/sites/1', {attachments: ['file1.png'], attachments_exception: true}) }.to raise_error(::Sdk4me::UploadFailed, message)
52
+ end
63
53
 
64
- it 'should set raise_exception flag to true when :attachments_exception is set' do
65
- stub_request(:get, 'https://api.4me.com/v1/requests/new?attachment_upload_token=true').with(basic_auth: ['secret', 'x']).to_return(body: {storage_upload: 'conf'}.to_json)
66
- expect(@attachments).to receive(:upload_attachment).with('conf', 'file1.png', true).ordered{ 'uploaded file1.png' }
67
- data = {leave: 'me alone', attachments: 'file1.png', attachments_exception: true}
68
- @attachments.upload_attachments!('/requests', data)
69
- expect(data[:attachments]).to be_nil
70
- expect(data[:attachments_exception]).to be_nil
71
- expect(data[:leave]).to eq('me alone')
72
- expect(data[:note_attachments]).to eq(['uploaded file1.png'].to_json)
73
- end
74
- end
54
+ it 'should add /new to the path for new records' do
55
+ stub_request(:get, 'https://api.4me.com/v1/sites/new?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {missing: 'storage'}.to_json)
56
+ expect_log('Attachments not allowed for /sites', :error)
57
+ expect(attachments(authentication).upload_attachments!('/sites', {attachments: ['file1.png']})).to be_nil
58
+ end
75
59
 
76
- context 'upload_attachment' do
60
+ [ [:requests, :note],
61
+ [:problems, :note],
62
+ [:contracts, :remarks],
63
+ [:cis, :remarks],
64
+ [:flsas, :remarks],
65
+ [:slas, :remarks],
66
+ [:service_instances, :remarks],
67
+ [:service_offerings, :summary],
68
+ [:any_other_model, :note]].each do |model, attribute|
77
69
 
78
- it 'should log an exception when the file could not be found' do
79
- expect_log('Attachment upload failed: file does not exist: unknown_file', :error)
80
- expect(@attachments.send(:upload_attachment, nil, 'unknown_file', false)).to be_nil
81
- end
70
+ it "should replace :attachments with :#{attribute}_attachments after upload at /#{model}" do
71
+ stub_request(:get, "https://api.4me.com/v1/#{model}/new?attachment_upload_token=true").with(credentials(authentication)).to_return(body: {storage_upload: 'conf'}.to_json)
72
+ expect(attachments(authentication)).to receive(:upload_attachment).with('conf', 'file1.png', false).ordered{ 'uploaded file1.png' }
73
+ expect(attachments(authentication)).to receive(:upload_attachment).with('conf', 'file2.zip', false).ordered{ 'uploaded file2.zip' }
74
+ data = {leave: 'me alone', attachments: %w(file1.png file2.zip)}
75
+ attachments(authentication).upload_attachments!("/#{model}", data)
76
+ expect(data[:attachments]).to be_nil
77
+ expect(data[:leave]).to eq('me alone')
78
+ expect(data[:"#{attribute}_attachments"]).to eq(['uploaded file1.png', 'uploaded file2.zip'].to_json)
79
+ end
80
+ end
82
81
 
83
- it 'should raise an exception when the file could not be found' do
84
- message = 'Attachment upload failed: file does not exist: unknown_file'
85
- expect{ @attachments.send(:upload_attachment, nil, 'unknown_file', true) }.to raise_error(::Sdk4me::UploadFailed, message)
86
- end
82
+ it 'should set raise_exception flag to true when :attachments_exception is set' do
83
+ stub_request(:get, 'https://api.4me.com/v1/requests/new?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {storage_upload: 'conf'}.to_json)
84
+ expect(attachments(authentication)).to receive(:upload_attachment).with('conf', 'file1.png', true).ordered{ 'uploaded file1.png' }
85
+ data = {leave: 'me alone', attachments: 'file1.png', attachments_exception: true}
86
+ attachments(authentication).upload_attachments!('/requests', data)
87
+ expect(data[:attachments]).to be_nil
88
+ expect(data[:attachments_exception]).to be_nil
89
+ expect(data[:leave]).to eq('me alone')
90
+ expect(data[:note_attachments]).to eq(['uploaded file1.png'].to_json)
91
+ end
92
+ end
87
93
 
88
- context 'aws' do
89
- before(:each) do
90
- @aws_conf = {
91
- provider: 'aws',
92
- upload_uri: 'https://itrp.s3.amazonaws.com/',
93
- access_key: 'AKIA6RYQ',
94
- success_url: 'https://mycompany.4me.com/s3_success?sig=99e82e8a046',
95
- policy: 'eydlgIH0=',
96
- signature: 'nbhdec4k=',
97
- upload_path: 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/'
98
- }
99
- @key_template = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}'
100
- @key = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/upload.txt'
101
-
102
- @multi_part_body = "--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\napplication/octet-stream\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"x-amz-server-side-encryption\"\r\n\r\nAES256\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\nattachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\nAKIA6RYQ\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"acl\"\r\n\r\nprivate\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"signature\"\r\n\r\nnbhdec4k=\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"policy\"\r\n\r\neydlgIH0=\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"file\"; filename=\"#{@fixture_dir}/upload.txt\"\r\nContent-Type: text/plain\r\n\r\ncontent\r\n--0123456789ABLEWASIEREISAWELBA9876543210--"
103
- @multi_part_headers = {'Accept'=>'*/*', 'Content-Type'=>'multipart/form-data; boundary=0123456789ABLEWASIEREISAWELBA9876543210', 'User-Agent'=>'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6'}
104
- end
94
+ context 'inline' do
95
+ it 'should not do anything when no [attachment:...] is present in the note' do
96
+ expect(attachments(authentication).upload_attachments!('/requests', {note: '[attachmen:/type]'})).to be_nil
97
+ end
105
98
 
106
- it 'should open a file from disk' do
107
- expect(@attachments).to receive(:aws_upload).with(@aws_conf, @key_template, @key, kind_of(File))
108
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
109
- end
99
+ it 'should not do anything when attachment is empty' do
100
+ expect(attachments(authentication).upload_attachments!('/requests', {note: '[attachment:]'})).to be_nil
101
+ end
110
102
 
111
- it 'should sent the upload to AWS' do
112
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: 'OK', status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
113
- stub_request(:get, "https://api.4me.com/v1/s3_success?sig=99e82e8a046&key=#{@key}").with(basic_auth: ['secret', 'x']).to_return(body: {}.to_json)
114
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
115
- end
103
+ it 'should show a error if no attachment may be uploaded' do
104
+ stub_request(:get, 'https://api.4me.com/v1/sites/1?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {name: 'site 1'}.to_json)
105
+ expect_log('Attachments not allowed for /sites/1', :error)
106
+ expect(attachments(authentication).upload_attachments!('/sites/1', {note: '[attachment:file1.png]'})).to be_nil
107
+ end
116
108
 
117
- it 'should report an error when AWS upload fails' do
118
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: %(<?xml version="1.0" encoding="UTF-8"?>\n<Error><Code>AccessDenied</Code><Message>Invalid according to Policy</Message><RequestId>1FECC4B719E426B1</RequestId><HostId>15+14lXt+HlF</HostId></Error>), status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
119
- expect_log("Attachment upload failed: AWS upload to https://itrp.s3.amazonaws.com/ for #{@key} failed: Invalid according to Policy", :error)
120
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
121
- end
109
+ it 'should raise an exception if no attachment may be uploaded' do
110
+ stub_request(:get, 'https://api.4me.com/v1/sites/1?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {name: 'site 1'}.to_json)
111
+ message = 'Attachments not allowed for /sites/1'
112
+ expect{ attachments(authentication).upload_attachments!('/sites/1', {note: '[attachment:file1.png]', attachments_exception: true}) }.to raise_error(::Sdk4me::UploadFailed, message)
113
+ end
122
114
 
123
- it 'should report an error when 4me confirmation fails' do
124
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: 'OK', status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
125
- stub_request(:get, "https://api.4me.com/v1/s3_success?sig=99e82e8a046&key=#{@key}").with(basic_auth: ['secret', 'x']).to_return(body: {message: 'oops!'}.to_json)
126
- expect_log('Request failed: oops!', :error)
127
- expect_log("Attachment upload failed: 4me confirmation s3_success?sig=99e82e8a046 for #{@key} failed: oops!", :error)
128
- expect(@attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
129
- end
115
+ it 'should add /new to the path for new records' do
116
+ stub_request(:get, 'https://api.4me.com/v1/sites/new?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {missing: 'storage'}.to_json)
117
+ expect_log('Attachments not allowed for /sites', :error)
118
+ expect(attachments(authentication).upload_attachments!('/sites', {note: '[attachment:file1.png]'})).to be_nil
119
+ end
130
120
 
131
- it 'should raise an exception when AWS upload fails' do
132
- stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: %(<?xml version="1.0" encoding="UTF-8"?>\n<Error><Code>AccessDenied</Code><Message>Invalid according to Policy</Message><RequestId>1FECC4B719E426B1</RequestId><HostId>15+14lXt+HlF</HostId></Error>), status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
133
- message = "Attachment upload failed: AWS upload to https://itrp.s3.amazonaws.com/ for #{@key} failed: Invalid according to Policy"
134
- expect{ @attachments.send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", true) }.to raise_error(::Sdk4me::UploadFailed, message)
135
- end
136
- end
121
+ [ [:requests, :note],
122
+ [:problems, :note],
123
+ [:contracts, :remarks],
124
+ [:cis, :remarks],
125
+ [:flsas, :remarks],
126
+ [:slas, :remarks],
127
+ [:service_instances, :remarks],
128
+ [:service_offerings, :summary],
129
+ [:any_other_model, :note]].each do |model, attribute|
137
130
 
138
- context '4me' do
139
- before(:each) do
140
- @sdk4me_conf = {
141
- provider: 'local',
142
- upload_uri: 'https://api.4me.com/attachments',
143
- upload_path: 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/'
144
- }
145
- @key_template = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}'
146
- @key = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/upload.txt'
147
-
148
- @multi_part_body = "--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\napplication/octet-stream\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"file\"; filename=\"#{@spec_dir}/support/fixtures/upload.txt\"\r\nContent-Type: text/plain\r\n\r\ncontent\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\nattachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}\r\n--0123456789ABLEWASIEREISAWELBA9876543210--"
149
- @multi_part_headers = {'Accept'=>'*/*', 'Content-Type'=>'multipart/form-data; boundary=0123456789ABLEWASIEREISAWELBA9876543210', 'User-Agent'=>'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6'}
150
- end
131
+ it "should replace :attachments with :#{attribute}_attachments after upload at /#{model}" do
132
+ stub_request(:get, "https://api.4me.com/v1/#{model}/new?attachment_upload_token=true").with(credentials(authentication)).to_return(body: {storage_upload: 'conf'}.to_json)
133
+ expect(attachments(authentication)).to receive(:upload_attachment).with('conf', 'file1.png', false).ordered{ {key: 'uploaded file1.png'} }
134
+ expect(attachments(authentication)).to receive(:upload_attachment).with('conf', 'file2.zip', false).ordered{ {key: 'uploaded file2.zip'} }
135
+ data = {leave: 'me alone', attribute => '[attachment:file1.png] and [attachment:file2.zip]'}
136
+ attachments(authentication).upload_attachments!("/#{model}", data)
137
+ expect(data[:attachments]).to be_nil
138
+ expect(data[:leave]).to eq('me alone')
139
+ expect(data[:"#{attribute}_attachments"]).to eq([{key: 'uploaded file1.png', inline: true}, {key: 'uploaded file2.zip', inline: true}].to_json)
140
+ expect(data[:"#{attribute}"]).to eq('![](uploaded file1.png) and ![](uploaded file2.zip)')
141
+ end
142
+ end
151
143
 
152
- it 'should open a file from disk' do
153
- expect(@attachments).to receive(:upload_to_4me).with(@sdk4me_conf, @key_template, @key, kind_of(File))
154
- expect(@attachments.send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
155
- end
144
+ it 'should set raise_exception flag to true when :attachments_exception is set' do
145
+ stub_request(:get, 'https://api.4me.com/v1/requests/new?attachment_upload_token=true').with(credentials(authentication)).to_return(body: {storage_upload: 'conf'}.to_json)
146
+ expect(attachments(authentication)).to receive(:upload_attachment).with('conf', 'file1.png', true).ordered{ {key: 'uploaded file1.png'} }
147
+ data = {leave: 'me alone', note: '[attachment:file1.png]', attachments_exception: true}
148
+ attachments(authentication).upload_attachments!('/requests', data)
149
+ expect(data[:attachments]).to be_nil
150
+ expect(data[:attachments_exception]).to be_nil
151
+ expect(data[:leave]).to eq('me alone')
152
+ expect(data[:note_attachments]).to eq([{key: 'uploaded file1.png', inline: true}].to_json)
153
+ expect(data[:note]).to eq('![](uploaded file1.png)')
154
+ end
155
+ end
156
156
 
157
- it 'should sent the upload to 4me' do
158
- stub_request(:post, 'https://api.4me.com/v1/attachments').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {}.to_json)
159
- expect(@attachments.send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
160
157
  end
161
158
 
162
- it 'should report an error when 4me upload fails' do
163
- stub_request(:post, 'https://api.4me.com/v1/attachments').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
164
- expect_log('Request failed: oops!', :error)
165
- expect_log("Attachment upload failed: 4me upload to https://api.4me.com/attachments for #{@key} failed: oops!", :error)
166
- expect(@attachments.send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
167
- end
159
+ context 'upload_attachment' do
160
+
161
+ it 'should log an exception when the file could not be found' do
162
+ expect_log('Attachment upload failed: file does not exist: unknown_file', :error)
163
+ expect(attachments(authentication).send(:upload_attachment, nil, 'unknown_file', false)).to be_nil
164
+ end
165
+
166
+ it 'should raise an exception when the file could not be found' do
167
+ message = 'Attachment upload failed: file does not exist: unknown_file'
168
+ expect{ attachments(authentication).send(:upload_attachment, nil, 'unknown_file', true) }.to raise_error(::Sdk4me::UploadFailed, message)
169
+ end
170
+
171
+ context 'aws' do
172
+ before(:each) do
173
+ @aws_conf = {
174
+ provider: 'aws',
175
+ upload_uri: 'https://itrp.s3.amazonaws.com/',
176
+ access_key: 'AKIA6RYQ',
177
+ success_url: 'https://mycompany.4me.com/s3_success?sig=99e82e8a046',
178
+ policy: 'eydlgIH0=',
179
+ signature: 'nbhdec4k=',
180
+ upload_path: 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/'
181
+ }
182
+ @key_template = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}'
183
+ @key = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/upload.txt'
184
+
185
+ @multi_part_body = "--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\napplication/octet-stream\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"x-amz-server-side-encryption\"\r\n\r\nAES256\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\nattachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\nAKIA6RYQ\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"acl\"\r\n\r\nprivate\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"signature\"\r\n\r\nnbhdec4k=\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"policy\"\r\n\r\neydlgIH0=\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"file\"; filename=\"#{@fixture_dir}/upload.txt\"\r\nContent-Type: text/plain\r\n\r\ncontent\r\n--0123456789ABLEWASIEREISAWELBA9876543210--"
186
+ @multi_part_headers = {'Accept'=>'*/*', 'Content-Type'=>'multipart/form-data; boundary=0123456789ABLEWASIEREISAWELBA9876543210', 'User-Agent'=>'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6'}
187
+ end
188
+
189
+ it 'should open a file from disk' do
190
+ expect(attachments(authentication)).to receive(:aws_upload).with(@aws_conf, @key_template, @key, kind_of(File))
191
+ expect(attachments(authentication).send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
192
+ end
193
+
194
+ it 'should sent the upload to AWS' do
195
+ stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: 'OK', status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
196
+ stub_request(:get, "https://api.4me.com/v1/s3_success?sig=99e82e8a046&key=#{@key}").with(credentials(authentication)).to_return(body: {}.to_json)
197
+ expect(attachments(authentication).send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
198
+ end
199
+
200
+ it 'should report an error when AWS upload fails' do
201
+ stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: %(<?xml version="1.0" encoding="UTF-8"?>\n<Error><Code>AccessDenied</Code><Message>Invalid according to Policy</Message><RequestId>1FECC4B719E426B1</RequestId><HostId>15+14lXt+HlF</HostId></Error>), status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
202
+ expect_log("Attachment upload failed: AWS upload to https://itrp.s3.amazonaws.com/ for #{@key} failed: Invalid according to Policy", :error)
203
+ expect(attachments(authentication).send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
204
+ end
205
+
206
+ it 'should report an error when 4me confirmation fails' do
207
+ stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: 'OK', status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
208
+ stub_request(:get, "https://api.4me.com/v1/s3_success?sig=99e82e8a046&key=#{@key}").with(credentials(authentication)).to_return(body: {message: 'oops!'}.to_json)
209
+ expect_log('GET request to api.4me.com:443/v1/s3_success?sig=99e82e8a046&key=attachments%2F5%2Freqs%2F000%2F070%2F451%2Fzxxb4ot60xfd6sjg%2Fupload%2Etxt failed: oops!', :error)
210
+ expect_log("Attachment upload failed: 4me confirmation s3_success?sig=99e82e8a046 for #{@key} failed: oops!", :error)
211
+ expect(attachments(authentication).send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
212
+ end
213
+
214
+ it 'should raise an exception when AWS upload fails' do
215
+ stub_request(:post, 'https://itrp.s3.amazonaws.com/').with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: %(<?xml version="1.0" encoding="UTF-8"?>\n<Error><Code>AccessDenied</Code><Message>Invalid according to Policy</Message><RequestId>1FECC4B719E426B1</RequestId><HostId>15+14lXt+HlF</HostId></Error>), status: 303, headers: {'Location' => 'https://mycompany.4me.com/s3_success?sig=99e82e8a046'})
216
+ message = "Attachment upload failed: AWS upload to https://itrp.s3.amazonaws.com/ for #{@key} failed: Invalid according to Policy"
217
+ expect{ attachments(authentication).send(:upload_attachment, @aws_conf, "#{@fixture_dir}/upload.txt", true) }.to raise_error(::Sdk4me::UploadFailed, message)
218
+ end
219
+ end
220
+
221
+ context '4me' do
222
+ before(:each) do
223
+ @sdk4me_conf = {
224
+ provider: 'local',
225
+ upload_uri: 'https://api.4me.com/attachments',
226
+ upload_path: 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/'
227
+ }
228
+ @key_template = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}'
229
+ @key = 'attachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/upload.txt'
230
+
231
+ @multi_part_body = "--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\napplication/octet-stream\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"file\"; filename=\"#{@spec_dir}/support/fixtures/upload.txt\"\r\nContent-Type: text/plain\r\n\r\ncontent\r\n--0123456789ABLEWASIEREISAWELBA9876543210\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\nattachments/5/reqs/000/070/451/zxxb4ot60xfd6sjg/${filename}\r\n--0123456789ABLEWASIEREISAWELBA9876543210--"
232
+ @multi_part_headers = {'Accept'=>'*/*', 'Content-Type'=>'multipart/form-data; boundary=0123456789ABLEWASIEREISAWELBA9876543210', 'User-Agent'=>'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6'}
233
+ end
234
+
235
+ it 'should open a file from disk' do
236
+ expect(attachments(authentication)).to receive(:upload_to_4me).with(@sdk4me_conf, @key_template, @key, kind_of(File))
237
+ expect(attachments(authentication).send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
238
+ end
239
+
240
+ it 'should sent the upload to 4me' do
241
+ stub_request(:post, 'https://api.4me.com/v1/attachments').with(credentials(authentication)).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {}.to_json)
242
+ expect(attachments(authentication).send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", false)).to eq({key: @key, filesize: 7})
243
+ end
244
+
245
+ it 'should report an error when 4me upload fails' do
246
+ stub_request(:post, 'https://api.4me.com/v1/attachments').with(credentials(authentication)).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
247
+ expect_log('POST request to api.4me.com:443/v1/attachments failed: oops!', :error)
248
+ expect_log("Attachment upload failed: 4me upload to https://api.4me.com/attachments for #{@key} failed: oops!", :error)
249
+ expect(attachments(authentication).send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", false)).to be_nil
250
+ end
251
+
252
+ it 'should raise an exception when 4me upload fails' do
253
+ stub_request(:post, 'https://api.4me.com/v1/attachments').with(credentials(authentication)).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
254
+ expect_log('POST request to api.4me.com:443/v1/attachments failed: oops!', :error)
255
+ message = "Attachment upload failed: 4me upload to https://api.4me.com/attachments for #{@key} failed: oops!"
256
+ expect{ attachments(authentication).send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", true) }.to raise_error(::Sdk4me::UploadFailed, message)
257
+ end
258
+ end
168
259
 
169
- it 'should raise an exception when 4me upload fails' do
170
- stub_request(:post, 'https://api.4me.com/v1/attachments').with(basic_auth: ['secret', 'x']).with(body: @multi_part_body, headers: @multi_part_headers).to_return(body: {message: 'oops!'}.to_json)
171
- expect_log('Request failed: oops!', :error)
172
- message = "Attachment upload failed: 4me upload to https://api.4me.com/attachments for #{@key} failed: oops!"
173
- expect{ @attachments.send(:upload_attachment, @sdk4me_conf, "#{@fixture_dir}/upload.txt", true) }.to raise_error(::Sdk4me::UploadFailed, message)
174
260
  end
175
261
  end
176
-
177
262
  end
178
263
  end
@@ -13,7 +13,21 @@ describe 'ca-bundle.crt' do
13
13
  expect(response.valid?).to be_falsey
14
14
 
15
15
  # expecting 401 error
16
- expect(response.message).to eq('401: Access credentials required')
16
+ expect(response.message).to eq('401: Bad credentials')
17
+ end
18
+
19
+ it 'should be able to connect to the 4me API (access token)' do
20
+ WebMock.allow_net_connect!
21
+ client = Sdk4me::Client.new(access_token: 'invalid', max_retry_time: -1)
22
+ result = {}
23
+
24
+ # no exception concerning the certificate
25
+ expect { result[:response] = client.get('me') }.not_to raise_error
26
+ response = result[:response]
27
+ expect(response.valid?).to be_falsey
28
+
29
+ # expecting 401 error
30
+ expect(response.message).to eq('401: Bad credentials')
17
31
  end
18
32
 
19
33
  it 'should be able to connect to S3' do