blob: 20c9b64fb961e7b7a333090f9b34ffd5108c11ea [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',
Akron59992122019-10-29 11:28:45 +010021 oauth2 => 1,
22 experimental_client_registration => 1
Akron33f5c672019-06-24 19:40:47 +020023 }
24});
25
26# Mount fake backend
27# Get the fixture path
28my $fixtures_path = path(Mojo::File->new(__FILE__)->dirname, '..', 'server');
29my $fake_backend = $t->app->plugin(
30 Mount => {
31 $mount_point =>
32 $fixtures_path->child('mock.pl')
33 }
34);
35# Configure fake backend
Akroncdfd9d52019-07-23 11:35:00 +020036my $fake_backend_app = $fake_backend->pattern->defaults->{app};
37
38# Set general app logger for simplicity
39$fake_backend_app->log($t->app->log);
40
41my $access_token = $fake_backend_app->get_token('access_token');
42my $refresh_token = $fake_backend_app->get_token('refresh_token');
43my $access_token_2 = $fake_backend_app->get_token('access_token_2');
44my $refresh_token_2 = $fake_backend_app->get_token('refresh_token_2');
45
46# Some routes to modify the session
47# This expires the session
48$t->app->routes->get('/x/expire')->to(
49 cb => sub {
50 my $c = shift;
51 $c->session(auth_exp => 0);
52 return $c->render(text => 'okay')
53 }
54);
55
56# This expires the session and removes the refresh token
57$t->app->routes->get('/x/expire-no-refresh')->to(
58 cb => sub {
59 my $c = shift;
60 $c->session(auth_exp => 0);
61 delete $c->session->{auth_r};
62 return $c->render(text => 'okay')
63 }
64);
65
66# This sets an invalid token
67$t->app->routes->get('/x/invalid')->to(
68 cb => sub {
69 my $c = shift;
70 $c->session(auth_exp => time + 1000);
71 $c->session(auth_r => $refresh_token_2);
72 $c->session(auth => 'Bearer inv4lid');
73 return $c->render(text => 'okay')
74 }
75);
76
77
78# This sets an invalid token
79$t->app->routes->get('/x/invalid-no-refresh')->to(
80 cb => sub {
81 my $c = shift;
82 $c->session(auth_exp => time + 1000);
83 delete $c->session->{auth_r};
84 $c->session(auth => 'Bearer inv4lid');
85 return $c->render(text => 'okay')
86 }
87);
88
89# This sets an invalid refresh token
90$t->app->routes->get('/x/expired-with-wrong-refresh')->to(
91 cb => sub {
92 my $c = shift;
93 $c->session(auth_exp => 0);
94 $c->session(auth => 'Bearer inv4lid');
95 $c->session(auth_r => 'inv4lid');
96 return $c->render(text => 'okay')
97 }
98);
99
Akronbc6b3f22021-01-13 14:53:12 +0100100my $q = qr!(?:\"|")!;
Akron33f5c672019-06-24 19:40:47 +0200101
Akron63d963b2019-07-05 15:35:51 +0200102$t->get_ok('/realapi/v1.0')
Akron33f5c672019-06-24 19:40:47 +0200103 ->status_is(200)
104 ->content_is('Fake server available');
105
106$t->get_ok('/?q=Baum')
107 ->status_is(200)
108 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
109 ->text_like('#total-results', qr/\d+$/)
Akronbc6b3f22021-01-13 14:53:12 +0100110 ->content_like(qr/${q}authorized${q}:null/)
Akron33f5c672019-06-24 19:40:47 +0200111 ->element_exists_not('div.button.top a')
112 ->element_exists_not('aside.active')
113 ->element_exists_not('aside.off')
114 ;
115
116$t->get_ok('/')
117 ->status_is(200)
Akrone208d302020-11-28 11:14:50 +0100118 ->element_exists('form[action=/user/login] input[name=handle]')
Akron33f5c672019-06-24 19:40:47 +0200119 ->element_exists('aside.active')
120 ->element_exists_not('aside.off')
121 ;
122
Akron3e0fdc12020-05-15 16:17:21 +0200123# Test for bug with long password
124$t->post_ok('/user/login' => form => {
Akrone208d302020-11-28 11:14:50 +0100125 handle => 'test',
Akron3e0fdc12020-05-15 16:17:21 +0200126 pwd => 'kjskjhndkjndqknaskjnakjdnkjdankajdnkjdsankjdsakjdfkjahzroiuqzriudjoijdmlamdlkmdsalkmdl' })
127 ->status_is(302)
128 ->header_is('Location' => '/');
129
Akrone208d302020-11-28 11:14:50 +0100130$t->post_ok('/user/login' => form => { handle => 'test', pwd => 'fail' })
Akron33f5c672019-06-24 19:40:47 +0200131 ->status_is(302)
132 ->header_is('Location' => '/');
133
134$t->get_ok('/')
135 ->status_is(200)
136 ->element_exists('div.notify-error')
137 ->text_is('div.notify-error', 'Bad CSRF token')
Akrone208d302020-11-28 11:14:50 +0100138 ->element_exists('input[name=handle][value=test]')
Akron33f5c672019-06-24 19:40:47 +0200139 ->element_exists_not('div.button.top a')
140 ;
141
Akrone208d302020-11-28 11:14:50 +0100142$t->post_ok('/user/login' => form => { handle => 'test', pwd => 'pass' })
Akron33f5c672019-06-24 19:40:47 +0200143 ->status_is(302)
144 ->header_is('Location' => '/');
145
146my $csrf = $t->get_ok('/')
147 ->status_is(200)
148 ->element_exists('div.notify-error')
149 ->text_is('div.notify-error', 'Bad CSRF token')
150 ->element_exists_not('div.button.top a')
151 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
152 ;
153
154$t->post_ok('/user/login' => form => {
Akrone208d302020-11-28 11:14:50 +0100155 handle => 'test',
Akron33f5c672019-06-24 19:40:47 +0200156 pwd => 'ldaperr',
157 csrf_token => $csrf
158})
159 ->status_is(302)
160 ->content_is('')
161 ->header_is('Location' => '/');
162
163$csrf = $t->get_ok('/')
164 ->status_is(200)
165 ->element_exists('div.notify-error')
166 ->text_is('div.notify-error', '2022: LDAP Authentication failed due to unknown user or password!')
Akrone208d302020-11-28 11:14:50 +0100167 ->element_exists('input[name=handle][value=test]')
Akron33f5c672019-06-24 19:40:47 +0200168 ->element_exists_not('div.button.top a')
Akron3b3c7af2020-05-15 16:23:55 +0200169 ->element_exists_not('div.notify-success')
Akron33f5c672019-06-24 19:40:47 +0200170 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
171 ;
172
173$t->post_ok('/user/login' => form => {
Akrone208d302020-11-28 11:14:50 +0100174 handle => 'test',
Akron33f5c672019-06-24 19:40:47 +0200175 pwd => 'unknown',
176 csrf_token => $csrf
177})
178 ->status_is(302)
179 ->content_is('')
180 ->header_is('Location' => '/');
181
182$csrf = $t->get_ok('/')
183 ->status_is(200)
184 ->element_exists('div.notify-error')
Akron8bbbecf2019-07-01 18:57:30 +0200185 ->text_is('div.notify-error', '2022: LDAP Authentication failed due to unknown user or password!')
Akrone208d302020-11-28 11:14:50 +0100186 ->element_exists('input[name=handle][value=test]')
Akron33f5c672019-06-24 19:40:47 +0200187 ->element_exists_not('div.button.top a')
188 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
189 ;
190
191$t->post_ok('/user/login' => form => {
Akrone208d302020-11-28 11:14:50 +0100192 handle => 'test',
Akron33f5c672019-06-24 19:40:47 +0200193 pwd => 'pass',
194 csrf_token => $csrf
195})
196 ->status_is(302)
197 ->content_is('')
198 ->header_is('Location' => '/');
199
200$t->get_ok('/')
201 ->status_is(200)
202 ->element_exists_not('div.notify-error')
203 ->element_exists('div.notify-success')
204 ->text_is('div.notify-success', 'Login successful')
Akron1d09b532021-06-15 18:18:25 +0200205 ->element_exists_not('aside.off')
206 ->element_exists('aside.active')
207 ->element_exists('aside.settings')
Akron33f5c672019-06-24 19:40:47 +0200208 ;
209
Akron33f5c672019-06-24 19:40:47 +0200210# Now the user is logged in and should be able to
211# search with authorization
212$t->get_ok('/?q=Baum')
213 ->status_is(200)
Akron4cefe1f2019-09-04 10:11:28 +0200214 ->session_has('/auth')
215 ->session_is('/auth', 'Bearer ' . $access_token)
216 ->session_is('/auth_r', $refresh_token)
217 ->session_is('/user', 'test')
Akron33f5c672019-06-24 19:40:47 +0200218 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
219 ->text_like('#total-results', qr/\d+$/)
220 ->element_exists_not('div.notify-error')
Akronbc6b3f22021-01-13 14:53:12 +0100221 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akron33f5c672019-06-24 19:40:47 +0200222 ->element_exists('div.button.top a')
223 ->element_exists('div.button.top a.logout[title~="test"]')
224 ;
225
Akron27031aa2020-04-28 14:57:10 +0200226$t->get_ok('/?q=Paum')
227 ->status_is(200)
228 ->text_like('h1 span', qr/KorAP: Find .Paum./i)
229 ->text_is('#total-results', '')
Akronbc6b3f22021-01-13 14:53:12 +0100230 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akron27031aa2020-04-28 14:57:10 +0200231 ->element_exists_not('p.hint')
232 ;
233
234
Akron33f5c672019-06-24 19:40:47 +0200235# Logout
236$t->get_ok('/user/logout')
237 ->status_is(302)
Akron4cefe1f2019-09-04 10:11:28 +0200238 ->session_hasnt('/auth')
239 ->session_hasnt('/auth_r')
240 ->session_hasnt('/user')
Akron33f5c672019-06-24 19:40:47 +0200241 ->header_is('Location' => '/');
242
243$t->get_ok('/')
244 ->status_is(200)
245 ->element_exists_not('div.notify-error')
246 ->element_exists('div.notify-success')
247 ->text_is('div.notify-success', 'Logout successful')
Akrone208d302020-11-28 11:14:50 +0100248 ->element_exists("input[name=handle]")
249 ->element_exists("input[name=handle][value=test]")
Akron33f5c672019-06-24 19:40:47 +0200250 ;
251
252$t->get_ok('/?q=Baum')
253 ->status_is(200)
254 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
255 ->text_like('#total-results', qr/\d+$/)
Akronbc6b3f22021-01-13 14:53:12 +0100256 ->content_like(qr/${q}authorized${q}:null/)
Akron33f5c672019-06-24 19:40:47 +0200257 ;
258
Akron27031aa2020-04-28 14:57:10 +0200259$t->get_ok('/?q=Paum')
260 ->status_is(200)
261 ->text_like('h1 span', qr/KorAP: Find .Paum./i)
262 ->text_is('#total-results', '')
Akronbc6b3f22021-01-13 14:53:12 +0100263 ->content_like(qr/${q}authorized${q}:null/)
Akron27031aa2020-04-28 14:57:10 +0200264 ->text_is('p.hint', 'Maybe you need to log in first?')
265 ;
266
267
Akron33f5c672019-06-24 19:40:47 +0200268# Get redirect
269my $fwd = $t->get_ok('/?q=Baum&ql=poliqarp')
270 ->status_is(200)
271 ->element_exists_not('div.notify-error')
272 ->tx->res->dom->at('input[name=fwd]')->attr('value')
273 ;
274
275is($fwd, '/?q=Baum&ql=poliqarp', 'Redirect is valid');
276
277$t->post_ok('/user/login' => form => {
Akrone208d302020-11-28 11:14:50 +0100278 handle => 'test',
Akron33f5c672019-06-24 19:40:47 +0200279 pwd => 'pass',
280 csrf_token => $csrf,
281 fwd => 'http://bad.example.com/test'
282})
283 ->status_is(302)
284 ->header_is('Location' => '/');
285
286$t->get_ok('/')
287 ->status_is(200)
288 ->element_exists('div.notify-error')
289 ->element_exists_not('div.notify-success')
290 ->text_is('div.notify-error', 'Redirect failure')
291 ;
292
293$t->post_ok('/user/login' => form => {
Akrone208d302020-11-28 11:14:50 +0100294 handle => 'test',
Akron33f5c672019-06-24 19:40:47 +0200295 pwd => 'pass',
296 csrf_token => $csrf,
297 fwd => $fwd
298})
299 ->status_is(302)
300 ->header_is('Location' => '/?q=Baum&ql=poliqarp');
301
Akron8bbbecf2019-07-01 18:57:30 +0200302$t->get_ok('/?q=Baum&ql=poliqarp')
303 ->status_is(200)
304 ->element_exists_not('div.notify-error')
305 ->element_exists('div.notify-success')
306 ->text_is('div.notify-success', 'Login successful')
Akroncdfd9d52019-07-23 11:35:00 +0200307 ->session_has('/auth')
308 ->session_is('/auth', 'Bearer ' . $access_token)
309 ->session_is('/auth_r', $refresh_token)
310 ->header_isnt('X-Kalamar-Cache', 'true')
Akron8bbbecf2019-07-01 18:57:30 +0200311 ;
312
Akroncdfd9d52019-07-23 11:35:00 +0200313# Expire the session
314# (makes the token be marked as expired - though it isn't serverside)
315$t->get_ok('/x/expire')
Akron8bbbecf2019-07-01 18:57:30 +0200316 ->status_is(200)
Akroncdfd9d52019-07-23 11:35:00 +0200317 ->content_is('okay')
318 ;
319
320## It may be a problem, but the cache is still valid
321$t->get_ok('/?q=Baum')
322 ->status_is(200)
323 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
324 ->text_like('#total-results', qr/\d+$/)
Akronbc6b3f22021-01-13 14:53:12 +0100325 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200326 ->header_is('X-Kalamar-Cache', 'true')
327 ;
328
329# Query without partial cache (unfortunately) (but no total results)
330$t->get_ok('/?q=baum&cutoff=true')
331 ->status_is(200)
332 ->session_is('/auth', 'Bearer ' . $access_token_2)
333 ->session_is('/auth_r', $refresh_token_2)
334 ->text_is('#error','')
335 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
336 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
337 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
Akronbc6b3f22021-01-13 14:53:12 +0100338 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200339 ->header_isnt('X-Kalamar-Cache', 'true')
Akronbc6b3f22021-01-13 14:53:12 +0100340 ->content_like(qr!${q}cutOff${q}:true!)
Akroncdfd9d52019-07-23 11:35:00 +0200341 ->element_exists_not('#total-results')
342 ;
343
344# Expire the session and remove the refresh option
345$t->get_ok('/x/expire-no-refresh')
346 ->status_is(200)
347 ->content_is('okay')
348 ;
349
350$t->app->defaults(no_cache => 1);
351
352
353$t->get_ok('/x/invalid-no-refresh')
354 ->status_is(200)
355 ->content_is('okay')
356 ;
357
358# Query without cache
359# The token is invalid and can't be refreshed!
360$t->get_ok('/?q=baum&cutoff=true')
Akron3c390c42020-03-30 09:06:21 +0200361 ->status_is(400)
Akroncdfd9d52019-07-23 11:35:00 +0200362 ->session_hasnt('/auth')
363 ->session_hasnt('/auth_r')
364 ->text_is('#error','')
365 ->text_is('div.notify-error','Access token invalid')
366 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
367 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
368 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
Akronbc6b3f22021-01-13 14:53:12 +0100369 ->content_unlike(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200370 ->header_isnt('X-Kalamar-Cache', 'true')
371 ->element_exists('p.no-results')
372 ;
373
374$t->get_ok('/x/invalid')
375 ->status_is(200)
376 ->content_is('okay')
377 ;
378
379# Query without cache
380# The token is invalid and can't be refreshed!
381$t->get_ok('/?q=baum&cutoff=true')
382 ->status_is(200)
383 ->session_is('/auth', 'Bearer ' . $access_token_2)
384 ->session_is('/auth_r', $refresh_token_2)
385 ->text_is('#error','')
386 ->element_exists_not('div.notify-error','Access token invalid')
387 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
388 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
389 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
Akronbc6b3f22021-01-13 14:53:12 +0100390 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200391 ->header_isnt('X-Kalamar-Cache', 'true')
392 ->element_exists_not('p.no-results')
Akron8bbbecf2019-07-01 18:57:30 +0200393 ;
394
Akron33f5c672019-06-24 19:40:47 +0200395
Akroncdfd9d52019-07-23 11:35:00 +0200396$t->get_ok('/x/expired-with-wrong-refresh')
397 ->status_is(200)
398 ->content_is('okay')
399 ;
Akron4796e002019-07-05 10:13:15 +0200400
Akron4796e002019-07-05 10:13:15 +0200401
Akroncdfd9d52019-07-23 11:35:00 +0200402# The token is invalid and can't be refreshed!
Akron59992122019-10-29 11:28:45 +0100403$csrf = $t->get_ok('/?q=baum&cutoff=true')
Akron3c390c42020-03-30 09:06:21 +0200404 ->status_is(400)
Akroncdfd9d52019-07-23 11:35:00 +0200405 ->session_hasnt('/auth')
406 ->session_hasnt('/auth_r')
407 ->text_is('#error','')
408 ->text_is('div.notify-error','Refresh token is expired')
409 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
Akronbc6b3f22021-01-13 14:53:12 +0100410 ->content_unlike(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200411 ->element_exists('p.no-results')
Akron59992122019-10-29 11:28:45 +0100412 ->tx->res->dom->at('input[name="csrf_token"]')
413 ->attr('value')
Akroncdfd9d52019-07-23 11:35:00 +0200414 ;
Akron4796e002019-07-05 10:13:15 +0200415
Akron59992122019-10-29 11:28:45 +0100416# Login:
417$t->post_ok('/user/login' => form => {
Akrone208d302020-11-28 11:14:50 +0100418 handle => 'test',
Akron59992122019-10-29 11:28:45 +0100419 pwd => 'pass',
420 csrf_token => $csrf
421})
422 ->status_is(302)
423 ->content_is('')
424 ->header_is('Location' => '/');
425
426$t->get_ok('/')
427 ->status_is(200)
428 ->element_exists_not('div.notify-error')
429 ->element_exists('div.notify-success')
430 ->text_is('div.notify-success', 'Login successful')
Akron1d09b532021-06-15 18:18:25 +0200431 ->element_exists_not('aside.off')
432 ->element_exists('aside.active')
433 ->element_exists('aside.settings')
Akron59992122019-10-29 11:28:45 +0100434 ;
435
436$t->get_ok('/settings/oauth')
437 ->text_is('form.form-table legend', 'Register new client application')
438 ->attr_is('form.oauth-register','action', '/settings/oauth/register')
Akron1a9d5be2020-03-19 17:28:33 +0100439 ->element_exists('ul.client-list')
440 ->element_exists_not('ul.client-list > li')
Akronad011bb2021-06-10 12:16:36 +0200441 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
442 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
443 ->header_is('Pragma','no-cache')
Akron59992122019-10-29 11:28:45 +0100444 ;
Akronad011bb2021-06-10 12:16:36 +0200445
Akron59992122019-10-29 11:28:45 +0100446$csrf = $t->post_ok('/settings/oauth/register' => form => {
447 name => 'MyApp',
448 type => 'PUBLIC',
449 desc => 'This is my application'
450})
451 ->text_is('div.notify-error', 'Bad CSRF token')
452 ->tx->res->dom->at('input[name="csrf_token"]')
453 ->attr('value')
454 ;
455
456$t->post_ok('/settings/oauth/register' => form => {
457 name => 'MyApp',
458 type => 'CONFIDENTIAL',
459 desc => 'This is my application',
460 csrf_token => $csrf
461})
462 ->status_is(200)
463 ->element_exists('div.notify-success')
464 ->text_is('legend', 'Client Credentials')
465 ->text_is('label[for=client_id]', 'ID of the client application')
466 ->element_exists('input[name=client_id][readonly][value]')
467 ->element_exists('input[name=client_secret][readonly][value]')
Akronad011bb2021-06-10 12:16:36 +0200468 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
469 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
470 ->header_is('Pragma','no-cache')
Akron59992122019-10-29 11:28:45 +0100471 ;
Akron4796e002019-07-05 10:13:15 +0200472
Akron1a9d5be2020-03-19 17:28:33 +0100473$t->get_ok('/settings/oauth')
Akronc1aaf932021-06-09 12:19:15 +0200474 ->text_is('.form-table legend', 'Register new client application')
475 ->attr_is('.oauth-register','action', '/settings/oauth/register')
Akron17de86e2020-04-16 16:03:40 +0200476 ->text_is('ul.client-list > li > span.client-name a', 'MyApp')
Akron1a9d5be2020-03-19 17:28:33 +0100477 ->text_is('ul.client-list > li > span.client-desc', 'This is my application')
478 ->text_is('ul.client-list > li > span.client-url a', '')
Akronad011bb2021-06-10 12:16:36 +0200479 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
480 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
481 ->header_is('Pragma','no-cache')
Akron17de86e2020-04-16 16:03:40 +0200482 ;
483
Akron041ca4d2021-06-10 11:52:51 +0200484$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akron17de86e2020-04-16 16:03:40 +0200485 ->status_is(200)
Akronc1aaf932021-06-09 12:19:15 +0200486 ->text_is('ul.client-list > li.client > span.client-name', 'MyApp')
487 ->text_is('ul.client-list > li.client > span.client-desc', 'This is my application')
Akron17de86e2020-04-16 16:03:40 +0200488 ->text_is('a.client-unregister', 'Unregister')
Akron041ca4d2021-06-10 11:52:51 +0200489 ->attr_is('a.client-unregister', 'href', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister?name=MyApp')
Akron1a9d5be2020-03-19 17:28:33 +0100490 ;
491
Akron041ca4d2021-06-10 11:52:51 +0200492$csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister?name=MyApp')
Akron1a9d5be2020-03-19 17:28:33 +0100493 ->content_like(qr!Do you really want to unregister \<span class="client-name"\>MyApp\<\/span\>?!)
Akronc1aaf932021-06-09 12:19:15 +0200494 ->attr_is('.form-table input[name=client-name]', 'value', 'MyApp')
Akronad011bb2021-06-10 12:16:36 +0200495 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
496 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
497 ->header_is('Pragma','no-cache')
Akron1a9d5be2020-03-19 17:28:33 +0100498 ->tx->res->dom->at('input[name="csrf_token"]')
499 ->attr('value')
500 ;
501
Akron041ca4d2021-06-10 11:52:51 +0200502$t->post_ok('/settings/oauth/xxxx==/unregister' => form => {
Akron1a9d5be2020-03-19 17:28:33 +0100503 'client-name' => 'MyApp',
Akron1a9d5be2020-03-19 17:28:33 +0100504 'csrf_token' => $csrf
505})->status_is(302)
506 ->content_is('')
507 ->header_is('Location' => '/settings/oauth')
508 ;
509
510$t->get_ok('/settings/oauth')
Akronc1aaf932021-06-09 12:19:15 +0200511 ->text_is('.form-table legend', 'Register new client application')
512 ->attr_is('.oauth-register','action', '/settings/oauth/register')
Akron1a9d5be2020-03-19 17:28:33 +0100513 ->element_exists('ul.client-list > li')
514 ->text_is('div.notify', 'Unknown client with xxxx==.')
Akronad011bb2021-06-10 12:16:36 +0200515 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
516 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
517 ->header_is('Pragma','no-cache')
Akron1a9d5be2020-03-19 17:28:33 +0100518 ;
519
Akron041ca4d2021-06-10 11:52:51 +0200520$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister' => form => {
Akron1a9d5be2020-03-19 17:28:33 +0100521 'client-name' => 'MyApp',
Akron1a9d5be2020-03-19 17:28:33 +0100522 'csrf_token' => $csrf
523})->status_is(302)
524 ->content_is('')
525 ->header_is('Location' => '/settings/oauth')
526 ;
527
528$t->get_ok('/settings/oauth')
Akronc1aaf932021-06-09 12:19:15 +0200529 ->text_is('.form-table legend', 'Register new client application')
530 ->attr_is('.oauth-register','action', '/settings/oauth/register')
Akron1a9d5be2020-03-19 17:28:33 +0100531 ->element_exists_not('ul.client-list > li')
532 ->text_is('div.notify-success', 'Successfully deleted MyApp')
Akronad011bb2021-06-10 12:16:36 +0200533 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
534 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
535 ->header_is('Pragma','no-cache')
Akron1a9d5be2020-03-19 17:28:33 +0100536 ;
537
Akron83209f72021-01-29 17:54:15 +0100538$t->post_ok('/settings/oauth/register' => form => {
539 name => 'MyApp2',
540 type => 'PUBLIC',
541 desc => 'This is my application',
542 csrf_token => $csrf
543})->status_is(200)
544 ->element_exists('div.notify-success')
545 ->text_is('legend', 'Client Credentials')
546 ->text_is('label[for=client_id]', 'ID of the client application')
547 ->element_exists('input[name=client_id][readonly][value]')
548 ->element_exists_not('input[name=client_secret][readonly][value]')
Akronad011bb2021-06-10 12:16:36 +0200549 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
550 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
551 ->header_is('Pragma','no-cache')
Akron83209f72021-01-29 17:54:15 +0100552 ;
553
Akron041ca4d2021-06-10 11:52:51 +0200554$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akron83209f72021-01-29 17:54:15 +0100555 ->text_is('.client-name', 'MyApp2')
556 ->text_is('.client-desc', 'This is my application')
Akrone997bb52021-06-11 16:44:06 +0200557 ->text_is('.client-issue-token', 'Issue new token')
Akron041ca4d2021-06-10 11:52:51 +0200558 ->attr_is('.client-issue-token', 'href', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?name=MyApp2')
Akronad011bb2021-06-10 12:16:36 +0200559 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
560 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
561 ->header_is('Pragma','no-cache')
Akrone997bb52021-06-11 16:44:06 +0200562 ->text_is('ul.token-list label[for=token]', 'Access Token')
563 ->text_is('p[name=created]', 'Created at ')
564 ->text_is('p[name=expires]', 'Expires in 31533851 seconds.')
Akron83209f72021-01-29 17:54:15 +0100565 ;
566
Akron041ca4d2021-06-10 11:52:51 +0200567$csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?name=MyApp2')
Akron83209f72021-01-29 17:54:15 +0100568 ->status_is(200)
Akron041ca4d2021-06-10 11:52:51 +0200569 ->attr_is('#issue-token','action', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token')
Akron83209f72021-01-29 17:54:15 +0100570 ->attr_is('input[name=client-id]', 'value', 'fCBbQkA2NDA3MzM1Yw==')
571 ->attr_is('input[name=name]', 'value', 'MyApp2')
Akronad011bb2021-06-10 12:16:36 +0200572 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
573 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
574 ->header_is('Pragma','no-cache')
Akrone997bb52021-06-11 16:44:06 +0200575 ->text_is('a.button-abort', 'Abort')
576 ->attr_is('#issue-token input[type=submit]', 'value', 'Issue new token')
577 ->content_like(qr!Issue a new token for!)
Akron83209f72021-01-29 17:54:15 +0100578 ->tx->res->dom->at('input[name="csrf_token"]')
579 ->attr('value')
580 ;
581
Akron041ca4d2021-06-10 11:52:51 +0200582$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token' => form => {
Akron83209f72021-01-29 17:54:15 +0100583 csrf_token => $csrf,
584 name => 'MyApp2',
585 'client-id' => 'fCBbQkA2NDA3MzM1Yw=='
586})
Akronbc94a9c2021-04-15 00:07:35 +0200587 ->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200588 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronbc94a9c2021-04-15 00:07:35 +0200589 ;
590
Akron041ca4d2021-06-10 11:52:51 +0200591$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
592 ->status_is(200)
Akronbc94a9c2021-04-15 00:07:35 +0200593 ->text_is('div.notify-success', 'New access token created')
Akronad011bb2021-06-10 12:16:36 +0200594 ->status_is(200)
595 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
596 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
597 ->header_is('Pragma','no-cache')
Akron83209f72021-01-29 17:54:15 +0100598 ;
599
Akron041ca4d2021-06-10 11:52:51 +0200600$csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200601 ->status_is(200)
Akron041ca4d2021-06-10 11:52:51 +0200602 ->attr_is('form.token-revoke', 'action', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token/revoke')
Akronc1aaf932021-06-09 12:19:15 +0200603 ->attr_is('form.token-revoke input[name=token]', 'value', 'jhkhkjhk_hjgjsfz67i')
604 ->attr_is('form.token-revoke input[name=name]', 'value', 'MyApp2')
605 ->tx->res->dom->at('input[name="csrf_token"]')
606 ->attr('value')
607 ;
608
Akron041ca4d2021-06-10 11:52:51 +0200609$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token/revoke' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200610 csrf_token => $csrf,
611 name => 'MyApp2',
612 token => 'jhkhkjhk_hjgjsfz67i'
613})
614 ->status_is(200)
Akron041ca4d2021-06-10 11:52:51 +0200615 ->attr_is('form#revoke-token','action','/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE')
Akronc1aaf932021-06-09 12:19:15 +0200616 ->attr_is('form#revoke-token','method','POST')
617 ->attr_is('form#revoke-token input[name=token]','value','jhkhkjhk_hjgjsfz67i')
Akrone997bb52021-06-11 16:44:06 +0200618 ->text_is('a.button-abort', 'Abort')
619 ->attr_is('#revoke-token input[type=submit]', 'value', 'Revoke')
620 ->content_like(qr!Revoke a token for!)
Akronc1aaf932021-06-09 12:19:15 +0200621;
622
623
624# CSRF missing
Akron041ca4d2021-06-10 11:52:51 +0200625$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200626 name => 'MyApp2',
627 token => 'jhkhkjhk_hjgjsfz67i'
628})->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200629 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200630 ;
631
Akron041ca4d2021-06-10 11:52:51 +0200632$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200633 ->element_exists_not('div.notify-success')
634 ->text_is('div.notify-error', 'Bad CSRF token')
635 ;
636
637# Token missing
Akron041ca4d2021-06-10 11:52:51 +0200638$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200639 name => 'MyApp2',
640 csrf_token => $csrf,
641})->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200642 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200643 ;
644
Akron041ca4d2021-06-10 11:52:51 +0200645$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200646 ->element_exists_not('div.notify-success')
647 ->text_is('div.notify-error', 'Some fields are invalid')
648 ;
649
Akron041ca4d2021-06-10 11:52:51 +0200650$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200651 name => 'MyApp2',
652 csrf_token => $csrf,
653 token => 'jhkhkjhk_hjgjsfz67i'
654})->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200655 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200656 ;
657
658
Akron041ca4d2021-06-10 11:52:51 +0200659$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200660 ->element_exists_not('div.notify-error')
661 ->text_is('div.notify-success', 'Token was revoked successfully')
662 ;
Akron83209f72021-01-29 17:54:15 +0100663
Akron33f5c672019-06-24 19:40:47 +0200664done_testing;
665__END__