omniauth-aleph 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,251 @@
1
+ require 'spec_helper'
2
+ describe "OmniAuth::Strategies::Aleph" do
3
+ let(:request) do
4
+ double('Request', params: {}, cookies: {}, env: {})
5
+ end
6
+
7
+ context "when it's improperly configured" do
8
+ let(:config) {{ host: "host" }}
9
+
10
+ subject(:strategy) do
11
+ OmniAuth::Strategies::Aleph.new(nil, config).tap do |strategy|
12
+ strategy.stub(:request) { request }
13
+ strategy.stub(:username) { aleph_username }
14
+ strategy.stub(:password) { aleph_password }
15
+ end
16
+ end
17
+
18
+ describe "#request_phase" do
19
+ it 'should raise an Argument Error' do
20
+ expect{ strategy.request_phase }.to raise_error(ArgumentError)
21
+ end
22
+ end
23
+
24
+ describe "#callback_phase" do
25
+ it 'should raise an Argument Error' do
26
+ expect{ strategy.callback_phase }.to raise_error(ArgumentError)
27
+ end
28
+ end
29
+ end
30
+
31
+ context "when it's properly configured" do
32
+ let(:config) do
33
+ { host: aleph_host,
34
+ library: aleph_library,
35
+ sub_library: aleph_sub_library }
36
+ end
37
+
38
+ subject(:strategy) do
39
+ # First argument is the app, which gets called with env,
40
+ # i.e. app.call(env), so fake it with a stabby lambda
41
+ OmniAuth::Strategies::Aleph.new(->(env) {}, config).tap do |strategy|
42
+ strategy.stub(:request) { request }
43
+ strategy.stub(:username) { aleph_username }
44
+ strategy.stub(:password) { aleph_password }
45
+ strategy.stub(:env) { {} }
46
+ strategy.stub(:fail!) { true }
47
+ end
48
+ end
49
+
50
+ describe '#options' do
51
+ it 'should not error' do
52
+ expect{ strategy.options }.not_to raise_error
53
+ end
54
+
55
+ subject(:options) { strategy.options }
56
+
57
+ describe'#name' do
58
+ it 'should equal "Aleph"' do
59
+ expect(options.name).to eq("aleph")
60
+ end
61
+ end
62
+
63
+ describe '#title' do
64
+ it 'should equal "Aleph Authentication"' do
65
+ expect(options.title).to eq("Aleph Authentication")
66
+ end
67
+ end
68
+
69
+ describe '#scheme' do
70
+ it 'should equal "http"' do
71
+ expect(options.scheme).to eq("http")
72
+ end
73
+ end
74
+
75
+ describe '#host' do
76
+ it 'should be the aleph host' do
77
+ expect(options.host).to eq(aleph_host)
78
+ end
79
+ end
80
+
81
+ describe '#port' do
82
+ it 'should be 80' do
83
+ expect(options.port).to be(80)
84
+ end
85
+ end
86
+
87
+ describe '#library' do
88
+ it 'should be the aleph library' do
89
+ expect(options.library).to eq(aleph_library)
90
+ end
91
+ end
92
+
93
+ describe '#sub_library' do
94
+ it 'should be the aleph sub_library' do
95
+ expect(options.sub_library).to eq(aleph_sub_library)
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#request_phase" do
101
+ it 'shouldn\'t raise an error' do
102
+ expect{ strategy.request_phase }.not_to raise_error
103
+ end
104
+ end
105
+
106
+ describe "#callback_phase", vcr: { cassette_name: "valid" } do
107
+ context "when the credentials are missing" do
108
+ before(:each) do |example|
109
+ strategy.stub(:username) { "" }
110
+ strategy.stub(:password) { "" }
111
+ end
112
+
113
+ it 'shouldn\'t raise an error' do
114
+ expect{ strategy.callback_phase }.not_to raise_error
115
+ end
116
+
117
+ it 'should fail!' do
118
+ strategy.callback_phase
119
+ expect(strategy).to have_received(:fail!)
120
+ end
121
+ end
122
+
123
+ context "when the credentials are included" do
124
+ before(:each) do
125
+ strategy.stub(:username) { aleph_username }
126
+ strategy.stub(:password) { aleph_password }
127
+ end
128
+
129
+ it 'shouldn\'t raise an error' do
130
+ expect{ strategy.callback_phase }.not_to raise_error
131
+ end
132
+
133
+ it 'shouldn\'t fail!' do
134
+ strategy.callback_phase
135
+ expect(strategy).not_to have_received(:fail!)
136
+ end
137
+ end
138
+ end
139
+ end
140
+ context "when it's used as middleware" do
141
+ let(:config) do
142
+ { title: "MY Aleph Authentication",
143
+ host: aleph_host,
144
+ library: aleph_library,
145
+ sub_library: aleph_sub_library }
146
+ end
147
+
148
+ let(:app) do
149
+ args = config
150
+ Rack::Builder.new {
151
+ use OmniAuth::Test::PhonySession
152
+ use OmniAuth::Strategies::Aleph, args
153
+ run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
154
+ }.to_app
155
+ end
156
+
157
+ let(:session) do
158
+ last_request.env['rack.session']
159
+ end
160
+
161
+ describe '/auth/aleph' do
162
+ before(:each){ get '/auth/aleph' }
163
+
164
+ it 'should display a form' do
165
+ expect(last_response.status).to be(200)
166
+ expect(last_response.body).to include("<form")
167
+ end
168
+
169
+ it 'should have the callback as the action for the form' do
170
+ expect(last_response.body).to include("action='/auth/aleph/callback'")
171
+ end
172
+
173
+ it 'should have a text field for each of the fields' do
174
+ expect(last_response.body.scan('<input').size).to be(2)
175
+ end
176
+ it 'should have a label of the form title' do
177
+ expect(last_response.body.scan('MY Aleph Authentication').size).to be > 1
178
+ end
179
+ end
180
+
181
+ describe 'post /auth/aleph/callback' do
182
+ context 'failure' do
183
+ context "when username is not present" do
184
+ it 'should redirect to error page' do
185
+ post('/auth/aleph/callback', {})
186
+ expect(last_response).to be_redirect
187
+ expect(last_response.headers['Location']).to match(%r{missing_credentials})
188
+ end
189
+ end
190
+
191
+ context "when username is empty" do
192
+ it 'should redirect to error page' do
193
+ post('/auth/aleph/callback', {:username => ""})
194
+ expect(last_response).to be_redirect
195
+ expect(last_response.headers['Location']).to match(%r{missing_credentials})
196
+ end
197
+ end
198
+
199
+ context "when username is present" do
200
+ context "and password is not present" do
201
+ it 'should redirect to error page' do
202
+ post('/auth/aleph/callback', {:username => aleph_username})
203
+ expect(last_response).to be_redirect
204
+ expect(last_response.headers['Location']).to match(%r{missing_credentials})
205
+ end
206
+ end
207
+
208
+ context "and password is empty" do
209
+ it 'should redirect to error page' do
210
+ post('/auth/aleph/callback', {:username => aleph_username, :password => ""})
211
+ expect(last_response).to be_redirect
212
+ expect(last_response.headers['Location']).to match(%r{missing_credentials})
213
+ end
214
+ end
215
+ end
216
+
217
+ context "when username and password are present" do
218
+ context "and authentication failed", vcr: { cassette_name: "invalid password" } do
219
+ it 'should redirect to error page' do
220
+ post('/auth/aleph/callback', {:username => aleph_username, :password => 'INVALID'})
221
+ expect(last_response).to be_redirect
222
+ expect(last_response.headers['Location']).to match(%r{Error in Verification})
223
+ end
224
+ end
225
+
226
+ context "and Aleph is down" do
227
+ it "should redirect to error page"
228
+ end
229
+ end
230
+ end
231
+
232
+ context 'success', vcr: { cassette_name: "valid" } do
233
+ let(:auth_hash){ last_request.env['omniauth.auth'] }
234
+
235
+ it 'should not redirect to error page' do
236
+ post('/auth/aleph/callback', { username: aleph_username, password: aleph_password })
237
+ expect(last_response).not_to be_redirect
238
+ end
239
+
240
+ it 'should map user info to Auth Hash' do
241
+ post('/auth/aleph/callback', { username: aleph_username, password: aleph_password })
242
+ expect(auth_hash.uid).to eq('USERNAME')
243
+ expect(auth_hash.info.name).to eq('USERNAME, TEST-RECORD')
244
+ expect(auth_hash.info.nickname).to eq('USERNAME')
245
+ expect(auth_hash.info.email).to eq('username@library.edu')
246
+ expect(auth_hash.info.phone).to be_nil
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,59 @@
1
+ $:.unshift File.expand_path('..', __FILE__)
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'coveralls'
4
+ Coveralls.wear!
5
+ require 'rspec'
6
+ require 'rack/test'
7
+ require 'vcr'
8
+ require 'faraday'
9
+ require 'omniauth'
10
+ require 'omniauth-aleph'
11
+ require 'pry'
12
+
13
+ def aleph_host
14
+ @aleph_host ||= (ENV['ALEPH_HOST'] || 'aleph.library.edu')
15
+ end
16
+
17
+ def aleph_username
18
+ @aleph_username ||= (ENV['ALEPH_USERNAME'] || "USERNAME")
19
+ end
20
+
21
+ def aleph_password
22
+ @aleph_password ||= (ENV['ALEPH_PASSWORD'] || "PASSWORD")
23
+ end
24
+
25
+ def aleph_email
26
+ @aleph_email ||= (ENV['ALEPH_EMAIL'] || "username@library.edu")
27
+ end
28
+
29
+ def aleph_library
30
+ @aleph_library ||= (ENV['ALEPH_LIBRARY'] || "ADM50")
31
+ end
32
+
33
+ def aleph_sub_library
34
+ @aleph_sub_library ||= (ENV['ALEPH_SUB_LIBRARY'] || "SUB")
35
+ end
36
+
37
+ VCR.configure do |c|
38
+ c.cassette_library_dir = 'spec/vcr_cassettes'
39
+ c.configure_rspec_metadata!
40
+ c.hook_into :webmock
41
+ c.filter_sensitive_data("aleph.library.edu") { aleph_host }
42
+ c.filter_sensitive_data("USERNAME") { aleph_username }
43
+ c.filter_sensitive_data("username") { aleph_username.downcase }
44
+ c.filter_sensitive_data("verification=PASSWORD") { "verification=#{aleph_password}" }
45
+ c.filter_sensitive_data("username@library.edu") { aleph_email }
46
+ c.filter_sensitive_data("ADM50") { aleph_library }
47
+ c.filter_sensitive_data("SUB") { aleph_sub_library }
48
+ end
49
+
50
+ RSpec.configure do |config|
51
+ config.include Rack::Test::Methods
52
+ config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
53
+ config.expect_with :rspec do |c|
54
+ c.syntax = :expect
55
+ end
56
+ # so we can use :vcr rather than :vcr => true;
57
+ # in RSpec 3 this will no longer be necessary.
58
+ config.treat_symbols_as_metadata_keys_with_true_values = true
59
+ end
@@ -0,0 +1,36 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://aleph.library.edu/X?bor_id=USERNAME&library=ADM50&op=bor-auth&sub_library=SUB&verification=PASSWORD
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.0
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - ! '*/*'
16
+ response:
17
+ status:
18
+ code: 303
19
+ message: See Other
20
+ headers:
21
+ Location:
22
+ - http://guidetest.a.id.opendns.com/?url=aleph%2Elibrary%2Eedu%2FX%3Fbor%5Fid%3DUSERNAME%26library%3DADM50%26op%3Dbor%2Dauth%26sub%5Flibrary%3DSUB%26verification%3DPASSWORD
23
+ Content-Length:
24
+ - '0'
25
+ Connection:
26
+ - close
27
+ Date:
28
+ - Thu, 23 Jan 2014 01:50:00 GMT
29
+ Server:
30
+ - OpenDNS Guide
31
+ body:
32
+ encoding: US-ASCII
33
+ string: ''
34
+ http_version:
35
+ recorded_at: Thu, 23 Jan 2014 01:49:59 GMT
36
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,48 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://example.com/X?bor_id=USERNAME&library=ADM50&op=bor-auth&sub_library=SUB&verification=PASSWORD
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.0
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - ! '*/*'
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Accept-Ranges:
22
+ - bytes
23
+ Cache-Control:
24
+ - max-age=604800
25
+ Content-Type:
26
+ - text/xml
27
+ Date:
28
+ - Wed, 22 Jan 2014 16:55:24 GMT
29
+ Etag:
30
+ - ! '"359670651"'
31
+ Expires:
32
+ - Wed, 29 Jan 2014 16:55:24 GMT
33
+ Last-Modified:
34
+ - Fri, 09 Aug 2013 23:54:35 GMT
35
+ Server:
36
+ - ECS (ewr/15E3)
37
+ X-Cache:
38
+ - HIT
39
+ X-Ec-Custom-Error:
40
+ - '1'
41
+ Content-Length:
42
+ - '1'
43
+ body:
44
+ encoding: US-ASCII
45
+ string: ! " "
46
+ http_version:
47
+ recorded_at: Wed, 22 Jan 2014 16:55:24 GMT
48
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,64 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://example.com/X?bor_id=USERNAME&library=ADM50&op=bor-auth&sub_library=SUB&verification=PASSWORD
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.0
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - ! '*/*'
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Accept-Ranges:
22
+ - bytes
23
+ Cache-Control:
24
+ - max-age=604800
25
+ Content-Type:
26
+ - text/html
27
+ Date:
28
+ - Wed, 22 Jan 2014 16:55:24 GMT
29
+ Etag:
30
+ - ! '"359670651"'
31
+ Expires:
32
+ - Wed, 29 Jan 2014 16:55:24 GMT
33
+ Last-Modified:
34
+ - Fri, 09 Aug 2013 23:54:35 GMT
35
+ Server:
36
+ - ECS (ewr/15E3)
37
+ X-Cache:
38
+ - HIT
39
+ X-Ec-Custom-Error:
40
+ - '1'
41
+ Content-Length:
42
+ - '1270'
43
+ body:
44
+ encoding: US-ASCII
45
+ string: ! "<!doctype html>\n<html>\n<head>\n <title>Example Domain</title>\n\n
46
+ \ <meta charset=\"utf-8\" />\n <meta http-equiv=\"Content-type\" content=\"text/html;
47
+ charset=utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width,
48
+ initial-scale=1\" />\n <style type=\"text/css\">\n body {\n background-color:
49
+ #f0f0f2;\n margin: 0;\n padding: 0;\n font-family: \"Open
50
+ Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n \n }\n
51
+ \ div {\n width: 600px;\n margin: 5em auto;\n padding:
52
+ 50px;\n background-color: #fff;\n border-radius: 1em;\n }\n
53
+ \ a:link, a:visited {\n color: #38488f;\n text-decoration:
54
+ none;\n }\n @media (max-width: 700px) {\n body {\n background-color:
55
+ #fff;\n }\n div {\n width: auto;\n margin:
56
+ 0 auto;\n border-radius: 0;\n padding: 1em;\n }\n
57
+ \ }\n </style> \n</head>\n\n<body>\n<div>\n <h1>Example Domain</h1>\n
58
+ \ <p>This domain is established to be used for illustrative examples in
59
+ documents. You may use this\n domain in examples without prior coordination
60
+ or asking for permission.</p>\n <p><a href=\"http://www.iana.org/domains/example\">More
61
+ information...</a></p>\n</div>\n</body>\n</html>\n"
62
+ http_version:
63
+ recorded_at: Wed, 22 Jan 2014 16:55:24 GMT
64
+ recorded_with: VCR 2.8.0