Bug 31378: (follow-up) Fix QA concerns
[koha-ffzg.git] / t / db_dependent / api / v1 / idp.t
1 #!/usr/bin/perl
2
3 # Copyright 2022 Theke Solutions
4 #
5 # This file is part of Koha
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21
22 use Test::More tests => 2;
23 use Test::Mojo;
24 use Test::Warn;
25 use Mojo::JWT;
26 use Crypt::OpenSSL::RSA;
27
28 use t::lib::TestBuilder;
29 use t::lib::Mocks;
30
31 use Koha::Database;
32 use C4::Auth;
33 use Koha::Auth::Identity::Providers;
34 use Koha::Auth::Identity::Provider::Domains;
35
36 my $schema  = Koha::Database->new->schema;
37 my $builder = t::lib::TestBuilder->new;
38
39 # FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling
40 # this affects the other REST api tests
41 t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' );
42
43 my $remote_address = '127.0.0.1';
44
45 # use t::lib::IdP::ExternalIdP;
46
47 # my $idp_port = t::lib::IdP::ExternalIdP->start;
48
49
50 my $oauth_provider_data = {
51   code        => 'oauth_test',
52   description => 'OAuth provider',
53   protocol    => 'OAuth',
54   mapping     => {
55         email     => 'users.0.email',
56         firstname => 'users.0.custom_name',
57         surname   => 'users.0.custom_surname',
58         userid    => 'users.0.id'
59   },
60   matchpoint  => 'email',
61   config      => {
62     authorize_url => "/idp/test/authorization_endpoint",
63     token_url     => "/idp/test/token_endpoint/without_id_token",
64     userinfo_url  => "/idp/test/userinfo_endpoint",
65     key           => "client_id",
66     secret        => "client_secret"
67   }
68 };
69
70 my $oidc_with_email_provider_data = {
71   code => 'oidc_email',
72   description => 'OIDC with email provider',
73   protocol => 'OIDC',
74   mapping => {
75     email     => 'email',
76     firstname => 'given_name',
77     surname   => 'family_name',
78     userid    => 'sub'
79   },
80   matchpoint => 'email',
81   config => {
82     authorize_url  => "/idp/test/authorization_endpoint",
83     well_known_url => "/idp/test/with_email/.well_known",
84     key            => "client_id",
85     secret         => "client_secret"
86   }
87 };
88
89 my $oidc_without_email_provider_data = {
90   code => 'oidc_no_email',
91   description => 'OIDC without email provider',
92   protocol => 'OIDC',
93   mapping => {
94     email     => 'users.0.email',
95     firstname => 'given_name',
96     surname   => 'family_name',
97     userid    => 'sub'
98   },
99   matchpoint => 'email',
100   config => {
101     authorize_url  => "/idp/test/authorization_endpoint",
102     well_known_url => "/idp/test/without_email/.well_known",
103     key            => "client_id",
104     secret         => "client_secret"
105   }
106 };
107
108 my $domain_not_matching = {
109   domain => 'gmail.com',
110   auto_register => 0,
111   update_on_auth => 0,
112   default_library_id => undef,
113   default_category_id => undef,
114   allow_opac => 1,
115   allow_staff => 0
116 };
117
118 my $domain_no_register = {
119   domain => 'some.library.com',
120   auto_register => 0,
121   update_on_auth => 0,
122   default_library_id => undef,
123   default_category_id => undef,
124   allow_opac => 1,
125   allow_staff => 0
126 };
127
128 my $library = $builder->build_object({class => 'Koha::Libraries'});
129 my $category = $builder->build_object({class => 'Koha::Patron::Categories'});
130
131 my $domain_register = {
132   domain => 'some.library.com',
133   auto_register => 1,
134   update_on_auth => 0,
135   default_library_id => $library->branchcode,
136   default_category_id => $category->categorycode,
137   allow_opac => 1,
138   allow_staff => 1
139 };
140
141 my $domain_register_update = {
142   domain => 'some.library.com',
143   auto_register => 1,
144   update_on_auth => 1,
145   default_library_id => $library->branchcode,
146   default_category_id => $category->categorycode,
147   allow_opac => 1,
148   allow_staff => 0
149 };
150
151 subtest 'provider endpoint tests' => sub {
152   plan tests => 12;
153
154   $schema->storage->txn_begin;
155
156   Koha::Auth::Identity::Provider::Domains->delete;
157   Koha::Auth::Identity::Providers->delete;
158
159   my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
160
161   my $t = Test::Mojo->new('Koha::REST::V1');
162
163   my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers", json => $oauth_provider_data );
164   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
165   $tx->req->env( { REMOTE_ADDR => $remote_address } );
166
167   $t->request_ok($tx)
168     ->status_is(201);
169
170   my $provider = Koha::Auth::Identity::Providers->search({code => 'oauth_test'})->next;
171   is ($provider->code, 'oauth_test', 'Provider was created');
172
173   $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers" );
174   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
175   $tx->req->env( { REMOTE_ADDR => $remote_address } );
176
177   $t->request_ok($tx)
178     ->json_has('/0/code', 'oauth_test');
179
180   my %modified_provider_data_hash = %{$oauth_provider_data};
181   my $modified_provider_data = \%modified_provider_data_hash;
182   $modified_provider_data->{code} = 'some_code';
183
184   $tx = $t->ua->build_tx( PUT => "/api/v1/auth/identity_providers/".$provider->identity_provider_id, json => $modified_provider_data);
185   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
186   $tx->req->env( { REMOTE_ADDR => $remote_address } );
187
188   $t->request_ok($tx)
189     ->status_is(200);
190
191   $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/".$provider->identity_provider_id);
192   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
193   $tx->req->env( { REMOTE_ADDR => $remote_address } );
194
195   $t->request_ok($tx)
196     ->json_has('/code', 'some_code');
197
198   $tx = $t->ua->build_tx( DELETE => "/api/v1/auth/identity_providers/".$provider->identity_provider_id);
199   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
200   $tx->req->env( { REMOTE_ADDR => $remote_address } );
201
202   $t->request_ok($tx)
203     ->status_is(204);
204   # p $t->tx->res;
205
206   $provider = Koha::Auth::Identity::Providers->search->next;
207   is ($provider, undef, 'All providers deleted');
208
209   $schema->storage->txn_rollback;
210 };
211
212 subtest 'domain endpoint tests' => sub {
213   plan tests => 12;
214
215   $schema->storage->txn_begin;
216
217   Koha::Auth::Identity::Provider::Domains->delete;
218   Koha::Auth::Identity::Providers->delete;
219
220   my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
221
222   my $t = Test::Mojo->new('Koha::REST::V1');
223
224   my $provider = $builder->build_object({class => 'Koha::Auth::Identity::Providers'});
225
226   my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains", json => $domain_not_matching );
227   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
228   $tx->req->env( { REMOTE_ADDR => $remote_address } );
229
230   $t->request_ok($tx)
231     ->status_is(201);
232
233   my $domain = Koha::Auth::Identity::Provider::Domains->search({domain => 'gmail.com'})->next;
234   is ($domain->domain, 'gmail.com', 'Provider was created');
235
236   $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains" );
237   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
238   $tx->req->env( { REMOTE_ADDR => $remote_address } );
239
240   $t->request_ok($tx)
241     ->json_has('/0/domain', 'gmail.com');
242
243   my %modified_domain_data_hash = %{$domain_not_matching};
244   my $modified_domain_data = \%modified_domain_data_hash;
245   $modified_domain_data->{domain} = 'some.domain.com';
246
247   $tx = $t->ua->build_tx( PUT => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains/".$domain->identity_provider_domain_id, json => $modified_domain_data);
248   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
249   $tx->req->env( { REMOTE_ADDR => $remote_address } );
250
251   $t->request_ok($tx)
252     ->status_is(200);
253
254   $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains/".$domain->identity_provider_domain_id);
255   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
256   $tx->req->env( { REMOTE_ADDR => $remote_address } );
257
258   $t->request_ok($tx)
259     ->json_has('/domain', 'some.domain.com');
260
261   $tx = $t->ua->build_tx( DELETE => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains/".$domain->identity_provider_domain_id);
262   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
263   $tx->req->env( { REMOTE_ADDR => $remote_address } );
264
265   $t->request_ok($tx)
266     ->status_is(204);
267   # p $t->tx->res;
268
269   $domain = Koha::Auth::Identity::Provider::Domains->search->next;
270   is ($domain, undef, 'All domains deleted');
271
272   $schema->storage->txn_rollback;
273 };
274
275 # subtest 'oauth login tests' => sub {
276 #   plan tests => 4;
277
278 #   $schema->storage->txn_begin;
279
280 #   Koha::Auth::Identity::Provider::Domains->delete;
281 #   Koha::Auth::Identity::Providers->delete;
282
283 #   my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
284
285 #   my $t = Test::Mojo->new('Koha::REST::V1');
286
287 #   # Build provider
288 #   my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers", json => $oauth_provider_data );
289 #   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
290 #   $tx->req->env( { REMOTE_ADDR => $remote_address } );
291
292 #   $t->request_ok($tx);
293 #   my $provider_id = $t->tx->res->json->{identity_provider_id};
294
295 #   # Build domain
296 #   $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers/$provider_id/domains", json => $domain_not_matching );
297 #   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
298 #   $tx->req->env( { REMOTE_ADDR => $remote_address } );
299
300 #   $t->request_ok($tx);
301
302 #   t::lib::Mocks::mock_preference( 'RESTPublicAPI', 1 );
303
304 #   # Simulate server restart
305 #   $t = Test::Mojo->new('Koha::REST::V1');
306
307 #   #$t->ua->max_redirects(10);
308 #   $t->get_ok("/api/v1/public/oauth/login/oauth_test/opac")
309 #     ->status_is(302);
310 #   $schema->storage->txn_rollback;
311 # };
312
313 sub create_user_and_session {
314
315     my $args  = shift;
316     my $flags = ( $args->{authorized} ) ? 1 : 0;
317
318     my $user = $builder->build(
319         {
320             source => 'Borrower',
321             value  => {
322                 flags => $flags
323             }
324         }
325     );
326
327     # Create a session for the authorized user
328     my $session = C4::Auth::get_session('');
329     $session->param( 'number',   $user->{borrowernumber} );
330     $session->param( 'id',       $user->{userid} );
331     $session->param( 'ip',       $remote_address );
332     $session->param( 'lasttime', time() );
333     $session->flush;
334
335     return ( $user->{borrowernumber}, $session->id );
336 }
337
338 1;