blob: b135f9640ab1267bd0523bfa7e7ee4e0e41a05b5 [file] [log] [blame]
Akron33f5c672019-06-24 19:40:47 +02001use Mojo::Base -strict;
2use Test::More;
Akron6a228db2021-10-14 15:57:00 +02003use Mojo::ByteStream 'b';
Akroncdfd9d52019-07-23 11:35:00 +02004use Test::Mojo::WithRoles 'Session';
Akron66ef3b52022-11-22 14:25:15 +01005use Mojo::File qw/path tempfile/;
Akron33f5c672019-06-24 19:40:47 +02006use Data::Dumper;
7
Akron33f5c672019-06-24 19:40:47 +02008#####################
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)
Akron9fa7cc52022-05-12 11:17:20 +0200118 ->element_exists('form[action=/user/login] input[name=handle_or_email]')
Uyen-Nhu Tran243fe732024-04-10 01:17:24 +0200119 ->element_exists('aside')
120 ->element_exists('aside.invisible')
Akron33f5c672019-06-24 19:40:47 +0200121 ;
122
Akronff088112021-06-15 15:26:04 +0200123$t->get_ok('/settings/oauth')
124 ->status_is(401)
125 ->text_is('p.no-results', 'Not authenticated')
126 ;
127
Helge278fbca2022-11-29 18:49:15 +0100128$t->get_ok('/settings/marketplace')
129 ->status_is(401)
130 ->text_is('p.no-results', 'Not authenticated')
131 ;
132
Akron3e0fdc12020-05-15 16:17:21 +0200133# Test for bug with long password
134$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200135 handle_or_email => 'test',
Akron3e0fdc12020-05-15 16:17:21 +0200136 pwd => 'kjskjhndkjndqknaskjnakjdnkjdankajdnkjdsankjdsakjdfkjahzroiuqzriudjoijdmlamdlkmdsalkmdl' })
137 ->status_is(302)
138 ->header_is('Location' => '/');
139
Akron9fa7cc52022-05-12 11:17:20 +0200140$t->post_ok('/user/login' => form => { handle_or_email => 'test', pwd => 'fail' })
Akron33f5c672019-06-24 19:40:47 +0200141 ->status_is(302)
142 ->header_is('Location' => '/');
143
144$t->get_ok('/')
145 ->status_is(200)
146 ->element_exists('div.notify-error')
147 ->text_is('div.notify-error', 'Bad CSRF token')
Akron9fa7cc52022-05-12 11:17:20 +0200148 ->element_exists('input[name=handle_or_email][value=test]')
Akron33f5c672019-06-24 19:40:47 +0200149 ->element_exists_not('div.button.top a')
150 ;
151
Akron9fa7cc52022-05-12 11:17:20 +0200152$t->post_ok('/user/login' => form => { handle_or_email => 'test', pwd => 'pass' })
Akron33f5c672019-06-24 19:40:47 +0200153 ->status_is(302)
154 ->header_is('Location' => '/');
155
156my $csrf = $t->get_ok('/')
157 ->status_is(200)
158 ->element_exists('div.notify-error')
159 ->text_is('div.notify-error', 'Bad CSRF token')
160 ->element_exists_not('div.button.top a')
161 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
162 ;
163
164$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200165 handle_or_email => 'test',
Akron33f5c672019-06-24 19:40:47 +0200166 pwd => 'ldaperr',
167 csrf_token => $csrf
168})
169 ->status_is(302)
170 ->content_is('')
171 ->header_is('Location' => '/');
172
173$csrf = $t->get_ok('/')
174 ->status_is(200)
175 ->element_exists('div.notify-error')
176 ->text_is('div.notify-error', '2022: LDAP Authentication failed due to unknown user or password!')
Akron9fa7cc52022-05-12 11:17:20 +0200177 ->element_exists('input[name=handle_or_email][value=test]')
Akron33f5c672019-06-24 19:40:47 +0200178 ->element_exists_not('div.button.top a')
Akron3b3c7af2020-05-15 16:23:55 +0200179 ->element_exists_not('div.notify-success')
Akron33f5c672019-06-24 19:40:47 +0200180 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
181 ;
182
183$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200184 handle_or_email => 'test',
Akron33f5c672019-06-24 19:40:47 +0200185 pwd => 'unknown',
186 csrf_token => $csrf
187})
188 ->status_is(302)
189 ->content_is('')
190 ->header_is('Location' => '/');
191
192$csrf = $t->get_ok('/')
193 ->status_is(200)
194 ->element_exists('div.notify-error')
Akron8bbbecf2019-07-01 18:57:30 +0200195 ->text_is('div.notify-error', '2022: LDAP Authentication failed due to unknown user or password!')
Akron9fa7cc52022-05-12 11:17:20 +0200196 ->element_exists('input[name=handle_or_email][value=test]')
Akron33f5c672019-06-24 19:40:47 +0200197 ->element_exists_not('div.button.top a')
198 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
199 ;
200
201$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200202 handle_or_email => 'test',
Akron33f5c672019-06-24 19:40:47 +0200203 pwd => 'pass',
204 csrf_token => $csrf
205})
206 ->status_is(302)
207 ->content_is('')
208 ->header_is('Location' => '/');
209
210$t->get_ok('/')
211 ->status_is(200)
212 ->element_exists_not('div.notify-error')
213 ->element_exists('div.notify-success')
214 ->text_is('div.notify-success', 'Login successful')
Akron1d09b532021-06-15 18:18:25 +0200215 ->element_exists_not('aside.off')
Akrondc0b3ab2021-06-18 11:52:43 +0200216 ->element_exists_not('aside.active')
Akron1d09b532021-06-15 18:18:25 +0200217 ->element_exists('aside.settings')
Akron33f5c672019-06-24 19:40:47 +0200218 ;
219
Akron33f5c672019-06-24 19:40:47 +0200220# Now the user is logged in and should be able to
221# search with authorization
222$t->get_ok('/?q=Baum')
223 ->status_is(200)
Akron4cefe1f2019-09-04 10:11:28 +0200224 ->session_has('/auth')
225 ->session_is('/auth', 'Bearer ' . $access_token)
226 ->session_is('/auth_r', $refresh_token)
227 ->session_is('/user', 'test')
Akron33f5c672019-06-24 19:40:47 +0200228 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
229 ->text_like('#total-results', qr/\d+$/)
230 ->element_exists_not('div.notify-error')
Akronbc6b3f22021-01-13 14:53:12 +0100231 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Uyen-Nhu Tran243fe732024-04-10 01:17:24 +0200232 ->element_exists('nav.dropdown')
233 ->element_exists('a.dropdown-item.logout[title~="test"]')
Akron33f5c672019-06-24 19:40:47 +0200234 ;
235
Akron27031aa2020-04-28 14:57:10 +0200236$t->get_ok('/?q=Paum')
237 ->status_is(200)
238 ->text_like('h1 span', qr/KorAP: Find .Paum./i)
239 ->text_is('#total-results', '')
Akronbc6b3f22021-01-13 14:53:12 +0100240 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akron27031aa2020-04-28 14:57:10 +0200241 ->element_exists_not('p.hint')
242 ;
243
Akroncce055c2021-07-02 12:18:03 +0200244# Query with error
245$t->get_ok('/?q=error')
246 ->status_is(400)
247 ->text_is('#notifications .notify-error','500: Internal Server Error')
248;
Akron27031aa2020-04-28 14:57:10 +0200249
Akron33f5c672019-06-24 19:40:47 +0200250# Logout
251$t->get_ok('/user/logout')
252 ->status_is(302)
Akron4cefe1f2019-09-04 10:11:28 +0200253 ->session_hasnt('/auth')
254 ->session_hasnt('/auth_r')
255 ->session_hasnt('/user')
Akron33f5c672019-06-24 19:40:47 +0200256 ->header_is('Location' => '/');
257
258$t->get_ok('/')
259 ->status_is(200)
260 ->element_exists_not('div.notify-error')
261 ->element_exists('div.notify-success')
262 ->text_is('div.notify-success', 'Logout successful')
Akron9fa7cc52022-05-12 11:17:20 +0200263 ->element_exists("input[name=handle_or_email]")
264 ->element_exists("input[name=handle_or_email][value=test]")
Akron33f5c672019-06-24 19:40:47 +0200265 ;
266
267$t->get_ok('/?q=Baum')
268 ->status_is(200)
269 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
270 ->text_like('#total-results', qr/\d+$/)
Akronbc6b3f22021-01-13 14:53:12 +0100271 ->content_like(qr/${q}authorized${q}:null/)
Akron33f5c672019-06-24 19:40:47 +0200272 ;
273
Akron27031aa2020-04-28 14:57:10 +0200274$t->get_ok('/?q=Paum')
275 ->status_is(200)
276 ->text_like('h1 span', qr/KorAP: Find .Paum./i)
277 ->text_is('#total-results', '')
Akronbc6b3f22021-01-13 14:53:12 +0100278 ->content_like(qr/${q}authorized${q}:null/)
Akron27031aa2020-04-28 14:57:10 +0200279 ->text_is('p.hint', 'Maybe you need to log in first?')
280 ;
281
282
Akron33f5c672019-06-24 19:40:47 +0200283# Get redirect
284my $fwd = $t->get_ok('/?q=Baum&ql=poliqarp')
285 ->status_is(200)
286 ->element_exists_not('div.notify-error')
287 ->tx->res->dom->at('input[name=fwd]')->attr('value')
288 ;
289
290is($fwd, '/?q=Baum&ql=poliqarp', 'Redirect is valid');
291
292$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200293 handle_or_email => 'test',
Akron33f5c672019-06-24 19:40:47 +0200294 pwd => 'pass',
295 csrf_token => $csrf,
296 fwd => 'http://bad.example.com/test'
297})
298 ->status_is(302)
299 ->header_is('Location' => '/');
300
301$t->get_ok('/')
302 ->status_is(200)
303 ->element_exists('div.notify-error')
304 ->element_exists_not('div.notify-success')
305 ->text_is('div.notify-error', 'Redirect failure')
306 ;
307
308$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200309 handle_or_email => 'test',
Akron33f5c672019-06-24 19:40:47 +0200310 pwd => 'pass',
311 csrf_token => $csrf,
312 fwd => $fwd
313})
314 ->status_is(302)
315 ->header_is('Location' => '/?q=Baum&ql=poliqarp');
316
Akron8bbbecf2019-07-01 18:57:30 +0200317$t->get_ok('/?q=Baum&ql=poliqarp')
318 ->status_is(200)
319 ->element_exists_not('div.notify-error')
320 ->element_exists('div.notify-success')
321 ->text_is('div.notify-success', 'Login successful')
Akroncdfd9d52019-07-23 11:35:00 +0200322 ->session_has('/auth')
323 ->session_is('/auth', 'Bearer ' . $access_token)
324 ->session_is('/auth_r', $refresh_token)
325 ->header_isnt('X-Kalamar-Cache', 'true')
Akron8bbbecf2019-07-01 18:57:30 +0200326 ;
327
Akroncdfd9d52019-07-23 11:35:00 +0200328# Expire the session
329# (makes the token be marked as expired - though it isn't serverside)
330$t->get_ok('/x/expire')
Akron8bbbecf2019-07-01 18:57:30 +0200331 ->status_is(200)
Akroncdfd9d52019-07-23 11:35:00 +0200332 ->content_is('okay')
333 ;
334
335## It may be a problem, but the cache is still valid
336$t->get_ok('/?q=Baum')
337 ->status_is(200)
338 ->text_like('h1 span', qr/KorAP: Find .Baum./i)
339 ->text_like('#total-results', qr/\d+$/)
Akronbc6b3f22021-01-13 14:53:12 +0100340 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200341 ->header_is('X-Kalamar-Cache', 'true')
342 ;
343
344# Query without partial cache (unfortunately) (but no total results)
Akron58c60992021-09-07 13:11:43 +0200345my $err = $t->get_ok('/?q=baum&cutoff=true')
Akroncdfd9d52019-07-23 11:35:00 +0200346 ->status_is(200)
347 ->session_is('/auth', 'Bearer ' . $access_token_2)
348 ->session_is('/auth_r', $refresh_token_2)
Akroncdfd9d52019-07-23 11:35:00 +0200349 ->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"]')
Akronbc6b3f22021-01-13 14:53:12 +0100352 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200353 ->header_isnt('X-Kalamar-Cache', 'true')
Akronbc6b3f22021-01-13 14:53:12 +0100354 ->content_like(qr!${q}cutOff${q}:true!)
Akroncdfd9d52019-07-23 11:35:00 +0200355 ->element_exists_not('#total-results')
Akron58c60992021-09-07 13:11:43 +0200356 ->tx->res->dom->at('#error')
Akroncdfd9d52019-07-23 11:35:00 +0200357 ;
Akron58c60992021-09-07 13:11:43 +0200358is(defined $err ? $err->text : '', '');
Akroncdfd9d52019-07-23 11:35:00 +0200359
360# Expire the session and remove the refresh option
361$t->get_ok('/x/expire-no-refresh')
362 ->status_is(200)
363 ->content_is('okay')
364 ;
365
366$t->app->defaults(no_cache => 1);
367
368
369$t->get_ok('/x/invalid-no-refresh')
370 ->status_is(200)
371 ->content_is('okay')
372 ;
373
374# Query without cache
375# The token is invalid and can't be refreshed!
Akron58c60992021-09-07 13:11:43 +0200376$err = $t->get_ok('/?q=baum&cutoff=true')
Akron3c390c42020-03-30 09:06:21 +0200377 ->status_is(400)
Akroncdfd9d52019-07-23 11:35:00 +0200378 ->session_hasnt('/auth')
379 ->session_hasnt('/auth_r')
Akroncdfd9d52019-07-23 11:35:00 +0200380 ->text_is('div.notify-error','Access token invalid')
381 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
382 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
383 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
Akronbc6b3f22021-01-13 14:53:12 +0100384 ->content_unlike(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200385 ->header_isnt('X-Kalamar-Cache', 'true')
386 ->element_exists('p.no-results')
Akron58c60992021-09-07 13:11:43 +0200387 ->tx->res->dom->at('#error')
Akroncdfd9d52019-07-23 11:35:00 +0200388 ;
Akron58c60992021-09-07 13:11:43 +0200389is(defined $err ? $err->text : '', '');
390
Akroncdfd9d52019-07-23 11:35:00 +0200391
392$t->get_ok('/x/invalid')
393 ->status_is(200)
394 ->content_is('okay')
395 ;
396
397# Query without cache
398# The token is invalid and can't be refreshed!
Akron58c60992021-09-07 13:11:43 +0200399$err = $t->get_ok('/?q=baum&cutoff=true')
Akroncdfd9d52019-07-23 11:35:00 +0200400 ->status_is(200)
401 ->session_is('/auth', 'Bearer ' . $access_token_2)
402 ->session_is('/auth_r', $refresh_token_2)
Akroncdfd9d52019-07-23 11:35:00 +0200403 ->element_exists_not('div.notify-error','Access token invalid')
404 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
405 ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
406 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
Akronbc6b3f22021-01-13 14:53:12 +0100407 ->content_like(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200408 ->header_isnt('X-Kalamar-Cache', 'true')
409 ->element_exists_not('p.no-results')
Akron58c60992021-09-07 13:11:43 +0200410 ->tx->res->dom->at('#error')
Akron8bbbecf2019-07-01 18:57:30 +0200411 ;
Akron58c60992021-09-07 13:11:43 +0200412is(defined $err ? $err->text : '', '');
Akron8bbbecf2019-07-01 18:57:30 +0200413
Akron33f5c672019-06-24 19:40:47 +0200414
Akroncdfd9d52019-07-23 11:35:00 +0200415$t->get_ok('/x/expired-with-wrong-refresh')
416 ->status_is(200)
417 ->content_is('okay')
418 ;
Akron4796e002019-07-05 10:13:15 +0200419
Akron4796e002019-07-05 10:13:15 +0200420
Akroncdfd9d52019-07-23 11:35:00 +0200421# The token is invalid and can't be refreshed!
Akron58c60992021-09-07 13:11:43 +0200422my $dom = $t->get_ok('/?q=baum&cutoff=true')
Akron3c390c42020-03-30 09:06:21 +0200423 ->status_is(400)
Akroncdfd9d52019-07-23 11:35:00 +0200424 ->session_hasnt('/auth')
425 ->session_hasnt('/auth_r')
Akroncdfd9d52019-07-23 11:35:00 +0200426 ->text_is('div.notify-error','Refresh token is expired')
427 ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
Akronbc6b3f22021-01-13 14:53:12 +0100428 ->content_unlike(qr/${q}authorized${q}:${q}yes${q}/)
Akroncdfd9d52019-07-23 11:35:00 +0200429 ->element_exists('p.no-results')
Akron58c60992021-09-07 13:11:43 +0200430 ->tx->res->dom;
431
432$csrf = $dom->at('input[name="csrf_token"]')
Akron59992122019-10-29 11:28:45 +0100433 ->attr('value')
Akroncdfd9d52019-07-23 11:35:00 +0200434 ;
Akron4796e002019-07-05 10:13:15 +0200435
Akron58c60992021-09-07 13:11:43 +0200436$err = $dom->at('#error');
437is(defined $err ? $err->text : '', '');
438
439
Akron6a228db2021-10-14 15:57:00 +0200440# This should fail
441my $wide_char_login = "\x{61}\x{E5}\x{61}"; # "\x{443}\x{434}";
Akron59992122019-10-29 11:28:45 +0100442$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200443 handle_or_email => $wide_char_login,
Akron6a228db2021-10-14 15:57:00 +0200444 pwd => 'pass',
445 csrf_token => $csrf,
446 fwd => $fwd
447})
448 ->status_is(302)
449 ->header_is('Location' => '/');
450
451$t->get_ok('/')
452 ->status_is(200)
453 ->element_exists('div.notify-error')
454 ->text_is('div.notify-error', 'Invalid character in request')
Akron9fa7cc52022-05-12 11:17:20 +0200455 ->element_exists('input[name=handle_or_email]:not([value])')
Akron6a228db2021-10-14 15:57:00 +0200456 ->element_exists_not('div.button.top a')
457 ;
458
459# Login:
460# UTF8 request
461my $username = b('täst')->encode;
462$t->post_ok('/user/login' => form => {
Akron9fa7cc52022-05-12 11:17:20 +0200463 handle_or_email => $username,
Akron59992122019-10-29 11:28:45 +0100464 pwd => 'pass',
465 csrf_token => $csrf
466})
467 ->status_is(302)
468 ->content_is('')
469 ->header_is('Location' => '/');
470
471$t->get_ok('/')
472 ->status_is(200)
Akron78e0b6f2023-04-12 12:50:29 +0200473 ->content_type_is('text/html;charset=UTF-8')
Akron59992122019-10-29 11:28:45 +0100474 ->element_exists_not('div.notify-error')
475 ->element_exists('div.notify-success')
476 ->text_is('div.notify-success', 'Login successful')
Akron78e0b6f2023-04-12 12:50:29 +0200477 # Weird error in certain environments otherwise
478 ->attr_like('a.logout', 'title', qr!^Logout: t.+st$!)
Akron1d09b532021-06-15 18:18:25 +0200479 ->element_exists_not('aside.off')
Akrondc0b3ab2021-06-18 11:52:43 +0200480 ->element_exists_not('aside.active')
Akron1d09b532021-06-15 18:18:25 +0200481 ->element_exists('aside.settings')
Uyen-Nhu Tran94f93b02024-11-20 20:17:57 +0100482 ->text_is('nav.dropdown a:first-child span','OAuth')
Akron59992122019-10-29 11:28:45 +0100483 ;
484
Uyen-Nhu Tran94f93b02024-11-20 20:17:57 +0100485
Akron59992122019-10-29 11:28:45 +0100486$t->get_ok('/settings/oauth')
487 ->text_is('form.form-table legend', 'Register new client application')
488 ->attr_is('form.oauth-register','action', '/settings/oauth/register')
Akron9f2ad342022-05-04 16:16:40 +0200489 ->text_is('label[for=name]','Name of the client application')
490 ->text_is('label[for=type]','Type of the client application')
491 ->text_is('label[for=desc]','Short description')
492 ->text_is('label[for=url]','Homepage')
493 ->text_is('label[for=redirect_uri]','Redirect URI')
494 ->text_is('label[for=src]','Declaration of the plugin (*.json file)')
Akron1a9d5be2020-03-19 17:28:33 +0100495 ->element_exists('ul.client-list')
496 ->element_exists_not('ul.client-list > li')
Akronad011bb2021-06-10 12:16:36 +0200497 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
498 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
499 ->header_is('Pragma','no-cache')
Akron59992122019-10-29 11:28:45 +0100500 ;
Akronad011bb2021-06-10 12:16:36 +0200501
Helgedb720ea2023-03-20 09:39:36 +0100502my $loglines = '';
503$t->app->log->on(
504 message => sub {
505 my ($log, $level, @lines) = @_;
506 if ($level eq 'warn') {
507 $loglines = join ',', @lines;
508 };
509 });
Helge278fbca2022-11-29 18:49:15 +0100510
511$t->get_ok('/settings/marketplace')
512 ->status_is(200)
513 ->text_is('html head title' => 'Marketplace')
Helgedb720ea2023-03-20 09:39:36 +0100514 ->element_exists_not('ul.plugin_list')
515 ->element_exists_not('ul.plugin_in-list')
Helge278fbca2022-11-29 18:49:15 +0100516 ;
517
Helgedb720ea2023-03-20 09:39:36 +0100518is($loglines, '', 'Check log is fine');
519
Akron59992122019-10-29 11:28:45 +0100520$csrf = $t->post_ok('/settings/oauth/register' => form => {
521 name => 'MyApp',
522 type => 'PUBLIC',
Akron6b75d122022-05-12 17:39:05 +0200523 desc => 'This is my plugin application'
Akron59992122019-10-29 11:28:45 +0100524})
525 ->text_is('div.notify-error', 'Bad CSRF token')
526 ->tx->res->dom->at('input[name="csrf_token"]')
527 ->attr('value')
528 ;
529
530$t->post_ok('/settings/oauth/register' => form => {
531 name => 'MyApp',
Akron99968a92022-06-03 12:32:07 +0200532 type => 'PUBLIC',
Akron6b75d122022-05-12 17:39:05 +0200533 desc => 'This is my plugin application',
Akron9f2ad342022-05-04 16:16:40 +0200534 csrf_token => $csrf,
535 src => {
536 filename => '',
537 content => ''
538 }
Akron59992122019-10-29 11:28:45 +0100539})
540 ->status_is(200)
541 ->element_exists('div.notify-success')
542 ->text_is('legend', 'Client Credentials')
543 ->text_is('label[for=client_id]', 'ID of the client application')
544 ->element_exists('input[name=client_id][readonly][value]')
Akron99968a92022-06-03 12:32:07 +0200545 ->element_exists_not('input[name=client_secret][readonly][value]')
Akronad011bb2021-06-10 12:16:36 +0200546 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
547 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
548 ->header_is('Pragma','no-cache')
Akron59992122019-10-29 11:28:45 +0100549 ;
Akron4796e002019-07-05 10:13:15 +0200550
Akron58c60992021-09-07 13:11:43 +0200551my $anchor = $t->get_ok('/settings/oauth')
Akronc1aaf932021-06-09 12:19:15 +0200552 ->text_is('.form-table legend', 'Register new client application')
553 ->attr_is('.oauth-register','action', '/settings/oauth/register')
Akron17de86e2020-04-16 16:03:40 +0200554 ->text_is('ul.client-list > li > span.client-name a', 'MyApp')
Akron6b75d122022-05-12 17:39:05 +0200555 ->text_is('ul.client-list > li > p.client-desc', 'This is my plugin application')
Akronad011bb2021-06-10 12:16:36 +0200556 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
557 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
558 ->header_is('Pragma','no-cache')
Akronb6b156e2022-03-31 14:57:49 +0200559 ->tx->res->dom->at('ul.client-list > li > p.client-url a')
Akron17de86e2020-04-16 16:03:40 +0200560 ;
Akron58c60992021-09-07 13:11:43 +0200561is(defined $anchor ? $anchor->text : '', '');
Akron17de86e2020-04-16 16:03:40 +0200562
Akron041ca4d2021-06-10 11:52:51 +0200563$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akron17de86e2020-04-16 16:03:40 +0200564 ->status_is(200)
Akronc1aaf932021-06-09 12:19:15 +0200565 ->text_is('ul.client-list > li.client > span.client-name', 'MyApp')
Akron6b75d122022-05-12 17:39:05 +0200566 ->text_is('ul.client-list > li.client > p.client-desc', 'This is my plugin application')
Akron17de86e2020-04-16 16:03:40 +0200567 ->text_is('a.client-unregister', 'Unregister')
Akron041ca4d2021-06-10 11:52:51 +0200568 ->attr_is('a.client-unregister', 'href', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister?name=MyApp')
Akron1a9d5be2020-03-19 17:28:33 +0100569 ;
570
Akron041ca4d2021-06-10 11:52:51 +0200571$csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister?name=MyApp')
Akron1a9d5be2020-03-19 17:28:33 +0100572 ->content_like(qr!Do you really want to unregister \<span class="client-name"\>MyApp\<\/span\>?!)
Akronc1aaf932021-06-09 12:19:15 +0200573 ->attr_is('.form-table input[name=client-name]', 'value', 'MyApp')
Akronad011bb2021-06-10 12:16:36 +0200574 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
575 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
576 ->header_is('Pragma','no-cache')
Akron1a9d5be2020-03-19 17:28:33 +0100577 ->tx->res->dom->at('input[name="csrf_token"]')
578 ->attr('value')
579 ;
580
Akron041ca4d2021-06-10 11:52:51 +0200581$t->post_ok('/settings/oauth/xxxx==/unregister' => form => {
Akron1a9d5be2020-03-19 17:28:33 +0100582 'client-name' => 'MyApp',
Akron1a9d5be2020-03-19 17:28:33 +0100583 'csrf_token' => $csrf
584})->status_is(302)
585 ->content_is('')
586 ->header_is('Location' => '/settings/oauth')
587 ;
588
589$t->get_ok('/settings/oauth')
Akronc1aaf932021-06-09 12:19:15 +0200590 ->text_is('.form-table legend', 'Register new client application')
591 ->attr_is('.oauth-register','action', '/settings/oauth/register')
Akron1a9d5be2020-03-19 17:28:33 +0100592 ->element_exists('ul.client-list > li')
593 ->text_is('div.notify', 'Unknown client with xxxx==.')
Akronad011bb2021-06-10 12:16:36 +0200594 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
595 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
596 ->header_is('Pragma','no-cache')
Akron1a9d5be2020-03-19 17:28:33 +0100597 ;
598
Akron041ca4d2021-06-10 11:52:51 +0200599$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister' => form => {
Akron1a9d5be2020-03-19 17:28:33 +0100600 'client-name' => 'MyApp',
Akron1a9d5be2020-03-19 17:28:33 +0100601 'csrf_token' => $csrf
602})->status_is(302)
603 ->content_is('')
604 ->header_is('Location' => '/settings/oauth')
605 ;
606
607$t->get_ok('/settings/oauth')
Akronc1aaf932021-06-09 12:19:15 +0200608 ->text_is('.form-table legend', 'Register new client application')
609 ->attr_is('.oauth-register','action', '/settings/oauth/register')
Akron1a9d5be2020-03-19 17:28:33 +0100610 ->element_exists_not('ul.client-list > li')
611 ->text_is('div.notify-success', 'Successfully deleted MyApp')
Akronad011bb2021-06-10 12:16:36 +0200612 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
613 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
614 ->header_is('Pragma','no-cache')
Akron1a9d5be2020-03-19 17:28:33 +0100615 ;
616
Akron83209f72021-01-29 17:54:15 +0100617$t->post_ok('/settings/oauth/register' => form => {
618 name => 'MyApp2',
619 type => 'PUBLIC',
Akron6b75d122022-05-12 17:39:05 +0200620 desc => 'This is my plugin application',
Akron83209f72021-01-29 17:54:15 +0100621 csrf_token => $csrf
622})->status_is(200)
623 ->element_exists('div.notify-success')
624 ->text_is('legend', 'Client Credentials')
625 ->text_is('label[for=client_id]', 'ID of the client application')
626 ->element_exists('input[name=client_id][readonly][value]')
627 ->element_exists_not('input[name=client_secret][readonly][value]')
Akronad011bb2021-06-10 12:16:36 +0200628 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
629 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
630 ->header_is('Pragma','no-cache')
Akronb6b156e2022-03-31 14:57:49 +0200631 ->element_exists('.client-issue-token')
Akron83209f72021-01-29 17:54:15 +0100632 ;
633
Akron041ca4d2021-06-10 11:52:51 +0200634$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akron83209f72021-01-29 17:54:15 +0100635 ->text_is('.client-name', 'MyApp2')
Akron6b75d122022-05-12 17:39:05 +0200636 ->text_is('.client-desc', 'This is my plugin application')
Akrone997bb52021-06-11 16:44:06 +0200637 ->text_is('.client-issue-token', 'Issue new token')
Akron041ca4d2021-06-10 11:52:51 +0200638 ->attr_is('.client-issue-token', 'href', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?name=MyApp2')
Akronad011bb2021-06-10 12:16:36 +0200639 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
640 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
641 ->header_is('Pragma','no-cache')
Akrone997bb52021-06-11 16:44:06 +0200642 ->text_is('ul.token-list label[for=token]', 'Access Token')
643 ->text_is('p[name=created]', 'Created at ')
644 ->text_is('p[name=expires]', 'Expires in 31533851 seconds.')
Akronb6b156e2022-03-31 14:57:49 +0200645 ->element_exists('.client-issue-token')
Akron83209f72021-01-29 17:54:15 +0100646 ;
647
Akron041ca4d2021-06-10 11:52:51 +0200648$csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?name=MyApp2')
Akron83209f72021-01-29 17:54:15 +0100649 ->status_is(200)
Akron041ca4d2021-06-10 11:52:51 +0200650 ->attr_is('#issue-token','action', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token')
Akron83209f72021-01-29 17:54:15 +0100651 ->attr_is('input[name=client-id]', 'value', 'fCBbQkA2NDA3MzM1Yw==')
652 ->attr_is('input[name=name]', 'value', 'MyApp2')
Akronad011bb2021-06-10 12:16:36 +0200653 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
654 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
655 ->header_is('Pragma','no-cache')
Akrone997bb52021-06-11 16:44:06 +0200656 ->text_is('a.button-abort', 'Abort')
657 ->attr_is('#issue-token input[type=submit]', 'value', 'Issue new token')
658 ->content_like(qr!Issue a new token for!)
Akron83209f72021-01-29 17:54:15 +0100659 ->tx->res->dom->at('input[name="csrf_token"]')
660 ->attr('value')
661 ;
662
Akron041ca4d2021-06-10 11:52:51 +0200663$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token' => form => {
Akron83209f72021-01-29 17:54:15 +0100664 csrf_token => $csrf,
665 name => 'MyApp2',
666 'client-id' => 'fCBbQkA2NDA3MzM1Yw=='
667})
Akronbc94a9c2021-04-15 00:07:35 +0200668 ->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200669 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronbc94a9c2021-04-15 00:07:35 +0200670 ;
671
Akron041ca4d2021-06-10 11:52:51 +0200672$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
673 ->status_is(200)
Akronbc94a9c2021-04-15 00:07:35 +0200674 ->text_is('div.notify-success', 'New access token created')
Akronad011bb2021-06-10 12:16:36 +0200675 ->status_is(200)
676 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
677 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
678 ->header_is('Pragma','no-cache')
Akron83209f72021-01-29 17:54:15 +0100679 ;
680
Akrone3daaeb2023-05-08 09:44:18 +0200681$t->post_ok('/settings/oauth/307/token' => form => {
682 csrf_token => $csrf,
683 name => 'MyApp2',
684})
685 ->status_is(302)
686 ->header_is('Location','/settings/oauth/307')
687 ;
688
689$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
690 ->status_is(200)
691 ->text_is('div.notify-success', 'New access token created')
692 ->status_is(200)
693 ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
694 ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
695 ->header_is('Pragma','no-cache')
696 ;
697
698
Akron041ca4d2021-06-10 11:52:51 +0200699$csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200700 ->status_is(200)
Akron041ca4d2021-06-10 11:52:51 +0200701 ->attr_is('form.token-revoke', 'action', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token/revoke')
Akronc1aaf932021-06-09 12:19:15 +0200702 ->attr_is('form.token-revoke input[name=token]', 'value', 'jhkhkjhk_hjgjsfz67i')
703 ->attr_is('form.token-revoke input[name=name]', 'value', 'MyApp2')
704 ->tx->res->dom->at('input[name="csrf_token"]')
705 ->attr('value')
706 ;
707
Akron041ca4d2021-06-10 11:52:51 +0200708$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token/revoke' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200709 csrf_token => $csrf,
710 name => 'MyApp2',
711 token => 'jhkhkjhk_hjgjsfz67i'
712})
713 ->status_is(200)
Akron041ca4d2021-06-10 11:52:51 +0200714 ->attr_is('form#revoke-token','action','/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE')
Akronc1aaf932021-06-09 12:19:15 +0200715 ->attr_is('form#revoke-token','method','POST')
716 ->attr_is('form#revoke-token input[name=token]','value','jhkhkjhk_hjgjsfz67i')
Akrone997bb52021-06-11 16:44:06 +0200717 ->text_is('a.button-abort', 'Abort')
718 ->attr_is('#revoke-token input[type=submit]', 'value', 'Revoke')
719 ->content_like(qr!Revoke a token for!)
Akronc1aaf932021-06-09 12:19:15 +0200720;
721
722
723# CSRF missing
Akron041ca4d2021-06-10 11:52:51 +0200724$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200725 name => 'MyApp2',
726 token => 'jhkhkjhk_hjgjsfz67i'
727})->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200728 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200729 ;
730
Akron041ca4d2021-06-10 11:52:51 +0200731$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200732 ->element_exists_not('div.notify-success')
733 ->text_is('div.notify-error', 'Bad CSRF token')
734 ;
735
736# Token missing
Akron041ca4d2021-06-10 11:52:51 +0200737$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200738 name => 'MyApp2',
739 csrf_token => $csrf,
740})->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200741 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200742 ;
743
Akron041ca4d2021-06-10 11:52:51 +0200744$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200745 ->element_exists_not('div.notify-success')
746 ->text_is('div.notify-error', 'Some fields are invalid')
747 ;
748
Akron041ca4d2021-06-10 11:52:51 +0200749$t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?_method=DELETE' => form => {
Akronc1aaf932021-06-09 12:19:15 +0200750 name => 'MyApp2',
751 csrf_token => $csrf,
752 token => 'jhkhkjhk_hjgjsfz67i'
753})->status_is(302)
Akron041ca4d2021-06-10 11:52:51 +0200754 ->header_is('Location','/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200755 ;
756
Akron041ca4d2021-06-10 11:52:51 +0200757$t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
Akronc1aaf932021-06-09 12:19:15 +0200758 ->element_exists_not('div.notify-error')
759 ->text_is('div.notify-success', 'Token was revoked successfully')
760 ;
Akron83209f72021-01-29 17:54:15 +0100761
Akronb6b156e2022-03-31 14:57:49 +0200762$t->app->routes->get('/x/redirect-target')->to(
763 cb => sub {
764 my $c = shift;
765 return $c->render(text => 'redirected');
766 }
767);
768
769$csrf = $t->post_ok('/settings/oauth/register' => form => {
770 name => 'MyConfApp',
771 type => 'CONFIDENTIAL',
Akron6b75d122022-05-12 17:39:05 +0200772 desc => 'This is my plugin application',
Akronb6b156e2022-03-31 14:57:49 +0200773})
774 ->text_is('div.notify-error', 'Bad CSRF token')
775 ->tx->res->dom->at('input[name="csrf_token"]')
776 ->attr('value')
777 ;
778
779$t->post_ok('/settings/oauth/register' => form => {
780 name => 'MyConfApp',
781 type => 'CONFIDENTIAL',
782 desc => 'This is my confidential application',
783 csrf_token => $csrf,
784 redirect_uri => 'http://localhost/redirect-target'
785})
786 ->text_is('div.notify-error', undef)
787 ->text_is('li.client span.client-name', 'MyConfApp')
788 ->text_is('li.client p.client-desc', 'This is my confidential application')
789 ->text_is('li.client .client-redirect-uri tt', 'http://localhost/redirect-target')
790 ->text_is('li.client .client-type tt', 'CONFIDENTIAL')
791 ->element_exists_not('.client-issue-token')
792 ;
793
794$t->post_ok('/settings/oauth/register' => form => {
795 name => 'MyConfApp2',
796 type => 'CONFIDENTIAL',
797 desc => 'This is my second confidential application',
798 csrf_token => $csrf,
799 redirect_uri => 'http://localhost/FAIL'
800})
801 ->status_is(302)
802 ->header_is('location','/settings/oauth/')
803 ;
804
805$t->get_ok('/settings/oauth/')
806 ->text_is('div.notify-error', 'invalid_request: http://localhost/FAIL is invalid.')
807 ;
808
Akrona8efaa92022-04-09 14:45:43 +0200809# OAuth client authorization flow
810$t->get_ok(Mojo::URL->new('/settings/oauth/authorize'))
811 ->status_is(302)
Akron5ea0f5d2023-01-20 11:51:43 +0100812 ->header_is('location','/settings/oauth')
813 ;
814
815$t->get_ok('/settings/oauth/')
Akron2c142ab2023-01-30 13:21:57 +0100816 ->text_is('div.notify-error', 'Client ID required')
817 ;
818
819$t->get_ok(Mojo::URL->new('/settings/oauth/authorize?client_id=xyz'))
820 ->status_is(302)
821 ->header_is('location','/settings/oauth')
822 ;
823
824$t->get_ok('/settings/oauth/')
825 ->text_is('div.notify-error', 'Scope required')
Akrona8efaa92022-04-09 14:45:43 +0200826 ;
827
Akrondb1f4672023-01-24 12:05:07 +0100828# OAuth client authorization flow
829$t->get_ok(Mojo::URL->new('/settings/oauth/authorize?client_id=abc'))
830 ->status_is(302)
831 ->header_is('location','/settings/oauth')
832 ;
833
834$t->get_ok('/settings/oauth/')
Akron2c142ab2023-01-30 13:21:57 +0100835 ->text_is('div.notify-error', 'Scope required')
836 ;
837
838# OAuth client authorization flow
839$t->get_ok(Mojo::URL->new('/settings/oauth/authorize?client_id=abc&scope=match'))
840 ->status_is(302)
841 ->header_is('location','/settings/oauth')
842 ;
843
844$t->get_ok('/settings/oauth/')
Akrondb1f4672023-01-24 12:05:07 +0100845 ->text_is('div.notify-error', 'Unknown client with abc.')
846 ;
847
Akrona8efaa92022-04-09 14:45:43 +0200848# Logout
849$t->get_ok('/x/expired-with-wrong-refresh');
850
851$t->get_ok('/user/logout')
852 ->status_is(302)
853 ->session_hasnt('/auth')
854 ->session_hasnt('/auth_r')
855 ->session_hasnt('/user')
856 ->header_is('Location' => '/');
857
Akron001dcd22023-02-07 08:38:11 +0100858$t->get_ok('/')
Akrona8efaa92022-04-09 14:45:43 +0200859 ->status_is(200)
860 ->element_exists_not('div.notify-error')
861 ->element_exists('div.notify-success')
862 ->text_is('div.notify-success', 'Logout successful')
Akron9fa7cc52022-05-12 11:17:20 +0200863 ->element_exists("input[name=handle_or_email]")
Akron001dcd22023-02-07 08:38:11 +0100864 ;
865
866# OAuth client authorization flow - but user not logged in
867$t->get_ok(Mojo::URL->new('/settings/oauth/authorize'))
868 ->status_is(302)
869 ->header_is('location','/')
870 ;
871
872$csrf = $t->get_ok('/')
873 ->status_is(200)
874 ->element_exists('div.notify-error')
875 ->element_exists_not('div.notify-success')
876 ->text_is('div.notify-error', 'Client ID required')
877 ->element_exists("input[name=handle_or_email]")
Akrona8efaa92022-04-09 14:45:43 +0200878 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
879 ;
880
Akron408bc7c2022-04-28 15:46:43 +0200881$fake_backend_app->add_client({
882 "client_id" => 'xyz',
883 "client_name" => 'New added client',
884 "client_description" => 'This is a new client',
885 "client_url" => 'http://example.com',
886 "client_type" => 'CONFIDENTIAL'
887# "client_redirect_uri" => $redirect_uri
888});
889
Akron0cbcc072024-10-08 14:04:42 +0200890$fake_backend_app->add_client({
891 "client_id" => 'xyz-public',
892 "client_name" => 'New added public client',
893 "client_description" => 'This is a new public client',
894 "client_url" => 'http://example.com',
895 "client_type" => 'PUBLIC'
896# "client_redirect_uri" => $redirect_uri
897});
898
Helge278fbca2022-11-29 18:49:15 +0100899
Akron9d826902023-01-25 10:20:52 +0100900$fake_backend_app->add_client({
901 "client_id" => 'xyz2',
902 "client_name" => 'New added client',
903 "client_description" => 'This is a new client',
904 "client_url" => 'http://example.com',
905 "client_type" => 'CONFIDENTIAL',
906 "client_redirect_uri" => 'http://redirect.url/'
907});
908
Akroneb39cf32023-04-03 14:40:48 +0200909$t->get_ok('/settings/oauth/xyz2')
910 ->status_is(200)
911 ->text_is('li.client span.client-name','New added client')
912 ->attr_is('li.client p.client-url a','href','http://example.com')
913 ->attr_is('li.client input[name=client_id]','value','xyz2')
914 ->element_exists('li.client p.client-type-confidential')
915 ->text_is('li.client p.client-redirect-uri tt','http://redirect.url/')
916 ;
917
Akron9d826902023-01-25 10:20:52 +0100918$fwd = $t->get_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
919 client_id => 'xyz2',
920 scope => 'search match',
921 redirect_uri => 'http://test.com/',
922}))
923 ->status_is(200)
924 ->text_is('div.notify-warn', 'redirect_uri host differs from registered host')
925 ->element_exists_not('div.notify-error')
926 ->element_exists_not('div.notify-success')
927 ->element_exists("input[name=handle_or_email]")
928 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
929 ;
930
931$fwd = $t->get_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
932 client_id => 'xyz2',
933 scope => 'search match',
934 redirect_uri => 'http://redirect.url:9000/',
935}))
936 ->status_is(200)
937 ->text_is('div.notify-warn', 'redirect_uri port differs from registered port')
938 ->element_exists_not('div.notify-error')
939 ->element_exists_not('div.notify-success')
940 ->element_exists("input[name=handle_or_email]")
941 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
942 ;
943
Helge278fbca2022-11-29 18:49:15 +0100944
945$fake_backend_app->add_plugin({
946"source" => {"key1" => 'wert1', "key2" => 'wert2'},
Helge278fbca2022-11-29 18:49:15 +0100947"client_id" => '52abc',
Helgedb720ea2023-03-20 09:39:36 +0100948"permitted" => 'true',
Helge278fbca2022-11-29 18:49:15 +0100949"client_name" => 'Plugin 1',
950"client_type" => 'CONFIDENTIAL',
Helgedb720ea2023-03-20 09:39:36 +0100951"client_description" => 'Description Plugin 1',
952"client_url" => 'http://example.client.de',
953"registration_date" => '2022-05-31T14:30:09+02:00[Europe/Berlin]',
Helge216a4822024-06-17 12:02:34 +0200954"registered_by" => 'testuser',
955"refresh_token_expiry" => '7776000',
Helge278fbca2022-11-29 18:49:15 +0100956});
957
958
Akrona8efaa92022-04-09 14:45:43 +0200959$fwd = $t->get_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
960 client_id => 'xyz',
961 state => 'abcde',
962 scope => 'search match',
963 redirect_uri => 'http://test.com/',
964}))
965 ->status_is(200)
966 ->attr_is('input[name=client_id]','value','xyz')
967 ->attr_is('input[name=state]','value','abcde')
Akrona8efaa92022-04-09 14:45:43 +0200968 ->attr_like('input[name=fwd]','value',qr!test\.com!)
Akron408bc7c2022-04-28 15:46:43 +0200969 ->text_is('span.client-name','New added client')
Akrona8efaa92022-04-09 14:45:43 +0200970 ->text_is('div.intro p:nth-child(2)', 'Please log in!')
971 ->tx->res->dom->at('input[name=fwd]')->attr('value')
972 ;
973
974$fwd = $t->post_ok(Mojo::URL->new('/user/login')->query({
975 csrf_token => $csrf,
976 client_id => 'xyz',
977 state => 'abcde',
978 scope => 'search match',
979 redirect_uri => 'http://test.com/',
Akron9fa7cc52022-05-12 11:17:20 +0200980 handle_or_email => 'test',
Akrona8efaa92022-04-09 14:45:43 +0200981 pwd => 'pass',
982 fwd => $fwd
983}))
984 ->status_is(302)
985 ->header_like('location', qr!/settings/oauth/authorize!)
986 ->tx->res->headers->header('location')
987 ;
988
989$t->get_ok($fwd)
990 ->status_is(200)
991 ->attr_is('input[name=client_id]','value','xyz')
992 ->attr_is('input[name=state]','value','abcde')
Akron9d826902023-01-25 10:20:52 +0100993 ->attr_like('input[name=redirect_uri]','value', qr!^http://test\.com\/\?crto=.{3,}!)
Akrona8efaa92022-04-09 14:45:43 +0200994 ->text_is('ul#scopes li:nth-child(1)','search')
995 ->text_is('ul#scopes li:nth-child(2)','match')
Akron408bc7c2022-04-28 15:46:43 +0200996 ->text_is('span.client-name','New added client')
Akrona8efaa92022-04-09 14:45:43 +0200997 ->attr_is('a.form-button','href','http://test.com/')
998 ->attr_is('a.embedded-link', 'href', '/doc/korap/kalamar')
Akron9d826902023-01-25 10:20:52 +0100999 ->element_exists_not('div.notify-error')
1000 ->element_exists_not('div.notify-warn')
1001 ->element_exists_not('blockquote.warning')
Akron0cbcc072024-10-08 14:04:42 +02001002 ->text_is('h2 + p', ' wants to have access')
Akrona8efaa92022-04-09 14:45:43 +02001003 ;
1004
Akron0cbcc072024-10-08 14:04:42 +02001005$fwd = $t->get_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
1006 client_id => 'xyz-public',
1007 state => 'abcde',
1008 scope => 'search match',
1009 redirect_uri => 'http://test.com/',
1010}))
1011 ->status_is(200)
1012 ->attr_is('input[name=client_id]','value','xyz-public')
1013 ->attr_is('input[name=state]','value','abcde')
1014 ->attr_like('input[name=redirect_uri]','value', qr!^http://test\.com\/\?crto=.{3,}!)
1015 ->text_is('ul#scopes li:nth-child(1)','search')
1016 ->text_is('ul#scopes li:nth-child(2)','match')
1017 ->text_is('span.client-name','New added public client')
1018 ->attr_is('a.form-button','href','http://test.com/')
1019 ->attr_is('a.embedded-link', 'href', '/doc/korap/kalamar')
1020 ->element_exists_not('div.notify-error')
1021 ->element_exists_not('div.notify-warn')
1022 ->text_is('blockquote.warning','Warning - this is a public client!')
1023 ->text_is('h2 + p', ' wants to have access')
1024 ;
1025
1026
Helge278fbca2022-11-29 18:49:15 +01001027$t->get_ok('/settings/marketplace')
1028 ->status_is(200)
1029 ->text_is('html head title' => 'Marketplace')
1030 ->element_exists('ul.plugin-list')
1031 ->element_exists('ul.plugin-list > li')
Helge278fbca2022-11-29 18:49:15 +01001032 ->text_is('span.client-name','Plugin 1')
1033 ->text_is('p.plugin-desc','Description Plugin 1')
Helge216a4822024-06-17 12:02:34 +02001034 ->text_is('p.registration_date', 'Date of registration: 2022-05-31T14:30:09+02:00[Europe/Berlin]')
1035 ->text_is('p.registered_by', 'Registered by: testuser')
Helge278fbca2022-11-29 18:49:15 +01001036 ;
1037
Helgedb720ea2023-03-20 09:39:36 +01001038
1039
Helge278fbca2022-11-29 18:49:15 +01001040$fake_backend_app->add_plugin({
1041"source" => {"one" => '1', "two" => '2'},
1042"permitted" => 'false',
1043"client_id" => '53abc',
1044"client_name" => 'Plugin 2',
1045"client_type" => 'CONFIDENTIAL',
1046"client_description" =>'Description Plugin 2'
1047});
1048
Helge278fbca2022-11-29 18:49:15 +01001049$t->get_ok('/settings/marketplace')
1050 ->status_is(200)
1051 ->element_exists('ul.plugin-list')
1052 ->element_exists('ul.plugin-list > li')
1053 ->text_is('span.client-name','Plugin 1')
1054 ->text_is('p.plugin-desc','Description Plugin 1')
1055 ->element_exists('ul.plugin-list > li + li')
Helgedb720ea2023-03-20 09:39:36 +01001056 ->text_is('ul.plugin-list > li + li >span.client-name','Plugin 2')
1057 ->text_is('ul.plugin-list > li + li >p.plugin-desc','Description Plugin 2')
Helge278fbca2022-11-29 18:49:15 +01001058 ;
1059
Helged36478d2023-06-08 17:43:01 +02001060$t->post_ok('/settings/marketplace/install', form => {'client-id' => '52abc'})
Helgedb720ea2023-03-20 09:39:36 +01001061 ->status_is(302)
1062 ->header_is(location => '/settings/marketplace')
1063 ;
Helgedb720ea2023-03-20 09:39:36 +01001064$t->ua->max_redirects(1);
1065
Helged36478d2023-06-08 17:43:01 +02001066$t->post_ok('/settings/marketplace/install', form => {'client-id' => '52abc'})
Helgedb720ea2023-03-20 09:39:36 +01001067 ->status_is(200)
1068 ->element_exists('ul.plugin-list')
1069 ->element_exists('ul.plugin-list > li')
1070 ->text_is('ul.plugin-list > li > span.client-name','Plugin 2')
1071 ->text_is('ul.plugin-list > li > p.plugin-desc','Description Plugin 2')
1072 ->element_exists_not('ul.plugin-list > li + li')
1073 ->element_exists('ul.plugin_in-list')
1074 ->element_exists('ul.plugin_in-list > li')
1075 ->text_is('ul.plugin_in-list > li > span.client-name','Plugin 1')
Helge216a4822024-06-17 12:02:34 +02001076 ->text_is('ul.plugin_in-list > li > p.inst_date','Installation date: 2022-12-13T16:33:27.621+01:00[Europe/Berlin]')
Helgedb720ea2023-03-20 09:39:36 +01001077 ;
1078
1079$t->ua->max_redirects(0);
1080
Helged36478d2023-06-08 17:43:01 +02001081 $t->post_ok('/settings/marketplace/install', form => {'client-id' => 'unsinn31'})
Helgedb720ea2023-03-20 09:39:36 +01001082 ->status_is(302)
1083 ->header_is(location => '/settings/marketplace')
1084 ;
1085
1086$t->ua->max_redirects(1);
1087
Helged36478d2023-06-08 17:43:01 +02001088$t->post_ok('/settings/marketplace/install', form => {'client-id' => 'unsinn31'})
Helgedb720ea2023-03-20 09:39:36 +01001089 ->status_is(200)
1090 ->text_is('div.notify-error', 'Plugin could not be installed')
1091 ;
1092
Helged36478d2023-06-08 17:43:01 +02001093$t->post_ok('/settings/marketplace/uninstall', form => {'client-id' => '52abc'})
1094 ->status_is(200)
1095 ->element_exists('ul.plugin-list')
1096 ->element_exists('ul.plugin-list > li')
1097 ->text_is('span.client-name','Plugin 1')
1098 ->text_is('p.plugin-desc','Description Plugin 1')
1099 ->element_exists('ul.plugin-list > li + li')
1100 ->text_is('ul.plugin-list > li + li >span.client-name','Plugin 2')
1101 ->text_is('ul.plugin-list > li + li >p.plugin-desc','Description Plugin 2')
1102 ->element_exists_not('ul.plugin_in-list')
1103 ;
1104
1105$t->post_ok('/settings/marketplace/uninstall', form => {'client-id' => 'quatsch12'})
1106 ->status_is(200)
1107 ->text_is('div.notify-error', 'Plugin could not be uninstalled')
1108 ;
1109
Helgedb720ea2023-03-20 09:39:36 +01001110$t->ua->max_redirects(0);
Helge278fbca2022-11-29 18:49:15 +01001111
Akrona8efaa92022-04-09 14:45:43 +02001112$t->get_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
1113 client_id => 'xyz',
1114 state => 'abcde',
1115 scope => 'search match',
1116 redirect_uri => 'http://test.com/'
1117}))
1118 ->status_is(200)
1119 ->attr_is('input[name=client_id]','value','xyz')
1120 ->attr_is('input[name=state]','value','abcde')
Akrona8efaa92022-04-09 14:45:43 +02001121 ->text_is('ul#scopes li:nth-child(1)','search')
1122 ->text_is('ul#scopes li:nth-child(2)','match')
Akron408bc7c2022-04-28 15:46:43 +02001123 ->text_is('span.client-name','New added client')
Akrona8efaa92022-04-09 14:45:43 +02001124 ->attr_is('a.form-button','href','http://test.com/')
1125 ->attr_is('a.embedded-link', 'href', '/doc/korap/kalamar')
1126 ;
1127
1128$t->post_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
1129 client_id => 'xyz',
1130 state => 'abcde',
1131 scope => 'search match',
1132 redirect_uri => 'http://test.com/'
1133}))
1134 ->status_is(302)
Akron9d826902023-01-25 10:20:52 +01001135 ->header_is('location', '/settings/oauth?error_description=Bad+CSRF+token')
Akrona8efaa92022-04-09 14:45:43 +02001136 ;
1137
Akrona8f87cc2023-02-23 12:21:30 +01001138
1139my $local_port = $t->get_ok('/')->tx->local_port;
1140my $remote_port = $t->get_ok('/')->tx->remote_port;
1141
1142like($local_port, qr!^\d+$!);
1143like($remote_port, qr!^\d+$!);
1144
1145my $port = $remote_port;
1146
1147my $redirect_url_fakeapi = $t->app->close_redirect_to(Mojo::URL->new('http://localhost:' . $port)->path($fake_backend_app->url_for('return_uri'))->to_abs->to_string);
1148
Akrona8efaa92022-04-09 14:45:43 +02001149$fwd = $t->post_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
1150 client_id => 'xyz',
1151 state => 'abcde',
1152 scope => 'search match',
Akrona8f87cc2023-02-23 12:21:30 +01001153 redirect_uri_server => 'http://localhost:'.$port,
1154 redirect_uri => "$redirect_url_fakeapi",
Akrona8efaa92022-04-09 14:45:43 +02001155 csrf_token => $csrf,
1156}))
1157 ->status_is(302)
Akrona8f87cc2023-02-23 12:21:30 +01001158 ->header_like('location', qr!^http://localhost:\d+/realapi/fakeclient/return\?code=.+$!)
Akrona8efaa92022-04-09 14:45:43 +02001159 ->tx->res->headers->header('location')
1160 ;
1161
Akronf47813c2023-05-08 16:24:03 +02001162unless ($^O eq 'MSWin32') {
1163 $t->get_ok($fwd)
1164 ->status_is(200)
1165 ->content_like(qr'welcome back! \[(.+?)\]')
1166 ;
1167};
Akrona8efaa92022-04-09 14:45:43 +02001168
Akrona8f87cc2023-02-23 12:21:30 +01001169my $fake_port = $port;
1170
1171while ($fake_port == $remote_port || $fake_port == $local_port) {
1172 $fake_port++;
1173};
1174
1175$redirect_url_fakeapi = $t->app->close_redirect_to(Mojo::URL->new('http://localhost:' . $fake_port)->path($fake_backend_app->url_for('return_uri'))->to_abs->to_string);
1176
1177$fwd = $t->post_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
1178 client_id => 'xyz',
1179 state => 'abcde',
1180 scope => 'search match',
1181 redirect_uri_server => 'http://localhost:'.$port,
1182 redirect_uri => "$redirect_url_fakeapi",
1183 csrf_token => $csrf,
1184}))
1185 ->status_is(302)
1186 ->header_unlike('location', qr!^http://localhost:\d+/realapi/fakeclient/return\?error_description=Connection\+refused$!)
1187 ->header_like('location', qr!^http://localhost:\d+/realapi/fakeclient/return\?code=.+?$!)
1188 ->tx->res->headers->header('location')
1189 ;
1190
Akrona8efaa92022-04-09 14:45:43 +02001191$t->post_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
1192 client_id => 'xyz',
Akron9ccf69a2023-01-31 14:21:37 +01001193 state => 'abcde',
1194 scope => 'search match',
1195 redirect_uri_server => 'http://example.com/',
1196 redirect_uri => $t->app->close_redirect_to('http://wrong'),
1197 csrf_token => $csrf,
1198}))
1199 ->status_is(302)
1200 ->header_is('location', '/settings/oauth')
1201 ->tx->res->headers->header('location')
1202 ;
1203
1204$t->get_ok('/settings/oauth')
1205 ->text_is('div.notify-error', 'Invalid redirect URI')
1206 ;
1207
1208$t->post_ok(Mojo::URL->new('/settings/oauth/authorize')->query({
1209 client_id => 'xyz',
Akrona8efaa92022-04-09 14:45:43 +02001210 state => 'fail',
1211 scope => 'search match',
Akron9d826902023-01-25 10:20:52 +01001212# redirect_uri_server => 'http://example.com/',
Akrona8efaa92022-04-09 14:45:43 +02001213 redirect_uri => $fake_backend_app->url_for('return_uri')->to_abs,
1214 csrf_token => $csrf,
1215}))
1216 ->status_is(302)
Akron9d826902023-01-25 10:20:52 +01001217 ->header_is('location', '/realapi/fakeclient/return?error_description=FAIL')
Akrona8efaa92022-04-09 14:45:43 +02001218 ;
1219
Akron9f2ad342022-05-04 16:16:40 +02001220my $json_post = {
1221 name => 'Funny',
1222 type => 'PUBLIC',
Akron6b75d122022-05-12 17:39:05 +02001223 desc => 'This is my plugin application 2',
Akron9f2ad342022-05-04 16:16:40 +02001224 csrf_token => $csrf,
1225 src => 'hMMM'
1226};
1227
1228$t->post_ok('/settings/oauth/register' => form => $json_post)
1229 ->status_is(200)
1230 ->element_exists('div.notify-error')
Akron99968a92022-06-03 12:32:07 +02001231 ->text_is('div.notify-error', 'Plugin declarations need to be json files')
1232 ;
1233
1234$json_post->{src} = {
1235 content => 'jjjjjj',
1236 filename => 'fun.txt'
1237};
1238
1239$t->post_ok('/settings/oauth/register' => form => $json_post)
1240 ->status_is(200)
1241 ->element_exists('div.notify-error')
Akron9f2ad342022-05-04 16:16:40 +02001242 ->text_is('div.notify-error', 'Plugins need to be confidential')
1243 ;
1244
1245$json_post->{type} = 'CONFIDENTIAL';
1246
Akron99968a92022-06-03 12:32:07 +02001247# This somehow gets removed in the last form send ...
Akron9f2ad342022-05-04 16:16:40 +02001248$json_post->{src} = {
1249 content => 'jjjjjj',
1250 filename => 'fun.txt'
1251};
1252
1253$t->post_ok('/settings/oauth/register' => form => $json_post)
1254 ->status_is(200)
1255 ->element_exists('div.notify-error')
1256 ->text_is('div.notify-error', 'Plugin declarations need to be json files')
1257 ;
1258
1259$json_post->{src} = {
1260 content => '{"name":"example"}',
1261 filename => 'fun.txt'
1262};
1263
1264$t->post_ok('/settings/oauth/register' => form => $json_post)
1265 ->status_is(200)
1266 ->element_exists_not('div.notify-error')
1267 ->element_exists('div.notify-success')
1268 ->text_is('div.notify-success', 'Registration successful')
1269 ;
1270
Akron6b75d122022-05-12 17:39:05 +02001271$t->get_ok('/settings/oauth/jh0gfjhjbfdsgzjghj==')
1272 ->status_is(200)
1273 ->text_is('div.notify-error', undef)
1274 ->text_is('li.client #client_source', '{"name":"example"}')
1275 ->text_is('li.client span.client-name', 'Funny')
1276 ->text_is('li.client p.client-desc', 'This is my plugin application 2')
1277 ->element_exists_not('li.client .client-redirect-uri tt')
1278 ->text_is('li.client .client-type tt', 'CONFIDENTIAL')
1279 ;
Akron9f2ad342022-05-04 16:16:40 +02001280
Akronb6b156e2022-03-31 14:57:49 +02001281
Akron66ef3b52022-11-22 14:25:15 +01001282# Retest client with super_client_file
1283my $client_file = tempfile;
1284
Akron889bc202024-03-15 17:16:55 +01001285$client_file->spew(
Akron66ef3b52022-11-22 14:25:15 +01001286 '{"client_id":"2","client_secret":"k414m4r-s3cr3t"}'
1287);
1288
1289$t = Test::Mojo::WithRoles->new('Kalamar' => {
1290 Kalamar => {
1291 plugins => ['Auth']
1292 },
1293 'Kalamar-Auth' => {
1294 client_file => $client_file,
1295 oauth2 => 1
1296 }
1297});
1298
1299$t->app->plugin(
1300 Mount => {
1301 $mount_point =>
1302 $fixtures_path->child('mock.pl')
1303 }
1304);
1305
1306$csrf = $t->get_ok('/')
1307 ->status_is(200)
1308 ->element_exists_not('div.button.top a')
1309 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
1310 ;
1311
1312$t->post_ok('/user/login' => form => {
1313 handle_or_email => 'test',
1314 pwd => 'pass',
1315 csrf_token => $csrf
1316})
1317 ->status_is(302)
1318 ->header_is('Location' => '/')
1319 ->content_is('');
1320
1321$t->get_ok('/')
1322 ->status_is(200)
1323 ->element_exists_not('div.notify-error')
1324 ->element_exists('div.notify-success')
1325 ->text_is('div.notify-success', 'Login successful')
1326 ->element_exists_not('aside.off')
1327 ->element_exists_not('aside.active')
1328 ->element_exists('aside.settings')
1329 ;
1330
Akron53a171e2022-12-05 18:22:58 +01001331$main::ENV{KALAMAR_CLIENT_FILE} = $client_file;
1332
1333$t = Test::Mojo::WithRoles->new('Kalamar' => {
1334 Kalamar => {
1335 plugins => ['Auth']
1336 },
1337 'Kalamar-Auth' => {
1338 oauth2 => 1,
1339# client_file => $client_file,
1340 }
1341});
1342
1343$t->app->plugin(
1344 Mount => {
1345 $mount_point =>
1346 $fixtures_path->child('mock.pl')
1347 }
1348);
1349
1350$csrf = $t->get_ok('/')
1351 ->status_is(200)
1352 ->element_exists_not('div.button.top a')
1353 ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
1354 ;
1355
1356$t->post_ok('/user/login' => form => {
1357 handle_or_email => 'test',
1358 pwd => 'pass',
1359 csrf_token => $csrf
1360})
1361 ->status_is(302)
1362 ->header_is('Location' => '/')
1363 ->content_is('');
1364
1365$t->get_ok('/')
1366 ->status_is(200)
1367 ->element_exists_not('div.notify-error')
1368 ->element_exists('div.notify-success')
1369 ->text_is('div.notify-success', 'Login successful')
1370 ->element_exists_not('aside.off')
1371 ->element_exists_not('aside.active')
1372 ->element_exists('aside.settings')
1373 ;
1374
Akron66ef3b52022-11-22 14:25:15 +01001375
Akron33f5c672019-06-24 19:40:47 +02001376done_testing;
1377__END__
Akrona8efaa92022-04-09 14:45:43 +02001378
1379