3 # Copyright 2022 Theke Solutions
5 # This file is part of Koha
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.
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.
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>.
22 use Test::More tests => 2;
26 use Crypt::OpenSSL::RSA;
28 use t::lib::TestBuilder;
33 use Koha::Auth::Identity::Providers;
34 use Koha::Auth::Identity::Provider::Domains;
36 my $schema = Koha::Database->new->schema;
37 my $builder = t::lib::TestBuilder->new;
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' );
43 my $remote_address = '127.0.0.1';
45 # use t::lib::IdP::ExternalIdP;
47 # my $idp_port = t::lib::IdP::ExternalIdP->start;
49 my $oauth_provider_data = {
51 description => 'OAuth provider',
54 email => 'users.0.email',
55 firstname => 'users.0.custom_name',
56 surname => 'users.0.custom_surname',
57 userid => 'users.0.id'
59 matchpoint => 'email',
61 authorize_url => "/idp/test/authorization_endpoint",
62 token_url => "/idp/test/token_endpoint/without_id_token",
63 userinfo_url => "/idp/test/userinfo_endpoint",
65 secret => "client_secret"
69 my $oidc_with_email_provider_data = {
71 description => 'OIDC with email provider',
75 firstname => 'given_name',
76 surname => 'family_name',
79 matchpoint => 'email',
81 authorize_url => "/idp/test/authorization_endpoint",
82 well_known_url => "/idp/test/with_email/.well_known",
84 secret => "client_secret"
88 my $oidc_without_email_provider_data = {
89 code => 'oidc_no_email',
90 description => 'OIDC without email provider',
93 email => 'users.0.email',
94 firstname => 'given_name',
95 surname => 'family_name',
98 matchpoint => 'email',
100 authorize_url => "/idp/test/authorization_endpoint",
101 well_known_url => "/idp/test/without_email/.well_known",
103 secret => "client_secret"
107 my $domain_not_matching = {
108 domain => 'gmail.com',
111 default_library_id => undef,
112 default_category_id => undef,
117 my $domain_no_register = {
118 domain => 'some.library.com',
121 default_library_id => undef,
122 default_category_id => undef,
127 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
128 my $category = $builder->build_object( { class => 'Koha::Patron::Categories' } );
130 my $domain_register = {
131 domain => 'some.library.com',
134 default_library_id => $library->branchcode,
135 default_category_id => $category->categorycode,
140 my $domain_register_update = {
141 domain => 'some.library.com',
144 default_library_id => $library->branchcode,
145 default_category_id => $category->categorycode,
150 subtest 'provider endpoint tests' => sub {
153 $schema->storage->txn_begin;
155 Koha::Auth::Identity::Provider::Domains->delete;
156 Koha::Auth::Identity::Providers->delete;
158 my ( $borrowernumber, $session_id ) = create_user_and_session( { authorized => 1 } );
160 my $t = Test::Mojo->new('Koha::REST::V1');
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 } );
166 $t->request_ok($tx)->status_is(201);
168 my $provider = Koha::Auth::Identity::Providers->search( { code => 'oauth_test' } )->next;
169 is( $provider->code, 'oauth_test', 'Provider was created' );
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 } );
175 $t->request_ok($tx)->json_has( '/0/code', 'oauth_test' );
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';
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 } );
185 $t->request_ok($tx)->status_is(200);
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 } );
191 $t->request_ok($tx)->json_has( '/code', 'some_code' );
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 } );
197 $t->request_ok($tx)->status_is(204);
199 $provider = Koha::Auth::Identity::Providers->search->next;
200 is( $provider, undef, 'All providers deleted' );
202 $schema->storage->txn_rollback;
205 subtest 'domain endpoint tests' => sub {
209 $schema->storage->txn_begin;
211 Koha::Auth::Identity::Provider::Domains->delete;
212 Koha::Auth::Identity::Providers->delete;
214 my ( $borrowernumber, $session_id ) = create_user_and_session( { authorized => 1 } );
216 my $t = Test::Mojo->new('Koha::REST::V1');
218 my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers' } );
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 } );
224 $t->request_ok($tx)->status_is(201);
226 my $domain = Koha::Auth::Identity::Provider::Domains->search( { domain => 'gmail.com' } )->next;
227 is( $domain->domain, 'gmail.com', 'Provider was created' );
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 } );
233 $t->request_ok($tx)->json_has( '/0/domain', 'gmail.com' );
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';
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
243 $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
244 $tx->req->env( { REMOTE_ADDR => $remote_address } );
246 $t->request_ok($tx)->status_is(200);
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 } );
252 $t->request_ok($tx)->json_has( '/domain', 'some.domain.com' );
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 } );
258 $t->request_ok($tx)->status_is(204);
260 $domain = Koha::Auth::Identity::Provider::Domains->search->next;
261 is( $domain, undef, 'All domains deleted' );
263 $schema->storage->txn_rollback;
266 # subtest 'oauth login tests' => sub {
269 # $schema->storage->txn_begin;
271 # Koha::Auth::Identity::Provider::Domains->delete;
272 # Koha::Auth::Identity::Providers->delete;
274 # my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
276 # my $t = Test::Mojo->new('Koha::REST::V1');
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 } );
283 # $t->request_ok($tx);
284 # my $provider_id = $t->tx->res->json->{identity_provider_id};
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 } );
291 # $t->request_ok($tx);
293 # t::lib::Mocks::mock_preference( 'RESTPublicAPI', 1 );
295 # # Simulate server restart
296 # $t = Test::Mojo->new('Koha::REST::V1');
298 # #$t->ua->max_redirects(10);
299 # $t->get_ok("/api/v1/public/oauth/login/oauth_test/opac")
301 # $schema->storage->txn_rollback;
304 sub create_user_and_session {
307 my $flags = ( $args->{authorized} ) ? 1 : 0;
309 my $user = $builder->build(
310 { source => 'Borrower',
311 value => { flags => $flags }
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() );
323 return ( $user->{borrowernumber}, $session->id );