Bugzilla – Attachment 141816 Details for
Bug 31378
Add a generic OAuth2/OIDC client implementation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 31378: Add authentication provider endpoints
Bug-31378-Add-authentication-provider-endpoints.patch (text/plain), 48.64 KB, created by
Martin Renvoize (ashimema)
on 2022-10-13 11:58:50 UTC
(
hide
)
Description:
Bug 31378: Add authentication provider endpoints
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2022-10-13 11:58:50 UTC
Size:
48.64 KB
patch
obsolete
>From 1c41f04c91c6e864e388d7018fb690a2a0663b6f Mon Sep 17 00:00:00 2001 >From: Tomas Cohen Arazi <tomascohen@theke.io> >Date: Tue, 30 Aug 2022 10:33:14 -0300 >Subject: [PATCH] Bug 31378: Add authentication provider endpoints > >This patch adds routes for handling authentication providers to the REST >API. > >To test: >1. Apply this patch >2. Run: > $ kshell > k$ prove t/db_dependent/api/v1/auth_providers.t >=> SUCCESS: Tests pass! >3. Sign off :-D > >Signed-off-by: Lukasz Koszyk <lukasz.koszyk@kit.edu> >--- > Koha/Auth/Provider.pm | 85 +++- > Koha/Auth/Provider/OAuth.pm | 65 +++ > Koha/Auth/Provider/OIDC.pm | 64 +++ > Koha/REST/V1/Auth/Provider/Domains.pm | 233 +++++++++ > Koha/REST/V1/Auth/Providers.pm | 237 +++++++++ > api/v1/swagger/definitions/auth_provider.yaml | 49 ++ > .../definitions/auth_provider_domain.yaml | 48 ++ > api/v1/swagger/paths/auth.yaml | 453 +++++++++++++++++- > api/v1/swagger/paths/oauth.yaml | 79 +++ > api/v1/swagger/paths/public_oauth.yaml | 26 +- > api/v1/swagger/swagger.yaml | 33 +- > t/db_dependent/Koha/Auth/Provider.t | 47 +- > 12 files changed, 1386 insertions(+), 33 deletions(-) > create mode 100644 Koha/Auth/Provider/OAuth.pm > create mode 100644 Koha/Auth/Provider/OIDC.pm > create mode 100644 Koha/REST/V1/Auth/Provider/Domains.pm > create mode 100644 Koha/REST/V1/Auth/Providers.pm > create mode 100644 api/v1/swagger/definitions/auth_provider.yaml > create mode 100644 api/v1/swagger/definitions/auth_provider_domain.yaml > >diff --git a/Koha/Auth/Provider.pm b/Koha/Auth/Provider.pm >index e8de84ada5..7a652dec55 100644 >--- a/Koha/Auth/Provider.pm >+++ b/Koha/Auth/Provider.pm >@@ -97,22 +97,11 @@ This method stores the passed config in JSON format. > sub set_config { > my ($self, $config) = @_; > >- my @mandatory; >- >- if ( $self->protocol eq 'OIDC' ) { >- @mandatory = qw(key secret well_known_url); >- } >- elsif ( $self->protocol eq 'OAuth' ) { >- @mandatory = qw(key secret authorize_url token_url); >- } >- else { >- Koha::Exception->throw( 'Unsupported protocol ' . $self->protocol ); >- } >+ my @mandatory = $self->mandatory_config_attributes; > > for my $param (@mandatory) { > unless ( defined( $config->{$param} ) ) { >- Koha::Exceptions::MissingParameter->throw( >- error => "The $param parameter is mandatory" ); >+ Koha::Exceptions::MissingParameter->throw( parameter => $param ); > } > } > >@@ -167,8 +156,51 @@ sub set_mapping { > return $self; > } > >+=head3 upgrade_class >+ >+ my $upgraded_object = $provider->upgrade_class >+ >+Returns a new instance of the object, with the right class. >+ >+=cut >+ >+sub upgrade_class { >+ my ( $self ) = @_; >+ my $protocol = $self->protocol; >+ >+ my $class = $self->protocol_to_class_mapping->{$protocol}; >+ >+ Koha::Exception->throw($protocol . ' is not a valid protocol') >+ unless $class; >+ >+ eval "require $class"; >+ return $class->_new_from_dbic( $self->_result ); >+} >+ > =head2 Internal methods > >+=head3 to_api >+ >+ my $json = $provider->to_api; >+ >+Overloaded method that returns a JSON representation of the Koha::Auth::Provider object, >+suitable for API output. >+ >+=cut >+ >+sub to_api { >+ my ( $self, $params ) = @_; >+ >+ my $config = $self->get_config; >+ my $mapping = $self->get_mapping; >+ >+ my $json = $self->SUPER::to_api($params); >+ $json->{config} = $config; >+ $json->{mapping} = $mapping; >+ >+ return $json; >+} >+ > =head3 _type > > =cut >@@ -177,4 +209,31 @@ sub _type { > return 'AuthProvider'; > } > >+=head3 protocol_to_class_mapping >+ >+ my $mapping = Koha::Auth::Provider::protocol_to_class_mapping >+ >+Internal method that returns a mapping between I<protocol> codes and >+implementing I<classes>. To be used by B<upgrade_class>. >+ >+=cut >+ >+sub protocol_to_class_mapping { >+ return { >+ OAuth => 'Koha::Auth::Provider::OAuth', >+ OIDC => 'Koha::Auth::Provider::OIDC', >+ }; >+} >+ >+=head3 mandatory_config_attributes >+ >+Stub method for raising exceptions on invalid protocols. >+ >+=cut >+ >+sub mandatory_config_attributes { >+ my ($self) = @_; >+ Koha::Exception->throw("This method needs to be subclassed"); >+} >+ > 1; >diff --git a/Koha/Auth/Provider/OAuth.pm b/Koha/Auth/Provider/OAuth.pm >new file mode 100644 >index 0000000000..b77f4af5ad >--- /dev/null >+++ b/Koha/Auth/Provider/OAuth.pm >@@ -0,0 +1,65 @@ >+package Koha::Auth::Provider::OAuth; >+ >+# Copyright Theke Solutions 2022 >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use base qw(Koha::Auth::Provider); >+ >+=head1 NAME >+ >+Koha::Auth::Provider::OAuth - Koha Auth Provider Object class >+ >+=head1 API >+ >+=head2 Class methods >+ >+=head3 new >+ >+ my $oauth = Koha::Auth::Provider::OAuth->new( \%{params} ); >+ >+Overloaded class to create a new OAuth provider. >+ >+=cut >+ >+sub new { >+ my ( $class, $params ) = @_; >+ >+ $params->{protocol} = 'OAuth'; >+ >+ return $class->SUPER::new($params); >+} >+ >+=head2 Internal methods >+ >+=head3 mandatory_config_attributes >+ >+Returns a list of the mandatory config entries for the protocol. >+ >+=cut >+ >+sub mandatory_config_attributes { >+ return qw( >+ key >+ secret >+ authorize_url >+ token_url >+ ); >+} >+ >+1; >diff --git a/Koha/Auth/Provider/OIDC.pm b/Koha/Auth/Provider/OIDC.pm >new file mode 100644 >index 0000000000..5945555994 >--- /dev/null >+++ b/Koha/Auth/Provider/OIDC.pm >@@ -0,0 +1,64 @@ >+package Koha::Auth::Provider::OIDC; >+ >+# Copyright Theke Solutions 2022 >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use base qw(Koha::Auth::Provider); >+ >+=head1 NAME >+ >+Koha::Auth::Provider::OIDC - Koha Auth Provider Object class >+ >+=head1 API >+ >+=head2 Class methods >+ >+=head3 new >+ >+ my $oidc = Koha::Auth::Provider::OIDC->new( \%{params} ); >+ >+Overloaded class to create a new OIDC provider. >+ >+=cut >+ >+sub new { >+ my ( $class, $params ) = @_; >+ >+ $params->{protocol} = 'OIDC'; >+ >+ return $class->SUPER::new($params); >+} >+ >+=head2 Internal methods >+ >+=head3 mandatory_config_attributes >+ >+Returns a list of the mandatory config entries for the protocol. >+ >+=cut >+ >+sub mandatory_config_attributes { >+ return qw( >+ key >+ secret >+ well_known_url >+ ); >+} >+ >+1; >diff --git a/Koha/REST/V1/Auth/Provider/Domains.pm b/Koha/REST/V1/Auth/Provider/Domains.pm >new file mode 100644 >index 0000000000..f53954ac9f >--- /dev/null >+++ b/Koha/REST/V1/Auth/Provider/Domains.pm >@@ -0,0 +1,233 @@ >+package Koha::REST::V1::Auth::Provider::Domains; >+ >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Mojo::Base 'Mojolicious::Controller'; >+ >+use Koha::Auth::Provider::Domains; >+use Koha::Auth::Providers; >+ >+use Koha::Database; >+ >+use Scalar::Util qw(blessed); >+use Try::Tiny; >+ >+=head1 NAME >+ >+Koha::REST::V1::Auth::Provider::Domains - Controller library for handling >+authentication provider domains routes. >+ >+=head2 Operations >+ >+=head3 list >+ >+Controller method for listing authentication provider domains. >+ >+=cut >+ >+sub list { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ my $auth_provider_id = $c->validation->param('auth_provider_id'); >+ my $provider = Koha::Auth::Providers->find($auth_provider_id); >+ >+ unless ($provider) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ my $domains_rs = $provider->domains; >+ return $c->render( >+ status => 200, >+ openapi => $c->objects->search($domains_rs) >+ ); >+ } catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 get >+ >+Controller method for retrieving an authentication provider domain. >+ >+=cut >+ >+sub get { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ >+ my $auth_provider_id = $c->validation->param('auth_provider_id'); >+ my $provider = Koha::Auth::Providers->find($auth_provider_id); >+ >+ unless ($provider) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ my $domains_rs = $provider->domains; >+ >+ my $auth_provider_domain_id = $c->validation->param('auth_provider_domain_id'); >+ my $domain = $c->objects->find( $domains_rs, $auth_provider_domain_id ); >+ >+ unless ($domain) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ return $c->render( status => 200, openapi => $domain ); >+ } catch { >+ $c->unhandled_exception($_); >+ } >+} >+ >+=head3 add >+ >+Controller method for adding an authentication provider. >+ >+=cut >+ >+sub add { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ >+ Koha::Database->new->schema->txn_do( >+ sub { >+ my $domain = Koha::Auth::Provider::Domain->new_from_api( $c->validation->param('body') ); >+ $domain->store; >+ >+ $c->res->headers->location( $c->req->url->to_string . '/' . $domain->id ); >+ return $c->render( >+ status => 201, >+ openapi => $domain->to_api >+ ); >+ } >+ ); >+ } catch { >+ if ( blessed($_) and $_->isa('Koha::Exceptions::Object::FKConstraint') ) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 update >+ >+Controller method for updating an authentication provider domain. >+ >+=cut >+ >+sub update { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $auth_provider_id = $c->validation->param('auth_provider_id'); >+ my $auth_provider_domain_id = $c->validation->param('auth_provider_domain_id'); >+ >+ my $domain = Koha::Auth::Provider::Domains->find( >+ { auth_provider_id => $auth_provider_id, auth_provider_domain_id => $auth_provider_domain_id } ); >+ >+ unless ($domain) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ return try { >+ >+ Koha::Database->new->schema->txn_do( >+ sub { >+ >+ $domain->set_from_api( $c->validation->param('body') ); >+ $domain->store->discard_changes; >+ >+ return $c->render( >+ status => 200, >+ openapi => $domain->to_api >+ ); >+ } >+ ); >+ } catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 delete >+ >+Controller method for deleting an authentication provider. >+ >+=cut >+ >+sub delete { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $auth_provider_id = $c->validation->param('auth_provider_id'); >+ my $auth_provider_domain_id = $c->validation->param('auth_provider_domain_id'); >+ >+ my $domain = Koha::Auth::Provider::Domains->find( >+ { auth_provider_id => $auth_provider_id, auth_provider_domain_id => $auth_provider_domain_id } ); >+ >+ unless ($domain) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ return try { >+ $domain->delete; >+ return $c->render( >+ status => 204, >+ openapi => q{} >+ ); >+ } catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ >+1; >diff --git a/Koha/REST/V1/Auth/Providers.pm b/Koha/REST/V1/Auth/Providers.pm >new file mode 100644 >index 0000000000..c31b2588bb >--- /dev/null >+++ b/Koha/REST/V1/Auth/Providers.pm >@@ -0,0 +1,237 @@ >+package Koha::REST::V1::Auth::Providers; >+ >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Mojo::Base 'Mojolicious::Controller'; >+ >+use Koha::Auth::Provider::OAuth; >+use Koha::Auth::Provider::OIDC; >+use Koha::Auth::Providers; >+ >+use Koha::Database; >+ >+use Scalar::Util qw(blessed); >+use Try::Tiny; >+ >+=head1 NAME >+ >+Koha::REST::V1::Auth::Providers - Controller library for handling >+authentication providers routes. >+ >+=head2 Operations >+ >+=head3 list >+ >+Controller method for listing authentication providers. >+ >+=cut >+ >+sub list { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ my $providers_rs = Koha::Auth::Providers->new; >+ return $c->render( >+ status => 200, >+ openapi => $c->objects->search($providers_rs) >+ ); >+ } catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 get >+ >+Controller method for retrieving an authentication provider. >+ >+=cut >+ >+sub get { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ >+ my $auth_provider_id = $c->validation->param('auth_provider_id'); >+ my $provider = $c->objects->find( Koha::Auth::Providers->new, $auth_provider_id ); >+ >+ unless ( $provider ) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ return $c->render( status => 200, openapi => $provider ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ } >+} >+ >+=head3 add >+ >+Controller method for adding an authentication provider. >+ >+=cut >+ >+sub add { >+ my $c = shift->openapi->valid_input or return; >+ >+ return try { >+ >+ Koha::Database->new->schema->txn_do( >+ sub { >+ >+ my $body = $c->validation->param('body'); >+ >+ my $config = delete $body->{config}; >+ my $mapping = delete $body->{mapping}; >+ my $protocol = delete $body->{protocol}; >+ >+ my $class = Koha::Auth::Provider::protocol_to_class_mapping->{$protocol}; >+ >+ my $provider = $class->new_from_api( $body ); >+ $provider->store; >+ >+ $provider->set_config( $config ); >+ $provider->set_mapping( $mapping ); >+ >+ $c->res->headers->location( $c->req->url->to_string . '/' . $provider->auth_provider_id ); >+ return $c->render( >+ status => 201, >+ openapi => $provider->to_api >+ ); >+ } >+ ); >+ } >+ catch { >+ if ( blessed($_) ) { >+ if ( $_->isa('Koha::Exceptions::MissingParameter') ) { >+ return $c->render( >+ status => 400, >+ openapi => { >+ error => "Missing parameter config." . $_->parameter, >+ error_code => 'missing_parameter' >+ } >+ ); >+ } >+ } >+ >+ $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 update >+ >+Controller method for updating an authentication provider. >+ >+=cut >+ >+sub update { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $auth_provider_id = $c->validation->param('auth_provider_id'); >+ my $provider = Koha::Auth::Providers->find( $auth_provider_id ); >+ >+ unless ( $provider ) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ return try { >+ >+ Koha::Database->new->schema->txn_do( >+ sub { >+ >+ my $body = $c->validation->param('body'); >+ >+ my $config = delete $body->{config}; >+ my $mapping = delete $body->{mapping}; >+ >+ $provider = $provider->set_from_api( $body )->upgrade_class; >+ >+ $provider->set_config( $config ); >+ $provider->set_mapping( $mapping ); >+ # set_config and set_mapping already called store() >+ $provider->discard_changes; >+ >+ return $c->render( >+ status => 200, >+ openapi => $provider->to_api >+ ); >+ } >+ ); >+ } >+ catch { >+ if ( blessed($_) ) { >+ if ( $_->isa('Koha::Exceptions::MissingParameter') ) { >+ return $c->render( >+ status => 400, >+ openapi => { >+ error => "Missing parameter config." . $_->parameter, >+ error_code => 'missing_parameter' >+ } >+ ); >+ } >+ } >+ >+ $c->unhandled_exception($_); >+ }; >+} >+ >+=head3 delete >+ >+Controller method for deleting an authentication provider. >+ >+=cut >+ >+sub delete { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $provider = Koha::Auth::Providers->find( $c->validation->param('auth_provider_id') ); >+ unless ( $provider ) { >+ return $c->render( >+ status => 404, >+ openapi => { >+ error => 'Object not found', >+ error_code => 'not_found', >+ } >+ ); >+ } >+ >+ return try { >+ $provider->delete; >+ return $c->render( >+ status => 204, >+ openapi => q{} >+ ); >+ } >+ catch { >+ $c->unhandled_exception($_); >+ }; >+} >+ >+1; >diff --git a/api/v1/swagger/definitions/auth_provider.yaml b/api/v1/swagger/definitions/auth_provider.yaml >new file mode 100644 >index 0000000000..93e587b2af >--- /dev/null >+++ b/api/v1/swagger/definitions/auth_provider.yaml >@@ -0,0 +1,49 @@ >+--- >+type: object >+properties: >+ auth_provider_id: >+ type: integer >+ description: Internally assigned authentication provider identifier >+ readOnly: true >+ code: >+ description: Authentication provider code >+ type: string >+ description: >+ description: User-oriented description for the provider >+ type: string >+ protocol: >+ description: Authentication protocol >+ type: string >+ enum: >+ - OAuth >+ - OIDC >+ - CAS (not implemented) >+ - LDAP (not implemented) >+ mapping: >+ description: Attribute mapping >+ type: >+ - object >+ - "null" >+ matchpoint: >+ description: Patron attribute that will be used to match >+ type: string >+ enum: >+ - email >+ - userid >+ - cardnumber >+ config: >+ description: Configuration >+ type: object >+ icon_url: >+ description: Icon url >+ type: string >+ domains: >+ description: Configured domains for the authentication provider >+ type: >+ - array >+ - "null" >+additionalProperties: false >+required: >+ - config >+ - code >+ - protocol >diff --git a/api/v1/swagger/definitions/auth_provider_domain.yaml b/api/v1/swagger/definitions/auth_provider_domain.yaml >new file mode 100644 >index 0000000000..bc9f60a7a3 >--- /dev/null >+++ b/api/v1/swagger/definitions/auth_provider_domain.yaml >@@ -0,0 +1,48 @@ >+--- >+type: object >+properties: >+ auth_provider_domain_id: >+ type: integer >+ description: Internally assigned authentication provider domain identifier >+ readOnly: true >+ auth_provider_id: >+ type: integer >+ description: Internally assigned authentication provider identifier >+ domain: >+ description: Matching domain ('*' used as wildcard) >+ type: >+ - string >+ - "null" >+ auto_register: >+ description: If patrons will be generated on login if required >+ type: boolean >+ update_on_auth: >+ description: If patron data is updated on login >+ type: boolean >+ default_library_id: >+ description: Internal identifier for the default library to be assigned to the new patrons >+ type: >+ - string >+ - "null" >+ default_category_id: >+ description: Internal identifier for the default patron's category >+ type: >+ - string >+ - "null" >+ allow_opac: >+ description: If this domain can be used for OPAC login >+ type: boolean >+ allow_staff: >+ description: If this domain can be used for staff login >+ type: boolean >+additionalProperties: false >+required: >+ - auth_provider_domain_id >+ - auth_provider_id >+ - domain >+ - auto_register >+ - update_on_auth >+ - default_library_id >+ - default_category_id >+ - allow_opac >+ - allow_staff >diff --git a/api/v1/swagger/paths/auth.yaml b/api/v1/swagger/paths/auth.yaml >index c147d0549d..2cebf00d27 100644 >--- a/api/v1/swagger/paths/auth.yaml >+++ b/api/v1/swagger/paths/auth.yaml >@@ -1,4 +1,3 @@ >---- > /auth/otp/token_delivery: > post: > x-mojo-to: TwoFactorAuth#send_otp_token >@@ -24,18 +23,462 @@ > "400": > description: Bad Request > schema: >- $ref: "../swagger.yaml#/definitions/error" >+ $ref: ../swagger.yaml#/definitions/error > "403": > description: Access forbidden > schema: >- $ref: "../swagger.yaml#/definitions/error" >+ $ref: ../swagger.yaml#/definitions/error > "500": > description: | > Internal server error. Possible `error_code` attribute values: > > * `internal_server_error` > schema: >- $ref: "../swagger.yaml#/definitions/error" >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+/auth/providers: >+ get: >+ x-mojo-to: Auth::Providers#list >+ operationId: listAuthProviders >+ tags: >+ - auth_providers >+ summary: List configured authentication providers >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/match >+ - $ref: ../swagger.yaml#/parameters/order_by >+ - $ref: ../swagger.yaml#/parameters/page >+ - $ref: ../swagger.yaml#/parameters/per_page >+ - $ref: ../swagger.yaml#/parameters/q_param >+ - $ref: ../swagger.yaml#/parameters/q_body >+ - $ref: ../swagger.yaml#/parameters/q_header >+ - $ref: ../swagger.yaml#/parameters/request_id_header >+ - name: x-koha-embed >+ in: header >+ required: false >+ description: Embed list sent as a request header >+ type: array >+ items: >+ type: string >+ enum: >+ - domains >+ collectionFormat: csv >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: A list of authentication providers >+ schema: >+ type: array >+ items: >+ $ref: ../swagger.yaml#/definitions/auth_provider >+ "400": >+ description: Bad Request >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+ post: >+ x-mojo-to: Auth::Providers#add >+ operationId: addAuthProvider >+ tags: >+ - auth_providers >+ summary: Add a new authentication provider >+ parameters: >+ - name: body >+ in: body >+ description: | >+ A JSON object containing OAuth provider parameters. >+ >+ The `config` object required attributes depends on the chosen `protocol` >+ >+ ## OAuth >+ >+ Requires: >+ >+ * key >+ * secret >+ * authorize_url >+ * token_url >+ >+ ## OIDC >+ >+ Requires: >+ >+ * key >+ * secret >+ * well_known_url >+ required: true >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider >+ produces: >+ - application/json >+ responses: >+ "201": >+ description: The generated authentication provider >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider >+ "400": >+ description: Bad Request >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+"/auth/providers/{auth_provider_id}": >+ get: >+ x-mojo-to: Auth::Providers#get >+ operationId: getAuthProvider >+ tags: >+ - auth_providers >+ summary: Get authentication provider >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/auth_provider_id_pp >+ - name: x-koha-embed >+ in: header >+ required: false >+ description: Embed list sent as a request header >+ type: array >+ items: >+ type: string >+ enum: >+ - domains >+ collectionFormat: csv >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: An authentication provider >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider >+ "404": >+ description: Object not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+ put: >+ x-mojo-to: Auth::Providers#update >+ operationId: updateAuthProvider >+ tags: >+ - auth_providers >+ summary: Update an authentication provider >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/auth_provider_id_pp >+ - name: body >+ in: body >+ description: | >+ A JSON object containing OAuth provider parameters. >+ >+ The `config` object required attributes depends on the chosen `protocol` >+ >+ ## OAuth >+ >+ Requires: >+ >+ * key >+ * secret >+ * authorize_url >+ * token_url >+ >+ ## OIDC >+ >+ Requires: >+ >+ * key >+ * secret >+ * well_known_url >+ required: true >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: Updated authentication provider >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider >+ "400": >+ description: Bad Request >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "404": >+ description: Object not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+ delete: >+ x-mojo-to: Auth::Providers#delete >+ operationId: delAuthProvider >+ tags: >+ - auth_providers >+ summary: Delete authentication provider >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/auth_provider_id_pp >+ produces: >+ - application/json >+ responses: >+ "204": >+ description: Authentication provider deleted >+ "401": >+ description: Authentication required >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "404": >+ description: City not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+"/auth/providers/{auth_provider_id}/domains": >+ get: >+ x-mojo-to: Auth::Provider::Domains#list >+ operationId: listAuthProviderDomains >+ tags: >+ - auth_providers >+ summary: Get authentication provider configured domains >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/auth_provider_id_pp >+ - $ref: ../swagger.yaml#/parameters/match >+ - $ref: ../swagger.yaml#/parameters/order_by >+ - $ref: ../swagger.yaml#/parameters/page >+ - $ref: ../swagger.yaml#/parameters/per_page >+ - $ref: ../swagger.yaml#/parameters/q_param >+ - $ref: ../swagger.yaml#/parameters/q_body >+ - $ref: ../swagger.yaml#/parameters/q_header >+ - $ref: ../swagger.yaml#/parameters/request_id_header >+ - name: x-koha-embed >+ in: header >+ required: false >+ description: Embed list sent as a request header >+ type: array >+ items: >+ type: string >+ enum: >+ - domains >+ collectionFormat: csv >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: An authentication provider >+ schema: >+ items: >+ $ref: ../swagger.yaml#/definitions/auth_provider_domain >+ "404": >+ description: Object not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+ post: >+ x-mojo-to: Auth::Provider::Domains#add >+ operationId: addAuthProviderDomain >+ tags: >+ - auth_providers >+ summary: Add an authentication provider domain >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/auth_provider_id_pp >+ - name: body >+ in: body >+ description: An authentication provider domain object >+ required: true >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider_domain >+ produces: >+ - application/json >+ responses: >+ "201": >+ description: Updated authentication provider domain >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider_domain >+ "400": >+ description: Bad Request >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "404": >+ description: Object not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+"/auth/providers/{auth_provider_id}/domains/{auth_provider_domain_id}": >+ get: >+ x-mojo-to: Auth::Provider::Domains#get >+ operationId: getAuthProviderDomain >+ tags: >+ - auth_providers >+ summary: Get authentication provider domain >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/auth_provider_id_pp >+ - $ref: ../swagger.yaml#/parameters/auth_provider_domain_id_pp >+ produces: >+ - application/json >+ responses: >+ "200": >+ description: An authentication provider >+ schema: >+ $ref: ../swagger.yaml#/definitions/auth_provider_domain >+ "404": >+ description: Object not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ x-koha-authorization: >+ permissions: >+ parameters: manage_authentication_providers >+ delete: >+ x-mojo-to: Auth::Provider::Domains#delete >+ operationId: delAuthProviderDomain >+ tags: >+ - auth_providers >+ summary: Delete authentication provider >+ parameters: >+ - $ref: ../swagger.yaml#/parameters/auth_provider_id_pp >+ - $ref: ../swagger.yaml#/parameters/auth_provider_domain_id_pp >+ produces: >+ - application/json >+ responses: >+ "204": >+ description: Authentication provider deleted >+ "401": >+ description: Authentication required >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "404": >+ description: City not found >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error > x-koha-authorization: > permissions: >- catalogue: "1" >+ parameters: manage_authentication_providers >diff --git a/api/v1/swagger/paths/oauth.yaml b/api/v1/swagger/paths/oauth.yaml >index 1d74ed6f1f..e471336ced 100644 >--- a/api/v1/swagger/paths/oauth.yaml >+++ b/api/v1/swagger/paths/oauth.yaml >@@ -43,3 +43,82 @@ > description: Access forbidden > schema: > $ref: "../swagger.yaml#/definitions/error" >+"/oauth/login/{provider_code}/{interface}": >+ get: >+ x-mojo-to: OAuth::Client#login >+ operationId: loginOAuthClient >+ tags: >+ - oauth >+ summary: Login to OAuth provider >+ produces: >+ - application/json >+ parameters: >+ - name: provider_code >+ in: path >+ description: Code for OAuth provider >+ required: true >+ type: string >+ - name: interface >+ in: path >+ description: Name of the interface this login is for >+ required: true >+ type: string >+ - name: code >+ in: query >+ description: Code returned from OAuth server for Authorization Code grant >+ required: false >+ type: string >+ - name: state >+ in: query >+ description: An opaque value used by the client to maintain state between the >+ request and callback. This is the callback part. >+ required: false >+ type: string >+ - name: scope >+ in: query >+ description: Scope returned by OAuth server >+ type: string >+ - name: prompt >+ in: query >+ description: Prompt returned by OAuth server >+ type: string >+ - name: authuser >+ in: query >+ description: Auth user returned by OAuth server >+ type: string >+ - name: error >+ in: query >+ description: OAuth error code >+ type: string >+ - name: error_description >+ in: query >+ description: OAuth error description >+ type: string >+ - name: error_uri >+ in: query >+ description: Web page with user friendly description of the error >+ type: string >+ responses: >+ "302": >+ description: User authorized >+ schema: >+ type: string >+ "400": >+ description: Bad Request >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "403": >+ description: Access forbidden >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >diff --git a/api/v1/swagger/paths/public_oauth.yaml b/api/v1/swagger/paths/public_oauth.yaml >index dc88455c1c..40fe951909 100644 >--- a/api/v1/swagger/paths/public_oauth.yaml >+++ b/api/v1/swagger/paths/public_oauth.yaml >@@ -1,16 +1,16 @@ >-"/public/oauth/login/{provider}/{interface}": >+"/public/oauth/login/{provider_code}/{interface}": > get: > x-mojo-to: OAuth::Client#login >- operationId: loginOAuthClient >+ operationId: loginOAuthClientPublic > tags: > - oauth > summary: Login to OAuth provider > produces: > - application/json > parameters: >- - name: provider >+ - name: provider_code > in: path >- description: Name of OAuth provider >+ description: Code for OAuth provider > required: true > type: string > - name: interface >@@ -25,7 +25,8 @@ > type: string > - name: state > in: query >- description: An opaque value used by the client to maintain state between the request and callback. This is the callback part. >+ description: An opaque value used by the client to maintain state between the >+ request and callback. This is the callback part. > required: false > type: string > - name: scope >@@ -60,8 +61,19 @@ > "400": > description: Bad Request > schema: >- $ref: "../swagger.yaml#/definitions/error" >+ $ref: ../swagger.yaml#/definitions/error > "403": > description: Access forbidden > schema: >- $ref: "../swagger.yaml#/definitions/error" >+ $ref: ../swagger.yaml#/definitions/error >+ "500": >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >+ "503": >+ description: Under maintenance >+ schema: >+ $ref: ../swagger.yaml#/definitions/error >diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml >index 27c16757e0..dfd3b00bcc 100644 >--- a/api/v1/swagger/swagger.yaml >+++ b/api/v1/swagger/swagger.yaml >@@ -8,6 +8,10 @@ definitions: > $ref: ./definitions/advancededitormacro.yaml > allows_renewal: > $ref: ./definitions/allows_renewal.yaml >+ auth_provider: >+ "$ref": ./definitions/auth_provider.yaml >+ auth_provider_domain: >+ "$ref": ./definitions/auth_provider_domain.yaml > basket: > $ref: ./definitions/basket.yaml > bundle_link: >@@ -105,6 +109,14 @@ paths: > $ref: "./paths/article_requests.yaml#/~1article_requests~1{article_request_id}" > /auth/otp/token_delivery: > $ref: paths/auth.yaml#/~1auth~1otp~1token_delivery >+ /auth/providers: >+ $ref: paths/auth.yaml#/~1auth~1providers >+ "/auth/providers/{auth_provider_id}": >+ $ref: paths/auth.yaml#/~1auth~1providers~1{auth_provider_id} >+ "/auth/providers/{auth_provider_id}/domains": >+ $ref: paths/auth.yaml#/~1auth~1providers~1{auth_provider_id}~1domains >+ "/auth/providers/{auth_provider_id}/domains/{auth_provider_domain_id}": >+ $ref: paths/auth.yaml#/~1auth~1providers~1{auth_provider_id}~1domains~1{auth_provider_domain_id} > "/biblios/{biblio_id}": > $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}" > "/biblios/{biblio_id}/checkouts": >@@ -189,6 +201,8 @@ paths: > $ref: ./paths/libraries.yaml#/~1libraries > "/libraries/{library_id}": > $ref: "./paths/libraries.yaml#/~1libraries~1{library_id}" >+ "/oauth/login/{provider}/{interface}": >+ $ref: ./paths/oauth.yaml#/~1oauth~1login~1{provider_code}~1{interface} > /oauth/token: > $ref: ./paths/oauth.yaml#/~1oauth~1token > /patrons: >@@ -219,8 +233,8 @@ paths: > $ref: ./paths/libraries.yaml#/~1public~1libraries > "/public/libraries/{library_id}": > $ref: "./paths/libraries.yaml#/~1public~1libraries~1{library_id}" >- "/public/oauth/login/{provider}/{interface}": >- $ref: ./paths/public_oauth.yaml#/~1public~1oauth~1login~1{provider}~1{interface} >+ "/public/oauth/login/{provider_code}/{interface}": >+ $ref: ./paths/public_oauth.yaml#/~1public~1oauth~1login~1{provider_code}~1{interface} > "/public/patrons/{patron_id}/article_requests/{article_request_id}": > $ref: "./paths/article_requests.yaml#/~1public~1patrons~1{patron_id}~1article_requests~1{article_request_id}" > "/public/patrons/{patron_id}/guarantors/can_see_charges": >@@ -262,6 +276,18 @@ parameters: > name: advancededitormacro_id > required: true > type: integer >+ auth_provider_id_pp: >+ description: Authentication provider internal identifier >+ in: path >+ name: auth_provider_id >+ required: true >+ type: integer >+ auth_provider_domain_id_pp: >+ description: Authentication provider domain internal identifier >+ in: path >+ name: auth_provider_domain_id >+ required: true >+ type: integer > biblio_id_pp: > description: Record internal identifier > in: path >@@ -564,6 +590,9 @@ tags: > - description: "Manage article requests\n" > name: article_requests > x-displayName: Article requests >+ - description: "Manage authentication providers\n" >+ name: auth_providers >+ x-displayName: Authentication providers > - description: "Manage baskets for the acquisitions module\n" > name: baskets > x-displayName: Baskets >diff --git a/t/db_dependent/Koha/Auth/Provider.t b/t/db_dependent/Koha/Auth/Provider.t >index d55b7bb000..197740ba5f 100755 >--- a/t/db_dependent/Koha/Auth/Provider.t >+++ b/t/db_dependent/Koha/Auth/Provider.t >@@ -19,7 +19,7 @@ > > use Modern::Perl; > >-use Test::More tests => 5; >+use Test::More tests => 6; > > use Test::MockModule; > use Test::Exception; >@@ -84,6 +84,7 @@ subtest 'set_config() tests' => sub { > plan tests => 4; > > my $provider = $builder->build_object( { class => 'Koha::Auth::Providers', value => { protocol => 'OIDC' } } ); >+ $provider = $provider->upgrade_class; > > my $config = { > key => 'key', >@@ -93,12 +94,12 @@ subtest 'set_config() tests' => sub { > throws_ok { $provider->set_config($config) } > 'Koha::Exceptions::MissingParameter', 'Exception thrown on missing parameter'; > >- is( $@->error, 'The well_known_url parameter is mandatory', 'Message is correct' ); >+ is( $@->parameter, 'well_known_url', 'Message is correct' ); > > $config->{well_known_url} = 'https://koha-community.org/auth'; > > my $return = $provider->set_config($config); >- is( ref($return), 'Koha::Auth::Provider', 'Return type is correct' ); >+ is( ref($return), 'Koha::Auth::Provider::OIDC', 'Return type is correct' ); > > is_deeply( $provider->get_config, $config, 'Configuration stored correctly' ); > }; >@@ -108,6 +109,7 @@ subtest 'set_config() tests' => sub { > plan tests => 4; > > my $provider = $builder->build_object( { class => 'Koha::Auth::Providers', value => { protocol => 'OAuth' } } ); >+ $provider = $provider->upgrade_class; > > my $config = { > key => 'key', >@@ -118,12 +120,12 @@ subtest 'set_config() tests' => sub { > throws_ok { $provider->set_config($config) } > 'Koha::Exceptions::MissingParameter', 'Exception thrown on missing parameter'; > >- is( $@->error, 'The authorize_url parameter is mandatory', 'Message is correct' ); >+ is( $@->parameter, 'authorize_url', 'Message is correct' ); > > $config->{authorize_url} = 'https://koha-community.org/auth/authorize'; > > my $return = $provider->set_config($config); >- is( ref($return), 'Koha::Auth::Provider', 'Return type is correct' ); >+ is( ref($return), 'Koha::Auth::Provider::OAuth', 'Return type is correct' ); > > is_deeply( $provider->get_config, $config, 'Configuration stored correctly' ); > }; >@@ -137,7 +139,7 @@ subtest 'set_config() tests' => sub { > throws_ok { $provider->set_config() } > 'Koha::Exception', 'Exception thrown on unsupported protocol'; > >- like( "$@", qr/Unsupported protocol CAS/, 'Message is correct' ); >+ like( "$@", qr/This method needs to be subclassed/, 'Message is correct' ); > }; > > $schema->storage->txn_rollback; >@@ -177,3 +179,36 @@ subtest 'set_mapping() tests' => sub { > > $schema->storage->txn_rollback; > }; >+ >+subtest 'upgrade_class() tests' => sub { >+ >+ plan tests => 5; >+ >+ $schema->storage->txn_begin; >+ >+ my $mapping = Koha::Auth::Provider::protocol_to_class_mapping; >+ my @protocols = keys %{ $mapping }; >+ >+ foreach my $protocol (@protocols) { >+ >+ my $provider = $builder->build_object( >+ { >+ class => 'Koha::Auth::Providers', >+ value => { protocol => $protocol }, >+ } >+ ); >+ >+ is( ref($provider), 'Koha::Auth::Provider', "Base class used for $protocol" ); >+ # upgrade >+ $provider = $provider->upgrade_class; >+ is( ref($provider), $mapping->{$protocol}, "Class upgraded to " . $mapping->{$protocol} . "for protocol $protocol" ); >+ } >+ >+ my $provider = Koha::Auth::Provider->new({ protocol => 'Invalid' }); >+ throws_ok >+ { $provider->upgrade } >+ 'Koha::Exception', >+ 'Exception throw on invalid protocol'; >+ >+ $schema->storage->txn_rollback; >+}; >-- >2.20.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 31378
:
141362
|
141363
|
141364
|
141365
|
141366
|
141367
|
141368
|
141369
|
141370
|
141371
|
141372
|
141373
|
141374
|
141375
|
141376
|
141377
|
141378
|
141514
|
141771
|
141772
|
141773
|
141774
|
141775
|
141776
|
141777
|
141778
|
141779
|
141780
|
141781
|
141782
|
141783
|
141784
|
141785
|
141786
|
141787
|
141788
|
141801
|
141802
|
141803
|
141804
|
141805
|
141806
|
141807
|
141808
|
141809
|
141810
|
141811
|
141812
|
141813
|
141814
|
141815
|
141816
|
141817
|
141818
|
141853
|
143056
|
143087
|
143088
|
143089
|
143090
|
143091
|
143092
|
143093
|
143094
|
143095
|
143096
|
143097
|
143098
|
143099
|
143100
|
143101
|
143102
|
143103
|
143104
|
143105
|
143106
|
143107
|
143186
|
143187
|
143188
|
143189
|
143190
|
143191
|
143192
|
143193
|
143194
|
143195
|
143196
|
143197
|
143198
|
143199
|
143200
|
143202
|
143204
|
143205
|
143206
|
143207
|
143208
|
143215
|
143216
|
143217
|
143218
|
143219
|
143220
|
143221
|
143222
|
143223
|
143224
|
143225
|
143226
|
143227
|
143228
|
143229
|
143230
|
143231
|
143232
|
143233
|
143234
|
143235
|
143236
|
143266
|
143267
|
143268
|
143269
|
143270
|
143271
|
143272
|
143273
|
143274
|
143275
|
143277
|
143278
|
143279
|
143280
|
143281
|
143282
|
143283
|
143284
|
143285
|
143286
|
143287
|
143288
|
143396
|
143397
|
143398
|
143399
|
143400
|
143401
|
143402
|
143403
|
143404
|
143405
|
143406
|
143407
|
143408
|
143409
|
143410
|
143411
|
143412
|
143413
|
143414
|
143415
|
143416
|
143417
|
143418
|
143420
|
143421
|
143422
|
143423
|
143424
|
143425
|
143426
|
143427
|
143428
|
143429
|
143430
|
143431
|
143432
|
143433
|
143434
|
143435
|
143436
|
143437
|
143438
|
143439
|
143440
|
143441
|
143442
|
143443
|
143450
|
144071
|
144175