Browse Source
CRUD for libraries via REST API. GET /api/v1/libraries - List all libraries GET /api/v1/libraries/{branchcode} - Get one Library POST /api/v1/libraries - Add new Library DELETE /api/v1/libraries/{branchcode} - Delete Library Test plan: - apply patch - run tests: t/db_dependent/api/v1/libraries.t - test API with some API tool or simple curl e.g.: curl http://host:port/api/v1/libraries curl http://host:port/api/v1/libraries/cpl Signed-off-by: Josef Moravec <josef.moravec@gmail.com> Signed-off-by: Benjamin Rokseth <benjamin.rokseth@kul.oslo.kommune.no> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io> Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io> Signed-off-by: Josef Moravec <josef.moravec@gmail.com> Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> Signed-off-by: Nick Clemens <nick@bywatersolutions.com>19.05.x
Jiří Kozlovský
8 years ago
committed by
root
9 changed files with 1029 additions and 0 deletions
@ -0,0 +1,141 @@ |
|||
package Koha::REST::V1::Library; |
|||
|
|||
# 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, write to the Free Software Foundation, Inc., |
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|||
|
|||
use Modern::Perl; |
|||
|
|||
use Mojo::Base 'Mojolicious::Controller'; |
|||
use Koha::Libraries; |
|||
|
|||
use Scalar::Util qw( blessed ); |
|||
|
|||
use Try::Tiny; |
|||
|
|||
sub list { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
my $libraries; |
|||
my $filter; |
|||
my $args = $c->req->params->to_hash; |
|||
|
|||
for my $filter_param ( keys %$args ) { |
|||
$filter->{$filter_param} = { LIKE => $args->{$filter_param} . "%" }; |
|||
} |
|||
|
|||
return try { |
|||
my $libraries = Koha::Libraries->search($filter); |
|||
return $c->render( status => 200, openapi => $libraries ); |
|||
} |
|||
catch { |
|||
if ( $_->isa('DBIx::Class::Exception') ) { |
|||
return $c->render( status => 500, |
|||
openapi => { error => $_->{msg} } ); |
|||
} |
|||
else { |
|||
return $c->render( status => 500, |
|||
openapi => { error => "Something went wrong, check the logs."} ); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
sub get { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
my $branchcode = $c->validation->param('branchcode'); |
|||
my $library = Koha::Libraries->find({ branchcode => $branchcode }); |
|||
unless ($library) { |
|||
return $c->render( status => 404, |
|||
openapi => { error => "Library not found" } ); |
|||
} |
|||
|
|||
return $c->render( status => 200, openapi => $library ); |
|||
} |
|||
|
|||
sub add { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
return try { |
|||
if (Koha::Libraries->find($c->req->json->{branchcode})) { |
|||
return $c->render( status => 400, |
|||
openapi => { error => 'Library already exists' } ); |
|||
} |
|||
my $library = Koha::Library->new($c->validation->param('body'))->store; |
|||
my $branchcode = $library->branchcode; |
|||
$c->res->headers->location($c->req->url->to_string.'/'.$branchcode); |
|||
return $c->render( status => 201, openapi => $library); |
|||
} |
|||
catch { |
|||
if ( $_->isa('DBIx::Class::Exception') ) { |
|||
return $c->render( status => 500, |
|||
openapi => { error => $_->{msg} } ); |
|||
} |
|||
else { |
|||
return $c->render( status => 500, |
|||
openapi => { error => "Something went wrong, check the logs."} ); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
sub update { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
my $library; |
|||
return try { |
|||
$library = Koha::Libraries->find($c->validation->param('branchcode')); |
|||
$library->set($c->validation->param('body'))->store; |
|||
return $c->render( status => 200, openapi => $library ); |
|||
} |
|||
catch { |
|||
if ( not defined $library ) { |
|||
return $c->render( status => 404, |
|||
openapi => { error => "Object not found" }); |
|||
} |
|||
elsif ( $_->isa('DBIx::Class::Exception') ) { |
|||
return $c->render( status => 500, |
|||
openapi => { error => $_->{msg} } ); |
|||
} |
|||
else { |
|||
return $c->render( status => 500, |
|||
openapi => { error => "Something went wrong, check the logs."} ); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
sub delete { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
my $library; |
|||
return try { |
|||
$library = Koha::Libraries->find($c->validation->param('branchcode')); |
|||
$library->delete; |
|||
return $c->render( status => 204, openapi => ''); |
|||
} |
|||
catch { |
|||
if ( not defined $library ) { |
|||
return $c->render( status => 404, openapi => { error => "Object not found" } ); |
|||
} |
|||
elsif ( $_->isa('DBIx::Class::Exception') ) { |
|||
return $c->render( status => 500, |
|||
openapi => { error => $_->{msg} } ); |
|||
} |
|||
else { |
|||
return $c->render( status => 500, |
|||
openapi => { error => "Something went wrong, check the logs."} ); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
1; |
@ -0,0 +1,86 @@ |
|||
{ |
|||
"type": "object", |
|||
"properties": { |
|||
"branchcode": { |
|||
"$ref": "../x-primitives.json#/branchcode" |
|||
}, |
|||
"branchname": { |
|||
"type": "string", |
|||
"description": "Printable name of library" |
|||
}, |
|||
"branchaddress1": { |
|||
"type": ["string", "null"], |
|||
"description": "the first address line of the library" |
|||
}, |
|||
"branchaddress2": { |
|||
"type": ["string", "null"], |
|||
"description": "the second address line of the library" |
|||
}, |
|||
"branchaddress3": { |
|||
"type": ["string", "null"], |
|||
"description": "the third address line of the library" |
|||
}, |
|||
"branchzip": { |
|||
"type": ["string", "null"], |
|||
"description": "the zip or postal code of the library" |
|||
}, |
|||
"branchcity": { |
|||
"type": ["string", "null"], |
|||
"description": "the city or province of the library" |
|||
}, |
|||
"branchstate": { |
|||
"type": ["string", "null"], |
|||
"description": "the reqional state of the library" |
|||
}, |
|||
"branchcountry": { |
|||
"type": ["string", "null"], |
|||
"description": "the county of the library" |
|||
}, |
|||
"branchphone": { |
|||
"type": ["string", "null"], |
|||
"description": "the primary phone of the library" |
|||
}, |
|||
"branchfax": { |
|||
"type": ["string", "null"], |
|||
"description": "the fax number of the library" |
|||
}, |
|||
"branchemail": { |
|||
"type": ["string", "null"], |
|||
"description": "the primary email address of the library" |
|||
}, |
|||
"branchreplyto": { |
|||
"type": ["string", "null"], |
|||
"description": "the email to be used as a Reply-To" |
|||
}, |
|||
"branchreturnpath": { |
|||
"type": ["string", "null"], |
|||
"description": "the email to be used as Return-Path" |
|||
}, |
|||
"branchurl": { |
|||
"type": ["string", "null"], |
|||
"description": "the URL for your library or branch's website" |
|||
}, |
|||
"issuing": { |
|||
"type": ["integer", "null"], |
|||
"description": "unused in Koha" |
|||
}, |
|||
"branchip": { |
|||
"type": ["string", "null"], |
|||
"description": "the IP address for your library or branch" |
|||
}, |
|||
"branchprinter": { |
|||
"type": ["string", "null"], |
|||
"description": "unused in Koha" |
|||
}, |
|||
"branchnotes": { |
|||
"type": ["string", "null"], |
|||
"description": "notes related to your library or branch" |
|||
}, |
|||
"opac_info": { |
|||
"type": ["string", "null"], |
|||
"description": "HTML that displays in OPAC" |
|||
} |
|||
}, |
|||
"additionalProperties": false, |
|||
"required": ["branchcode", "branchname"] |
|||
} |
@ -0,0 +1,9 @@ |
|||
{ |
|||
"branchcodePathParam": { |
|||
"name": "branchcode", |
|||
"in": "path", |
|||
"description": "Branch identifier code", |
|||
"required": true, |
|||
"type": "string" |
|||
} |
|||
} |
@ -0,0 +1,362 @@ |
|||
{ |
|||
"/libraries": { |
|||
"get": { |
|||
"x-mojo-to": "Library#list", |
|||
"operationId": "listLibrary", |
|||
"tags": ["library"], |
|||
"parameters": [{ |
|||
"name": "branchname", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on name", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchaddress1", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on address1", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchaddress2", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on address2", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchaddress3", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on address3", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchzip", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on zipcode", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchcity", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on city", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchstate", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on state", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchcountry", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on country", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchphone", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on phone number", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchfax", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on fax number", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchemail", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on email address", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchreplyto", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on Reply-To email address", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchreturnpath", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on Return-Path email address", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchurl", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on website URL", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "issuing", |
|||
"in": "query", |
|||
"description": "Unused in Koha", |
|||
"required": false, |
|||
"type": "integer" |
|||
}, { |
|||
"name": "branchip", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on IP address", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchprinter", |
|||
"in": "query", |
|||
"description": "Unused in Koha", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "branchnotes", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts_with' search on notes", |
|||
"required": false, |
|||
"type": "string" |
|||
}, { |
|||
"name": "opac_info", |
|||
"in": "query", |
|||
"description": "Case insensitive 'starts-with' search on OPAC info", |
|||
"required": false, |
|||
"type": "string" |
|||
}], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "A list of libraries", |
|||
"schema": { |
|||
"type": "array", |
|||
"items": { |
|||
"$ref": "../definitions.json#/library" |
|||
} |
|||
} |
|||
}, |
|||
"500": { |
|||
"description": "Internal error", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"503": { |
|||
"description": "Under maintenance", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"post": { |
|||
"x-mojo-to": "Library#add", |
|||
"operationId": "addLibrary", |
|||
"tags": ["library"], |
|||
"parameters": [{ |
|||
"name": "body", |
|||
"in": "body", |
|||
"description": "A JSON object containing informations about the new library", |
|||
"required": true, |
|||
"schema": { |
|||
"$ref": "../definitions.json#/library" |
|||
} |
|||
}], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"201": { |
|||
"description": "Library added", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/library" |
|||
} |
|||
}, |
|||
"400": { |
|||
"description": "Bad request", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"401": { |
|||
"description": "Authentication required", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"403": { |
|||
"description": "Access forbidden", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"500": { |
|||
"description": "Internal error", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"503": { |
|||
"description": "Under maintenance", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
} |
|||
}, |
|||
"x-koha-authorization": { |
|||
"permissions": { |
|||
"parameters": "parameters_remaining_permissions" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"/libraries/{branchcode}": { |
|||
"get": { |
|||
"x-mojo-to": "Library#get", |
|||
"operationId": "getLibrary", |
|||
"tags": ["library"], |
|||
"parameters": [ |
|||
{ |
|||
"$ref": "../parameters.json#/branchcodePathParam" |
|||
} |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "A library", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/library" |
|||
} |
|||
}, |
|||
"404": { |
|||
"description": "Library not found", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"put": { |
|||
"x-mojo-to": "Library#update", |
|||
"operationId": "updateLibrary", |
|||
"tags": ["library"], |
|||
"parameters": [{ |
|||
"$ref": "../parameters.json#/branchcodePathParam" |
|||
}, { |
|||
"name": "body", |
|||
"in": "body", |
|||
"description": "A JSON object containing information on the library", |
|||
"required": true, |
|||
"schema": { |
|||
"$ref": "../definitions.json#/library" |
|||
} |
|||
}], |
|||
"consumes": [ |
|||
"application/json" |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "A library", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/library" |
|||
} |
|||
}, |
|||
"400": { |
|||
"description": "Bad request", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"401": { |
|||
"description": "Authentication required", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"403": { |
|||
"description": "Access forbidden", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"404": { |
|||
"description": "Library not found", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"500": { |
|||
"description": "Internal error", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"503": { |
|||
"description": "Under maintenance", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
} |
|||
}, |
|||
"x-koha-authorization": { |
|||
"permissions": { |
|||
"parameters": "parameters_remaining_permissions" |
|||
} |
|||
} |
|||
}, |
|||
"delete": { |
|||
"x-mojo-to": "Library#delete", |
|||
"operationId": "deleteLibrary", |
|||
"tags": ["library"], |
|||
"parameters": [{ |
|||
"$ref": "../parameters.json#/branchcodePathParam" |
|||
}], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"204": { |
|||
"description": "Library deleted", |
|||
"schema": { "type": "string" } |
|||
}, |
|||
"401": { |
|||
"description": "Authentication required", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"403": { |
|||
"description": "Access forbidden", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"404": { |
|||
"description": "Library not found", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"500": { |
|||
"description": "Internal error", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"503": { |
|||
"description": "Under maintenance", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
} |
|||
}, |
|||
"x-koha-authorization": { |
|||
"permissions": { |
|||
"parameters": "parameters_remaining_permissions" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,413 @@ |
|||
#!/usr/bin/env perl |
|||
|
|||
# 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, write to the Free Software Foundation, Inc., |
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|||
|
|||
use Modern::Perl; |
|||
|
|||
use Test::More tests => 5; |
|||
use Test::Mojo; |
|||
use Test::Warn; |
|||
|
|||
use t::lib::TestBuilder; |
|||
use t::lib::Mocks; |
|||
|
|||
use C4::Auth; |
|||
use Koha::Libraries; |
|||
use Koha::Database; |
|||
|
|||
my $schema = Koha::Database->new->schema; |
|||
my $builder = t::lib::TestBuilder->new; |
|||
|
|||
# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling |
|||
# this affects the other REST api tests |
|||
t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' ); |
|||
|
|||
my $remote_address = '127.0.0.1'; |
|||
my $t = Test::Mojo->new('Koha::REST::V1'); |
|||
|
|||
subtest 'list() tests' => sub { |
|||
plan tests => 8; |
|||
|
|||
$schema->storage->txn_begin; |
|||
|
|||
# Create test context |
|||
my $library = $builder->build( { source => 'Branch' } ); |
|||
my $another_library = { %$library }; # create a copy of $library but make |
|||
delete $another_library->{branchcode}; # sure branchcode will be regenerated |
|||
$another_library = $builder->build( |
|||
{ source => 'Branch', value => $another_library } ); |
|||
my ( $borrowernumber, $session_id ) = |
|||
create_user_and_session( { authorized => 0 } ); |
|||
|
|||
## Authorized user tests |
|||
my $count_of_libraries = Koha::Libraries->search->count; |
|||
# Make sure we are returned with the correct amount of libraries |
|||
my $tx = $t->ua->build_tx( GET => '/api/v1/libraries' ); |
|||
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(200) |
|||
->json_has('/'.($count_of_libraries-1).'/branchcode') |
|||
->json_hasnt('/'.($count_of_libraries).'/branchcode'); |
|||
|
|||
subtest 'query parameters' => sub { |
|||
my @fields = qw( |
|||
branchname branchaddress1 branchaddress2 branchaddress3 |
|||
branchzip branchcity branchstate branchcountry |
|||
branchphone branchfax branchemail branchreplyto |
|||
branchreturnpath branchurl issuing branchip |
|||
branchprinter branchnotes opac_info |
|||
); |
|||
plan tests => scalar(@fields)*3; |
|||
|
|||
foreach my $field (@fields) { |
|||
$tx = $t->ua->build_tx( GET => |
|||
"/api/v1/libraries?$field=$library->{$field}" ); |
|||
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
my $result = |
|||
$t->request_ok($tx) |
|||
->status_is(200) |
|||
->json_has( [ $library, $another_library ] ); |
|||
} |
|||
}; |
|||
|
|||
# Warn on unsupported query parameter |
|||
$tx = $t->ua->build_tx( GET => '/api/v1/libraries?library_blah=blah' ); |
|||
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(400) |
|||
->json_is( [{ path => '/query/library_blah', message => 'Malformed query string'}] ); |
|||
|
|||
$schema->storage->txn_rollback; |
|||
}; |
|||
|
|||
subtest 'get() tests' => sub { |
|||
|
|||
plan tests => 6; |
|||
|
|||
$schema->storage->txn_begin; |
|||
|
|||
my $library = $builder->build( { source => 'Branch' } ); |
|||
my ( $borrowernumber, $session_id ) = |
|||
create_user_and_session( { authorized => 0 } ); |
|||
|
|||
my $tx = $t->ua->build_tx( GET => "/api/v1/libraries/" . $library->{branchcode} ); |
|||
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(200) |
|||
->json_is($library); |
|||
|
|||
my $non_existent_code = 'non_existent'.int(rand(10000)); |
|||
$tx = $t->ua->build_tx( GET => "/api/v1/libraries/" . $non_existent_code ); |
|||
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(404) |
|||
->json_is( '/error' => 'Library not found' ); |
|||
|
|||
$schema->storage->txn_rollback; |
|||
}; |
|||
|
|||
subtest 'add() tests' => sub { |
|||
plan tests => 31; |
|||
|
|||
$schema->storage->txn_begin; |
|||
|
|||
my ( $unauthorized_borrowernumber, $unauthorized_session_id ) = |
|||
create_user_and_session( { authorized => 0 } ); |
|||
my ( $authorized_borrowernumber, $authorized_session_id ) = |
|||
create_user_and_session( { authorized => 1 } ); |
|||
my $library = { |
|||
branchcode => "LIBRARYBR1", |
|||
branchname => "Library Name", |
|||
branchaddress1 => "Library Address1", |
|||
branchaddress2 => "Library Address2", |
|||
branchaddress3 => "Library Address3", |
|||
branchzip => "Library Zipcode", |
|||
branchcity => "Library City", |
|||
branchstate => "Library State", |
|||
branchcountry => "Library Country", |
|||
branchphone => "Library Phone", |
|||
branchfax => "Library Fax", |
|||
branchemail => "Library Email", |
|||
branchreplyto => "Library Reply-To", |
|||
branchreturnpath => "Library Return-Path", |
|||
branchurl => "http://library.url", |
|||
issuing => undef, # unused in Koha |
|||
branchip => "127.0.0.1", |
|||
branchprinter => "Library Printer", # unused in Koha |
|||
branchnotes => "Library Notes", |
|||
opac_info => "<p>Library OPAC info</p>", |
|||
}; |
|||
|
|||
# Unauthorized attempt to write |
|||
my $tx = $t->ua->build_tx( POST => "/api/v1/libraries" => json => $library ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $unauthorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(403); |
|||
|
|||
# Authorized attempt to write invalid data |
|||
my $library_with_invalid_field = { %$library }; |
|||
$library_with_invalid_field->{'branchinvalid'} = 'Library invalid'; |
|||
|
|||
$tx = $t->ua->build_tx( |
|||
POST => "/api/v1/libraries" => json => $library_with_invalid_field ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(400) |
|||
->json_is( |
|||
"/errors" => [ |
|||
{ |
|||
message => "Properties not allowed: branchinvalid.", |
|||
path => "/body" |
|||
} |
|||
] |
|||
); |
|||
|
|||
# Authorized attempt to write |
|||
$tx = $t->ua->build_tx( POST => "/api/v1/libraries" => json => $library ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
my $branchcode = $t->request_ok($tx) |
|||
->status_is(201) |
|||
->json_is( '/branchname' => $library->{branchname} ) |
|||
->json_is( '/branchaddress1' => $library->{branchaddress1} ) |
|||
->json_is( '/branchaddress2' => $library->{branchaddress2} ) |
|||
->json_is( '/branchaddress3' => $library->{branchaddress3} ) |
|||
->json_is( '/branchzip' => $library->{branchzip} ) |
|||
->json_is( '/branchcity' => $library->{branchcity} ) |
|||
->json_is( '/branchstate' => $library->{branchstate} ) |
|||
->json_is( '/branchcountry' => $library->{branchcountry} ) |
|||
->json_is( '/branchphone' => $library->{branchphone} ) |
|||
->json_is( '/branchfax' => $library->{branchfax} ) |
|||
->json_is( '/branchemail' => $library->{branchemail} ) |
|||
->json_is( '/branchreplyto' => $library->{branchreplyto} ) |
|||
->json_is( '/branchreturnpath' => $library->{branchreturnpath} ) |
|||
->json_is( '/branchurl' => $library->{branchurl} ) |
|||
->json_is( '/branchip' => $library->{branchip} ) |
|||
->json_is( '/branchnotes' => $library->{branchnotes} ) |
|||
->json_is( '/opac_info' => $library->{opac_info} ) |
|||
->header_is(Location => "/api/v1/libraries/$library->{branchcode}") |
|||
->tx->res->json->{branchcode}; |
|||
|
|||
# Authorized attempt to create with null id |
|||
$library->{branchcode} = undef; |
|||
$tx = $t->ua->build_tx( |
|||
POST => "/api/v1/libraries" => json => $library ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(400) |
|||
->json_has('/errors'); |
|||
|
|||
# Authorized attempt to create with existing id |
|||
$library->{branchcode} = $branchcode; |
|||
$tx = $t->ua->build_tx( |
|||
POST => "/api/v1/libraries" => json => $library ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(400) |
|||
->json_is('/error' => 'Library already exists'); |
|||
|
|||
$schema->storage->txn_rollback; |
|||
}; |
|||
|
|||
subtest 'update() tests' => sub { |
|||
plan tests => 13; |
|||
|
|||
$schema->storage->txn_begin; |
|||
|
|||
my ( $unauthorized_borrowernumber, $unauthorized_session_id ) = |
|||
create_user_and_session( { authorized => 0 } ); |
|||
my ( $authorized_borrowernumber, $authorized_session_id ) = |
|||
create_user_and_session( { authorized => 1 } ); |
|||
|
|||
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; |
|||
|
|||
# Unauthorized attempt to update |
|||
my $tx = $t->ua->build_tx( PUT => "/api/v1/libraries/$branchcode" |
|||
=> json => { branchname => 'New unauthorized name change' } ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $unauthorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(403); |
|||
|
|||
# Attempt partial update on a PUT |
|||
my $library_with_missing_field = { |
|||
branchaddress1 => "New library address", |
|||
}; |
|||
|
|||
$tx = $t->ua->build_tx( PUT => "/api/v1/libraries/$branchcode" => |
|||
json => $library_with_missing_field ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(400) |
|||
->json_has( "/errors" => |
|||
[ { message => "Missing property.", path => "/body/branchaddress2" } ] |
|||
); |
|||
|
|||
# Full object update on PUT |
|||
my $library_with_updated_field = { |
|||
branchcode => "LIBRARYBR2", |
|||
branchname => "Library Name", |
|||
branchaddress1 => "Library Address1", |
|||
branchaddress2 => "Library Address2", |
|||
branchaddress3 => "Library Address3", |
|||
branchzip => "Library Zipcode", |
|||
branchcity => "Library City", |
|||
branchstate => "Library State", |
|||
branchcountry => "Library Country", |
|||
branchphone => "Library Phone", |
|||
branchfax => "Library Fax", |
|||
branchemail => "Library Email", |
|||
branchreplyto => "Library Reply-To", |
|||
branchreturnpath => "Library Return-Path", |
|||
branchurl => "http://library.url", |
|||
issuing => undef, # unused in Koha |
|||
branchip => "127.0.0.1", |
|||
branchprinter => "Library Printer", # unused in Koha |
|||
branchnotes => "Library Notes", |
|||
opac_info => "<p>Library OPAC info</p>", |
|||
}; |
|||
|
|||
$tx = $t->ua->build_tx( |
|||
PUT => "/api/v1/libraries/$branchcode" => json => $library_with_updated_field ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(200) |
|||
->json_is( '/branchname' => 'Library Name' ); |
|||
|
|||
# Authorized attempt to write invalid data |
|||
my $library_with_invalid_field = { %$library_with_updated_field }; |
|||
$library_with_invalid_field->{'branchinvalid'} = 'Library invalid'; |
|||
|
|||
$tx = $t->ua->build_tx( |
|||
PUT => "/api/v1/libraries/$branchcode" => json => $library_with_invalid_field ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(400) |
|||
->json_is( |
|||
"/errors" => [ |
|||
{ |
|||
message => "Properties not allowed: branchinvalid.", |
|||
path => "/body" |
|||
} |
|||
] |
|||
); |
|||
|
|||
my $non_existent_code = 'nope'.int(rand(10000)); |
|||
$tx = |
|||
$t->ua->build_tx( PUT => "/api/v1/libraries/$non_existent_code" => json => |
|||
$library_with_updated_field ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(404); |
|||
|
|||
$schema->storage->txn_rollback; |
|||
}; |
|||
|
|||
subtest 'delete() tests' => sub { |
|||
plan tests => 7; |
|||
|
|||
$schema->storage->txn_begin; |
|||
|
|||
my ( $unauthorized_borrowernumber, $unauthorized_session_id ) = |
|||
create_user_and_session( { authorized => 0 } ); |
|||
my ( $authorized_borrowernumber, $authorized_session_id ) = |
|||
create_user_and_session( { authorized => 1 } ); |
|||
|
|||
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; |
|||
|
|||
# Unauthorized attempt to delete |
|||
my $tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $unauthorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(403); |
|||
|
|||
$tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(204) |
|||
->content_is(''); |
|||
|
|||
$tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" ); |
|||
$tx->req->cookies( |
|||
{ name => 'CGISESSID', value => $authorized_session_id } ); |
|||
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
|||
$t->request_ok($tx) |
|||
->status_is(404); |
|||
|
|||
$schema->storage->txn_rollback; |
|||
}; |
|||
|
|||
sub create_user_and_session { |
|||
|
|||
my $args = shift; |
|||
my $flags = ( $args->{authorized} ) ? $args->{authorized} : 0; |
|||
my $dbh = C4::Context->dbh; |
|||
|
|||
my $user = $builder->build( |
|||
{ |
|||
source => 'Borrower', |
|||
value => { |
|||
flags => $flags |
|||
} |
|||
} |
|||
); |
|||
|
|||
# Create a session for the authorized user |
|||
my $session = C4::Auth::get_session(''); |
|||
$session->param( 'number', $user->{borrowernumber} ); |
|||
$session->param( 'id', $user->{userid} ); |
|||
$session->param( 'ip', '127.0.0.1' ); |
|||
$session->param( 'lasttime', time() ); |
|||
$session->flush; |
|||
|
|||
if ( $args->{authorized} ) { |
|||
$dbh->do( " |
|||
INSERT INTO user_permissions (borrowernumber,module_bit,code) |
|||
VALUES (?,3,'parameters_remaining_permissions')", undef, |
|||
$user->{borrowernumber} ); |
|||
} |
|||
|
|||
return ( $user->{borrowernumber}, $session->id ); |
|||
} |
|||
|
|||
1; |
Loading…
Reference in new issue