Bug 29234: Further clean Z3950 Tests
[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 my $oauth_provider_data = {
50     code        => 'oauth_test',
51     description => 'OAuth provider',
52     protocol    => 'OAuth',
53     mapping     => {
54         email     => 'users.0.email',
55         firstname => 'users.0.custom_name',
56         surname   => 'users.0.custom_surname',
57         userid    => 'users.0.id'
58     },
59     matchpoint => 'email',
60     config     => {
61         authorize_url => "/idp/test/authorization_endpoint",
62         token_url     => "/idp/test/token_endpoint/without_id_token",
63         userinfo_url  => "/idp/test/userinfo_endpoint",
64         key           => "client_id",
65         secret        => "client_secret"
66     }
67 };
68
69 my $oidc_with_email_provider_data = {
70     code        => 'oidc_email',
71     description => 'OIDC with email provider',
72     protocol    => 'OIDC',
73     mapping     => {
74         email     => 'email',
75         firstname => 'given_name',
76         surname   => 'family_name',
77         userid    => 'sub'
78     },
79     matchpoint => 'email',
80     config     => {
81         authorize_url  => "/idp/test/authorization_endpoint",
82         well_known_url => "/idp/test/with_email/.well_known",
83         key            => "client_id",
84         secret         => "client_secret"
85     }
86 };
87
88 my $oidc_without_email_provider_data = {
89     code        => 'oidc_no_email',
90     description => 'OIDC without email provider',
91     protocol    => 'OIDC',
92     mapping     => {
93         email     => 'users.0.email',
94         firstname => 'given_name',
95         surname   => 'family_name',
96         userid    => 'sub'
97     },
98     matchpoint => 'email',
99     config     => {
100         authorize_url  => "/idp/test/authorization_endpoint",
101         well_known_url => "/idp/test/without_email/.well_known",
102         key            => "client_id",
103         secret         => "client_secret"
104     }
105 };
106
107 my $domain_not_matching = {
108     domain              => 'gmail.com',
109     auto_register       => 0,
110     update_on_auth      => 0,
111     default_library_id  => undef,
112     default_category_id => undef,
113     allow_opac          => 1,
114     allow_staff         => 0
115 };
116
117 my $domain_no_register = {
118     domain              => 'some.library.com',
119     auto_register       => 0,
120     update_on_auth      => 0,
121     default_library_id  => undef,
122     default_category_id => undef,
123     allow_opac          => 1,
124     allow_staff         => 0
125 };
126
127 my $library  = $builder->build_object( { class => 'Koha::Libraries' } );
128 my $category = $builder->build_object( { class => 'Koha::Patron::Categories' } );
129
130 my $domain_register = {
131     domain              => 'some.library.com',
132     auto_register       => 1,
133     update_on_auth      => 0,
134     default_library_id  => $library->branchcode,
135     default_category_id => $category->categorycode,
136     allow_opac          => 1,
137     allow_staff         => 1
138 };
139
140 my $domain_register_update = {
141     domain              => 'some.library.com',
142     auto_register       => 1,
143     update_on_auth      => 1,
144     default_library_id  => $library->branchcode,
145     default_category_id => $category->categorycode,
146     allow_opac          => 1,
147     allow_staff         => 0
148 };
149
150 subtest 'provider endpoint tests' => sub {
151     plan tests => 12;
152
153     $schema->storage->txn_begin;
154
155     Koha::Auth::Identity::Provider::Domains->delete;
156     Koha::Auth::Identity::Providers->delete;
157
158     my ( $borrowernumber, $session_id ) = create_user_and_session( { authorized => 1 } );
159
160     my $t = Test::Mojo->new('Koha::REST::V1');
161
162     my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers", json => $oauth_provider_data );
163     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
164     $tx->req->env( { REMOTE_ADDR => $remote_address } );
165
166     $t->request_ok($tx)->status_is(201);
167
168     my $provider = Koha::Auth::Identity::Providers->search( { code => 'oauth_test' } )->next;
169     is( $provider->code, 'oauth_test', 'Provider was created' );
170
171     $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers" );
172     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
173     $tx->req->env( { REMOTE_ADDR => $remote_address } );
174
175     $t->request_ok($tx)->json_has( '/0/code', 'oauth_test' );
176
177     my %modified_provider_data_hash = %{$oauth_provider_data};
178     my $modified_provider_data      = \%modified_provider_data_hash;
179     $modified_provider_data->{code} = 'some_code';
180
181     $tx = $t->ua->build_tx( PUT => "/api/v1/auth/identity_providers/" . $provider->identity_provider_id, json => $modified_provider_data );
182     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
183     $tx->req->env( { REMOTE_ADDR => $remote_address } );
184
185     $t->request_ok($tx)->status_is(200);
186
187     $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/" . $provider->identity_provider_id );
188     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
189     $tx->req->env( { REMOTE_ADDR => $remote_address } );
190
191     $t->request_ok($tx)->json_has( '/code', 'some_code' );
192
193     $tx = $t->ua->build_tx( DELETE => "/api/v1/auth/identity_providers/" . $provider->identity_provider_id );
194     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
195     $tx->req->env( { REMOTE_ADDR => $remote_address } );
196
197     $t->request_ok($tx)->status_is(204);
198
199     $provider = Koha::Auth::Identity::Providers->search->next;
200     is( $provider, undef, 'All providers deleted' );
201
202     $schema->storage->txn_rollback;
203 };
204
205 subtest 'domain endpoint tests' => sub {
206
207     plan tests => 12;
208
209     $schema->storage->txn_begin;
210
211     Koha::Auth::Identity::Provider::Domains->delete;
212     Koha::Auth::Identity::Providers->delete;
213
214     my ( $borrowernumber, $session_id ) = create_user_and_session( { authorized => 1 } );
215
216     my $t = Test::Mojo->new('Koha::REST::V1');
217
218     my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers' } );
219
220     my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers/" . $provider->identity_provider_id . "/domains", json => $domain_not_matching );
221     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
222     $tx->req->env( { REMOTE_ADDR => $remote_address } );
223
224     $t->request_ok($tx)->status_is(201);
225
226     my $domain = Koha::Auth::Identity::Provider::Domains->search( { domain => 'gmail.com' } )->next;
227     is( $domain->domain, 'gmail.com', 'Provider was created' );
228
229     $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/" . $provider->identity_provider_id . "/domains" );
230     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
231     $tx->req->env( { REMOTE_ADDR => $remote_address } );
232
233     $t->request_ok($tx)->json_has( '/0/domain', 'gmail.com' );
234
235     my %modified_domain_data_hash = %{$domain_not_matching};
236     my $modified_domain_data      = \%modified_domain_data_hash;
237     $modified_domain_data->{domain} = 'some.domain.com';
238
239     $tx = $t->ua->build_tx(
240         PUT  => "/api/v1/auth/identity_providers/" . $provider->identity_provider_id . "/domains/" . $domain->identity_provider_domain_id,
241         json => $modified_domain_data
242     );
243     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
244     $tx->req->env( { REMOTE_ADDR => $remote_address } );
245
246     $t->request_ok($tx)->status_is(200);
247
248     $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/" . $provider->identity_provider_id . "/domains/" . $domain->identity_provider_domain_id );
249     $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
250     $tx->req->env( { REMOTE_ADDR => $remote_address } );
251
252     $t->request_ok($tx)->json_has( '/domain', 'some.domain.com' );
253
254     $tx = $t->ua->build_tx( DELETE => "/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)->status_is(204);
259
260     $domain = Koha::Auth::Identity::Provider::Domains->search->next;
261     is( $domain, undef, 'All domains deleted' );
262
263     $schema->storage->txn_rollback;
264 };
265
266 # subtest 'oauth login tests' => sub {
267 #   plan tests => 4;
268
269 #   $schema->storage->txn_begin;
270
271 #   Koha::Auth::Identity::Provider::Domains->delete;
272 #   Koha::Auth::Identity::Providers->delete;
273
274 #   my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
275
276 #   my $t = Test::Mojo->new('Koha::REST::V1');
277
278 #   # Build provider
279 #   my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers", json => $oauth_provider_data );
280 #   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
281 #   $tx->req->env( { REMOTE_ADDR => $remote_address } );
282
283 #   $t->request_ok($tx);
284 #   my $provider_id = $t->tx->res->json->{identity_provider_id};
285
286 #   # Build domain
287 #   $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers/$provider_id/domains", json => $domain_not_matching );
288 #   $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
289 #   $tx->req->env( { REMOTE_ADDR => $remote_address } );
290
291 #   $t->request_ok($tx);
292
293 #   t::lib::Mocks::mock_preference( 'RESTPublicAPI', 1 );
294
295 #   # Simulate server restart
296 #   $t = Test::Mojo->new('Koha::REST::V1');
297
298 #   #$t->ua->max_redirects(10);
299 #   $t->get_ok("/api/v1/public/oauth/login/oauth_test/opac")
300 #     ->status_is(302);
301 #   $schema->storage->txn_rollback;
302 # };
303
304 sub create_user_and_session {
305
306     my $args  = shift;
307     my $flags = ( $args->{authorized} ) ? 1 : 0;
308
309     my $user = $builder->build(
310         {   source => 'Borrower',
311             value  => { flags => $flags }
312         }
313     );
314
315     # Create a session for the authorized user
316     my $session = C4::Auth::get_session('');
317     $session->param( 'number',   $user->{borrowernumber} );
318     $session->param( 'id',       $user->{userid} );
319     $session->param( 'ip',       $remote_address );
320     $session->param( 'lasttime', time() );
321     $session->flush;
322
323     return ( $user->{borrowernumber}, $session->id );
324 }