From 738dda632646a6248fbb9b3b36670aa1e7d2770d Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Sun, 22 Feb 2026 20:19:12 +0000 Subject: [PATCH] Bug 39224: REST API for identity providers, mappings and hostnames Adds REST API endpoints for managing identity providers, their field mappings, and hostname associations: - GET/POST /api/v1/auth/identity_providers/{id}/mappings - GET/PUT/DELETE /api/v1/auth/identity_providers/{id}/mappings/{id} - GET/POST /api/v1/auth/identity_providers/{id}/hostnames - GET/PUT/DELETE /api/v1/auth/identity_providers/{id}/hostnames/{id} - GET /api/v1/auth/hostnames (for hostname lookup) - Updates existing provider endpoints with new fields Includes OpenAPI/Swagger definitions for all new endpoints and updated definitions for existing endpoints. Test plan: 1. Run: prove t/db_dependent/api/v1/identity_providers.t 2. Test CRUD operations on mappings and hostnames via API Sponsored-by: ByWater Solutions --- Koha/REST/V1/Auth/Hostnames.pm | 76 +++ .../V1/Auth/Identity/Provider/Hostnames.pm | 239 +++++++++ .../V1/Auth/Identity/Provider/Mappings.pm | 210 ++++++++ Koha/REST/V1/Auth/Identity/Providers.pm | 18 +- api/v1/swagger/definitions/hostname.yaml | 13 + .../definitions/identity_provider.yaml | 36 +- .../definitions/identity_provider_domain.yaml | 4 + .../identity_provider_hostname.yaml | 28 + .../identity_provider_mapping.yaml | 30 ++ api/v1/swagger/paths/auth.yaml | 500 ++++++++++++++++++ api/v1/swagger/swagger.yaml | 36 ++ 11 files changed, 1164 insertions(+), 26 deletions(-) create mode 100644 Koha/REST/V1/Auth/Hostnames.pm create mode 100644 Koha/REST/V1/Auth/Identity/Provider/Hostnames.pm create mode 100644 Koha/REST/V1/Auth/Identity/Provider/Mappings.pm create mode 100644 api/v1/swagger/definitions/hostname.yaml create mode 100644 api/v1/swagger/definitions/identity_provider_hostname.yaml create mode 100644 api/v1/swagger/definitions/identity_provider_mapping.yaml diff --git a/Koha/REST/V1/Auth/Hostnames.pm b/Koha/REST/V1/Auth/Hostnames.pm new file mode 100644 index 00000000000..338af56c302 --- /dev/null +++ b/Koha/REST/V1/Auth/Hostnames.pm @@ -0,0 +1,76 @@ +package Koha::REST::V1::Auth::Hostnames; + +# 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 . + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::Auth::Hostname; +use Koha::Auth::Hostnames; + +use Try::Tiny; + +=head1 NAME + +Koha::REST::V1::Auth::Hostnames - Controller library for handling hostname routes. + +=head2 Operations + +=head3 list + +Controller method for listing all known hostnames. + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + return $c->render( + status => 200, + openapi => $c->objects->search( Koha::Auth::Hostnames->new ), + ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 get + +Controller method for retrieving a single hostname by ID. + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + return try { + my $hostname = $c->objects->find( + Koha::Auth::Hostnames->new, + $c->param('hostname_id') + ); + + return $c->render_resource_not_found("Hostname") + unless $hostname; + + return $c->render( status => 200, openapi => $hostname ); + } catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/Koha/REST/V1/Auth/Identity/Provider/Hostnames.pm b/Koha/REST/V1/Auth/Identity/Provider/Hostnames.pm new file mode 100644 index 00000000000..ab22b84ced7 --- /dev/null +++ b/Koha/REST/V1/Auth/Identity/Provider/Hostnames.pm @@ -0,0 +1,239 @@ +package Koha::REST::V1::Auth::Identity::Provider::Hostnames; + +# 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 . + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::Auth::Hostname; +use Koha::Auth::Hostnames; +use Koha::Auth::Identity::Provider::Hostname; +use Koha::Auth::Identity::Provider::Hostnames; +use Koha::Auth::Identity::Providers; + +use Koha::Database; + +use Scalar::Util qw(blessed); +use Try::Tiny; + +=head1 NAME + +Koha::REST::V1::Auth::Identity::Provider::Hostnames - Controller library for handling +identity provider hostname routes. + +Each row is a many-to-many association between a hostname (via hostname_id FK) and an +identity provider. The unique constraint is on (hostname_id, identity_provider_id). + +=head2 Operations + +=head3 list + +Controller method for listing identity provider hostnames. + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $provider = Koha::Auth::Identity::Providers->find( $c->param('identity_provider_id') ); + + return $c->render_resource_not_found("Identity provider") + unless $provider; + + my $hostnames_rs = $provider->hostnames; + return $c->render( + status => 200, + openapi => $c->objects->search($hostnames_rs), + ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 get + +Controller method for retrieving an identity provider hostname. + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + return try { + my $provider = Koha::Auth::Identity::Providers->find( $c->param('identity_provider_id') ); + + return $c->render_resource_not_found("Identity provider") + unless $provider; + + my $hostnames_rs = $provider->hostnames; + + my $hostname = $c->objects->find( + $hostnames_rs, + $c->param('identity_provider_hostname_id') + ); + + return $c->render_resource_not_found("Identity provider hostname") + unless $hostname; + + return $c->render( status => 200, openapi => $hostname ); + } catch { + $c->unhandled_exception($_); + } +} + +=head3 add + +Controller method for adding an identity provider hostname. + +Accepts either a C integer (direct FK reference) or a C +string (the backend will find-or-create the canonical hostname record and resolve +it to a C before creating the bridge row). + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + return try { + my $provider = Koha::Auth::Identity::Providers->find( $c->param('identity_provider_id') ); + + return $c->render_resource_not_found("Identity provider") + unless $provider; + + Koha::Database->new->schema->txn_do( + sub { + my $body = $c->req->json; + $body->{identity_provider_id} = $c->param('identity_provider_id'); + + # If caller sent a hostname string instead of hostname_id, + # resolve it via find_or_create on the hostnames table. + unless ( $body->{hostname_id} ) { + my $hostname_str = delete $body->{hostname}; + my $hostname_rec = Koha::Auth::Hostnames->search( { hostname => $hostname_str } )->next + // Koha::Auth::Hostname->new( { hostname => $hostname_str } )->store; + $body->{hostname_id} = $hostname_rec->hostname_id; + } else { + + # hostname string is readOnly in the schema; strip it if present + delete $body->{hostname}; + } + + my $hostname = Koha::Auth::Identity::Provider::Hostname->new_from_api($body); + $hostname->store; + + $c->res->headers->location( $c->req->url->to_string . '/' . $hostname->id ); + return $c->render( + status => 201, + openapi => $c->objects->to_api($hostname), + ); + } + ); + } catch { + if ( blessed($_) and $_->isa('Koha::Exceptions::Object::DuplicateID') ) { + return $c->render( + status => 409, + openapi => { + error => 'A hostname entry with this hostname already exists for this provider', + error_code => 'duplicate_hostname', + } + ); + } + + $c->unhandled_exception($_); + }; +} + +=head3 update + +Controller method for updating an identity provider hostname. + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $hostname = Koha::Auth::Identity::Provider::Hostnames->find( + { + identity_provider_id => $c->param('identity_provider_id'), + identity_provider_hostname_id => $c->param('identity_provider_hostname_id'), + } + ); + + return $c->render_resource_not_found("Identity provider hostname") + unless $hostname; + + return try { + Koha::Database->new->schema->txn_do( + sub { + my $body = $c->req->json; + + # hostname string is readOnly; strip it to avoid set_from_api errors + delete $body->{hostname}; + + $hostname->set_from_api($body); + $hostname->store->discard_changes; + + return $c->render( + status => 200, + openapi => $c->objects->to_api($hostname), + ); + } + ); + } catch { + if ( blessed($_) and $_->isa('Koha::Exceptions::Object::DuplicateID') ) { + return $c->render( + status => 409, + openapi => { + error => 'A hostname entry with this hostname already exists for this provider', + error_code => 'duplicate_hostname', + } + ); + } + + $c->unhandled_exception($_); + }; +} + +=head3 delete + +Controller method for deleting an identity provider hostname. + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $hostname = Koha::Auth::Identity::Provider::Hostnames->find( + { + identity_provider_id => $c->param('identity_provider_id'), + identity_provider_hostname_id => $c->param('identity_provider_hostname_id'), + } + ); + + return $c->render_resource_not_found("Identity provider hostname") + unless $hostname; + + return try { + $hostname->delete; + return $c->render_resource_deleted; + } catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/Koha/REST/V1/Auth/Identity/Provider/Mappings.pm b/Koha/REST/V1/Auth/Identity/Provider/Mappings.pm new file mode 100644 index 00000000000..ac4c21952d9 --- /dev/null +++ b/Koha/REST/V1/Auth/Identity/Provider/Mappings.pm @@ -0,0 +1,210 @@ +package Koha::REST::V1::Auth::Identity::Provider::Mappings; + +# 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 . + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::Auth::Identity::Provider::Mapping; +use Koha::Auth::Identity::Provider::Mappings; +use Koha::Auth::Identity::Providers; + +use Koha::Database; + +use Scalar::Util qw(blessed); +use Try::Tiny; + +=head1 NAME + +Koha::REST::V1::Auth::Identity::Provider::Mappings - Controller for identity +provider field mapping routes. + +=head2 Operations + +=head3 list + +Controller method for listing field mappings for an identity provider. + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $provider = Koha::Auth::Identity::Providers->find( $c->param('identity_provider_id') ); + + return $c->render_resource_not_found("Identity provider") + unless $provider; + + my $mappings_rs = $provider->mappings; + return $c->render( + status => 200, + openapi => $c->objects->search($mappings_rs) + ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 get + +Controller method for retrieving a single field mapping. + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + return try { + my $provider = Koha::Auth::Identity::Providers->find( $c->param('identity_provider_id') ); + + return $c->render_resource_not_found("Identity provider") + unless $provider; + + my $mapping = $c->objects->find( + $provider->mappings, + $c->param('identity_provider_mapping_id') + ); + + return $c->render_resource_not_found("Identity provider mapping") + unless $mapping; + + return $c->render( status => 200, openapi => $mapping ); + } catch { + $c->unhandled_exception($_); + }; +} + +=head3 add + +Controller method for adding a field mapping to an identity provider. + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + return try { + my $provider = Koha::Auth::Identity::Providers->find( $c->param('identity_provider_id') ); + + return $c->render_resource_not_found("Identity provider") + unless $provider; + + Koha::Database->new->schema->txn_do( + sub { + my $params = $c->req->json; + $params->{identity_provider_id} = $c->param('identity_provider_id'); + + my $mapping = Koha::Auth::Identity::Provider::Mapping->new_from_api($params); + $mapping->store; + + $c->res->headers->location( $c->req->url->to_string . '/' . $mapping->id ); + return $c->render( + status => 201, + openapi => $c->objects->to_api($mapping), + ); + } + ); + } catch { + if ( blessed($_) and $_->isa('Koha::Exceptions::MissingParameter') ) { + return $c->render( + status => 400, + openapi => { + error => 'Missing parameter: ' . $_->parameter, + error_code => 'missing_parameter', + } + ); + } + + $c->unhandled_exception($_); + }; +} + +=head3 update + +Controller method for updating a field mapping. + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $mapping = Koha::Auth::Identity::Provider::Mappings->find( + { + identity_provider_id => $c->param('identity_provider_id'), + mapping_id => $c->param('identity_provider_mapping_id'), + } + ); + + return $c->render_resource_not_found("Identity provider mapping") + unless $mapping; + + return try { + Koha::Database->new->schema->txn_do( + sub { + $mapping->set_from_api( $c->req->json ); + $mapping->store->discard_changes; + + return $c->render( + status => 200, + openapi => $c->objects->to_api($mapping), + ); + } + ); + } catch { + if ( blessed($_) and $_->isa('Koha::Exceptions::MissingParameter') ) { + return $c->render( + status => 400, + openapi => { + error => 'Missing parameter: ' . $_->parameter, + error_code => 'missing_parameter', + } + ); + } + + $c->unhandled_exception($_); + }; +} + +=head3 delete + +Controller method for deleting a field mapping. + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $mapping = Koha::Auth::Identity::Provider::Mappings->find( + { + identity_provider_id => $c->param('identity_provider_id'), + mapping_id => $c->param('identity_provider_mapping_id'), + } + ); + + return $c->render_resource_not_found("Identity provider mapping") + unless $mapping; + + return try { + $mapping->delete; + return $c->render_resource_deleted; + } catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/Koha/REST/V1/Auth/Identity/Providers.pm b/Koha/REST/V1/Auth/Identity/Providers.pm index b3ad363f067..748d929db59 100644 --- a/Koha/REST/V1/Auth/Identity/Providers.pm +++ b/Koha/REST/V1/Auth/Identity/Providers.pm @@ -19,8 +19,6 @@ use Modern::Perl; use Mojo::Base 'Mojolicious::Controller'; -use Koha::Auth::Identity::Provider::OAuth; -use Koha::Auth::Identity::Provider::OIDC; use Koha::Auth::Identity::Providers; use Koha::Database; @@ -94,12 +92,13 @@ sub add { my $body = $c->req->json; my $config = delete $body->{config}; - my $mapping = delete $body->{mapping}; my $protocol = delete $body->{protocol}; - my $class = Koha::Auth::Identity::Provider::protocol_to_class_mapping->{$protocol}; + my $class = Koha::Auth::Identity::Providers->new->_polymorphic_map->{$protocol}; - my $provider = $class->new_from_api($body)->set_config($config)->set_mapping($mapping)->store; + Koha::Exception->throw("$protocol is not a valid protocol") unless $class; + + my $provider = $class->new_from_api($body)->set_config($config)->store; $c->res->headers->location( $c->req->url->to_string . '/' . $provider->identity_provider_id ); return $c->render( @@ -146,12 +145,13 @@ sub update { my $body = $c->req->json; - my $config = delete $body->{config}; - my $mapping = delete $body->{mapping}; + my $config = delete $body->{config}; - $provider = $provider->set_from_api($body)->upgrade_class; + $provider->set_from_api($body); + $provider = Koha::Auth::Identity::Providers->new->object_class( $provider->_result ) + ->_new_from_dbic( $provider->_result ); - $provider->set_config($config)->set_mapping($mapping)->store; + $provider->set_config($config)->store; $provider->discard_changes; diff --git a/api/v1/swagger/definitions/hostname.yaml b/api/v1/swagger/definitions/hostname.yaml new file mode 100644 index 00000000000..f884429806b --- /dev/null +++ b/api/v1/swagger/definitions/hostname.yaml @@ -0,0 +1,13 @@ +--- +type: object +properties: + hostname_id: + description: Internally assigned identifier for this hostname + type: integer + readOnly: true + hostname: + description: Server hostname string (matches SERVER_NAME) + type: string +additionalProperties: false +required: + - hostname diff --git a/api/v1/swagger/definitions/identity_provider.yaml b/api/v1/swagger/definitions/identity_provider.yaml index c9fc649d428..69a32058b77 100644 --- a/api/v1/swagger/definitions/identity_provider.yaml +++ b/api/v1/swagger/definitions/identity_provider.yaml @@ -17,33 +17,35 @@ properties: enum: - OAuth - OIDC - - CAS (not implemented) - - LDAP (not implemented) - mapping: - description: Attribute mapping + - SAML2 + config: + description: Protocol-specific configuration 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 + description: Icon url for display on login buttons type: - - string - - "null" + - string + - "null" + enabled: + description: Whether this provider is active + type: boolean domains: description: Configured domains for the identity provider type: - array - "null" + hostnames: + description: Configured hostnames for the identity provider + type: + - array + - "null" + mappings: + description: Configured mappings for the identity provider + type: + - array + - "null" additionalProperties: false required: - config diff --git a/api/v1/swagger/definitions/identity_provider_domain.yaml b/api/v1/swagger/definitions/identity_provider_domain.yaml index b18b1a6f6d6..db3b6209c93 100644 --- a/api/v1/swagger/definitions/identity_provider_domain.yaml +++ b/api/v1/swagger/definitions/identity_provider_domain.yaml @@ -38,6 +38,9 @@ properties: allow_staff: description: If this domain can be used for staff login type: boolean + send_welcome_email: + description: Send welcome email to patron on first login via this domain + type: boolean additionalProperties: false required: - identity_provider_domain_id @@ -49,3 +52,4 @@ required: - default_category_id - allow_opac - allow_staff + - send_welcome_email diff --git a/api/v1/swagger/definitions/identity_provider_hostname.yaml b/api/v1/swagger/definitions/identity_provider_hostname.yaml new file mode 100644 index 00000000000..473dc45094b --- /dev/null +++ b/api/v1/swagger/definitions/identity_provider_hostname.yaml @@ -0,0 +1,28 @@ +--- +type: object +properties: + identity_provider_hostname_id: + type: integer + description: Internally assigned identifier for this hostname-provider association + readOnly: true + hostname_id: + description: Identifier of the associated hostname record + type: integer + hostname: + description: > + Server hostname string. When creating a new association, supply either + this field (the backend will find-or-create the canonical hostname record) + or hostname_id. In responses this field is always populated. + type: string + identity_provider_id: + description: Identity provider associated with this hostname + type: integer + is_enabled: + description: Whether this hostname is active for this provider + type: boolean + force_sso: + description: > + Force SSO redirect for users visiting this hostname. Only one + identity provider should have this enabled per hostname. + type: boolean +additionalProperties: false diff --git a/api/v1/swagger/definitions/identity_provider_mapping.yaml b/api/v1/swagger/definitions/identity_provider_mapping.yaml new file mode 100644 index 00000000000..11658bf7cb3 --- /dev/null +++ b/api/v1/swagger/definitions/identity_provider_mapping.yaml @@ -0,0 +1,30 @@ +--- +type: object +properties: + mapping_id: + type: integer + description: Internally assigned mapping identifier + readOnly: true + identity_provider_id: + type: integer + description: Reference to identity provider + readOnly: true + provider_field: + type: + - string + - "null" + description: Attribute name from the identity provider + koha_field: + type: string + description: Corresponding field in Koha borrowers table + default_content: + type: + - string + - "null" + description: Default value to use if the provider does not supply this attribute + is_matchpoint: + type: boolean + description: Use this field to match existing patrons (only one per provider) +additionalProperties: false +required: + - koha_field diff --git a/api/v1/swagger/paths/auth.yaml b/api/v1/swagger/paths/auth.yaml index 700023cf555..f63e8a5d749 100644 --- a/api/v1/swagger/paths/auth.yaml +++ b/api/v1/swagger/paths/auth.yaml @@ -616,6 +616,8 @@ type: string enum: - domains + - hostnames + - mappings collectionFormat: csv produces: - application/json @@ -731,6 +733,8 @@ type: string enum: - domains + - hostnames + - mappings collectionFormat: csv produces: - application/json @@ -1104,6 +1108,183 @@ x-koha-authorization: permissions: parameters: manage_identity_providers +"/auth/identity_providers/{identity_provider_id}/mappings": + get: + x-mojo-to: Auth::Identity::Provider::Mappings#list + operationId: listIdentityProviderMappings + tags: + - identity_providers + summary: List field mappings for an identity provider + parameters: + - $ref: ../swagger.yaml#/parameters/identity_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/request_id_header + produces: + - application/json + responses: + "200": + description: List of field mappings + schema: + type: array + items: + $ref: ../swagger.yaml#/definitions/identity_provider_mapping + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + schema: + $ref: ../swagger.yaml#/definitions/error + "403": + description: Access forbidden + schema: + $ref: ../swagger.yaml#/definitions/error + "404": + description: Identity provider not found + schema: + $ref: ../swagger.yaml#/definitions/error + x-koha-authorization: + permissions: + parameters: manage_identity_providers + post: + x-mojo-to: Auth::Identity::Provider::Mappings#add + operationId: addIdentityProviderMapping + tags: + - identity_providers + summary: Add a field mapping to an identity provider + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - name: body + in: body + description: A field mapping object + required: true + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_mapping + produces: + - application/json + responses: + "201": + description: The created field mapping + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_mapping + "400": + description: Bad request + schema: + $ref: ../swagger.yaml#/definitions/error + "403": + description: Access forbidden + schema: + $ref: ../swagger.yaml#/definitions/error + "404": + description: Identity provider not found + schema: + $ref: ../swagger.yaml#/definitions/error + x-koha-authorization: + permissions: + parameters: manage_identity_providers +"/auth/identity_providers/{identity_provider_id}/mappings/{identity_provider_mapping_id}": + get: + x-mojo-to: Auth::Identity::Provider::Mappings#get + operationId: getIdentityProviderMapping + tags: + - identity_providers + summary: Get a field mapping + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - $ref: ../swagger.yaml#/parameters/identity_provider_mapping_id_pp + produces: + - application/json + responses: + "200": + description: A field mapping + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_mapping + "400": + description: Bad request + schema: + $ref: ../swagger.yaml#/definitions/error + "403": + description: Access forbidden + schema: + $ref: ../swagger.yaml#/definitions/error + "404": + description: Mapping not found + schema: + $ref: ../swagger.yaml#/definitions/error + x-koha-authorization: + permissions: + parameters: manage_identity_providers + put: + x-mojo-to: Auth::Identity::Provider::Mappings#update + operationId: updateIdentityProviderMapping + tags: + - identity_providers + summary: Update a field mapping + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - $ref: ../swagger.yaml#/parameters/identity_provider_mapping_id_pp + - name: body + in: body + description: Updated mapping object + required: true + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_mapping + produces: + - application/json + responses: + "200": + description: Updated field mapping + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_mapping + "400": + description: Bad request + schema: + $ref: ../swagger.yaml#/definitions/error + "403": + description: Access forbidden + schema: + $ref: ../swagger.yaml#/definitions/error + "404": + description: Mapping not found + schema: + $ref: ../swagger.yaml#/definitions/error + x-koha-authorization: + permissions: + parameters: manage_identity_providers + delete: + x-mojo-to: Auth::Identity::Provider::Mappings#delete + operationId: delIdentityProviderMapping + tags: + - identity_providers + summary: Delete a field mapping + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - $ref: ../swagger.yaml#/parameters/identity_provider_mapping_id_pp + produces: + - application/json + responses: + "204": + description: Field mapping deleted + "400": + description: Bad request + schema: + $ref: ../swagger.yaml#/definitions/error + "403": + description: Access forbidden + schema: + $ref: ../swagger.yaml#/definitions/error + "404": + description: Mapping not found + schema: + $ref: ../swagger.yaml#/definitions/error + x-koha-authorization: + permissions: + parameters: manage_identity_providers "/auth/password/validation": post: x-mojo-to: Auth::Password#validate @@ -1184,3 +1365,322 @@ x-koha-authorization: permissions: borrowers: api_validate_password +"/auth/identity_providers/{identity_provider_id}/hostnames": + get: + x-mojo-to: Auth::Identity::Provider::Hostnames#list + operationId: listIdentityProviderHostnames + tags: + - identity_providers + summary: List identity provider hostnames + parameters: + - $ref: ../swagger.yaml#/parameters/identity_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/request_id_header + produces: + - application/json + responses: + "200": + description: A list of identity provider hostnames + schema: + type: array + items: + $ref: ../swagger.yaml#/definitions/identity_provider_hostname + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + 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_identity_providers + post: + x-mojo-to: Auth::Identity::Provider::Hostnames#add + operationId: addIdentityProviderHostname + tags: + - identity_providers + summary: Add an identity provider hostname + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - name: body + in: body + description: An identity provider hostname object + required: true + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_hostname + produces: + - application/json + responses: + "201": + description: Created identity provider hostname + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_hostname + "400": + description: Bad request + schema: + $ref: ../swagger.yaml#/definitions/error + "403": + description: Access forbidden + schema: + $ref: ../swagger.yaml#/definitions/error + "404": + description: Identity provider not found + schema: + $ref: ../swagger.yaml#/definitions/error + "409": + description: Conflict - hostname already exists + 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_identity_providers +"/auth/identity_providers/{identity_provider_id}/hostnames/{identity_provider_hostname_id}": + get: + x-mojo-to: Auth::Identity::Provider::Hostnames#get + operationId: getIdentityProviderHostname + tags: + - identity_providers + summary: Get an identity provider hostname + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - $ref: ../swagger.yaml#/parameters/identity_provider_hostname_id_pp + produces: + - application/json + responses: + "200": + description: An identity provider hostname + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_hostname + "400": + description: Bad request + 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_identity_providers + put: + x-mojo-to: Auth::Identity::Provider::Hostnames#update + operationId: updateIdentityProviderHostname + tags: + - identity_providers + summary: Update an identity provider hostname + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - $ref: ../swagger.yaml#/parameters/identity_provider_hostname_id_pp + - name: body + in: body + description: An identity provider hostname object + required: true + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_hostname + produces: + - application/json + responses: + "200": + description: Updated identity provider hostname + schema: + $ref: ../swagger.yaml#/definitions/identity_provider_hostname + "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 + "409": + description: Conflict - hostname already exists + 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_identity_providers + delete: + x-mojo-to: Auth::Identity::Provider::Hostnames#delete + operationId: deleteIdentityProviderHostname + tags: + - identity_providers + summary: Delete an identity provider hostname + parameters: + - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp + - $ref: ../swagger.yaml#/parameters/identity_provider_hostname_id_pp + produces: + - application/json + responses: + "204": + description: Identity provider hostname deleted + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "401": + description: Authentication required + 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_identity_providers +/auth/hostnames: + get: + x-mojo-to: Auth::Hostnames#list + operationId: listHostnames + tags: + - identity_providers + summary: List all known hostnames + 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/request_id_header + produces: + - application/json + responses: + "200": + description: A list of hostnames + schema: + type: array + items: + $ref: ../swagger.yaml#/definitions/hostname + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + 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_identity_providers +"/auth/hostnames/{hostname_id}": + get: + x-mojo-to: Auth::Hostnames#get + operationId: getHostname + tags: + - identity_providers + summary: Get a hostname + parameters: + - $ref: ../swagger.yaml#/parameters/hostname_id_pp + produces: + - application/json + responses: + "200": + description: A hostname + schema: + $ref: ../swagger.yaml#/definitions/hostname + "400": + description: Bad request + 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_identity_providers diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 9a9b7af7565..16805682ce9 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -20,6 +20,12 @@ definitions: $ref: ./definitions/identity_provider.yaml identity_provider_domain: $ref: ./definitions/identity_provider_domain.yaml + identity_provider_mapping: + $ref: ./definitions/identity_provider_mapping.yaml + hostname: + $ref: ./definitions/hostname.yaml + identity_provider_hostname: + $ref: ./definitions/identity_provider_hostname.yaml basket: $ref: ./definitions/basket.yaml booking: @@ -269,6 +275,18 @@ paths: $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}": $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id} + "/auth/identity_providers/{identity_provider_id}/mappings": + $ref: ./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1mappings + "/auth/identity_providers/{identity_provider_id}/mappings/{identity_provider_mapping_id}": + $ref: "./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1mappings~1{identity_provider_mapping_id}" + /auth/hostnames: + $ref: ./paths/auth.yaml#/~1auth~1hostnames + "/auth/hostnames/{hostname_id}": + $ref: "./paths/auth.yaml#/~1auth~1hostnames~1{hostname_id}" + "/auth/identity_providers/{identity_provider_id}/hostnames": + $ref: "./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1hostnames" + "/auth/identity_providers/{identity_provider_id}/hostnames/{identity_provider_hostname_id}": + $ref: "./paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1hostnames~1{identity_provider_hostname_id}" /authorised_value_categories: $ref: ./paths/authorised_value_categories.yaml#/~1authorised_value_categories "/authorised_value_categories/{authorised_value_category_name}/authorised_values": @@ -711,6 +729,24 @@ parameters: name: identity_provider_domain_id required: true type: integer + identity_provider_mapping_id_pp: + description: Identity provider field mapping internal identifier + in: path + name: identity_provider_mapping_id + required: true + type: integer + hostname_id_pp: + description: Hostname internal identifier + in: path + name: hostname_id + required: true + type: integer + identity_provider_hostname_id_pp: + description: Identity provider hostname internal identifier + in: path + name: identity_provider_hostname_id + required: true + type: integer biblio_id_pp: description: Record internal identifier in: path -- 2.53.0