Bugzilla – Attachment 151912 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), 34.69 KB, created by
Julian Maurice
on 2023-06-01 10:35:07 UTC
(
hide
)
Description:
Bug 17505: REST API route for messaging preferences
Filename:
MIME Type:
Creator:
Julian Maurice
Created:
2023-06-01 10:35:07 UTC
Size:
34.69 KB
patch
obsolete
>From 2d506dbff3dad94d2049b60fe40671d9cbfe9fc5 Mon Sep 17 00:00:00 2001 >From: Julian Maurice <julian.maurice@biblibre.com> >Date: Fri, 23 Dec 2022 09:45:16 +0100 >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/MessagePreference.pm | 51 +++ > Koha/Patron/MessagePreferences.pm | 29 ++ > Koha/REST/V1/Patron/Message/Preference.pm | 169 +++++++ > .../definitions/messagingpreference.yaml | 12 + > .../messagingpreference/transport.yaml | 37 ++ > .../swagger/paths/messagingpreferences.yaml | 117 +++++ > api/v1/swagger/swagger.yaml | 4 + > t/db_dependent/api/v1/messagingpreferences.t | 420 ++++++++++++++++++ > 8 files changed, 839 insertions(+) > create mode 100644 Koha/REST/V1/Patron/Message/Preference.pm > create mode 100644 api/v1/swagger/definitions/messagingpreference.yaml > create mode 100644 api/v1/swagger/definitions/messagingpreference/transport.yaml > create mode 100644 api/v1/swagger/paths/messagingpreferences.yaml > create mode 100644 t/db_dependent/api/v1/messagingpreferences.t > >diff --git a/Koha/Patron/MessagePreference.pm b/Koha/Patron/MessagePreference.pm >index ceac1f4ea3..9f40b01104 100644 >--- a/Koha/Patron/MessagePreference.pm >+++ b/Koha/Patron/MessagePreference.pm >@@ -311,6 +311,57 @@ sub store { > return $self; > } > >+sub TO_JSON { >+ my ($self, $params) = @_; >+ >+ my $json = {}; >+ my $pref; >+ $params->{'options'} ||= Koha::Patron::MessagePreferences->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/MessagePreferences.pm b/Koha/Patron/MessagePreferences.pm >index c13e096cc7..d5fc1548c6 100644 >--- a/Koha/Patron/MessagePreferences.pm >+++ b/Koha/Patron/MessagePreferences.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::MessagePreference::Attributes->find({ >+ message_name => $option->{'message_name'} >+ })->message_attribute_id; >+ $preferences->{$option->{'message_name'}} = >+ Koha::Patron::MessagePreference->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 0000000000..583502c22a >--- /dev/null >+++ b/Koha/REST/V1/Patron/Message/Preference.pm >@@ -0,0 +1,169 @@ >+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::MessagePreference::Attributes; >+use Koha::Patron::MessagePreference::Transport::Types; >+use Koha::Patron::MessagePreference::Transports; >+use Koha::Patron::MessagePreferences; >+ >+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::MessagePreferences->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" } ); >+ } >+ >+ $_->rethrow(); >+ }; >+} >+ >+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::MessagePreferences->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::MessagePreference::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::MessagePreference->new($edited_preference)->store; >+ } >+ # Otherwise, modify the already-existing one >+ else { >+ $preference->set($edited_preference)->store; >+ } >+ } >+ >+ # Finally, return the preferences >+ my $preferences = Koha::Patron::MessagePreferences->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 }); >+ } >+ if ($_->isa('Koha::Exceptions::Patron::MessagePreference')) { >+ return $c->render( status => 400, openapi => { error => $_->error }); >+ } >+ >+ $_->rethrow(); >+ }; >+} >+ >+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/messagingpreference.yaml b/api/v1/swagger/definitions/messagingpreference.yaml >new file mode 100644 >index 0000000000..f961d1c2eb >--- /dev/null >+++ b/api/v1/swagger/definitions/messagingpreference.yaml >@@ -0,0 +1,12 @@ >+type: object >+properties: >+ Item_Due: >+ $ref: ./messagingpreference/transport.yaml >+ Advance_Notice: >+ $ref: ./messagingpreference/transport.yaml >+ Hold_Filled: >+ $ref: ./messagingpreference/transport.yaml >+ Item_Check_in: >+ $ref: ./messagingpreference/transport.yaml >+ Item_Checkout: >+ $ref: ./messagingpreference/transport.yaml >diff --git a/api/v1/swagger/definitions/messagingpreference/transport.yaml b/api/v1/swagger/definitions/messagingpreference/transport.yaml >new file mode 100644 >index 0000000000..be5e1f073e >--- /dev/null >+++ b/api/v1/swagger/definitions/messagingpreference/transport.yaml >@@ -0,0 +1,37 @@ >+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/messagingpreferences.yaml b/api/v1/swagger/paths/messagingpreferences.yaml >new file mode 100644 >index 0000000000..713ae226ba >--- /dev/null >+++ b/api/v1/swagger/paths/messagingpreferences.yaml >@@ -0,0 +1,117 @@ >+/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/messagingpreference.yaml >+ '400': >+ description: Bad parameter given >+ schema: >+ $ref: ../definitions/error.yaml >+ '401': >+ description: Authentication required >+ schema: >+ $ref: ../definitions/error.yaml >+ '403': >+ description: Access forbidden >+ schema: >+ $ref: ../definitions/error.yaml >+ '404': >+ description: Preferences not found >+ schema: >+ $ref: ../definitions/error.yaml >+ '500': >+ description: Internal error >+ schema: >+ $ref: ../definitions/error.yaml >+ '503': >+ description: Under maintenance >+ schema: >+ $ref: ../definitions/error.yaml >+ 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/messagingpreference.yaml >+ produces: >+ - application/json >+ responses: >+ '200': >+ description: A messaging preferences object >+ schema: >+ $ref: ../definitions/messagingpreference.yaml >+ '400': >+ description: Missing or wrong parameters >+ schema: >+ $ref: ../definitions/error.yaml >+ '401': >+ description: Authentication required >+ schema: >+ $ref: ../definitions/error.yaml >+ '403': >+ description: Access forbidden >+ schema: >+ $ref: ../definitions/error.yaml >+ '404': >+ description: Patron or category not found >+ schema: >+ $ref: ../definitions/error.yaml >+ '500': >+ description: Internal error >+ schema: >+ $ref: ../definitions/error.yaml >+ '503': >+ description: Under maintenance >+ schema: >+ $ref: ../definitions/error.yaml >diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml >index 280610c261..14a84c90af 100644 >--- a/api/v1/swagger/swagger.yaml >+++ b/api/v1/swagger/swagger.yaml >@@ -76,6 +76,8 @@ definitions: > $ref: ./definitions/job.yaml > library: > $ref: ./definitions/library.yaml >+ messagingpreference: >+ $ref: ./definitions/messagingpreference.yaml > order: > $ref: ./definitions/order.yaml > patron: >@@ -281,6 +283,8 @@ paths: > $ref: ./paths/libraries.yaml#/~1libraries > "/libraries/{library_id}": > $ref: "./paths/libraries.yaml#/~1libraries~1{library_id}" >+ "/messaging_preferences": >+ $ref: "./paths/messagingpreferences.yaml#/~1messaging_preferences" > "/oauth/login/{provider_code}/{interface}": > $ref: ./paths/oauth.yaml#/~1oauth~1login~1{provider_code}~1{interface} > /oauth/token: >diff --git a/t/db_dependent/api/v1/messagingpreferences.t b/t/db_dependent/api/v1/messagingpreferences.t >new file mode 100644 >index 0000000000..42e502c556 >--- /dev/null >+++ b/t/db_dependent/api/v1/messagingpreferences.t >@@ -0,0 +1,420 @@ >+#!/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::MessagePreferences; >+use Koha::Patron::MessagePreference::Attributes; >+use Koha::Patron::MessagePreference::Transport; >+use Koha::Patron::MessagePreference::Transport::Types; >+ >+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 cannot be selected/); >+ >+ $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::MessagePreference::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::MessagePreference::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::MessagePreference::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::MessagePreference::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::MessagePreference::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::MessagePreference->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::MessagePreference::Transport::Preference->new({ >+ borrower_message_preference_id => $default->borrower_message_preference_id, >+ message_transport_type => $mtt1->message_transport_type, >+ })->store; >+ Koha::Patron::MessagePreference::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::MessagePreferences->search({ >+ borrowernumber => $patron->borrowernumber >+ })->next, $mtt1, $mtt2); >+} >-- >2.30.2
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