gitlab-mail_room 0.0.4 → 0.0.20
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.
- checksums.yaml +4 -4
- data/.gitlab/issue_templates/Default.md +9 -0
- data/.gitlab/issue_templates/Release.md +8 -0
- data/.gitlab-ci.yml +18 -16
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +494 -0
- data/.ruby-version +1 -1
- data/.travis.yml +12 -5
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +40 -0
- data/README.md +136 -10
- data/Rakefile +1 -1
- data/lib/mail_room/arbitration/redis.rb +1 -1
- data/lib/mail_room/cli.rb +2 -2
- data/lib/mail_room/configuration.rb +11 -1
- data/lib/mail_room/connection.rb +10 -177
- data/lib/mail_room/coordinator.rb +8 -4
- data/lib/mail_room/crash_handler.rb +8 -12
- data/lib/mail_room/delivery/letter_opener.rb +1 -1
- data/lib/mail_room/delivery/postback.rb +36 -4
- data/lib/mail_room/delivery/sidekiq.rb +4 -3
- data/lib/mail_room/health_check.rb +60 -0
- data/lib/mail_room/imap/connection.rb +200 -0
- data/lib/mail_room/imap/message.rb +19 -0
- data/lib/mail_room/imap.rb +8 -0
- data/lib/mail_room/jwt.rb +39 -0
- data/lib/mail_room/logger/structured.rb +15 -1
- data/lib/mail_room/mailbox.rb +62 -20
- data/lib/mail_room/mailbox_watcher.rb +15 -2
- data/lib/mail_room/message.rb +16 -0
- data/lib/mail_room/microsoft_graph/connection.rb +243 -0
- data/lib/mail_room/microsoft_graph.rb +7 -0
- data/lib/mail_room/version.rb +2 -2
- data/lib/mail_room.rb +2 -0
- data/mail_room.gemspec +13 -4
- data/spec/fixtures/jwt_secret +1 -0
- data/spec/fixtures/test_config.yml +3 -0
- data/spec/lib/arbitration/redis_spec.rb +9 -7
- data/spec/lib/cli_spec.rb +32 -17
- data/spec/lib/configuration_spec.rb +10 -3
- data/spec/lib/coordinator_spec.rb +27 -11
- data/spec/lib/crash_handler_spec.rb +10 -9
- data/spec/lib/delivery/letter_opener_spec.rb +10 -6
- data/spec/lib/delivery/logger_spec.rb +8 -10
- data/spec/lib/delivery/postback_spec.rb +73 -41
- data/spec/lib/delivery/que_spec.rb +5 -8
- data/spec/lib/delivery/sidekiq_spec.rb +33 -11
- data/spec/lib/health_check_spec.rb +57 -0
- data/spec/lib/{connection_spec.rb → imap/connection_spec.rb} +13 -17
- data/spec/lib/imap/message_spec.rb +36 -0
- data/spec/lib/jwt_spec.rb +80 -0
- data/spec/lib/logger/structured_spec.rb +34 -2
- data/spec/lib/mailbox_spec.rb +79 -34
- data/spec/lib/mailbox_watcher_spec.rb +54 -41
- data/spec/lib/message_spec.rb +35 -0
- data/spec/lib/microsoft_graph/connection_spec.rb +252 -0
- data/spec/spec_helper.rb +14 -4
- metadata +130 -21
@@ -9,24 +9,22 @@ describe MailRoom::Delivery::Logger do
|
|
9
9
|
it 'creates a new ruby logger' do
|
10
10
|
::Logger.stubs(:new)
|
11
11
|
|
12
|
-
|
12
|
+
::Logger.expects(:new).with(STDOUT)
|
13
13
|
|
14
|
-
|
14
|
+
MailRoom::Delivery::Logger.new(mailbox)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
context "with a log path" do
|
19
|
-
let(:mailbox) {build_mailbox(:
|
19
|
+
let(:mailbox) {build_mailbox(log_path: '/var/log/mail-room.log')}
|
20
20
|
|
21
21
|
it 'creates a new file to append to' do
|
22
|
-
::Logger.stubs(:new)
|
23
22
|
file = stub(:sync=)
|
24
|
-
::File.stubs(:open).returns(file)
|
25
23
|
|
26
|
-
|
24
|
+
File.expects(:open).with('/var/log/mail-room.log', 'a').returns(file)
|
25
|
+
::Logger.stubs(:new).with(file)
|
27
26
|
|
28
|
-
|
29
|
-
expect(::Logger).to have_received(:new).with(file)
|
27
|
+
MailRoom::Delivery::Logger.new(mailbox)
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end
|
@@ -38,9 +36,9 @@ describe MailRoom::Delivery::Logger do
|
|
38
36
|
logger = stub(:info)
|
39
37
|
::Logger.stubs(:new).returns(logger)
|
40
38
|
|
41
|
-
|
39
|
+
logger.expects(:info).with('a message')
|
42
40
|
|
43
|
-
|
41
|
+
MailRoom::Delivery::Logger.new(mailbox).deliver('a message')
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
@@ -5,8 +5,8 @@ describe MailRoom::Delivery::Postback do
|
|
5
5
|
describe '#deliver' do
|
6
6
|
context 'with token auth delivery' do
|
7
7
|
let(:mailbox) {build_mailbox({
|
8
|
-
:
|
9
|
-
:
|
8
|
+
delivery_url: 'http://localhost/inbox',
|
9
|
+
delivery_token: 'abcdefg'
|
10
10
|
})}
|
11
11
|
|
12
12
|
let(:delivery_options) {
|
@@ -18,28 +18,22 @@ describe MailRoom::Delivery::Postback do
|
|
18
18
|
request = stub
|
19
19
|
Faraday.stubs(:new).returns(connection)
|
20
20
|
|
21
|
-
connection.
|
22
|
-
connection.
|
21
|
+
connection.expects(:token_auth).with('abcdefg')
|
22
|
+
connection.expects(:post).yields(request)
|
23
23
|
|
24
|
-
request.
|
25
|
-
request.
|
24
|
+
request.expects(:url).with('http://localhost/inbox')
|
25
|
+
request.expects(:body=).with('a message')
|
26
26
|
|
27
27
|
MailRoom::Delivery::Postback.new(delivery_options).deliver('a message')
|
28
|
-
|
29
|
-
expect(connection).to have_received(:token_auth).with('abcdefg')
|
30
|
-
expect(connection).to have_received(:post)
|
31
|
-
|
32
|
-
expect(request).to have_received(:url).with('http://localhost/inbox')
|
33
|
-
expect(request).to have_received(:body=).with('a message')
|
34
28
|
end
|
35
29
|
end
|
36
30
|
|
37
31
|
context 'with basic auth delivery options' do
|
38
32
|
let(:mailbox) {build_mailbox({
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
33
|
+
delivery_options: {
|
34
|
+
url: 'http://localhost/inbox',
|
35
|
+
username: 'user1',
|
36
|
+
password: 'password123abc'
|
43
37
|
}
|
44
38
|
})}
|
45
39
|
|
@@ -52,56 +46,94 @@ describe MailRoom::Delivery::Postback do
|
|
52
46
|
request = stub
|
53
47
|
Faraday.stubs(:new).returns(connection)
|
54
48
|
|
55
|
-
connection.
|
56
|
-
connection.
|
49
|
+
connection.expects(:basic_auth).with('user1', 'password123abc')
|
50
|
+
connection.expects(:post).yields(request)
|
57
51
|
|
58
|
-
request.
|
59
|
-
request.
|
52
|
+
request.expects(:url).with('http://localhost/inbox')
|
53
|
+
request.expects(:body=).with('a message')
|
60
54
|
|
61
55
|
MailRoom::Delivery::Postback.new(delivery_options).deliver('a message')
|
62
|
-
|
63
|
-
expect(connection).to have_received(:basic_auth).with('user1', 'password123abc')
|
64
|
-
expect(connection).to have_received(:post)
|
65
|
-
|
66
|
-
expect(request).to have_received(:url).with('http://localhost/inbox')
|
67
|
-
expect(request).to have_received(:body=).with('a message')
|
68
56
|
end
|
69
57
|
|
70
58
|
context 'with content type in the delivery options' do
|
71
59
|
let(:mailbox) {build_mailbox({
|
72
|
-
:
|
73
|
-
:
|
74
|
-
:
|
75
|
-
:
|
76
|
-
:
|
60
|
+
delivery_options: {
|
61
|
+
url: 'http://localhost/inbox',
|
62
|
+
username: 'user1',
|
63
|
+
password: 'password123abc',
|
64
|
+
content_type: 'text/plain'
|
77
65
|
}
|
78
66
|
})}
|
79
67
|
|
80
|
-
|
81
68
|
let(:delivery_options) {
|
82
69
|
MailRoom::Delivery::Postback::Options.new(mailbox)
|
83
70
|
}
|
84
|
-
|
71
|
+
|
85
72
|
it 'posts the message with faraday' do
|
86
73
|
connection = stub
|
87
74
|
request = stub
|
88
75
|
Faraday.stubs(:new).returns(connection)
|
89
|
-
|
90
|
-
connection.
|
91
|
-
connection.stubs(:post).yields(request)
|
92
|
-
|
76
|
+
|
77
|
+
connection.expects(:post).yields(request)
|
93
78
|
request.stubs(:url)
|
94
79
|
request.stubs(:body=)
|
95
80
|
request.stubs(:headers).returns({})
|
81
|
+
connection.expects(:basic_auth).with('user1', 'password123abc')
|
96
82
|
|
97
83
|
MailRoom::Delivery::Postback.new(delivery_options).deliver('a message')
|
98
|
-
|
99
|
-
expect(connection).to have_received(:basic_auth).with('user1', 'password123abc')
|
100
|
-
expect(connection).to have_received(:post)
|
101
|
-
|
84
|
+
|
102
85
|
expect(request.headers['Content-Type']).to eq('text/plain')
|
103
86
|
end
|
104
87
|
end
|
88
|
+
|
89
|
+
context 'with jwt token in the delivery options' do
|
90
|
+
let(:mailbox) {build_mailbox({
|
91
|
+
delivery_options: {
|
92
|
+
url: 'http://localhost/inbox',
|
93
|
+
jwt_auth_header: "Mailroom-Api-Request",
|
94
|
+
jwt_issuer: "mailroom",
|
95
|
+
jwt_algorithm: "HS256",
|
96
|
+
jwt_secret_path: "secret_path"
|
97
|
+
}
|
98
|
+
})}
|
99
|
+
|
100
|
+
let(:delivery_options) {
|
101
|
+
MailRoom::Delivery::Postback::Options.new(mailbox)
|
102
|
+
}
|
103
|
+
|
104
|
+
it 'posts the message with faraday' do
|
105
|
+
connection = stub
|
106
|
+
request = stub
|
107
|
+
Faraday.stubs(:new).returns(connection)
|
108
|
+
|
109
|
+
connection.expects(:post).yields(request).twice
|
110
|
+
request.stubs(:url)
|
111
|
+
request.stubs(:body=)
|
112
|
+
request.stubs(:headers).returns({})
|
113
|
+
|
114
|
+
jwt = stub
|
115
|
+
MailRoom::JWT.expects(:new).with(
|
116
|
+
header: 'Mailroom-Api-Request',
|
117
|
+
issuer: 'mailroom',
|
118
|
+
algorithm: 'HS256',
|
119
|
+
secret_path: 'secret_path'
|
120
|
+
).returns(jwt)
|
121
|
+
jwt.stubs(:valid?).returns(true)
|
122
|
+
jwt.stubs(:header).returns('Mailroom-Api-Request')
|
123
|
+
jwt.stubs(:token).returns('a_jwt_token')
|
124
|
+
|
125
|
+
delivery = MailRoom::Delivery::Postback.new(delivery_options)
|
126
|
+
|
127
|
+
delivery.deliver('a message')
|
128
|
+
expect(request.headers['Mailroom-Api-Request']).to eql('a_jwt_token')
|
129
|
+
|
130
|
+
# A different jwt token for the second time
|
131
|
+
jwt.stubs(:token).returns('another_jwt_token')
|
132
|
+
|
133
|
+
delivery.deliver('another message')
|
134
|
+
expect(request.headers['Mailroom-Api-Request']).to eql('another_jwt_token')
|
135
|
+
end
|
136
|
+
end
|
105
137
|
end
|
106
138
|
end
|
107
139
|
end
|
@@ -18,20 +18,15 @@ describe MailRoom::Delivery::Que do
|
|
18
18
|
let(:options) {MailRoom::Delivery::Que::Options.new(mailbox)}
|
19
19
|
|
20
20
|
it 'stores the message in que_jobs table' do
|
21
|
-
PG.
|
22
|
-
connection.stubs(:exec)
|
23
|
-
|
24
|
-
MailRoom::Delivery::Que.new(options).deliver('email')
|
25
|
-
|
26
|
-
expect(PG).to have_received(:connect).with({
|
21
|
+
PG.expects(:connect).with({
|
27
22
|
host: 'localhost',
|
28
23
|
port: 5432,
|
29
24
|
dbname: 'delivery_test',
|
30
25
|
user: 'postgres',
|
31
26
|
password: ''
|
32
|
-
})
|
27
|
+
}).returns(connection)
|
33
28
|
|
34
|
-
|
29
|
+
connection.expects(:exec).with(
|
35
30
|
"INSERT INTO que_jobs (priority, job_class, queue, args) VALUES ($1, $2, $3, $4)",
|
36
31
|
[
|
37
32
|
5,
|
@@ -40,6 +35,8 @@ describe MailRoom::Delivery::Que do
|
|
40
35
|
JSON.dump(['email'])
|
41
36
|
]
|
42
37
|
)
|
38
|
+
|
39
|
+
MailRoom::Delivery::Que.new(options).deliver('email')
|
43
40
|
end
|
44
41
|
end
|
45
42
|
end
|
@@ -4,27 +4,49 @@ require 'mail_room/delivery/sidekiq'
|
|
4
4
|
describe MailRoom::Delivery::Sidekiq do
|
5
5
|
subject { described_class.new(options) }
|
6
6
|
let(:redis) { subject.send(:client) }
|
7
|
+
let(:raw_client) { redis._client }
|
7
8
|
let(:options) { MailRoom::Delivery::Sidekiq::Options.new(mailbox) }
|
8
9
|
|
9
10
|
describe '#options' do
|
10
11
|
let(:redis_url) { 'redis://localhost' }
|
12
|
+
let(:redis_options) { { redis_url: redis_url } }
|
11
13
|
|
12
14
|
context 'when only redis_url is specified' do
|
13
15
|
let(:mailbox) {
|
14
16
|
build_mailbox(
|
15
17
|
delivery_method: :sidekiq,
|
16
|
-
delivery_options:
|
17
|
-
redis_url: redis_url
|
18
|
-
}
|
18
|
+
delivery_options: redis_options
|
19
19
|
)
|
20
20
|
}
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
context 'with simple redis url' do
|
23
|
+
it 'client has same specified redis_url' do
|
24
|
+
expect(raw_client.options[:url]).to eq(redis_url)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'client is a instance of RedisNamespace class' do
|
28
|
+
expect(redis).to be_a ::Redis
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'connection has correct values' do
|
32
|
+
expect(redis.connection[:host]).to eq('localhost')
|
33
|
+
expect(redis.connection[:db]).to eq(0)
|
34
|
+
end
|
24
35
|
end
|
25
36
|
|
26
|
-
|
27
|
-
|
37
|
+
context 'with redis_db specified in options' do
|
38
|
+
before do
|
39
|
+
redis_options[:redis_db] = 4
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'client has correct redis_url' do
|
43
|
+
expect(raw_client.options[:url]).to eq(redis_url)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'connection has correct values' do
|
47
|
+
expect(redis.connection[:host]).to eq('localhost')
|
48
|
+
expect(redis.connection[:db]).to eq(4)
|
49
|
+
end
|
28
50
|
end
|
29
51
|
end
|
30
52
|
|
@@ -65,10 +87,10 @@ describe MailRoom::Delivery::Sidekiq do
|
|
65
87
|
before { ::Redis::Client::Connector::Sentinel.any_instance.stubs(:resolve).returns(sentinels) }
|
66
88
|
|
67
89
|
it 'client has same specified sentinel params' do
|
68
|
-
expect(
|
69
|
-
expect(
|
70
|
-
expect(
|
71
|
-
expect(
|
90
|
+
expect(raw_client.instance_variable_get(:@connector)).to be_a Redis::Client::Connector::Sentinel
|
91
|
+
expect(raw_client.options[:host]).to eq('sentinel-master')
|
92
|
+
expect(raw_client.options[:password]).to eq('mypassword')
|
93
|
+
expect(raw_client.options[:sentinels]).to eq(sentinels)
|
72
94
|
end
|
73
95
|
end
|
74
96
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe MailRoom::HealthCheck do
|
6
|
+
let(:address) { '127.0.0.1' }
|
7
|
+
let(:port) { 8000 }
|
8
|
+
let(:params) { { address: address, port: port } }
|
9
|
+
subject { described_class.new(params) }
|
10
|
+
|
11
|
+
describe '#initialize' do
|
12
|
+
context 'with valid parameters' do
|
13
|
+
it 'validates successfully' do
|
14
|
+
expect(subject).to be_a(described_class)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with invalid address' do
|
19
|
+
let(:address) { nil }
|
20
|
+
|
21
|
+
it 'raises an error' do
|
22
|
+
expect { subject }.to raise_error('No health check address specified')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with invalid port' do
|
27
|
+
let(:port) { nil }
|
28
|
+
|
29
|
+
it 'raises an error' do
|
30
|
+
expect { subject }.to raise_error('Health check port 0 is invalid')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#run' do
|
36
|
+
it 'sets running to true' do
|
37
|
+
server = stub(start: true)
|
38
|
+
subject.stubs(:create_server).returns(server)
|
39
|
+
|
40
|
+
subject.run
|
41
|
+
|
42
|
+
expect(subject.running).to be true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#quit' do
|
47
|
+
it 'sets running to false' do
|
48
|
+
server = stub(start: true, shutdown: true)
|
49
|
+
subject.stubs(:create_server).returns(server)
|
50
|
+
|
51
|
+
subject.run
|
52
|
+
subject.quit
|
53
|
+
|
54
|
+
expect(subject.running).to be false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe MailRoom::Connection do
|
3
|
+
describe MailRoom::IMAP::Connection do
|
4
4
|
let(:imap) {stub}
|
5
5
|
let(:mailbox) {build_mailbox(delete_after_delivery: true, expunge_deleted: true)}
|
6
6
|
|
@@ -9,7 +9,9 @@ describe MailRoom::Connection do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
context "with imap set up" do
|
12
|
-
let(:connection) {MailRoom::Connection.new(mailbox)}
|
12
|
+
let(:connection) {MailRoom::IMAP::Connection.new(mailbox)}
|
13
|
+
let(:uid) { 1 }
|
14
|
+
let(:seqno) { 8 }
|
13
15
|
|
14
16
|
before :each do
|
15
17
|
imap.stubs(:starttls)
|
@@ -36,30 +38,24 @@ describe MailRoom::Connection do
|
|
36
38
|
end
|
37
39
|
|
38
40
|
it "waits for a message to process" do
|
39
|
-
new_message = 'a message'
|
40
|
-
new_message.stubs(:seqno).returns(8)
|
41
|
+
new_message = MailRoom::IMAP::Message.new(uid: uid, body: 'a message', seqno: seqno)
|
41
42
|
|
42
43
|
connection.on_new_message do |message|
|
43
44
|
expect(message).to eq(new_message)
|
44
45
|
true
|
45
46
|
end
|
46
47
|
|
47
|
-
|
48
|
+
attr = { 'UID' => uid, 'RFC822' => new_message.body }
|
49
|
+
fetch_data = Net::IMAP::FetchData.new(seqno, attr)
|
48
50
|
|
49
|
-
imap.
|
50
|
-
imap.stubs(:uid_search).
|
51
|
-
imap.
|
52
|
-
|
53
|
-
imap.
|
51
|
+
imap.expects(:idle)
|
52
|
+
imap.stubs(:uid_search).with(mailbox.search_command).returns([], [uid])
|
53
|
+
imap.expects(:uid_fetch).with([uid], "RFC822").returns([fetch_data])
|
54
|
+
mailbox.expects(:deliver?).with(uid).returns(true)
|
55
|
+
imap.expects(:store).with(seqno, "+FLAGS", [Net::IMAP::DELETED])
|
56
|
+
imap.expects(:expunge).once
|
54
57
|
|
55
58
|
connection.wait
|
56
|
-
|
57
|
-
expect(imap).to have_received(:idle)
|
58
|
-
expect(imap).to have_received(:uid_search).with(mailbox.search_command).twice
|
59
|
-
expect(imap).to have_received(:uid_fetch).with([1], "RFC822")
|
60
|
-
expect(mailbox).to have_received(:deliver?).with(1)
|
61
|
-
expect(imap).to have_received(:store).with(8, "+FLAGS", [Net::IMAP::DELETED])
|
62
|
-
expect(imap).to have_received(:expunge).once
|
63
59
|
end
|
64
60
|
end
|
65
61
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal:true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
describe MailRoom::IMAP::Message do
|
7
|
+
let(:uid) { SecureRandom.hex }
|
8
|
+
let(:body) { 'hello world' }
|
9
|
+
let(:seqno) { 5 }
|
10
|
+
|
11
|
+
subject { described_class.new(uid: uid, body: body, seqno: seqno) }
|
12
|
+
|
13
|
+
describe '#initalize' do
|
14
|
+
it 'initializes with required parameters' do
|
15
|
+
subject
|
16
|
+
|
17
|
+
expect(subject.uid).to eq(uid)
|
18
|
+
expect(subject.body).to eq(body)
|
19
|
+
expect(subject.seqno).to eq(seqno)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#==' do
|
24
|
+
let(:dup) { described_class.new(uid: uid, body: body, seqno: seqno) }
|
25
|
+
let(:base_msg) { MailRoom::Message.new(uid: uid, body: body) }
|
26
|
+
|
27
|
+
it 'matches an equivalent message' do
|
28
|
+
expect(dup == subject).to be true
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'does not match a base message' do
|
32
|
+
expect(subject == base_msg).to be false
|
33
|
+
expect(base_msg == subject).to be false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'mail_room/jwt'
|
4
|
+
|
5
|
+
describe MailRoom::JWT do
|
6
|
+
let(:secret_path) { File.expand_path('../fixtures/jwt_secret', File.dirname(__FILE__)) }
|
7
|
+
let(:secret) { Base64.strict_decode64(File.read(secret_path).chomp) }
|
8
|
+
|
9
|
+
let(:standard_config) do
|
10
|
+
{
|
11
|
+
secret_path: secret_path,
|
12
|
+
issuer: 'mailroom',
|
13
|
+
header: 'Mailroom-Api-Request',
|
14
|
+
algorithm: 'HS256'
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#token' do
|
19
|
+
let(:jwt) { described_class.new(**standard_config) }
|
20
|
+
|
21
|
+
it 'generates a valid jwt token' do
|
22
|
+
token = jwt.token
|
23
|
+
expect(token).not_to be_empty
|
24
|
+
|
25
|
+
payload = nil
|
26
|
+
expect do
|
27
|
+
payload = JWT.decode(token, secret, true, iss: 'mailroom', verify_iat: true, verify_iss: true, algorithm: 'HS256')
|
28
|
+
end.not_to raise_error
|
29
|
+
expect(payload).to be_an(Array)
|
30
|
+
expect(payload).to match(
|
31
|
+
[
|
32
|
+
a_hash_including(
|
33
|
+
'iss' => 'mailroom',
|
34
|
+
'nonce' => be_a(String),
|
35
|
+
'iat' => be_a(Integer)
|
36
|
+
),
|
37
|
+
{ 'alg' => 'HS256' }
|
38
|
+
]
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'generates a different token for each invocation' do
|
43
|
+
expect(jwt.token).not_to eql(jwt.token)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#valid?' do
|
48
|
+
it 'returns true if all essential components are present' do
|
49
|
+
jwt = described_class.new(**standard_config)
|
50
|
+
expect(jwt.valid?).to eql(true)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns true if header and secret path are present' do
|
54
|
+
jwt = described_class.new(
|
55
|
+
secret_path: secret_path,
|
56
|
+
header: 'Mailroom-Api-Request',
|
57
|
+
issuer: nil,
|
58
|
+
algorithm: nil
|
59
|
+
)
|
60
|
+
expect(jwt.valid?).to eql(true)
|
61
|
+
expect(jwt.issuer).to eql(described_class::DEFAULT_ISSUER)
|
62
|
+
expect(jwt.algorithm).to eql(described_class::DEFAULT_ALGORITHM)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns false if either header or secret_path are missing' do
|
66
|
+
expect(described_class.new(
|
67
|
+
secret_path: nil,
|
68
|
+
header: 'Mailroom-Api-Request',
|
69
|
+
issuer: nil,
|
70
|
+
algorithm: nil
|
71
|
+
).valid?).to eql(false)
|
72
|
+
expect(described_class.new(
|
73
|
+
secret_path: secret_path,
|
74
|
+
header: nil,
|
75
|
+
issuer: nil,
|
76
|
+
algorithm: nil
|
77
|
+
).valid?).to eql(false)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -5,6 +5,7 @@ describe MailRoom::Logger::Structured do
|
|
5
5
|
subject { described_class.new $stdout }
|
6
6
|
|
7
7
|
let!(:now) { Time.now }
|
8
|
+
let(:timestamp) { now.to_datetime.iso8601(3) }
|
8
9
|
let(:message) { { action: 'exciting development', message: 'testing 123' } }
|
9
10
|
|
10
11
|
before do
|
@@ -32,7 +33,7 @@ describe MailRoom::Logger::Structured do
|
|
32
33
|
}
|
33
34
|
expected = {
|
34
35
|
severity: 'DEBUG',
|
35
|
-
time:
|
36
|
+
time: timestamp,
|
36
37
|
additional_field: "some value"
|
37
38
|
}
|
38
39
|
|
@@ -40,10 +41,41 @@ describe MailRoom::Logger::Structured do
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
44
|
+
describe '#format_message' do
|
45
|
+
shared_examples 'timestamp formatting' do
|
46
|
+
it 'outputs ISO8601 timestamps' do
|
47
|
+
data = JSON.parse(subject.format_message('debug', input_timestamp, 'test', { message: 'hello' } ))
|
48
|
+
|
49
|
+
expect(data['time']).to eq(expected_timestamp)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with no timestamp' do
|
54
|
+
let(:input_timestamp) { nil }
|
55
|
+
let(:expected_timestamp) { timestamp }
|
56
|
+
|
57
|
+
it_behaves_like 'timestamp formatting'
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with DateTime' do
|
61
|
+
let(:input_timestamp) { now.to_datetime }
|
62
|
+
let(:expected_timestamp) { timestamp }
|
63
|
+
|
64
|
+
it_behaves_like 'timestamp formatting'
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with string' do
|
68
|
+
let(:input_timestamp) { now.to_s }
|
69
|
+
let(:expected_timestamp) { input_timestamp }
|
70
|
+
|
71
|
+
it_behaves_like 'timestamp formatting'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
43
75
|
def json_matching(level, message)
|
44
76
|
contents = {
|
45
77
|
severity: level,
|
46
|
-
time:
|
78
|
+
time: timestamp
|
47
79
|
}.merge(message)
|
48
80
|
|
49
81
|
as_regex(contents)
|