Bug 37893: (QA follow-up): Nuke server params and listeners from UI

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Pedro Amorim 2025-10-09 14:57:05 +00:00 committed by Lucas Gass
parent 6b28a7da7d
commit 3866d85555
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
29 changed files with 42 additions and 2219 deletions

View File

@ -24,7 +24,6 @@ use C4::SIP::Sip::Checksum qw(checksum verify_cksum);
use C4::SIP::Sip::MsgType qw( handle login_core );
use C4::SIP::Logger qw(set_logger);
use Koha::SIP2::ServerParams;
use Koha::Caches;
use Koha::Logger;
@ -223,6 +222,7 @@ sub post_accept_hook {
sub _config_up_to_date {
my ($self) = @_;
#TODO: Reimplement config_timestamp
my $serverparam = Koha::SIP2::ServerParams->find( { key => 'config_timestamp' } );
unless ($serverparam) {

View File

@ -15,9 +15,6 @@ use C4::SIP::Sip qw(siplog);
use Koha::Libraries;
use Koha::SIP2::Institutions;
use Koha::SIP2::Accounts;
use Koha::SIP2::Listeners;
use Koha::SIP2::ServerParam;
use Koha::SIP2::ServerParams;
use Koha::SIP2::SystemPreferenceOverrides;
my $parser = XML::Simple->new(
@ -56,10 +53,8 @@ sub get_configuration {
}
$cfg->{listeners} = \%listeners;
$cfg->{accounts} = Koha::SIP2::Accounts->get_for_config() if Koha::SIP2::Accounts->search()->count;
$cfg->{institutions} = Koha::SIP2::Institutions->get_for_config() if Koha::SIP2::Institutions->search()->count;
$cfg->{listeners} = Koha::SIP2::Listeners->get_for_config() if Koha::SIP2::Listeners->search()->count;
$cfg->{'server-params'} = Koha::SIP2::ServerParams->get_for_config() if Koha::SIP2::ServerParams->search()->count;
$cfg->{accounts} = Koha::SIP2::Accounts->get_for_config() if Koha::SIP2::Accounts->search()->count;
$cfg->{institutions} = Koha::SIP2::Institutions->get_for_config() if Koha::SIP2::Institutions->search()->count;
$cfg->{'syspref_overrides'} = Koha::SIP2::SystemPreferenceOverrides->get_for_config()
if Koha::SIP2::SystemPreferenceOverrides->search()->count;

View File

@ -1,188 +0,0 @@
package Koha::REST::V1::SIP2::Listeners;
# 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::SIP2::Listener;
use Koha::SIP2::Listeners;
use Try::Tiny qw( catch try );
=head1 API
=head2 Methods
=head3 list
=cut
sub list {
my $c = shift->openapi->valid_input or return;
return try {
my $listeners = $c->objects->search( Koha::SIP2::Listeners->new );
return $c->render( status => 200, openapi => $listeners );
} catch {
$c->unhandled_exception($_);
};
}
=head3 get
Controller function that handles retrieving a single Koha::SIP2::Listener object
=cut
sub get {
my $c = shift->openapi->valid_input or return;
return try {
my $listener = $c->objects->find( Koha::SIP2::Listeners->search, $c->param('sip_listener_id') );
return $c->render_resource_not_found("Listener")
unless $listener;
return $c->render(
status => 200,
openapi => $listener
);
} catch {
$c->unhandled_exception($_);
};
}
=head3 add
Controller function that handles adding a new Koha::SIP2::Listener object
=cut
sub add {
my $c = shift->openapi->valid_input or return;
return try {
Koha::Database->new->schema->txn_do(
sub {
my $body = $c->req->json;
my $listener = Koha::SIP2::Listener->new_from_api($body)->store;
$c->res->headers->location( $c->req->url->to_string . '/' . $listener->sip_listener_id );
return $c->render(
status => 201,
openapi => $c->objects->to_api($listener),
);
}
);
} catch {
my $to_api_mapping = Koha::SIP2::Listener->new->to_api_mapping;
if ( blessed $_ ) {
if ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) {
return $c->render(
status => 409,
openapi => { error => $_->error, conflict => $_->duplicate_id }
);
} elsif ( $_->isa('Koha::Exceptions::BadParameter') ) {
return $c->render(
status => 400,
openapi => { error => "Given " . $to_api_mapping->{ $_->parameter } . " does not exist" }
);
}
elsif ( $_->isa('Koha::Exceptions::ObjectNotCreated') ) {
return $c->render(
status => 500,
openapi => { error => $_->error }
);
}
}
$c->unhandled_exception($_);
};
}
=head3 update
Controller function that handles updating a Koha::SIP2::Listener object
=cut
sub update {
my $c = shift->openapi->valid_input or return;
my $listener = Koha::SIP2::Listeners->find( $c->param('sip_listener_id') );
return $c->render_resource_not_found("Listener")
unless $listener;
return try {
Koha::Database->new->schema->txn_do(
sub {
my $body = $c->req->json;
$listener->set_from_api($body)->store;
$c->res->headers->location( $c->req->url->to_string . '/' . $listener->sip_listener_id );
return $c->render(
status => 200,
openapi => $c->objects->to_api($listener),
);
}
);
} catch {
my $to_api_mapping = Koha::SIP2::Listener->new->to_api_mapping;
if ( blessed $_ ) {
if ( $_->isa('Koha::Exceptions::BadParameter') ) {
return $c->render(
status => 400,
openapi => { error => "Given " . $to_api_mapping->{ $_->parameter } . " does not exist" }
);
}
}
$c->unhandled_exception($_);
};
}
=head3 delete
=cut
sub delete {
my $c = shift->openapi->valid_input or return;
my $listener = Koha::SIP2::Listeners->find( $c->param('sip_listener_id') );
return $c->render_resource_not_found("Listener")
unless $listener;
return try {
$listener->delete;
return $c->render_resource_deleted;
} catch {
$c->unhandled_exception($_);
};
}
1;

View File

@ -1,111 +0,0 @@
package Koha::REST::V1::SIP2::ServerParams;
# 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::SIP2::ServerParam;
use Koha::SIP2::ServerParams;
use Try::Tiny qw( catch try );
=head1 API
=head2 Methods
=head3 list
=cut
sub list {
my $c = shift->openapi->valid_input or return;
return try {
my $server_params = $c->objects->search( Koha::SIP2::ServerParams->new );
return $c->render( status => 200, openapi => $server_params );
} catch {
$c->unhandled_exception($_);
};
}
sub update_server_params {
my ($c) = @_;
my $body = $c->req->json;
unless ( $body && ref $body eq 'ARRAY' ) {
return $c->render(
status => 400,
openapi => { error => "Invalid request body" }
);
}
foreach my $server_param (@$body) {
my $server_param_id = $server_param->{key};
my $server_param_obj = Koha::SIP2::ServerParams->search( { key => $server_param->{key} } )->last;
if ( !$server_param_obj ) {
try {
Koha::Database->new->schema->txn_do(
sub {
$server_param_obj = Koha::SIP2::ServerParam->new_from_api($server_param)->store;
}
);
} catch {
if ( blessed $_ ) {
if ( $_->isa('Koha::Exceptions::BadParameter') ) {
return $c->render(
status => 400,
json => { message => 'Some error occurred' }
);
}
}
$c->unhandled_exception($_);
}
} else {
try {
Koha::Database->new->schema->txn_do(
sub {
$server_param_obj->set_from_api($server_param)->store;
}
);
} catch {
if ( blessed $_ ) {
if ( $_->isa('Koha::Exceptions::BadParameter') ) {
return $c->render(
status => 400,
json => { message => 'Some error occurred' }
);
}
}
$c->unhandled_exception($_);
}
}
}
$c->res->headers->location( $c->req->url->to_string );
return $c->render(
status => 200,
json => { message => 'Server params updated successfully' },
);
}
1;

View File

@ -1,88 +0,0 @@
package Koha::SIP2::Listener;
# 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::Object);
use IO::Socket;
=head1 NAME
Koha::SIP2::Listener- Koha Sip Listener Object class
=head1 API
=head2 Class Methods
=cut
=head3 store
store
=cut
sub store {
my ($self) = @_;
my ($port) = $self->port =~ /:(\d+)/;
my ($addr) = $self->port =~ /([0-9.]+)/;
my $socket = IO::Socket::INET->new(
LocalAddr => $addr,
LocalPort => $port,
Proto => 'tcp',
ReuseAddr => 0,
Listen => 1
);
unless ($socket) {
Koha::Exceptions::ObjectNotCreated->throw(
error => "Can't listen on port " . $self->port . ". Port already in use." );
}
return $self->SUPER::store;
}
=head3 get_for_config
Returns the listener hashref as expected by C4/SIP/Sip/Configuration->new;
=cut
sub get_for_config {
my ($self) = @_;
my $return_hash = $self->unblessed;
delete $return_hash->{sip_listener_id};
foreach my $key ( keys %$return_hash ) {
delete $return_hash->{$key} if !defined $return_hash->{$key};
$return_hash->{$key} = "$return_hash->{$key}" if defined $return_hash->{$key};
}
return $return_hash;
}
=head3 type
=cut
sub _type {
return 'SipListener';
}
1;

View File

@ -1,68 +0,0 @@
package Koha::SIP2::Listeners;
# 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 Koha::SIP2::Listener;
use base qw(Koha::Objects);
=head1 NAME
Koha::SIP2::Listeners- Koha Sip Listener Object set class
=head1 API
=head2 Class Methods
=cut
=head3 get_for_config
Returns the listeners hashref as expected by C4/SIP/Sip/Configuration->new;
=cut
sub get_for_config {
my ($self) = @_;
my $listeners = $self->search();
my $return_hash;
while ( my $sip2_listener = $listeners->next() ) {
$return_hash->{ lc $sip2_listener->port } = $sip2_listener->get_for_config();
}
return $return_hash;
}
=head3 type
=cut
sub _type {
return 'SipListener';
}
=head3 object_class
=cut
sub object_class {
return 'Koha::SIP2::Listener';
}
1;

View File

@ -21,8 +21,6 @@ use base qw(Koha::Object);
use DateTime;
# use Koha::SIP2::ServerParams;
=head1 NAME
Koha::SIP2::Object - Base class for SIP2 objects
@ -60,6 +58,7 @@ sub delete {
sub _update_config_timestamp {
return 1;
#TODO: Reimplement config_timestamp
# my $timestamp = DateTime->now;
# my $config_timestamp = Koha::SIP2::ServerParams->find( { key => 'config_timestamp' } )

View File

@ -1,40 +0,0 @@
package Koha::SIP2::ServerParam;
# 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::Object);
=head1 NAME
Koha::SIP2::ServerParam- Koha Sip Server Param Object class
=head1 API
=head2 Class Methods
=cut
=head3 type
=cut
sub _type {
return 'SipServerParam';
}
1;

View File

@ -1,69 +0,0 @@
package Koha::SIP2::ServerParams;
# 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 Koha::SIP2::ServerParam;
use base qw(Koha::Objects);
=head1 NAME
Koha::SIP2::ServerParams- Koha Sip Server Param Object set class
=head1 API
=head2 Class Methods
=cut
=head3 get_for_config
Returns the server params hashref as expected by C4/SIP/Sip/Configuration->new;
=cut
sub get_for_config {
my ($self) = @_;
my $server_params = $self->search();
my $return_hash;
while ( my $server_param = $server_params->next() ) {
next if $server_param->key eq 'config_timestamp';
$return_hash->{ $server_param->key } = $server_param->value;
}
return $return_hash;
}
=head3 type
=cut
sub _type {
return 'SipServerParam';
}
=head3 object_class
=cut
sub object_class {
return 'Koha::SIP2::ServerParam';
}
1;

View File

@ -1,116 +0,0 @@
use utf8;
package Koha::Schema::Result::SipListener;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Koha::Schema::Result::SipListener
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 TABLE: C<sip_listeners>
=cut
__PACKAGE__->table("sip_listeners");
=head1 ACCESSORS
=head2 sip_listener_id
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 client_timeout
data_type: 'integer'
is_nullable: 1
=head2 port
data_type: 'varchar'
is_nullable: 0
size: 80
=head2 protocol
data_type: 'varchar'
is_nullable: 0
size: 80
=head2 timeout
data_type: 'integer'
is_nullable: 0
=head2 transport
data_type: 'varchar'
is_nullable: 0
size: 80
=cut
__PACKAGE__->add_columns(
"sip_listener_id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"client_timeout",
{ data_type => "integer", is_nullable => 1 },
"port",
{ data_type => "varchar", is_nullable => 0, size => 80 },
"protocol",
{ data_type => "varchar", is_nullable => 0, size => 80 },
"timeout",
{ data_type => "integer", is_nullable => 0 },
"transport",
{ data_type => "varchar", is_nullable => 0, size => 80 },
);
=head1 PRIMARY KEY
=over 4
=item * L</sip_listener_id>
=back
=cut
__PACKAGE__->set_primary_key("sip_listener_id");
=head1 UNIQUE CONSTRAINTS
=head2 C<listener_port>
=over 4
=item * L</port>
=back
=cut
__PACKAGE__->add_unique_constraint("listener_port", ["port"]);
# Created by DBIx::Class::Schema::Loader v0.07051 @ 2025-02-05 13:46:36
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:4SKqHurtcyjF3Vvaq2BAFw
sub koha_objects_class {
'Koha::SIP2::Listeners';
}
sub koha_object_class {
'Koha::SIP2::Listener';
}
1;

View File

@ -1,87 +0,0 @@
use utf8;
package Koha::Schema::Result::SipServerParam;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Koha::Schema::Result::SipServerParam
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 TABLE: C<sip_server_params>
=cut
__PACKAGE__->table("sip_server_params");
=head1 ACCESSORS
=head2 sip_server_param_id
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 key
data_type: 'varchar'
is_nullable: 1
size: 80
=head2 value
data_type: 'varchar'
is_nullable: 0
size: 255
=cut
__PACKAGE__->add_columns(
"sip_server_param_id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"key",
{ data_type => "varchar", is_nullable => 1, size => 80 },
"value",
{ data_type => "varchar", is_nullable => 0, size => 255 },
);
=head1 PRIMARY KEY
=over 4
=item * L</sip_server_param_id>
=back
=cut
__PACKAGE__->set_primary_key("sip_server_param_id");
=head1 UNIQUE CONSTRAINTS
=head2 C<server_param_key>
=over 4
=item * L</key>
=back
=cut
__PACKAGE__->add_unique_constraint("server_param_key", ["key"]);
# Created by DBIx::Class::Schema::Loader v0.07051 @ 2025-02-07 16:23:07
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VU5dn7xlVS8ZZKB1i2V6oQ
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View File

@ -2866,16 +2866,6 @@ modules:
-
columnname: login_id
listeners:
listeners:
columns:
-
columnname: sip_listener_id
-
columnname: port
-
columnname: protocol
system_preference_overrides:
system_preference_overrides:
columns:

View File

@ -1,28 +0,0 @@
---
type: object
properties:
sip_listener_id:
type: integer
description: unique identifier
readOnly: true
port:
description: port
type: string
client_timeout:
description: protocol
type:
- integer
- "null"
protocol:
description: protocol
type: string
timeout:
description: timeout
type: integer
transport:
description: timeout
type: string
additionalProperties: false
required:
- sip_listener_id

View File

@ -1,19 +0,0 @@
---
type: object
properties:
sip_server_param_id:
type: integer
description: unique identifier
readOnly: true
key:
description: port
type: string
value:
description: protocol
type:
- string
- number
- "null"
additionalProperties: false
required:
- sip_server_param_id

View File

@ -1,276 +0,0 @@
---
/sip2/listeners:
get:
x-mojo-to: SIP2::Listeners#list
operationId: listSip2Listeners
tags:
- sip2_listeners
summary: List listeners
produces:
- application/json
parameters:
- description: Case insensitive search on listener sip_listener_id
in: query
name: sip_listener_id
required: false
type: string
collectionFormat: csv
- $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"
responses:
200:
description: A list of SIP2 listeners
schema:
items:
$ref: "../swagger.yaml#/definitions/sip2_listener"
type: array
"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"
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:
superlibrarian: 1 # TODO: Fix this, currently for superlibrarians only
post:
x-mojo-to: SIP2::Listeners#add
operationId: addSip2Listeners
tags:
- sip2_listeners
summary: Add listeners
consumes:
- application/json
produces:
- application/json
parameters:
- description: A JSON object containing information about the new listener
in: body
name: body
required: true
schema:
$ref: "../swagger.yaml#/definitions/sip2_listener"
responses:
201:
description: A successfully created listener
schema:
items:
$ref: "../swagger.yaml#/definitions/sip2_listener"
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: Ressource not found
schema:
$ref: "../swagger.yaml#/definitions/error"
409:
description: Conflict in creating resource
schema:
$ref: "../swagger.yaml#/definitions/error"
413:
description: Payload too large
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:
superlibrarian: 1 # TODO: Fix this, currently for superlibrarians only
"/sip2/listeners/{sip_listener_id}":
get:
x-mojo-to: SIP2::Listeners#get
operationId: getSip2Listeners
tags:
- sip2_listeners
summary: Get SIP2 listener
produces:
- application/json
parameters:
- $ref: "../swagger.yaml#/parameters/sip_listener_id_pp"
- name: x-koha-embed
in: header
required: false
description: Embed list sent as a request header
type: array
items:
type: string
enum:
- custom_item_fields
- item_fields
- custom_patron_fields
- patron_attributes
collectionFormat: csv
responses:
200:
description: A SIP2 listener
schema:
items:
$ref: "../swagger.yaml#/definitions/sip2_listener"
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: Ressource 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:
superlibrarian: 1 # TODO: Fix this, currently for superlibrarians only
put:
x-mojo-to: SIP2::Listeners#update
operationId: updateSip2Listeners
tags:
- sip2_listeners
summary: Update listener
consumes:
- application/json
produces:
- application/json
parameters:
- $ref: "../swagger.yaml#/parameters/sip_listener_id_pp"
- name: body
in: body
description: A JSON object containing new information about existing listener
required: true
schema:
$ref: "../swagger.yaml#/definitions/sip2_listener"
responses:
200:
description: A successfully updated listener
schema:
items:
$ref: "../swagger.yaml#/definitions/sip2_listener"
400:
description: Bad request
schema:
$ref: "../swagger.yaml#/definitions/error"
403:
description: Access forbidden
schema:
$ref: "../swagger.yaml#/definitions/error"
404:
description: Ressource not found
schema:
$ref: "../swagger.yaml#/definitions/error"
409:
description: Conflict in updating resource
schema:
$ref: "../swagger.yaml#/definitions/error"
413:
description: Payload too large
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:
superlibrarian: 1 # TODO: Fix this, currently for superlibrarians only
delete:
x-mojo-to: SIP2::Listeners#delete
operationId: deleteSip2Listeners
tags:
- sip2_listeners
summary: Delete listener
produces:
- application/json
parameters:
- $ref: "../swagger.yaml#/parameters/sip_listener_id_pp"
responses:
204:
description: Listener 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: Resource not found
schema:
$ref: "../swagger.yaml#/definitions/error"
409:
description: Conflict in deleting resource
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:
superlibrarian: 1 # TODO: Fix this, currently for superlibrarians only

View File

@ -1,114 +0,0 @@
---
/sip2/server_params:
get:
x-mojo-to: SIP2::ServerParams#list
operationId: listSip2ServerParams
tags:
- sip2_server_params
summary: List server params
produces:
- application/json
parameters:
- description: Case insensitive search on server_param sip_server_param_id
in: query
name: sip_server_param_id
required: false
type: string
collectionFormat: csv
- $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"
responses:
200:
description: A list of SIP2 server params
schema:
items:
$ref: "../swagger.yaml#/definitions/sip2_server_param"
type: array
"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"
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:
superlibrarian: 1 # TODO: Fix this, currently for superlibrarians only
patch:
x-mojo-to: SIP2::ServerParams#update_server_params
operationId: updateSip2ServerParams
tags:
- sip2_server_params
summary: Update server params
consumes:
- application/json
produces:
- application/json
parameters:
- description: A JSON object containing information about the server params updates
in: body
name: body
required: true
schema:
$ref: "../swagger.yaml#/definitions/sip2_server_param"
responses:
201:
description: A successfully created listener
schema:
items:
$ref: "../swagger.yaml#/definitions/sip2_listener"
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: Ressource not found
schema:
$ref: "../swagger.yaml#/definitions/error"
409:
description: Conflict in creating resource
schema:
$ref: "../swagger.yaml#/definitions/error"
413:
description: Payload too large
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:
superlibrarian: 1 # TODO: Fix this, currently for superlibrarians only

View File

@ -184,10 +184,6 @@ definitions:
$ref: ./definitions/sip2_account.yaml
sip2_institution:
$ref: ./definitions/sip2_institution.yaml
sip2_listener:
$ref: ./definitions/sip2_listener.yaml
sip2_server_param:
$ref: ./definitions/sip2_server_param.yaml
sip2_system_preference_override:
$ref: ./definitions/sip2_system_preference_override.yaml
smtp_server:
@ -615,12 +611,6 @@ paths:
$ref: ./paths/sip2_institutions.yaml#/~1sip2~1institutions
"/sip2/institutions/{sip_institution_id}":
$ref: "./paths/sip2_institutions.yaml#/~1sip2~1institutions~1{sip_institution_id}"
/sip2/listeners:
$ref: ./paths/sip2_listeners.yaml#/~1sip2~1listeners
"/sip2/listeners/{sip_listener_id}":
$ref: "./paths/sip2_listeners.yaml#/~1sip2~1listeners~1{sip_listener_id}"
/sip2/serverparams:
$ref: "./paths/sip2_server_params.yaml#/~1sip2~1server_params"
/sip2/system_preference_overrides:
$ref: ./paths/sip2_system_preference_overrides.yaml#/~1sip2~1system_preference_overrides
"/sip2/system_preference_overrides/{sip_system_preference_override_id}":

View File

@ -220,39 +220,6 @@ return {
say_success( $out, "Added new table 'sip_account_system_preference_overrides'" );
}
if ( !TableExists('sip_listeners') ) {
$dbh->do(
q{
CREATE TABLE IF NOT EXISTS `sip_listeners` (
`sip_listener_id` int(11) NOT NULL AUTO_INCREMENT,
`client_timeout` int(11) DEFAULT NULL,
`port` varchar(80) NOT NULL,
`protocol` varchar(80) NOT NULL,
`timeout` int(11) NOT NULL,
`transport` varchar(80) NOT NULL,
PRIMARY KEY(`sip_listener_id`),
UNIQUE KEY `listener_port` (`port`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
}
);
say_success( $out, "Added new table 'sip_listeners'" );
}
if ( !TableExists('sip_server_params') ) {
$dbh->do(
q{
CREATE TABLE IF NOT EXISTS `sip_server_params` (
`sip_server_param_id` int(11) NOT NULL AUTO_INCREMENT,
`key` varchar(80) DEFAULT NULL,
`value` varchar(255) NOT NULL,
PRIMARY KEY(`sip_server_param_id`),
UNIQUE KEY `server_param_key` (`key`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
}
);
say_success( $out, "Added new table 'sip_server_params'" );
}
if ( !TableExists('sip_system_preference_overrides') ) {
$dbh->do(
q{
@ -548,39 +515,6 @@ return {
}
# Listeners #
my @listener_keys = keys %{ $SIPconfig->{listeners} };
foreach my $listener_key (@listener_keys) {
my $insert_listeners = $dbh->prepare(
q{INSERT IGNORE INTO sip_listeners (client_timeout, port, protocol, timeout, transport) VALUES (?, ?, ?, ?, ?)}
);
my $test = $insert_listeners->execute(
$SIPconfig->{listeners}->{$listener_key}->{client_timeout},
$SIPconfig->{listeners}->{$listener_key}->{port},
$SIPconfig->{listeners}->{$listener_key}->{protocol},
$SIPconfig->{listeners}->{$listener_key}->{timeout},
$SIPconfig->{listeners}->{$listener_key}->{transport}
);
}
# Server params #
my @server_params_keys = keys %{ $SIPconfig->{'server-params'} };
foreach my $server_params_key (@server_params_keys) {
my $insert_listeners = $dbh->prepare(q{INSERT IGNORE INTO sip_server_params (`key`, value) VALUES (?, ?) });
$insert_listeners->execute(
$server_params_key,
$SIPconfig->{'server-params'}->{$server_params_key}
);
}
my $delete_config_timestamp = $dbh->prepare(q{DELETE FROM sip_server_params WHERE `key` = 'config_timestamp' });
$delete_config_timestamp->execute();
my $timestamp = DateTime->now;
my $insert_config_timestamp = $dbh->prepare(q{INSERT INTO sip_server_params (`key`, value) VALUES (?, ?) });
$insert_config_timestamp->execute( 'config_timestamp', $timestamp->epoch );
# System preference overrides
my @system_preference_overrides =
ref $SIPconfig->{syspref_overrides} eq "ARRAY"

View File

@ -6285,39 +6285,6 @@ CREATE TABLE `sip_institutions` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `sip_listeners`
--
DROP TABLE IF EXISTS `sip_listeners`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `sip_listeners` (
`sip_listener_id` int(11) NOT NULL AUTO_INCREMENT,
`client_timeout` int(11) DEFAULT NULL,
`port` varchar(80) NOT NULL,
`protocol` varchar(80) NOT NULL,
`timeout` int(11) NOT NULL,
`transport` varchar(80) NOT NULL,
PRIMARY KEY (`sip_listener_id`),
UNIQUE KEY `listener_port` (`port`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Table structure for table `sip_listeners`
--
DROP TABLE IF EXISTS `sip_server_params`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `sip_server_params` (
`sip_server_param_id` int(11) NOT NULL AUTO_INCREMENT,
`key` varchar(80) DEFAULT NULL,
`value` varchar(255) NOT NULL,
PRIMARY KEY (`sip_server_param_id`),
UNIQUE KEY `server_param_key` (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Table structure for table `sip_system_preference_overrides`
--

View File

@ -22,7 +22,6 @@
<script>
const institutions_table_settings = [% TablesSettings.GetTableSettings( 'sip2', 'institutions', 'institutions', 'json' ) | $raw %];
const accounts_table_settings = [% TablesSettings.GetTableSettings( 'sip2', 'accounts', 'accounts', 'json' ) | $raw %];
const listeners_table_settings = [% TablesSettings.GetTableSettings( 'sip2', 'listeners', 'listeners', 'json' ) | $raw %];
const system_preference_overrides_table_settings = [% TablesSettings.GetTableSettings( 'sip2', 'system_preference_overrides', 'system_preference_overrides', 'json' ) | $raw %];
const logged_in_user = [% To.json(logged_in_user.unblessed) | $raw %];
</script>

View File

@ -83,57 +83,6 @@ export class SIP2APIClient {
};
}
get listeners() {
return {
get: id =>
this.httpClient.get({
endpoint: "listeners/" + id,
}),
getAll: params =>
this.httpClient.getAll({
endpoint: "listeners",
}),
delete: id =>
this.httpClient.delete({
endpoint: "listeners/" + id,
}),
create: listener =>
this.httpClient.post({
endpoint: "listeners",
body: listener,
}),
update: (listener, id) =>
this.httpClient.put({
endpoint: "listeners/" + id,
body: listener,
}),
count: (query = {}) =>
this.httpClient.count({
endpoint:
"listeners?" +
new URLSearchParams({
_page: 1,
_per_page: 1,
...(query && { q: JSON.stringify(query) }),
}),
}),
};
}
get serverparams() {
return {
getAll: params =>
this.httpClient.getAll({
endpoint: "serverparams",
}),
updateAll: body =>
this.httpClient.patch({
endpoint: "serverparams",
body: body,
}),
};
}
get system_preference_overrides() {
return {
get: id =>

View File

@ -888,6 +888,25 @@ export default {
},
];
const additionalToolbarButtons = (resource, componentData) => {
const buttons = {
form: [
{
title: $__("Submit"),
form: componentData.resourceForm,
},
{
to: {
name: "SIP2AccountsList",
},
title: $__("Cancel"),
cssClass: "btn btn-link",
},
],
};
return buttons;
};
const baseResource = useBaseResource({
resourceName: "account",
nameAttr: "login_id",
@ -914,6 +933,8 @@ export default {
APIClient.sip2.httpClient._baseURL + "accounts",
options: { embed: "institution" },
},
additionalToolbarButtons,
stickyToolbar: ["Form"],
embedded: props.embedded,
formGroupsDisplayMode: "accordion",
resourceAttrs,

View File

@ -1,180 +0,0 @@
<script>
import BaseResource from "./../BaseResource.vue";
import { inject } from "vue";
import { APIClient } from "../../fetch/api-client.js";
export default {
extends: BaseResource,
props: {
routeAction: String,
},
setup(props) {
const { setMessage } = inject("mainStore");
setMessage(
__(
"Please note: Changes to listeners require a SIP server restart"
),
true
);
return {
...BaseResource.setup({
resourceName: "listener",
nameAttr: "port",
idAttr: "sip_listener_id",
showComponent: "SIP2ListenersShow",
listComponent: "SIP2ListenersList",
addComponent: "SIP2ListenersFormAdd",
editComponent: "SIP2ListenersFormAddEdit",
apiClient: APIClient.sip2.listeners,
resourceTableUrl: APIClient.sip2._baseURL + "listeners",
i18n: {
displayName: __("Listener"),
displayNameLowerCase: __("listener"),
displayNamePlural: __("listeners"),
},
}),
};
},
data() {
return {
resourceAttrs: [
{
name: "port",
required: true,
type: "text",
label: __("Port"),
placeholder: "127.0.0.1:8023/tcp/IPv4",
},
{
name: "client_timeout",
type: "number",
label: __("Client timeout"),
placeholder: "600",
toolTip: "Client timeout in seconds",
defaultValue: 600,
},
{
name: "protocol",
required: true,
type: "text",
label: __("Protocol"),
placeholder: "SIP/2.00",
defaultValue: "SIP/2.00",
},
{
name: "timeout",
type: "number",
label: __("Timeout"),
placeholder: "60",
toolTip: "Timeout in seconds",
defaultValue: 60,
},
{
name: "transport",
required: true,
type: "select",
options: [
{ value: "RAW", description: "RAW" },
{ value: "telnet", description: "telnet" },
],
requiredKey: "value",
selectLabel: "description",
label: __("Transport"),
defaultValue: "RAW",
},
],
tableOptions: {
columns: this.getTableColumns(),
url: () => this.resourceTableUrl,
table_settings: this.listeners_table_settings,
actions: {
0: ["show"],
"-1": this.embedded
? [
{
select: {
text: this.$__("Select"),
icon: "fa fa-check",
},
},
]
: ["edit", "delete"],
},
},
};
},
methods: {
getTableColumns: function () {
return [
{
title: __("Port"),
data: "port",
searchable: true,
orderable: true,
render: function (data, type, row, meta) {
return (
'<a role="button" class="show">' +
escape_str(`${row.port}`) +
"</a>"
);
},
},
{
title: __("Client timeout"),
data: "client_timeout",
searchable: true,
orderable: true,
},
{
title: __("Protocol"),
data: "protocol",
searchable: true,
orderable: true,
},
{
title: __("Timeout"),
data: "timeout",
searchable: true,
orderable: true,
},
{
title: __("Transport"),
data: "transport",
searchable: true,
orderable: true,
},
];
},
onSubmit(e, listenerToSave) {
e.preventDefault();
let listener = JSON.parse(JSON.stringify(listenerToSave)); // copy
let sip_listener_id = listener.sip_listener_id;
delete listener.sip_listener_id;
const client = APIClient.sip2;
if (sip_listener_id) {
client.listeners.update(listener, sip_listener_id).then(
success => {
this.setMessage(this.$__("Listener updated"));
this.$router.push({ name: "SIP2ListenersList" });
},
error => {}
);
} else {
client.listeners.create(listener).then(
success => {
this.setMessage(this.$__("Listener created"));
this.$router.push({ name: "SIP2ListenersList" });
},
error => {}
);
}
},
},
name: "SIP2ListenerResource",
};
</script>

View File

@ -1,182 +0,0 @@
<template>
<div v-if="!initialized">{{ $__("Loading") }}</div>
<div v-else id="serverparams">
<h2>
{{ $__("Edit server params") }}
</h2>
<div>
<form @submit="onSubmit($event)">
<fieldset class="rows">
<ol>
<li
v-for="(param, index) in this
.server_params_definitions"
v-bind:key="index"
>
<FormElement
:resource="this.server_params"
:attr="param"
:index="index"
/>
</li>
</ol>
</fieldset>
<fieldset class="action">
<ButtonSubmit />
</fieldset>
</form>
</div>
</div>
</template>
<script>
import { inject } from "vue";
import { APIClient } from "../../fetch/api-client.js";
import FormElement from "../FormElement.vue";
import ButtonSubmit from "../ButtonSubmit.vue";
export default {
setup() {
const { setMessage } = inject("mainStore");
setMessage(
__(
"Please note: Changes to server params require a SIP server restart"
),
true
);
return {
setMessage,
};
},
data() {
return {
initialized: false,
server_params_definitions: [
{
name: "min_servers",
required: true,
type: "number",
label: "min_servers",
},
{
name: "min_spare_servers",
required: true,
type: "number",
label: "min_spare_servers",
},
{
name: "max_servers",
required: true,
type: "number",
label: "max_servers",
},
{
name: "setsid",
required: true,
type: "number",
label: "setsid",
},
{
name: "user",
required: true,
type: "text",
label: "user",
},
{
name: "group",
required: true,
type: "text",
label: "group",
},
{
name: "pid_file",
required: true,
type: "text",
label: "pid_file",
},
{
name: "custom_tcp_keepalive",
required: true,
type: "number",
label: "custom_tcp_keepalive",
},
{
name: "custom_tcp_keepalive_time",
required: true,
type: "number",
label: "custom_tcp_keepalive_time",
},
{
name: "custom_tcp_keepalive_intvl",
required: true,
type: "number",
label: "custom_tcp_keepalive_intvl",
},
],
server_params: {
min_servers: "1",
min_spare_servers: "0",
max_servers: "1",
setsid: "1",
user: "koha",
group: "koha",
pid_file: "/var/run/sipserver.pid",
custom_tcp_keepalive: "0",
custom_tcp_keepalive_time: "7200",
custom_tcp_keepalive_intvl: "75",
},
};
},
created() {
this.getServerParams();
},
methods: {
async getServerParams() {
const client = APIClient.sip2;
client.serverparams.getAll().then(
returned_server_params => {
returned_server_params.forEach(server_param => {
this.server_params[server_param.key] =
server_param.value;
});
this.initialized = true;
},
error => {}
);
},
onSubmit(e) {
e.preventDefault();
const client = APIClient.sip2;
const updatedParams = Object.keys(this.server_params).map(key => {
return { key: key, value: this.server_params[key] };
});
client.serverparams.updateAll(updatedParams).then(
success => {
this.setMessage(
this.$__(
"Server parameters updated. Please restart the SIP server."
),
true
);
},
error => {}
);
},
},
components: {
ButtonSubmit,
FormElement,
},
name: "SIP2ServerParams",
};
</script>
<style scoped>
:deep(fieldset.rows) label {
width: 15rem;
}
</style>

View File

@ -9,11 +9,12 @@ import {
faPencil,
faTrash,
faSpinner,
faSave,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import vSelect from "vue-select";
library.add(faPlus, faMinus, faPencil, faTrash, faSpinner);
library.add(faPlus, faMinus, faPencil, faTrash, faSpinner, faSave);
import App from "../components/SIP2/Main.vue";

View File

@ -2,7 +2,6 @@ import { markRaw } from "vue";
import Home from "../components/SIP2/Home.vue";
import ResourceWrapper from "../components/ResourceWrapper.vue";
import ServerParams from "../components/SIP2/SIP2ServerParams.vue";
import { $__ } from "../i18n";
export const routes = [
@ -82,38 +81,6 @@ export const routes = [
},
],
},
{
path: "/cgi-bin/koha/sip2/listeners",
title: $__("Listeners"),
icon: "fa fa-signal",
is_end_node: true,
resource: "SIP2/SIP2ListenerResource.vue",
children: [
{
path: "",
name: "SIP2ListenersList",
component: markRaw(ResourceWrapper),
},
{
path: ":sip_listener_id",
name: "SIP2ListenersShow",
component: markRaw(ResourceWrapper),
title: $__("Show listener"),
},
{
path: "add",
name: "SIP2ListenersFormAdd",
component: markRaw(ResourceWrapper),
title: $__("Add listener"),
},
{
path: "edit/:sip_listener_id",
name: "SIP2ListenersFormAddEdit",
component: markRaw(ResourceWrapper),
title: $__("Edit listener"),
},
],
},
{
path: "/cgi-bin/koha/sip2/system_preference_overrides",
title: $__("System preference overrides"),
@ -146,19 +113,6 @@ export const routes = [
},
],
},
{
path: "/cgi-bin/koha/sip2/serverparams",
title: $__("Server params"),
icon: "fa fa-server",
is_end_node: true,
children: [
{
path: "",
name: "SIP2ServerParams",
component: markRaw(ServerParams),
},
],
},
],
},
];

View File

@ -1,274 +0,0 @@
import { mount } from "@cypress/vue";
function get_listener() {
return {
client_timeout: 600,
port: "127.0.0.1:8023/tcp/IPv4",
protocol: "SIP/2.00",
sip_listener_id: 1,
timeout: 60,
transport: "RAW",
};
}
describe("Listeners", () => {
beforeEach(() => {
cy.login();
cy.title().should("eq", "Koha staff interface");
});
it("List listeners", () => {
// GET listeners returns 500
cy.intercept("GET", "/api/v1/sip2/listeners*", {
statusCode: 500,
error: "Something went wrong",
});
cy.visit("/cgi-bin/koha/sip2/sip2.pl");
cy.get("#navmenulist").contains("Listeners").click();
cy.get("main div[class='alert alert-warning']").contains(
/Something went wrong/
);
// GET listeners returns empty list
cy.intercept("GET", "/api/v1/sip2/listeners*", []);
cy.visit("/cgi-bin/koha/sip2/listeners");
cy.get("#listener_list").contains("There are no listeners defined");
// GET listeners returns something
let listener = get_listener();
let listeners = [listener];
cy.intercept("GET", "/api/v1/sip2/listeners*", {
statusCode: 200,
body: listeners,
headers: {
"X-Base-Total-Count": "1",
"X-Total-Count": "1",
},
});
cy.intercept("GET", "/api/v1/sip2/listeners/*", listeners);
cy.visit("/cgi-bin/koha/sip2/listeners/");
cy.get("#listener_list").contains("Showing 1 to 1 of 1 entries");
});
it("Add listeners", () => {
let listener = get_listener();
// No listeners
cy.intercept("GET", "/api/v1/sip2/listeners**", {
statusCode: 200,
body: [],
});
// Click the button in the toolbar
cy.visit("/cgi-bin/koha/sip2/listeners");
cy.contains("New listener").click();
cy.get("#listener_add h2").contains("New listener");
cy.left_menu_active_item_is("Listeners");
// Fill in the form for normal attributes
cy.get("#listener_add").contains("Submit").click();
cy.get("input:invalid,textarea:invalid,select:invalid").should(
"have.length",
1
);
cy.get("#port").type(listener.port);
cy.get("#client_timeout").type(listener.client_timeout);
cy.get("#protocol").type(listener.protocol);
cy.get("#timeout").type(listener.timeout);
cy.get("#transport").type(listener.transport);
// Submit the form, get 500
cy.intercept("POST", "/api/v1/sip2/listeners", {
statusCode: 500,
});
cy.get("#listener_add").contains("Submit").click();
cy.get("main div[class='alert alert-warning']").contains(
"Something went wrong: Error: Internal Server Error"
);
// Submit the form, success!
cy.intercept("POST", "/api/v1/sip2/listeners", {
statusCode: 201,
body: listener,
});
cy.get("#listener_add").contains("Submit").click();
});
it("Edit listeners", () => {
let listener = get_listener();
let listeners = [listener];
// Intercept follow-up 'search' request after entering /listeners
cy.intercept("GET", "/api/v1/sip2/listeners?_page*", {
statusCode: 200,
body: listeners,
headers: {
"X-Base-Total-Count": "1",
"X-Total-Count": "1",
},
}).as("get-single-listeners-search-result");
cy.visit("/cgi-bin/koha/sip2/listeners");
cy.wait("@get-single-listeners-search-result");
// Intercept request after edit click
cy.intercept("GET", "/api/v1/sip2/listeners/*", listener).as(
"get-listeners"
);
// Click the 'Edit' button from the list
cy.get("#listener_list table tbody tr:first").contains("Edit").click();
cy.wait("@get-listeners");
cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet!
cy.get("#listener_add h2").contains("Edit listener");
cy.left_menu_active_item_is("Listeners");
// Form has been correctly filled in
cy.get("#port").should("have.value", listeners[0].port);
cy.get("#client_timeout").should(
"have.value",
listeners[0].client_timeout
);
cy.get("#protocol").should("have.value", listeners[0].protocol);
cy.get("#timeout").should("have.value", listeners[0].timeout);
cy.get("#transport .vs__selected-options").contains(
listeners[0].transport
);
// Submit the form, get 500
cy.intercept("PUT", "/api/v1/sip2/listeners/*", req => {
req.reply({
statusCode: 500,
delay: 1000,
});
});
cy.get("#listener_add").contains("Submit").click();
cy.get("main div[class='modal_centered']").contains("Submitting...");
cy.wait(1000);
cy.get("main div[class='alert alert-warning']").contains(
"Something went wrong: Error: Internal Server Error"
);
// Submit the form, success!
cy.intercept("PUT", "/api/v1/sip2/listeners/*", {
statusCode: 200,
body: listeners,
});
cy.get("#listener_add").contains("Submit").click();
});
it("Show listeners", () => {
let listener = get_listener();
let listeners = [listener];
// Click the "name" link from the list
cy.intercept("GET", "/api/v1/sip2/listeners*", {
statusCode: 200,
body: listeners,
headers: {
"X-Base-Total-Count": "1",
"X-Total-Count": "1",
},
});
cy.intercept("GET", "/api/v1/sip2/listeners/*", listener).as(
"get-listeners"
);
cy.visit("/cgi-bin/koha/sip2/listeners");
let name_link = cy.get(
"#listener_list table tbody tr:first td:first a"
);
name_link.should("have.text", listener.port);
name_link.click();
cy.wait("@get-listeners");
cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet!
cy.get("#listener_show h2").contains(
"Listener #" + listener.sip_listener_id
);
cy.left_menu_active_item_is("Listeners");
});
it("Delete listeners", () => {
let listener = get_listener();
let listeners = [listener];
// Delete from list
// Click the 'Delete' button from the list
cy.intercept("GET", "/api/v1/sip2/listeners*", {
statusCode: 200,
body: listeners,
headers: {
"X-Base-Total-Count": "1",
"X-Total-Count": "1",
},
});
cy.intercept("GET", "/api/v1/sip2/listeners/*", listener);
cy.visit("/cgi-bin/koha/sip2/listeners");
cy.get("#listener_list table tbody tr:first")
.contains("Delete")
.click();
cy.get(".alert-warning.confirmation h1").contains(
"remove this listener"
);
cy.contains(listener.port);
// Accept the confirmation dialog, get 500
cy.intercept("DELETE", "/api/v1/sip2/listeners/*", {
statusCode: 500,
});
cy.contains("Yes, delete").click();
cy.get("main div[class='alert alert-warning']").contains(
"Something went wrong: Error: Internal Server Error"
);
// Accept the confirmation dialog, success!
cy.intercept("DELETE", "/api/v1/sip2/listeners/*", {
statusCode: 204,
body: null,
});
cy.get("#listener_list table tbody tr:first")
.contains("Delete")
.click();
cy.get(".alert-warning.confirmation h1").contains(
"remove this listener"
);
cy.contains("Yes, delete").click();
cy.get("main div[class='alert alert-info']")
.contains("Listener")
.contains("deleted");
// Delete from show
// Click the "name" link from the list
cy.intercept("GET", "/api/v1/sip2/listeners*", {
statusCode: 200,
body: listeners,
headers: {
"X-Base-Total-Count": "1",
"X-Total-Count": "1",
},
});
cy.intercept("GET", "/api/v1/sip2/listeners/*", listener).as(
"get-listener"
);
cy.visit("/cgi-bin/koha/sip2/listeners");
let name_link = cy.get(
"#listener_list table tbody tr:first td:first a"
);
name_link.should("have.text", listener.port);
name_link.click();
cy.wait("@get-listener");
cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet!
cy.get("#listener_show h2").contains(
"Listener #" + listener.sip_listener_id
);
cy.get("#listener_show #toolbar").contains("Delete").click();
cy.get(".alert-warning.confirmation h1").contains(
"remove this listener"
);
cy.contains("Yes, delete").click();
//Make sure we return to list after deleting from show
cy.get("#listener_list table tbody tr:first");
});
});

View File

@ -1,131 +0,0 @@
import { mount } from "@cypress/vue";
function get_server_params() {
return [
{
key: "min_servers",
sip_server_param_id: 1,
value: "1",
},
{
key: "min_spare_servers",
sip_server_param_id: 2,
value: "0",
},
{
key: "max_servers",
sip_server_param_id: 3,
value: "1",
},
{
key: "setsid",
sip_server_param_id: 4,
value: "1",
},
{
key: "user",
sip_server_param_id: 5,
value: "koha",
},
{
key: "group",
sip_server_param_id: 6,
value: "koha",
},
{
key: "pid_file",
sip_server_param_id: 7,
value: "/var/run/sipserver.pid",
},
{
key: "custom_tcp_keepalive",
sip_server_param_id: 8,
value: "0",
},
{
key: "custom_tcp_keepalive_time",
sip_server_param_id: 9,
value: "7200",
},
{
key: "custom_tcp_keepalive_intvl",
sip_server_param_id: 10,
value: "75",
},
];
}
describe("ServerParams", () => {
beforeEach(() => {
cy.login();
cy.title().should("eq", "Koha staff interface");
});
it("Edit server params", () => {
let server_params = get_server_params();
// Intercept follow-up 'search' request after entering /system_preference_overrides
cy.intercept("GET", "/api/v1/sip2/serverparams**", {
statusCode: 200,
body: server_params,
}).as("get-server_params");
cy.visit("/cgi-bin/koha/sip2/serverparams");
cy.wait("@get-server_params");
cy.left_menu_active_item_is("Server params");
// Form has been correctly filled in
cy.get("#min_servers").should(
"have.value",
server_params.find(p => p.key === "min_servers").value
);
cy.get("#min_spare_servers").should(
"have.value",
server_params.find(p => p.key === "min_spare_servers").value
);
cy.get("#max_servers").should(
"have.value",
server_params.find(p => p.key === "max_servers").value
);
cy.get("#setsid").should(
"have.value",
server_params.find(p => p.key === "setsid").value
);
cy.get("#user").should(
"have.value",
server_params.find(p => p.key === "user").value
);
cy.get("#group").should(
"have.value",
server_params.find(p => p.key === "group").value
);
cy.get("#pid_file").should(
"have.value",
server_params.find(p => p.key === "pid_file").value
);
cy.get("#custom_tcp_keepalive").should(
"have.value",
server_params.find(p => p.key === "custom_tcp_keepalive").value
);
cy.get("#custom_tcp_keepalive_time").should(
"have.value",
server_params.find(p => p.key === "custom_tcp_keepalive_time").value
);
cy.get("#custom_tcp_keepalive_intvl").should(
"have.value",
server_params.find(p => p.key === "custom_tcp_keepalive_intvl")
.value
);
cy.intercept("PATCH", "/api/v1/sip2/serverparams", req => {
req.reply({
message: "Server params updated successfully",
});
});
cy.get("#serverparams").contains("Submit").click();
cy.get("main div[class='alert alert-info']").contains(
"Server parameters updated"
);
});
});

View File

@ -27,8 +27,6 @@ use XML::Simple;
use Koha::SIP2::Institutions;
use Koha::SIP2::Accounts;
use Koha::SIP2::Listeners;
use Koha::SIP2::ServerParams;
use Koha::SIP2::SystemPreferenceOverrides;
subtest 'Config from XML matches config from database' => sub {
@ -40,8 +38,6 @@ subtest 'Config from XML matches config from database' => sub {
Koha::SIP2::Institutions->delete;
Koha::SIP2::Accounts->delete;
Koha::SIP2::Listeners->delete;
Koha::SIP2::ServerParams->delete;
Koha::SIP2::SystemPreferenceOverrides->delete;
my $koha_instance = $ENV{KOHA_CONF} =~ m!^.+/sites/([^/]+)/koha-conf\.xml$! ? $1 : undef;
@ -83,15 +79,13 @@ subtest 'Config from XML matches config from database' => sub {
subtest 'config_timestamp is updated when database configuration changes' => sub {
plan tests => 3;
plan tests => 1;
my $schema = Koha::Database->new->schema;
$schema->storage->txn_begin;
Koha::SIP2::Institutions->delete;
Koha::SIP2::Accounts->delete;
Koha::SIP2::Listeners->delete;
Koha::SIP2::ServerParams->delete;
Koha::SIP2::SystemPreferenceOverrides->delete;
my $builder = t::lib::TestBuilder->new();
@ -141,23 +135,24 @@ subtest 'config_timestamp is updated when database configuration changes' => sub
'$cfg->{accounts}->{$sip_account->login_id}->{allow_fields} is empty'
);
my $original_timestamp = Koha::SIP2::ServerParams->find( { key => 'config_timestamp' } );
#TODO: Update these tests
# my $original_timestamp = Koha::SIP2::ServerParams->find( { key => 'config_timestamp' } );
sleep 1;
$sip_account->allow_fields('AB')->store();
my $new_cfg = C4::SIP::Sip::Configuration->get_configuration();
# sleep 1;
# $sip_account->allow_fields('AB')->store();
# my $new_cfg = C4::SIP::Sip::Configuration->get_configuration();
my $last_timestamp = Koha::SIP2::ServerParams->find( { key => 'config_timestamp' } );
# my $last_timestamp = Koha::SIP2::ServerParams->find( { key => 'config_timestamp' } );
isnt(
$original_timestamp->value, $last_timestamp->value,
'config_timestamp should be updated when database configuration changes'
);
# isnt(
# $original_timestamp->value, $last_timestamp->value,
# 'config_timestamp should be updated when database configuration changes'
# );
is(
$cfg->{accounts}->{ $sip_account->login_id }->{allow_fields}, $sip_account->allow_fields,
'$cfg->{accounts}->{$sip_account->login_id}->{allow_fields} should now return the new value'
);
# is(
# $cfg->{accounts}->{ $sip_account->login_id }->{allow_fields}, $sip_account->allow_fields,
# '$cfg->{accounts}->{$sip_account->login_id}->{allow_fields} should now return the new value'
# );
$schema->storage->txn_rollback;
};