omniauth-aleph 0.1.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.
@@ -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