blob: 4ce999abc01154bae08fcacb4e2a40bd75aeec45 [file] [log] [blame]
Akron33f5c672019-06-24 19:40:47 +02001use Mojo::Base -strict;
2use Test::More;
Akroncdfd9d52019-07-23 11:35:00 +02003use Test::Mojo::WithRoles 'Session';
Akron33f5c672019-06-24 19:40:47 +02004use Mojo::File qw/path/;
5use Data::Dumper;
6
7
8#####################
9# Start Fake server #
10#####################
Akron63d963b2019-07-05 15:35:51 +020011my $mount_point = '/realapi/';
Akron33f5c672019-06-24 19:40:47 +020012$ENV{KALAMAR_API} = $mount_point;
13
Akroncdfd9d52019-07-23 11:35:00 +020014my $t = Test::Mojo::WithRoles->new('Kalamar' => {
Akron33f5c672019-06-24 19:40:47 +020015 Kalamar => {
16 plugins => ['Auth']
17 },
18 'Kalamar-Auth' => {
19 client_id => 2,
20 client_secret => 'k414m4r-s3cr3t',
21 oauth2 => 1
22 }
23});
24
25# Mount fake backend
26# Get the fixture path
27my $fixtures_path = path(Mojo::File->new(__FILE__)->dirname, '..', 'server');
28my $fake_backend = $t->app->plugin(
29 Mount => {
30 $mount_point =>
31 $fixtures_path->child('mock.pl')
32 }
33);
34# Configure fake backend
Akroncdfd9d52019-07-23 11:35:00 +020035my $fake_backend_app = $fake_backend->pattern->defaults->{app};
36
37# Set general app logger for simplicity
38$fake_backend_app->log($t->app->log);
39
40my $access_token = $fake_backend_app->get_token('access_token');
41my $refresh_token = $fake_backend_app->get_token('refresh_token');
42my $access_token_2 = $fake_backend_app->get_token('access_token_2');
43my $refresh_token_2 = $fake_backend_app->get_token('refresh_token_2');
44
45# Some routes to modify the session
46# This expires the session
47$t->app->routes->get('/x/expire')->to(
48 cb => sub {
49 my $c = shift;
50 $c->session(auth_exp => 0);
51 return $c->render(text => 'okay')
52 }
53);
54
55# This expires the session and removes the refresh token
56$t->app->routes->get('/x/expire-no-refresh')->to(
57 cb => sub {
58 my $c = shift;
59 $c->session(auth_exp => 0);
60 delete $c->session->{auth_r};
61 return $c->render(text => 'okay')
62 }
63);
64
65# This sets an invalid token
66$t->app->routes->get('/x/invalid')->to(
67 cb => sub {
68 my $c = shift;
69 $c->session(auth_exp => time + 1000);
70 $c->session(auth_r => $refresh_token_2);
71 $c->session(auth => 'Bearer inv4lid');
72 return $c->render(text => 'okay')
73 }
74);
75
76
77# This sets an invalid token
78$t->app->routes->get('/x/invalid-no-refresh')->to(
79 cb => sub {
80 my $c = shift;
81 $c->session(auth_exp => time + 1000);
82 delete $c->session->{auth_r};
83 $c->session(auth => 'Bearer inv4lid');
84 return $c->render(text => 'okay')
85 }
86);
87
88# This sets an invalid refresh token
89$t->app->routes->get('/x/expired-with-wrong-refresh')->to(
90 cb => sub {
91 my $c = shift;
92 $c->session(auth_exp => 0);
93 $c->session(auth => 'Bearer inv4lid');
94 $c->session(auth_r => 'inv4lid');
95 return $c->render(text => 'okay')
96 }
97);
98
Akron33f5c672019-06-24 19:40:47 +020099
Akron63d963b2019-07-05 15:35:51 +0200100$t->get_ok('/realapi/v1.0')
Akron33f5c672019-06-24 19:40:47 +0200101 ->status_is(200)
102 ->content_is('Fake server available');
103
104$t->get_ok('/?q=Baum')
105 ->status_is(200)
106 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
107 ->text_like('#total-results', qr/\d+$/)
108 ->content_like(qr/\"authorized\"\:null/)
109 ->element_exists_not('div.button.top a')
110 ->element_exists_not('aside.active')
111 ->element_exists_not('aside.off')
112 ;
113
114$t->get_ok('/')
115 ->status_is(200)
116 ->element_exists('form[action=/user/login] input[name=handle_or_email]')
117 ->element_exists('aside.active')
118 ->element_exists_not('aside.off')
119 ;
120
121$t->post_ok('/user/login' => form => { handle_or_email => 'test', pwd => 'fail' })
122 ->status_is(302)
123 ->header_is('Location' => '/');
124
125$t->get_ok('/')
126 ->status_is(200)
127 ->element_exists('div.notify-error')
128 ->text_is('div.notify-error', 'Bad CSRF token')
129 ->element_exists('input[name=handle_or_email][value=test]')
130 ->element_exists_not('div.button.top a')
131 ;
132
133$t->post_ok('/user/login' => form => { handle_or_email => 'test', pwd => 'pass' })
134 ->status_is(302)
135 ->header_is('Location' => '/');
136
137my $csrf = $t->get_ok('/')
138 ->status_is(200)
139 ->element_exists('div.notify-error')
140 ->text_is('div.notify-error', 'Bad CSRF token')
141 ->element_exists_not('div.button.top a')
142 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
143 ;
144
145$t->post_ok('/user/login' => form => {
146 handle_or_email => 'test',
147 pwd => 'ldaperr',
148 csrf_token => $csrf
149})
150 ->status_is(302)
151 ->content_is('')
152 ->header_is('Location' => '/');
153
154$csrf = $t->get_ok('/')
155 ->status_is(200)
156 ->element_exists('div.notify-error')
157 ->text_is('div.notify-error', '2022: LDAP Authentication failed due to unknown user or password!')
158 ->element_exists('input[name=handle_or_email][value=test]')
159 ->element_exists_not('div.button.top a')
160 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
161 ;
162
163$t->post_ok('/user/login' => form => {
164 handle_or_email => 'test',
165 pwd => 'unknown',
166 csrf_token => $csrf
167})
168 ->status_is(302)
169 ->content_is('')
170 ->header_is('Location' => '/');
171
172$csrf = $t->get_ok('/')
173 ->status_is(200)
174 ->element_exists('div.notify-error')
Akron8bbbecf2019-07-01 18:57:30 +0200175 ->text_is('div.notify-error', '2022: LDAP Authentication failed due to unknown user or password!')
Akron33f5c672019-06-24 19:40:47 +0200176 ->element_exists('input[name=handle_or_email][value=test]')
177 ->element_exists_not('div.button.top a')
178 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
179 ;
180
181$t->post_ok('/user/login' => form => {
182 handle_or_email => 'test',
183 pwd => 'pass',
184 csrf_token => $csrf
185})
186 ->status_is(302)
187 ->content_is('')
188 ->header_is('Location' => '/');
189
190$t->get_ok('/')
191 ->status_is(200)
192 ->element_exists_not('div.notify-error')
193 ->element_exists('div.notify-success')
194 ->text_is('div.notify-success', 'Login successful')
195 ->element_exists('aside.off')
196 ->element_exists_not('aside.active')
197 ;
198
Akron33f5c672019-06-24 19:40:47 +0200199# Now the user is logged in and should be able to
200# search with authorization
201$t->get_ok('/?q=Baum')
202 ->status_is(200)
203 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
204 ->text_like('#total-results', qr/\d+$/)
205 ->element_exists_not('div.notify-error')
206 ->content_like(qr/\"authorized\"\:\"yes\"/)
207 ->element_exists('div.button.top a')
208 ->element_exists('div.button.top a.logout[title~="test"]')
209 ;
210
211# Logout
212$t->get_ok('/user/logout')
213 ->status_is(302)
214 ->header_is('Location' => '/');
215
216$t->get_ok('/')
217 ->status_is(200)
218 ->element_exists_not('div.notify-error')
219 ->element_exists('div.notify-success')
220 ->text_is('div.notify-success', 'Logout successful')
221 ;
222
223$t->get_ok('/?q=Baum')
224 ->status_is(200)
225 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
226 ->text_like('#total-results', qr/\d+$/)
227 ->content_like(qr/\"authorized\"\:null/)
228 ;
229
230# Get redirect
231my $fwd = $t->get_ok('/?q=Baum&ql=poliqarp')
232 ->status_is(200)
233 ->element_exists_not('div.notify-error')
234 ->tx->res->dom->at('input[name=fwd]')->attr('value')
235 ;
236
237is($fwd, '/?q=Baum&ql=poliqarp', 'Redirect is valid');
238
239$t->post_ok('/user/login' => form => {
240 handle_or_email => 'test',
241 pwd => 'pass',
242 csrf_token => $csrf,
243 fwd => 'http://bad.example.com/test'
244})
245 ->status_is(302)
246 ->header_is('Location' => '/');
247
248$t->get_ok('/')
249 ->status_is(200)
250 ->element_exists('div.notify-error')
251 ->element_exists_not('div.notify-success')
252 ->text_is('div.notify-error', 'Redirect failure')
253 ;
254
255$t->post_ok('/user/login' => form => {
256 handle_or_email => 'test',
257 pwd => 'pass',
258 csrf_token => $csrf,
259 fwd => $fwd
260})
261 ->status_is(302)
262 ->header_is('Location' => '/?q=Baum&ql=poliqarp');
263
Akron8bbbecf2019-07-01 18:57:30 +0200264$t->get_ok('/?q=Baum&ql=poliqarp')
265 ->status_is(200)
266 ->element_exists_not('div.notify-error')
267 ->element_exists('div.notify-success')
268 ->text_is('div.notify-success', 'Login successful')
Akroncdfd9d52019-07-23 11:35:00 +0200269 ->session_has('/auth')
270 ->session_is('/auth', 'Bearer ' . $access_token)
271 ->session_is('/auth_r', $refresh_token)
272 ->header_isnt('X-Kalamar-Cache', 'true')
Akron8bbbecf2019-07-01 18:57:30 +0200273 ;
274
Akroncdfd9d52019-07-23 11:35:00 +0200275# Expire the session
276# (makes the token be marked as expired - though it isn't serverside)
277$t->get_ok('/x/expire')
Akron8bbbecf2019-07-01 18:57:30 +0200278 ->status_is(200)
Akroncdfd9d52019-07-23 11:35:00 +0200279 ->content_is('okay')
280 ;
281
282## It may be a problem, but the cache is still valid
283$t->get_ok('/?q=Baum')
284 ->status_is(200)
285 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
286 ->text_like('#total-results', qr/\d+$/)
287 ->content_like(qr/\"authorized\"\:\"yes\"/)
288 ->header_is('X-Kalamar-Cache', 'true')
289 ;
290
291# Query without partial cache (unfortunately) (but no total results)
292$t->get_ok('/?q=baum&cutoff=true')
293 ->status_is(200)
294 ->session_is('/auth', 'Bearer ' . $access_token_2)
295 ->session_is('/auth_r', $refresh_token_2)
296 ->text_is('#error','')
297 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
298 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
299 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
300 ->content_like(qr/\"authorized\"\:\"yes\"/)
301 ->header_isnt('X-Kalamar-Cache', 'true')
302 ->content_like(qr!\"cutOff":true!)
303 ->element_exists_not('#total-results')
304 ;
305
306# Expire the session and remove the refresh option
307$t->get_ok('/x/expire-no-refresh')
308 ->status_is(200)
309 ->content_is('okay')
310 ;
311
312$t->app->defaults(no_cache => 1);
313
314
315$t->get_ok('/x/invalid-no-refresh')
316 ->status_is(200)
317 ->content_is('okay')
318 ;
319
320# Query without cache
321# The token is invalid and can't be refreshed!
322$t->get_ok('/?q=baum&cutoff=true')
323 ->status_is(200)
324 ->session_hasnt('/auth')
325 ->session_hasnt('/auth_r')
326 ->text_is('#error','')
327 ->text_is('div.notify-error','Access token invalid')
328 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
329 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
330 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
331 ->content_unlike(qr/\"authorized\"\:\"yes\"/)
332 ->header_isnt('X-Kalamar-Cache', 'true')
333 ->element_exists('p.no-results')
334 ;
335
336$t->get_ok('/x/invalid')
337 ->status_is(200)
338 ->content_is('okay')
339 ;
340
341# Query without cache
342# The token is invalid and can't be refreshed!
343$t->get_ok('/?q=baum&cutoff=true')
344 ->status_is(200)
345 ->session_is('/auth', 'Bearer ' . $access_token_2)
346 ->session_is('/auth_r', $refresh_token_2)
347 ->text_is('#error','')
348 ->element_exists_not('div.notify-error','Access token invalid')
349 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
350 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
351 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
352 ->content_like(qr/\"authorized\"\:\"yes\"/)
353 ->header_isnt('X-Kalamar-Cache', 'true')
354 ->element_exists_not('p.no-results')
Akron8bbbecf2019-07-01 18:57:30 +0200355 ;
356
Akron33f5c672019-06-24 19:40:47 +0200357
Akroncdfd9d52019-07-23 11:35:00 +0200358$t->get_ok('/x/expired-with-wrong-refresh')
359 ->status_is(200)
360 ->content_is('okay')
361 ;
Akron4796e002019-07-05 10:13:15 +0200362
Akron4796e002019-07-05 10:13:15 +0200363
Akroncdfd9d52019-07-23 11:35:00 +0200364# The token is invalid and can't be refreshed!
365$t->get_ok('/?q=baum&cutoff=true')
366 ->status_is(200)
367 ->session_hasnt('/auth')
368 ->session_hasnt('/auth_r')
369 ->text_is('#error','')
370 ->text_is('div.notify-error','Refresh token is expired')
371 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
372 ->content_unlike(qr/\"authorized\"\:\"yes\"/)
373 ->element_exists('p.no-results')
374 ;
Akron4796e002019-07-05 10:13:15 +0200375
Akron4796e002019-07-05 10:13:15 +0200376
Akron33f5c672019-06-24 19:40:47 +0200377done_testing;
378__END__
379