4me-sdk 1.1.4 → 1.2.0

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