Bugzilla – Attachment 65326 Details for
Bug 17505
Add routes for messaging preferences
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 17505: REST API route for messaging preferences
Bug-17505-REST-API-route-for-messaging-preferences.patch (text/plain), 35.92 KB, created by
Jiri Kozlovsky
on 2017-07-30 14:30:01 UTC
(
hide
)
Description:
Bug 17505: REST API route for messaging preferences
Filename:
MIME Type:
Creator:
Jiri Kozlovsky
Created:
2017-07-30 14:30:01 UTC
Size:
35.92 KB
patch
obsolete
>From 17fac91349066e7aeaf7271f9609c269d1f9ca35 Mon Sep 17 00:00:00 2001 >From: Lari Taskula <lari.taskula@jns.fi> >Date: Mon, 15 May 2017 16:49:56 +0300 >Subject: [PATCH] Bug 17505: REST API route for messaging preferences > >Get patron's / category's messaging preferences: > GET /messaging_preferences?borrowernumber=123 > - allowed if getting own preferences > - otherwise borrowers flag required > GET /messaging_preferences?categorycode=K > - borrowers flag required > >Modify patron's / category's messaging preferences: > PUT /messaging_preferences?borrowernumber=123 > - allowed if modifying own preferences > - otherwise borrowers flag required > > PUT /messaging_preferences?categorycode=K > - borrowers flag required > >Returns the following JSON object (same for PUT except for readOnly values): >{ > "Advanced_Notice": { > "days_in_advance": { > "configurable": true, > "value": 20 > }, > "digest": { > "configurable": true, > "value": true > }, > "transport_types": { > "email": true, > "sms": false > } > }, > "Another_Message_Name": { > "days_in_advance": { > "configurable": false, > "value": null > }, > "digest": { ... > }, > ... >} > >To test: >1. prove t/db_dependent/api/v1/messagingpreferences.t >2. Send GET and PUT requests to /api/v1/messaging_preferences > >Signed-off-by: Jiri Kozlovsky <mail@jkozlovsky.cz> >--- > Koha/Patron/Message/Preference.pm | 51 +++ > Koha/Patron/Message/Preferences.pm | 29 ++ > Koha/REST/V1/Patron/Message/Preference.pm | 164 ++++++++ > api/v1/swagger/definitions.json | 3 + > .../swagger/definitions/messagingpreference.json | 20 + > .../definitions/messagingpreference/transport.json | 52 +++ > api/v1/swagger/paths.json | 3 + > api/v1/swagger/paths/messagingpreferences.json | 155 ++++++++ > t/db_dependent/api/v1/messagingpreferences.t | 417 +++++++++++++++++++++ > 9 files changed, 894 insertions(+) > create mode 100644 Koha/REST/V1/Patron/Message/Preference.pm > create mode 100644 api/v1/swagger/definitions/messagingpreference.json > create mode 100644 api/v1/swagger/definitions/messagingpreference/transport.json > create mode 100644 api/v1/swagger/paths/messagingpreferences.json > create mode 100644 t/db_dependent/api/v1/messagingpreferences.t > >diff --git a/Koha/Patron/Message/Preference.pm b/Koha/Patron/Message/Preference.pm >index 6fb7fb8..37b5fe9 100644 >--- a/Koha/Patron/Message/Preference.pm >+++ b/Koha/Patron/Message/Preference.pm >@@ -281,6 +281,57 @@ sub store { > return $self; > } > >+sub TO_JSON { >+ my ($self, $params) = @_; >+ >+ my $json = {}; >+ my $pref; >+ $params->{'options'} ||= Koha::Patron::Message::Preferences->get_options; >+ my $transports = $self->message_transport_types; >+ >+ foreach my $option (@{$params->{'options'}}) { >+ foreach my $param (keys %$option) { >+ if ($param eq 'message_attribute_id' && >+ $option->{$param} == $self->message_attribute_id) { >+ $pref = $option; >+ last; >+ } >+ } >+ } >+ >+ foreach my $conf (keys %$pref) { >+ if ($conf =~ /^transport_/) { >+ my $mtt = $conf =~ s/^transport_//r; >+ if ($mtt eq 'sms' && !C4::Context->preference('SMSSendDriver')) { >+ next; >+ } >+ if ($mtt eq 'phone' && >+ !C4::Context->preference('TalkingTechItivaPhoneNotification')) { >+ next; >+ } >+ $json->{'transport_types'}->{$mtt} = $transports->{$mtt} ? >+ Mojo::JSON->true : Mojo::JSON->false; >+ } >+ } >+ >+ $json->{'days_in_advance'} = { >+ configurable => $pref->{'takes_days'} ? >+ Mojo::JSON->true : Mojo::JSON->false, >+ value => defined $self->days_in_advance ? >+ 0+$self->days_in_advance : undef >+ }; >+ $json->{'digest'} = { >+ configurable => $self->wants_digest >+ ? $pref->{'has_digest_off'} # can digest be unchecked? >+ ? Mojo::JSON->true : Mojo::JSON->false >+ : $pref->{'has_digest'} # can digest be checked? >+ ? Mojo::JSON->true : Mojo::JSON->false, >+ value => $self->wants_digest ? Mojo::JSON->true : Mojo::JSON->false >+ }; >+ >+ return $json; >+} >+ > =head3 validate > > Makes a basic validation for object. >diff --git a/Koha/Patron/Message/Preferences.pm b/Koha/Patron/Message/Preferences.pm >index 500bb85..dc96bfc 100644 >--- a/Koha/Patron/Message/Preferences.pm >+++ b/Koha/Patron/Message/Preferences.pm >@@ -125,6 +125,35 @@ sub search_with_message_name { > return $self->SUPER::search($params, $attributes); > } > >+sub TO_JSON { >+ my ($self) = @_; >+ >+ my $preferences = {}; >+ my $options = $self->get_options; >+ foreach my $preference ($self->as_list) { >+ $preferences->{$preference->message_name} = $preference->TO_JSON({ >+ options => $options >+ }); >+ } >+ >+ # If some preferences are not stored even though they are valid options, >+ # then add those options to the returned HASHref as well >+ foreach my $option (@$options) { >+ unless ($preferences->{$option->{'message_name'}}) { >+ my $message_attribute_id = Koha::Patron::Message::Attributes->find({ >+ message_name => $option->{'message_name'} >+ })->message_attribute_id; >+ $preferences->{$option->{'message_name'}} = >+ Koha::Patron::Message::Preference->new({ >+ borrowernumber => -1, >+ message_attribute_id => $message_attribute_id, >+ })->TO_JSON({ options => $options }); >+ } >+ } >+ >+ return $preferences; >+} >+ > =head3 type > > =cut >diff --git a/Koha/REST/V1/Patron/Message/Preference.pm b/Koha/REST/V1/Patron/Message/Preference.pm >new file mode 100644 >index 0000000..d8f845d >--- /dev/null >+++ b/Koha/REST/V1/Patron/Message/Preference.pm >@@ -0,0 +1,164 @@ >+package Koha::REST::V1::Patron::Message::Preference; >+ >+# 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::Patron::Message::Attributes; >+use Koha::Patron::Message::Preferences; >+use Koha::Patron::Message::Transport::Types; >+use Koha::Patron::Message::Transports; >+ >+use Try::Tiny; >+ >+sub list { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $enabled = _check_system_preferences($c); >+ return $enabled if $enabled; >+ >+ my $borrowernumber = $c->validation->param('borrowernumber'); >+ my $categorycode = $c->validation->param('categorycode'); >+ >+ my $found = $borrowernumber >+ ? Koha::Patrons->find($borrowernumber) >+ : Koha::Patron::Categories->find($categorycode); >+ >+ return try { >+ die unless $found; >+ my $preferences = Koha::Patron::Message::Preferences->search({ >+ borrowernumber => $borrowernumber, >+ categorycode => $categorycode, >+ }); >+ >+ return $c->render(status => 200, openapi => $preferences); >+ } >+ catch { >+ unless ($found) { >+ return $c->render( status => 400, openapi => { >+ error => "Patron or category not found" } ); >+ } >+ Koha::Exceptions::rethrow_exception($_); >+ }; >+} >+ >+sub edit { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $enabled = _check_system_preferences($c); >+ return $enabled if $enabled; >+ >+ my $borrowernumber = $c->validation->param('borrowernumber'); >+ my $categorycode = $c->validation->param('categorycode'); >+ my $body = $c->validation->param('body'); >+ >+ my $found = $borrowernumber >+ ? Koha::Patrons->find($borrowernumber) >+ : Koha::Patron::Categories->find($categorycode); >+ >+ return try { >+ die unless $found; >+ foreach my $in (keys %{$body}) { >+ my $preference = >+ Koha::Patron::Message::Preferences->find_with_message_name({ >+ borrowernumber => $borrowernumber, >+ categorycode => $categorycode, >+ message_name => $in >+ }); >+ >+ # Format wants_digest and days_in_advance values >+ my $wants_digest = $body->{$in}->{'digest'} ? >+ $body->{$in}->{'digest'}->{'value'} ? 1 : 0 : 0; >+ my $days_in_advance = $body->{$in}->{'days_in_advance'} ? >+ defined $body->{$in}->{'days_in_advance'}->{'value'} ? >+ $body->{$in}->{'days_in_advance'}->{'value'} : undef : undef; >+ >+ # HASHref for updated preference >+ my @transport_types; >+ foreach my $mtt (keys %{$body->{$in}->{'transport_types'}}) { >+ if ($body->{$in}->{'transport_types'}->{$mtt}) { >+ push @transport_types, $mtt; >+ } >+ } >+ my $edited_preference = { >+ wants_digest => $wants_digest, >+ days_in_advance => $days_in_advance, >+ message_transport_types => \@transport_types >+ }; >+ >+ # Unless a preference for this message name exists, create it >+ unless ($preference) { >+ my $attr = Koha::Patron::Message::Attributes->find({ >+ message_name => $in >+ }); >+ unless ($attr) { >+ Koha::Exceptions::BadParameter->throw( >+ error => "Message type $in not found." >+ ); >+ } >+ $edited_preference->{'message_attribute_id'} = >+ $attr->message_attribute_id; >+ if ($borrowernumber) { >+ $edited_preference->{'borrowernumber'}=$found->borrowernumber; >+ } else { >+ $edited_preference->{'categorycode'}=$found->categorycode; >+ } >+ Koha::Patron::Message::Preference->new($edited_preference)->store; >+ } >+ # Otherwise, modify the already-existing one >+ else { >+ $preference->set($edited_preference)->store; >+ } >+ } >+ >+ # Finally, return the preferences >+ my $preferences = Koha::Patron::Message::Preferences->search({ >+ borrowernumber => $borrowernumber, >+ categorycode => $categorycode, >+ }); >+ >+ return $c->render( status => 200, openapi => $preferences); >+ } >+ catch { >+ unless ($found) { >+ return $c->render( status => 400, openapi => { >+ error => "Patron or category not found" } ); >+ } >+ if ($_->isa('Koha::Exceptions::BadParameter')) { >+ return $c->render( status => 400, openapi => { error => $_->error }); >+ } >+ Koha::Exceptions::rethrow_exception($_); >+ }; >+} >+ >+sub _check_system_preferences { >+ my $c = shift; >+ if ( ! C4::Context->preference('EnhancedMessagingPreferences') ) { >+ return $c->render( status => 403, openapi => { >+ error => "Enhanced messaging preferences are not enabled"}); >+ } >+ if (($c->stash('is_owner_access') || $c->stash('is_guarantor_access')) >+ && ! C4::Context->preference('EnhancedMessagingPreferencesOPAC')) { >+ return $c->render( status => 403, openapi => { >+ error => "Patrons does not have access to enhanced messaging" >+ ." preferences" }); >+ } >+ return; >+} >+ >+1; >diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json >index 939baa8..b31e8f2 100644 >--- a/api/v1/swagger/definitions.json >+++ b/api/v1/swagger/definitions.json >@@ -11,6 +11,9 @@ > "holds": { > "$ref": "definitions/holds.json" > }, >+ "messagingpreference": { >+ "$ref": "definitions/messagingpreference.json" >+ }, > "patron": { > "$ref": "definitions/patron.json" > } >diff --git a/api/v1/swagger/definitions/messagingpreference.json b/api/v1/swagger/definitions/messagingpreference.json >new file mode 100644 >index 0000000..9de782f >--- /dev/null >+++ b/api/v1/swagger/definitions/messagingpreference.json >@@ -0,0 +1,20 @@ >+{ >+ "type": "object", >+ "properties": { >+ "Item_Due": { >+ "$ref": "messagingpreference/transport.json" >+ }, >+ "Advance_Notice": { >+ "$ref": "messagingpreference/transport.json" >+ }, >+ "Hold_Filled": { >+ "$ref": "messagingpreference/transport.json" >+ }, >+ "Item_Check_in": { >+ "$ref": "messagingpreference/transport.json" >+ }, >+ "Item_Checkout": { >+ "$ref": "messagingpreference/transport.json" >+ } >+ } >+} >diff --git a/api/v1/swagger/definitions/messagingpreference/transport.json b/api/v1/swagger/definitions/messagingpreference/transport.json >new file mode 100644 >index 0000000..7b8b28b >--- /dev/null >+++ b/api/v1/swagger/definitions/messagingpreference/transport.json >@@ -0,0 +1,52 @@ >+{ >+ "type": "object", >+ "properties": { >+ "transport_types": { >+ "type": "object", >+ "properties": { >+ "email": { >+ "type": "boolean" >+ }, >+ "phone": { >+ "type": "boolean" >+ }, >+ "print": { >+ "type": "boolean" >+ }, >+ "sms": { >+ "type": "boolean" >+ } >+ } >+ }, >+ "days_in_advance": { >+ "type": "object", >+ "properties": { >+ "configurable": { >+ "description": "Can this message have a value for days in advance", >+ "type": "boolean", >+ "readOnly": true >+ }, >+ "value": { >+ "type": ["integer", "null"], >+ "minimum": 0, >+ "maximum": 30 >+ } >+ } >+ }, >+ "digest": { >+ "type": "object", >+ "properties": { >+ "configurable": { >+ "description": "Can this message be requested as digest", >+ "type": "boolean", >+ "readOnly": true >+ }, >+ "value": { >+ "description": "Is digest enabled", >+ "type": "boolean" >+ } >+ } >+ } >+ }, >+ "additionalProperties": false >+} >diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json >index b1fcf40..394b347 100644 >--- a/api/v1/swagger/paths.json >+++ b/api/v1/swagger/paths.json >@@ -11,6 +11,9 @@ > "/holds/{reserve_id}": { > "$ref": "paths/holds.json#/~1holds~1{reserve_id}" > }, >+ "/messaging_preferences": { >+ "$ref": "paths/messagingpreferences.json#/~1messaging_preferences" >+ }, > "/patrons": { > "$ref": "paths/patrons.json#/~1patrons" > }, >diff --git a/api/v1/swagger/paths/messagingpreferences.json b/api/v1/swagger/paths/messagingpreferences.json >new file mode 100644 >index 0000000..5c27239 >--- /dev/null >+++ b/api/v1/swagger/paths/messagingpreferences.json >@@ -0,0 +1,155 @@ >+{ >+ "/messaging_preferences": { >+ "get": { >+ "x-mojo-to": "Patron::Message::Preference#list", >+ "operationId": "listMessagingPreferences", >+ "x-koha-authorization": { >+ "permissions": { >+ "borrowers": "*" >+ }, >+ "allow-owner": true, >+ "allow-guarantor": true >+ }, >+ "tags": ["notices"], >+ "parameters": [{ >+ "name": "borrowernumber", >+ "in": "query", >+ "description": "Patron's borrowernumber", >+ "required": false, >+ "type": "integer" >+ }, { >+ "name": "categorycode", >+ "in": "query", >+ "description": "Categorycode to find default messaging preferences for a category", >+ "required": false, >+ "type": "string" >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "A messaging preference object", >+ "schema": { >+ "$ref" : "../definitions.json#/messagingpreference" >+ } >+ }, >+ "400": { >+ "description": "Bad parameter given", >+ "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": "Preferences 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" >+ } >+ } >+ } >+ }, >+ "put": { >+ "x-mojo-to": "Patron::Message::Preference#edit", >+ "operationId": "editMessagingPreferences", >+ "description": "Modifies patron's messaging preferences. Please note that not all parameters defined in body object's documentation can actually be used for each message option due to dynamic configuration. Make a GET request first to see whether an option is configurable or if message transport type is available.", >+ "x-koha-authorization": { >+ "permissions": { >+ "borrowers": "*" >+ }, >+ "allow-owner": true, >+ "allow-guarantor": true >+ }, >+ "tags": ["notices"], >+ "parameters": [ >+ { >+ "name": "borrowernumber", >+ "in": "query", >+ "description": "Patron's borrowernumber", >+ "required": false, >+ "type": "integer" >+ }, { >+ "name": "categorycode", >+ "in": "query", >+ "description": "Categorycode to find default messaging preferences for a category", >+ "required": false, >+ "type": "string" >+ }, { >+ "name": "body", >+ "in": "body", >+ "description": "A JSON object containing information on messaging preferences", >+ "required": true, >+ "schema": { "$ref" : "../definitions.json#/messagingpreference" } >+ } >+ ], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "A messaging preferences object", >+ "schema": { >+ "$ref" : "../definitions.json#/messagingpreference" >+ } >+ }, >+ "400": { >+ "description": "Missing or wrong parameters", >+ "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": "Patron or category 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" >+ } >+ } >+ } >+ } >+ } >+} >diff --git a/t/db_dependent/api/v1/messagingpreferences.t b/t/db_dependent/api/v1/messagingpreferences.t >new file mode 100644 >index 0000000..64d148f >--- /dev/null >+++ b/t/db_dependent/api/v1/messagingpreferences.t >@@ -0,0 +1,417 @@ >+#!/usr/bin/env perl >+ >+# Copyright Koha-Suomi Oy 2017 >+# >+# 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 => 2; >+use Test::Mojo; >+use t::lib::Mocks; >+use t::lib::TestBuilder; >+ >+use C4::Auth; >+use C4::Context; >+ >+use Koha::Database; >+use Koha::Notice::Templates; >+use Koha::Patron::Message::Preferences; >+ >+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 => 34; >+ >+ $schema->storage->txn_begin; >+ >+ my $path = '/api/v1/messaging_preferences'; >+ >+ my ($patron, $session) = create_user_and_session(); >+ my $borrowernumber = $patron->borrowernumber; >+ my $categorycode = $patron->categorycode; >+ my ($another_patron, undef) = create_user_and_session(); >+ my ($librarian, $librarian_session) = create_user_and_session({ >+ flags => 16 >+ }); >+ my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({ >+ patron => $patron >+ }); >+ my ($preference2, $mtt1_2, $mtt2_2) = build_a_test_category_preference({ >+ patron => $patron >+ }); >+ >+ t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1); >+ my $tx = $t->ua->build_tx(GET => $path); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(401); >+ >+ $tx = $t->ua->build_tx(GET => "$path?borrowernumber=" >+ .$another_patron->borrowernumber); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(403); >+ >+ $tx = $t->ua->build_tx(GET => "$path?categorycode=$categorycode"); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(403); >+ >+ $tx = $t->ua->build_tx(GET => $path); >+ $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(400) >+ ->json_is('/error', 'Patron or category not found'); >+ >+ t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 0); >+ $tx = $t->ua->build_tx(GET => "$path?borrowernumber=$borrowernumber"); >+ $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(403) >+ ->json_is('/error' => 'Enhanced messaging preferences are not enabled'); >+ t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1); >+ >+ $tx = $t->ua->build_tx(GET => "$path?borrowernumber=$borrowernumber"); >+ $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(200) >+ ->json_has('/'.$preference->message_name); >+ >+ $tx = $t->ua->build_tx(GET => "$path?borrowernumber=$borrowernumber"); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(200) >+ ->json_has('/'.$preference->message_name) >+ ->json_has('/'.$preference2->message_name) >+ ->json_is('/'.$preference->message_name.'/transport_types/' >+ .$mtt1->message_transport_type => Mojo::JSON->true) >+ ->json_is('/'.$preference->message_name.'/transport_types/' >+ .$mtt2->message_transport_type => Mojo::JSON->true) >+ ->json_is('/'.$preference->message_name.'/days_in_advance/configurable' >+ => Mojo::JSON->false) >+ ->json_is('/'.$preference->message_name.'/days_in_advance/value' >+ => undef) >+ ->json_is('/'.$preference->message_name.'/digest/configurable' >+ => Mojo::JSON->false) >+ ->json_is('/'.$preference->message_name.'/digest/value' >+ => Mojo::JSON->false); >+ >+ $tx = $t->ua->build_tx(GET => "$path?categorycode=$categorycode"); >+ $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(200) >+ ->json_has('/'.$preference->message_name) >+ ->json_has('/'.$preference2->message_name) >+ ->json_is('/'.$preference2->message_name.'/transport_types/' >+ .$mtt1_2->message_transport_type => Mojo::JSON->true) >+ ->json_is('/'.$preference2->message_name.'/transport_types/' >+ .$mtt2_2->message_transport_type => Mojo::JSON->true) >+ ->json_is('/'.$preference2->message_name.'/days_in_advance/configurable' >+ => Mojo::JSON->false) >+ ->json_is('/'.$preference2->message_name.'/days_in_advance/value' >+ => undef) >+ ->json_is('/'.$preference2->message_name.'/digest/value' >+ => Mojo::JSON->false); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'edit() tests' => sub { >+ plan tests => 28; >+ >+ $schema->storage->txn_begin; >+ >+ my $path = '/api/v1/messaging_preferences'; >+ >+ my ($patron, $session) = create_user_and_session(); >+ my ($librarian, $librarian_session) = create_user_and_session({ >+ flags => 16 >+ }); >+ my ($another_patron, undef) = create_user_and_session(); >+ my $borrowernumber = $patron->borrowernumber; >+ my $categorycode = $patron->categorycode; >+ my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({ >+ patron => $patron >+ }); >+ my ($preference2, $mtt1_2, $mtt2_2) = build_a_test_category_preference({ >+ patron => $patron >+ }); >+ >+ my $edited_preference = { >+ $preference->message_name => { >+ digest => { >+ value => Mojo::JSON->true >+ }, >+ days_in_advance => { >+ value => 15 >+ }, >+ transport_types => { >+ $mtt1->message_transport_type => Mojo::JSON->true, >+ $mtt2->message_transport_type => Mojo::JSON->false >+ } >+ } >+ }; >+ >+ t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1); >+ my $tx = $t->ua->build_tx(PUT => $path => json => $edited_preference); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(401); >+ >+ $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=" >+ .$another_patron->borrowernumber >+ => json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(403); >+ >+ $tx = $t->ua->build_tx(PUT => "$path?categorycode=$categorycode" >+ => json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(403); >+ >+ $tx = $t->ua->build_tx(PUT => $path => json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(400) >+ ->json_is('/error', 'Patron or category not found'); >+ >+ t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 0); >+ $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" => >+ json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(403) >+ ->json_is('/error' => 'Enhanced messaging preferences are not enabled'); >+ t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1); >+ >+ $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" => >+ json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(400) >+ ->json_like('/error' => qr/^days_in_advance cannot/); >+ >+ $edited_preference->{$preference->message_name}-> >+ {days_in_advance}->{value} = undef; >+ $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" => >+ json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(400) >+ ->json_like('/error' => qr/igest not available/); >+ >+ $edited_preference->{$preference->message_name}->{digest}->{value} >+ = Mojo::JSON->false; >+ $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" => >+ json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(200) >+ ->json_is('/'.$preference->message_name.'/transport_types/'. >+ $mtt2->message_transport_type => Mojo::JSON->false) >+ ->json_is('/'.$preference->message_name.'/transport_types/'. >+ $mtt1->message_transport_type => Mojo::JSON->true); >+ >+ Koha::Patron::Message::Transports->search({ >+ message_attribute_id => $preference->message_attribute_id, >+ })->update({ is_digest => 1 }); >+ $edited_preference->{$preference->message_name}->{digest}->{value} >+ = Mojo::JSON->true; >+ $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" => >+ json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(200) >+ ->json_is('/'.$preference->message_name.'/digest/value' => Mojo::JSON->true); >+ >+ # Test librarian access >+ $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" => >+ json => $edited_preference); >+ $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id}); >+ $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+ $t->request_ok($tx) >+ ->status_is(200) >+ ->json_is('/'.$preference->message_name.'/digest/value' => Mojo::JSON->true); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+sub create_user_and_session { >+ my ($params) = @_; >+ >+ my $categorycode = $builder->build({ source => 'Category' })->{categorycode}; >+ my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; >+ >+ my $borrower = $builder->build({ >+ source => 'Borrower', >+ value => { >+ branchcode => $branchcode, >+ categorycode => $categorycode, >+ flags => $params->{'flags'} || 0, >+ } >+ }); >+ >+ my $session = C4::Auth::get_session(''); >+ $session->param('number', $borrower->{ borrowernumber }); >+ $session->param('id', $borrower->{ userid }); >+ $session->param('ip', '127.0.0.1'); >+ $session->param('lasttime', time()); >+ $session->flush; >+ my $patron = Koha::Patrons->find($borrower->{borrowernumber}); >+ >+ return ($patron, $session); >+} >+ >+ >+sub build_a_test_attribute { >+ my ($params) = @_; >+ >+ $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0 >+ ? 1 : 0; >+ >+ my $attribute = $builder->build({ >+ source => 'MessageAttribute', >+ value => $params, >+ }); >+ >+ return Koha::Patron::Message::Attributes->find( >+ $attribute->{message_attribute_id} >+ ); >+} >+ >+sub build_a_test_category { >+ my $categorycode = $builder->build({ >+ source => 'Category' })->{categorycode}; >+ >+ return Koha::Patron::Categories->find($categorycode); >+} >+ >+sub build_a_test_letter { >+ my ($params) = @_; >+ >+ my $mtt = $params->{mtt} ? $params->{mtt} : 'email'; >+ my $branchcode = $builder->build({ >+ source => 'Branch' })->{branchcode}; >+ my $letter = $builder->build({ >+ source => 'Letter', >+ value => { >+ branchcode => '', >+ is_html => 0, >+ message_transport_type => $mtt >+ } >+ }); >+ >+ return Koha::Notice::Templates->find({ >+ module => $letter->{module}, >+ code => $letter->{code}, >+ branchcode => $letter->{branchcode}, >+ }); >+} >+ >+sub build_a_test_transport_type { >+ my $mtt = $builder->build({ >+ source => 'MessageTransportType' }); >+ >+ return Koha::Patron::Message::Transport::Types->find( >+ $mtt->{message_transport_type} >+ ); >+} >+ >+sub build_a_test_category_preference { >+ my ($params) = @_; >+ >+ my $patron = $params->{patron}; >+ my $attr = $params->{attr} >+ ? $params->{attr} >+ : build_a_test_attribute($params->{days_in_advance}); >+ >+ my $letter = $params->{letter} ? $params->{letter} : build_a_test_letter(); >+ my $mtt1 = $params->{mtt1} ? $params->{mtt1} : build_a_test_transport_type(); >+ my $mtt2 = $params->{mtt2} ? $params->{mtt2} : build_a_test_transport_type(); >+ >+ Koha::Patron::Message::Transport->new({ >+ message_attribute_id => $attr->message_attribute_id, >+ message_transport_type => $mtt1->message_transport_type, >+ is_digest => $params->{digest} ? 1 : 0, >+ letter_module => $letter->module, >+ letter_code => $letter->code, >+ })->store; >+ >+ Koha::Patron::Message::Transport->new({ >+ message_attribute_id => $attr->message_attribute_id, >+ message_transport_type => $mtt2->message_transport_type, >+ is_digest => $params->{digest} ? 1 : 0, >+ letter_module => $letter->module, >+ letter_code => $letter->code, >+ })->store; >+ >+ my $default = Koha::Patron::Message::Preference->new({ >+ categorycode => $patron->categorycode, >+ message_attribute_id => $attr->message_attribute_id, >+ wants_digest => $params->{digest} ? 1 : 0, >+ days_in_advance => $params->{days_in_advance} >+ ? $params->{days_in_advance} : undef, >+ })->store; >+ >+ Koha::Patron::Message::Transport::Preference->new({ >+ borrower_message_preference_id => $default->borrower_message_preference_id, >+ message_transport_type => $mtt1->message_transport_type, >+ })->store; >+ Koha::Patron::Message::Transport::Preference->new({ >+ borrower_message_preference_id => $default->borrower_message_preference_id, >+ message_transport_type => $mtt2->message_transport_type, >+ })->store; >+ >+ return ($default, $mtt1, $mtt2); >+} >+ >+sub build_a_test_complete_preference { >+ my ($params) = @_; >+ >+ my ($default, $mtt1, $mtt2) = build_a_test_category_preference($params); >+ my $patron = $params->{patron}; >+ $patron->set_default_messaging_preferences; >+ return (Koha::Patron::Message::Preferences->search({ >+ borrowernumber => $patron->borrowernumber >+ })->next, $mtt1, $mtt2); >+} >-- >2.1.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 17505
:
64796
|
65326
|
151912