Bugzilla – Attachment 103508 Details for
Bug 17268
Advanced cataloging editor - rancor - macros are lost when browser storage cleared
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 17268: Advanced cataloging editor macros - add endpoint
Bug-17268-Advanced-cataloging-editor-macros---add-.patch (text/plain), 52.77 KB, created by
Nick Clemens (kidclamp)
on 2020-04-22 21:15:31 UTC
(
hide
)
Description:
Bug 17268: Advanced cataloging editor macros - add endpoint
Filename:
MIME Type:
Creator:
Nick Clemens (kidclamp)
Created:
2020-04-22 21:15:31 UTC
Size:
52.77 KB
patch
obsolete
>From d356fd6af320317ea94b058709370b51e2deb699 Mon Sep 17 00:00:00 2001 >From: Nick Clemens <nick@bywatersolutions.com> >Date: Wed, 4 Dec 2019 11:39:41 +0000 >Subject: [PATCH] Bug 17268: Advanced cataloging editor macros - add endpoint > >Bug 17268: Make shared macros use their own path > >Bug 17268: Update API to use shared instead of public > >Bug 17268: (follow-up) Update API field definition to boolean > >Signed-off-by: Andrew Fuerste-Henry <andrew@bywatersolutions.com> > >Signed-off-by: Heather Hernandez <Heather_Hernandez@nps.gov> >--- > Koha/AdvancedEditorMacro.pm | 57 +++ > Koha/AdvancedEditorMacros.pm | 50 ++ > Koha/REST/V1/AdvancedEditorMacro.pm | 397 ++++++++++++++++ > api/v1/swagger/definitions.json | 3 + > .../swagger/definitions/advancededitormacro.json | 26 + > api/v1/swagger/parameters.json | 3 + > api/v1/swagger/parameters/advancededitormacro.json | 9 + > api/v1/swagger/paths.json | 12 + > api/v1/swagger/paths/advancededitormacros.json | 521 +++++++++++++++++++++ > api/v1/swagger/x-primitives.json | 5 + > t/db_dependent/api/v1/advanced_editor_macros.t | 475 +++++++++++++++++++ > 11 files changed, 1558 insertions(+) > create mode 100644 Koha/AdvancedEditorMacro.pm > create mode 100644 Koha/AdvancedEditorMacros.pm > create mode 100644 Koha/REST/V1/AdvancedEditorMacro.pm > create mode 100644 api/v1/swagger/definitions/advancededitormacro.json > create mode 100644 api/v1/swagger/parameters/advancededitormacro.json > create mode 100644 api/v1/swagger/paths/advancededitormacros.json > create mode 100644 t/db_dependent/api/v1/advanced_editor_macros.t > >diff --git a/Koha/AdvancedEditorMacro.pm b/Koha/AdvancedEditorMacro.pm >new file mode 100644 >index 0000000000..d30fcc5f16 >--- /dev/null >+++ b/Koha/AdvancedEditorMacro.pm >@@ -0,0 +1,57 @@ >+package Koha::AdvancedEditorMacro; >+ >+# 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 Carp; >+ >+use Koha::Database; >+ >+use base qw(Koha::Object); >+ >+=head1 NAME >+ >+Koha::AdvancedEditorMacro - Koha Advanced Editor Macro Object class >+ >+=head1 API >+ >+=head2 Class methods >+ >+=head3 to_api_mapping >+ >+=cut >+ >+sub to_api_mapping { >+ return { >+ id => 'macro_id', >+ macro => 'macro_text', >+ borrowernumber => 'patron_id', >+ }; >+} >+ >+ >+=head2 Internal methods >+ >+=head3 _type >+ >+=cut >+ >+sub _type { >+ return 'AdvancedEditorMacro'; >+} >+ >+1; >diff --git a/Koha/AdvancedEditorMacros.pm b/Koha/AdvancedEditorMacros.pm >new file mode 100644 >index 0000000000..67d44281a1 >--- /dev/null >+++ b/Koha/AdvancedEditorMacros.pm >@@ -0,0 +1,50 @@ >+package Koha::AdvancedEditorMacros; >+ >+# 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 Carp; >+ >+use Koha::Database; >+ >+use Koha::AdvancedEditorMacro; >+ >+use base qw(Koha::Objects); >+ >+=head1 NAME >+ >+Koha::AdvancedEditorMacros - Koha Advanced Editor Macro Object set class >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 type >+ >+=cut >+ >+sub _type { >+ return 'AdvancedEditorMacro'; >+} >+ >+sub object_class { >+ return 'Koha::AdvancedEditorMacro'; >+} >+ >+1; >diff --git a/Koha/REST/V1/AdvancedEditorMacro.pm b/Koha/REST/V1/AdvancedEditorMacro.pm >new file mode 100644 >index 0000000000..92f6730c2a >--- /dev/null >+++ b/Koha/REST/V1/AdvancedEditorMacro.pm >@@ -0,0 +1,397 @@ >+package Koha::REST::V1::AdvancedEditorMacro; >+ >+# 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::AdvancedEditorMacros; >+ >+use Try::Tiny; >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 list >+ >+Controller function that handles listing Koha::AdvancedEditorMacro objects >+ >+=cut >+ >+sub list { >+ my $c = shift->openapi->valid_input or return; >+ my $patron = $c->stash('koha.user'); >+ return try { >+ my $macros_set = Koha::AdvancedEditorMacros->search({ -or => { shared => 1, borrowernumber => $patron->borrowernumber } }); >+ my $macros = $c->objects->search( $macros_set, \&_to_model, \&_to_api ); >+ return $c->render( status => 200, openapi => $macros ); >+ } >+ 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. $_"} ); >+ } >+ }; >+ >+} >+ >+=head3 get >+ >+Controller function that handles retrieving a single Koha::AdvancedEditorMacro >+ >+=cut >+ >+sub get { >+ my $c = shift->openapi->valid_input or return; >+ my $patron = $c->stash('koha.user'); >+ my $macro = Koha::AdvancedEditorMacros->find({ >+ id => $c->validation->param('advancededitormacro_id'), >+ }); >+ unless ($macro) { >+ return $c->render( status => 404, >+ openapi => { error => "Macro not found" } ); >+ } >+ if( $macro->shared ){ >+ return $c->render( status => 403, openapi => { >+ error => "This macro is shared, you must access it via advancededitormacros/shared" >+ }); >+ } >+ warn $macro->borrowernumber; >+ warn $patron->borrowernumber; >+ if( $macro->borrowernumber != $patron->borrowernumber ){ >+ return $c->render( status => 403, openapi => { >+ error => "You do not have permission to access this macro" >+ }); >+ } >+ >+ return $c->render( status => 200, openapi => $macro->to_api ); >+} >+ >+=head3 get_shared >+ >+Controller function that handles retrieving a single Koha::AdvancedEditorMacro >+ >+=cut >+ >+sub get_shared { >+ my $c = shift->openapi->valid_input or return; >+ my $patron = $c->stash('koha.user'); >+ my $macro = Koha::AdvancedEditorMacros->find({ >+ id => $c->validation->param('advancededitormacro_id'), >+ }); >+ unless ($macro) { >+ return $c->render( status => 404, >+ openapi => { error => "Macro not found" } ); >+ } >+ unless( $macro->shared ){ >+ return $c->render( status => 403, openapi => { >+ error => "This macro is not shared, you must access it via advancededitormacros" >+ }); >+ } >+ return $c->render( status => 200, openapi => $macro->to_api ); >+} >+ >+=head3 add >+ >+Controller function that handles adding a new Koha::AdvancedEditorMacro object >+ >+=cut >+ >+sub add { >+ my $c = shift->openapi->valid_input or return; >+ >+ if( defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){ >+ return $c->render( status => 403, >+ openapi => { error => "To create shared macros you must use advancededitor/shared" } ); >+ } >+ >+ return try { >+ my $macro = Koha::AdvancedEditorMacro->new( _to_model( $c->validation->param('body') ) ); >+ $macro->store; >+ $c->res->headers->location( $c->req->url->to_string . '/' . $macro->id ); >+ return $c->render( >+ status => 201, >+ openapi => $macro->to_api >+ ); >+ } >+ catch { handle_error($_) }; >+} >+ >+=head3 add_shared >+ >+Controller function that handles adding a new shared Koha::AdvancedEditorMacro object >+ >+=cut >+ >+sub add_shared { >+ my $c = shift->openapi->valid_input or return; >+ >+ unless( defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){ >+ return $c->render( status => 403, >+ openapi => { error => "To create private macros you must use advancededitor" } ); >+ } >+ >+ return try { >+ my $macro = Koha::AdvancedEditorMacro->new( _to_model( $c->validation->param('body') ) ); >+ $macro->store; >+ $c->res->headers->location( $c->req->url->to_string . '/' . $macro->id ); >+ return $c->render( >+ status => 201, >+ openapi => $macro->to_api >+ ); >+ } >+ catch { handle_error($_) }; >+} >+ >+=head3 update >+ >+Controller function that handles updating a Koha::AdvancedEditorMacro object >+ >+=cut >+ >+sub update { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') ); >+ >+ if ( not defined $macro ) { >+ return $c->render( status => 404, >+ openapi => { error => "Object not found" } ); >+ } >+ my $patron = $c->stash('koha.user'); >+ >+ if( $macro->shared == 1 || defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){ >+ return $c->render( status => 403, >+ openapi => { error => "To update a macro as shared you must use the advancededitormacros/shared endpoint" } ); >+ } else { >+ unless ( $macro->borrowernumber == $patron->borrowernumber ){ >+ return $c->render( status => 403, >+ openapi => { error => "You can only edit macros you own" } ); >+ } >+ } >+ >+ return try { >+ my $params = $c->req->json; >+ $macro->set( _to_model($params) ); >+ $macro->store(); >+ return $c->render( status => 200, openapi => $macro->to_api ); >+ } >+ catch { handle_error($_) }; >+} >+ >+=head3 update_shared >+ >+Controller function that handles updating a shared Koha::AdvancedEditorMacro object >+ >+=cut >+ >+sub update_shared { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') ); >+ >+ if ( not defined $macro ) { >+ return $c->render( status => 404, >+ openapi => { error => "Object not found" } ); >+ } >+ >+ unless( $macro->shared == 1 || defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){ >+ return $c->render( status => 403, >+ openapi => { error => "You can only update shared macros using this endpoint" } ); >+ } >+ >+ return try { >+ my $params = $c->req->json; >+ $macro->set( _to_model($params) ); >+ $macro->store(); >+ return $c->render( status => 200, openapi => $macro->to_api ); >+ } >+ catch { handle_error($_) }; >+} >+ >+=head3 delete >+ >+Controller function that handles deleting a Koha::AdvancedEditorMacro object >+ >+=cut >+ >+sub delete { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') ); >+ if ( not defined $macro ) { >+ return $c->render( status => 404, >+ openapi => { error => "Object not found" } ); >+ } >+ >+ my $patron = $c->stash('koha.user'); >+ if( $macro->shared == 1 ){ >+ return $c->render( status => 403, >+ openapi => { error => "You cannot delete shared macros using this endpoint" } ); >+ } else { >+ unless ( $macro->borrowernumber == $patron->borrowernumber ){ >+ return $c->render( status => 403, >+ openapi => { error => "You can only delete macros you own" } ); >+ } >+ } >+ >+ return try { >+ $macro->delete; >+ return $c->render( status => 200, openapi => "" ); >+ } >+ catch { handle_error($_) }; >+} >+ >+=head3 delete_shared >+ >+Controller function that handles deleting a shared Koha::AdvancedEditorMacro object >+ >+=cut >+ >+sub delete_shared { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') ); >+ if ( not defined $macro ) { >+ return $c->render( status => 404, >+ openapi => { error => "Object not found" } ); >+ } >+ >+ unless( $macro->shared == 1 ){ >+ return $c->render( status => 403, >+ openapi => { error => "You can only delete shared macros using this endpoint" } ); >+ } >+ >+ return try { >+ $macro->delete; >+ return $c->render( status => 200, openapi => "" ); >+ } >+ catch { handle_error($_,$c) }; >+} >+ >+=head3 _handle_error >+ >+Helper function that passes exception or error >+ >+=cut >+ >+sub _handle_error { >+ my ($err,$c) = @_; >+ if ( $err->isa('DBIx::Class::Exception') ) { >+ return $c->render( status => 500, >+ openapi => { error => $err->{msg} } ); >+ } >+ else { >+ return $c->render( status => 500, >+ openapi => { error => "Something went wrong, check the logs."} ); >+ } >+}; >+ >+ >+=head3 _to_api >+ >+Helper function that maps a hashref of Koha::AdvancedEditorMacro attributes into REST api >+attribute names. >+ >+=cut >+ >+sub _to_api { >+ my $macro = shift; >+ >+ # Rename attributes >+ foreach my $column ( keys %{ $Koha::REST::V1::AdvancedEditorMacro::to_api_mapping } ) { >+ my $mapped_column = $Koha::REST::V1::AdvancedEditorMacro::to_api_mapping->{$column}; >+ if ( exists $macro->{ $column } >+ && defined $mapped_column ) >+ { >+ # key /= undef >+ $macro->{ $mapped_column } = delete $macro->{ $column }; >+ } >+ elsif ( exists $macro->{ $column } >+ && !defined $mapped_column ) >+ { >+ # key == undef => to be deleted >+ delete $macro->{ $column }; >+ } >+ } >+ >+ return $macro; >+} >+ >+=head3 _to_model >+ >+Helper function that maps REST api objects into Koha::AdvancedEditorMacros >+attribute names. >+ >+=cut >+ >+sub _to_model { >+ my $macro = shift; >+ >+ foreach my $attribute ( keys %{ $Koha::REST::V1::AdvancedEditorMacro::to_model_mapping } ) { >+ my $mapped_attribute = $Koha::REST::V1::AdvancedEditorMacro::to_model_mapping->{$attribute}; >+ if ( exists $macro->{ $attribute } >+ && defined $mapped_attribute ) >+ { >+ # key /= undef >+ $macro->{ $mapped_attribute } = delete $macro->{ $attribute }; >+ } >+ elsif ( exists $macro->{ $attribute } >+ && !defined $mapped_attribute ) >+ { >+ # key == undef => to be deleted >+ delete $macro->{ $attribute }; >+ } >+ } >+ >+ if ( exists $macro->{shared} ) { >+ $macro->{shared} = ($macro->{shared}) ? 1 : 0; >+ } >+ >+ >+ return $macro; >+} >+ >+=head2 Global variables >+ >+=head3 $to_api_mapping >+ >+=cut >+ >+our $to_api_mapping = { >+ id => 'macro_id', >+ macro => 'macro_text', >+ borrowernumber => 'patron_id', >+}; >+ >+=head3 $to_model_mapping >+ >+=cut >+ >+our $to_model_mapping = { >+ macro_id => 'id', >+ macro_text => 'macro', >+ patron_id => 'borrowernumber', >+}; >+ >+1; >diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json >index 4b21d32f32..716e8703b6 100644 >--- a/api/v1/swagger/definitions.json >+++ b/api/v1/swagger/definitions.json >@@ -47,6 +47,9 @@ > "order": { > "$ref": "definitions/order.json" > }, >+ "advancededitormacro": { >+ "$ref": "definitions/advancededitormacro.json" >+ }, > "patron": { > "$ref": "definitions/patron.json" > }, >diff --git a/api/v1/swagger/definitions/advancededitormacro.json b/api/v1/swagger/definitions/advancededitormacro.json >new file mode 100644 >index 0000000000..46e6eebee9 >--- /dev/null >+++ b/api/v1/swagger/definitions/advancededitormacro.json >@@ -0,0 +1,26 @@ >+{ >+ "type": "object", >+ "properties": { >+ "macro_id": { >+ "$ref": "../x-primitives.json#/advancededitormacro_id" >+ }, >+ "name": { >+ "description": "macro name", >+ "type": "string" >+ }, >+ "macro_text": { >+ "description": "macro text", >+ "type": ["string", "null"] >+ }, >+ "patron_id": { >+ "description": "borrower number", >+ "type": ["integer", "null"] >+ }, >+ "shared": { >+ "description": "is macro shared", >+ "type": ["boolean", "null"] >+ } >+ }, >+ "additionalProperties": false, >+ "required": ["name", "macro_text", "patron_id", "shared"] >+} >diff --git a/api/v1/swagger/parameters.json b/api/v1/swagger/parameters.json >index 9c3d7ebc96..cab2d53b47 100644 >--- a/api/v1/swagger/parameters.json >+++ b/api/v1/swagger/parameters.json >@@ -2,6 +2,9 @@ > "biblio_id_pp": { > "$ref": "parameters/biblio.json#/biblio_id_pp" > }, >+ "advancededitormacro_id_pp": { >+ "$ref": "parameters/advancededitormacro.json#/advancededitormacro_id_pp" >+ }, > "patron_id_pp": { > "$ref": "parameters/patron.json#/patron_id_pp" > }, >diff --git a/api/v1/swagger/parameters/advancededitormacro.json b/api/v1/swagger/parameters/advancededitormacro.json >new file mode 100644 >index 0000000000..482e0bc917 >--- /dev/null >+++ b/api/v1/swagger/parameters/advancededitormacro.json >@@ -0,0 +1,9 @@ >+{ >+ "advancededitormacro_id_pp": { >+ "name": "advancededitormacro_id", >+ "in": "path", >+ "description": "Advanced Editor Macro internal identifier", >+ "required": true, >+ "type": "integer" >+ } >+} >diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json >index 0631ecb53b..f46e741821 100644 >--- a/api/v1/swagger/paths.json >+++ b/api/v1/swagger/paths.json >@@ -68,6 +68,18 @@ > "/checkouts/{checkout_id}/allows_renewal": { > "$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}~1allows_renewal" > }, >+ "/advancededitormacros": { >+ "$ref": "paths/advancededitormacros.json#/~1advancededitormacros" >+ }, >+ "/advancededitormacros/{advancededitormacro_id}": { >+ "$ref": "paths/advancededitormacros.json#/~1advancededitormacros~1{advancededitormacro_id}" >+ }, >+ "/advancededitormacros/shared": { >+ "$ref": "paths/advancededitormacros.json#/~1advancededitormacros~1shared" >+ }, >+ "/advancededitormacros/shared/{advancededitormacro_id}": { >+ "$ref": "paths/advancededitormacros.json#/~1advancededitormacros~1shared~1{advancededitormacro_id}" >+ }, > "/patrons": { > "$ref": "paths/patrons.json#/~1patrons" > }, >diff --git a/api/v1/swagger/paths/advancededitormacros.json b/api/v1/swagger/paths/advancededitormacros.json >new file mode 100644 >index 0000000000..7c7eb93aaa >--- /dev/null >+++ b/api/v1/swagger/paths/advancededitormacros.json >@@ -0,0 +1,521 @@ >+{ >+ "/advancededitormacros": { >+ "get": { >+ "x-mojo-to": "AdvancedEditorMacro#list", >+ "operationId": "listMacro", >+ "tags": ["advancededitormacro"], >+ "produces": [ >+ "application/json" >+ ], >+ "parameters": [ >+ { >+ "name": "name", >+ "in": "query", >+ "description": "Case insensative search on macro name", >+ "required": false, >+ "type": "string" >+ }, >+ { >+ "name": "macro_text", >+ "in": "query", >+ "description": "Case insensative search on macro text", >+ "required": false, >+ "type": "string" >+ }, >+ { >+ "name": "patron_id", >+ "in": "query", >+ "description": "Search on internal patron_id", >+ "required": false, >+ "type": "string" >+ }, >+ { >+ "name": "shared", >+ "in": "query", >+ "description": "Search on shared macros", >+ "required": false, >+ "type": "string" >+ } >+ ], >+ "responses": { >+ "200": { >+ "description": "A list of macros", >+ "schema": { >+ "type": "array", >+ "items": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ } >+ }, >+ "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": { >+ "editcatalogue": "advanced_editor" >+ } >+ } >+ }, >+ "post": { >+ "x-mojo-to": "AdvancedEditorMacro#add", >+ "operationId": "addAdvancedEditorMacro", >+ "tags": ["advancededitormacro"], >+ "parameters": [{ >+ "name": "body", >+ "in": "body", >+ "description": "A JSON object containing informations about the new macro", >+ "required": true, >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "201": { >+ "description": "Macro added", >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }, >+ "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": { >+ "editcatalogue": "advanced_editor" >+ } >+ } >+ } >+ }, >+ "/advancededitormacros/shared": { >+ "post": { >+ "x-mojo-to": "AdvancedEditorMacro#add_shared", >+ "operationId": "addsharedAdvancedEditorMacro", >+ "tags": ["advancededitormacro"], >+ "parameters": [{ >+ "name": "body", >+ "in": "body", >+ "description": "A JSON object containing informations about the new macro", >+ "required": true, >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "201": { >+ "description": "Macro added", >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }, >+ "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": { >+ "editcatalogue": "advanced_editor", >+ "editcatalogue": "create_shared_macros" >+ } >+ } >+ } >+ }, >+ "/advancededitormacros/{advancededitormacro_id}": { >+ "get": { >+ "x-mojo-to": "AdvancedEditorMacro#get", >+ "operationId": "getAdvancedEditorMacro", >+ "tags": ["advancededitormacros"], >+ "parameters": [{ >+ "$ref": "../parameters.json#/advancededitormacro_id_pp" >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "A macro", >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "AdvancedEditorMacro 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": { >+ "editcatalogue": "advanced_editor" >+ } >+ } >+ }, >+ "put": { >+ "x-mojo-to": "AdvancedEditorMacro#update", >+ "operationId": "updateAdvancedEditorMacro", >+ "tags": ["advancededitormacros"], >+ "parameters": [{ >+ "$ref": "../parameters.json#/advancededitormacro_id_pp" >+ }, { >+ "name": "body", >+ "in": "body", >+ "description": "An advanced editor macro object", >+ "required": true, >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "An advanced editor macro", >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Macro 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": { >+ "editcatalogue": "advanced_editor" >+ } >+ } >+ }, >+ "delete": { >+ "x-mojo-to": "AdvancedEditorMacro#delete", >+ "operationId": "deleteAdvancedEditorMacro", >+ "tags": ["advancededitormacros"], >+ "parameters": [{ >+ "$ref": "../parameters.json#/advancededitormacro_id_pp" >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "Advanced editor macro deleted", >+ "schema": { >+ "type": "string" >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Macro 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": { >+ "editcatalogue": "advanced_editor" >+ } >+ } >+ } >+ }, >+ "/advancededitormacros/shared/{advancededitormacro_id}": { >+ "get": { >+ "x-mojo-to": "AdvancedEditorMacro#get_shared", >+ "operationId": "getsharedAdvancedEditorMacro", >+ "tags": ["advancededitormacros"], >+ "parameters": [{ >+ "$ref": "../parameters.json#/advancededitormacro_id_pp" >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "A macro", >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "AdvancedEditorMacro 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": { >+ "editcatalogue": "advanced_editor" >+ } >+ } >+ }, >+ "put": { >+ "x-mojo-to": "AdvancedEditorMacro#update_shared", >+ "operationId": "updatesharedAdvancedEditorMacro", >+ "tags": ["advancededitormacros"], >+ "parameters": [{ >+ "$ref": "../parameters.json#/advancededitormacro_id_pp" >+ }, { >+ "name": "body", >+ "in": "body", >+ "description": "An advanced editor macro object", >+ "required": true, >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "An advanced editor macro", >+ "schema": { >+ "$ref": "../definitions.json#/advancededitormacro" >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Macro 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": { >+ "editcatalogue": "advanced_editor", >+ "editcatalogue": "create_shared_macros" >+ } >+ } >+ }, >+ "delete": { >+ "x-mojo-to": "AdvancedEditorMacro#delete_shared", >+ "operationId": "deletesharedAdvancedEditorMacro", >+ "tags": ["advancededitormacros"], >+ "parameters": [{ >+ "$ref": "../parameters.json#/advancededitormacro_id_pp" >+ }], >+ "produces": [ >+ "application/json" >+ ], >+ "responses": { >+ "200": { >+ "description": "Advanced editor macro deleted", >+ "schema": { >+ "type": "string" >+ } >+ }, >+ "401": { >+ "description": "Authentication required", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Macro 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": { >+ "editcatalogue": "advanced_editor", >+ "editcatalogue": "delete_shared_macros" >+ } >+ } >+ } >+ } >+} >diff --git a/api/v1/swagger/x-primitives.json b/api/v1/swagger/x-primitives.json >index 19bc8dc012..0594264be9 100644 >--- a/api/v1/swagger/x-primitives.json >+++ b/api/v1/swagger/x-primitives.json >@@ -3,6 +3,11 @@ > "type": "integer", > "description": "Internal biblio identifier" > }, >+ "advancededitormacro_id": { >+ "type": "integer", >+ "description": "Internal advanced editor macro identifier", >+ "readOnly": true >+ }, > "patron_id": { > "type": "integer", > "description": "Internal patron identifier" >diff --git a/t/db_dependent/api/v1/advanced_editor_macros.t b/t/db_dependent/api/v1/advanced_editor_macros.t >new file mode 100644 >index 0000000000..025c73fa2d >--- /dev/null >+++ b/t/db_dependent/api/v1/advanced_editor_macros.t >@@ -0,0 +1,475 @@ >+#!/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 Koha::AdvancedEditorMacros; >+use Koha::Database; >+ >+my $schema = Koha::Database->new->schema; >+my $builder = t::lib::TestBuilder->new; >+ >+t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); >+ >+my $t = Test::Mojo->new('Koha::REST::V1'); >+ >+$schema->storage->txn_begin; >+ >+subtest 'list() tests' => sub { >+ plan tests => 8; >+ >+ >+ my $patron_1 = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 9 } >+ }); >+ my $patron_2 = $builder->build_object({ >+ class => 'Koha::Patrons', >+ }); >+ my $password = 'thePassword123'; >+ $patron_1->set_password({ password => $password, skip_validation => 1 }); >+ my $userid = $patron_1->userid; >+ >+ # Create test context >+ my $macro_1 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value => >+ { >+ name => 'Test1', >+ macro => 'delete 100', >+ borrowernumber => $patron_1->borrowernumber, >+ } >+ }); >+ my $macro_2 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value => >+ { >+ name => 'Test2', >+ macro => 'delete 100', >+ borrowernumber => $patron_1->borrowernumber, >+ shared=> 1, >+ } >+ }); >+ my $macro_3 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value => >+ { >+ name => 'Test3', >+ macro => 'delete 100', >+ borrowernumber => $patron_2->borrowernumber, >+ } >+ }); >+ my $macro_4 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value => >+ { >+ name => 'Test4', >+ macro => 'delete 100', >+ borrowernumber => $patron_2->borrowernumber, >+ shared => 1, >+ } >+ }); >+ >+ my $macros_index = Koha::AdvancedEditorMacros->search({ -or => { shared => 1, borrowernumber => $patron_1->borrowernumber } })->count-1; >+ ## Authorized user tests >+ # Make sure we are returned with the correct amount of macros >+ $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros" ) >+ ->status_is( 200, 'SWAGGER3.2.2' ) >+ ->json_has('/' . $macros_index . '/macro_id') >+ ->json_hasnt('/' . ($macros_index + 1) . '/macro_id'); >+ >+ subtest 'query parameters' => sub { >+ >+ plan tests => 15; >+ $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?name=" . $macro_2->name) >+ ->status_is(200) >+ ->json_has( [ $macro_2 ] ); >+ $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?name=" . $macro_3->name) >+ ->status_is(200) >+ ->json_has( [ ] ); >+ $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?macro_text=delete 100") >+ ->status_is(200) >+ ->json_has( [ $macro_1, $macro_2, $macro_4 ] ); >+ $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?patron_id=" . $patron_1->borrowernumber) >+ ->status_is(200) >+ ->json_has( [ $macro_1, $macro_2 ] ); >+ $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?shared=1") >+ ->status_is(200) >+ ->json_has( [ $macro_2, $macro_4 ] ); >+ }; >+ >+ # Warn on unsupported query parameter >+ $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros?macro_blah=blah" ) >+ ->status_is(400) >+ ->json_is( [{ path => '/query/macro_blah', message => 'Malformed query string'}] ); >+ >+}; >+ >+subtest 'get() tests' => sub { >+ >+ plan tests => 15; >+ >+ my $patron = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 1 } >+ }); >+ my $password = 'thePassword123'; >+ $patron->set_password({ password => $password, skip_validation => 1 }); >+ my $userid = $patron->userid; >+ >+ my $macro_1 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => { >+ shared => 1, >+ } >+ }); >+ my $macro_2 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => { >+ shared => 0, >+ } >+ }); >+ my $macro_3 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => { >+ borrowernumber => $patron->borrowernumber, >+ shared => 0, >+ } >+ }); >+ >+ $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $macro_1->id ) >+ ->status_is( 403, 'Cannot get a shared macro via regular endpoint' ) >+ ->json_is( '/error' => 'This macro is shared, you must access it via advancededitormacros/shared' ); >+ >+ $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/shared/" . $macro_1->id ) >+ ->status_is( 200, 'Can get a shared macro via shared endpoint' ) >+ ->json_is( '' => Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro_1->TO_JSON ), 'Macro correctly retrieved' ); >+ >+ $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $macro_2->id ) >+ ->status_is( 403, 'Cannot access another users macro' ) >+ ->json_is( '/error' => 'You do not have permission to access this macro' ); >+ >+ $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $macro_3->id ) >+ ->status_is( 200, 'Can get your own private macro' ) >+ ->json_is( '' => Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro_3->TO_JSON ), 'Macro correctly retrieved' ); >+ >+ my $non_existent_code = $macro_1->id; >+ $macro_1->delete; >+ >+ $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $non_existent_code ) >+ ->status_is(404) >+ ->json_is( '/error' => 'Macro not found' ); >+ >+}; >+ >+subtest 'add() tests' => sub { >+ >+ plan tests => 24; >+ >+ my $authorized_patron = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 0 } >+ }); >+ $builder->build({ >+ source => 'UserPermission', >+ value => { >+ borrowernumber => $authorized_patron->borrowernumber, >+ module_bit => 9, >+ code => 'advanced_editor', >+ }, >+ }); >+ >+ my $password = 'thePassword123'; >+ $authorized_patron->set_password({ password => $password, skip_validation => 1 }); >+ my $auth_userid = $authorized_patron->userid; >+ >+ my $unauthorized_patron = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 0 } >+ }); >+ $unauthorized_patron->set_password({ password => $password, skip_validation => 1 }); >+ my $unauth_userid = $unauthorized_patron->userid; >+ >+ my $macro = $builder->build_object({ >+ class => 'Koha::AdvancedEditorMacros', >+ value => { shared => 0 } >+ }); >+ my $macro_values = Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro->TO_JSON ); >+ delete $macro_values->{macro_id}; >+ $macro->delete; >+ >+ # Unauthorized attempt to write >+ $t->post_ok( "//$unauth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values ) >+ ->status_is(403); >+ >+ # Authorized attempt to write invalid data >+ my $macro_with_invalid_field = { %$macro_values }; >+ $macro_with_invalid_field->{'big_mac_ro'} = 'Mac attack'; >+ >+ $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_with_invalid_field ) >+ ->status_is(400) >+ ->json_is( >+ "/errors" => [ >+ { >+ message => "Properties not allowed: big_mac_ro.", >+ path => "/body" >+ } >+ ] >+ ); >+ >+ # Authorized attempt to write >+ $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values ) >+ ->status_is( 201, 'SWAGGER3.2.1' ) >+ ->json_has( '/macro_id', 'We generated a new id' ) >+ ->json_is( '/name' => $macro_values->{name}, 'The name matches what we supplied' ) >+ ->json_is( '/macro_text' => $macro_values->{macro_text}, 'The text matches what we supplied' ) >+ ->json_is( '/patron_id' => $macro_values->{patron_id}, 'The borrower matches the borrower who submitted' ) >+ ->json_is( '/shared' => 0, 'The macro is not shared' ) >+ ->header_like( Location => qr|^\/api\/v1\/advancededitormacros\/d*|, 'Correct location' ); >+ >+ # save the library_id >+ my $macro_id = 999; >+ >+ # Authorized attempt to create with existing id >+ $macro_values->{macro_id} = $macro_id; >+ >+ $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values ) >+ ->status_is(400) >+ ->json_is( '/errors' => [ >+ { >+ message => "Read-only.", >+ path => "/body/macro_id" >+ } >+ ] >+ ); >+ >+ $macro_values->{shared} = 1; >+ delete $macro_values->{macro_id}; >+ >+ # Unauthorized attempt to write a shared macro on private endpoint >+ $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values ) >+ ->status_is(403); >+ # Unauthorized attempt to write a private macro on shared endpoint >+ $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared" => json => $macro_values ) >+ ->status_is(403); >+ >+ $builder->build({ >+ source => 'UserPermission', >+ value => { >+ borrowernumber => $authorized_patron->borrowernumber, >+ module_bit => 9, >+ code => 'create_shared_macros', >+ }, >+ }); >+ >+ # Authorized attempt to write a shared macro on private endpoint >+ $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values ) >+ ->status_is(403); >+ >+ # Authorized attempt to write a shared macro on shared endpoint >+ $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared" => json => $macro_values ) >+ ->status_is(201); >+ >+}; >+ >+subtest 'update() tests' => sub { >+ plan tests => 32; >+ >+ my $authorized_patron = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 0 } >+ }); >+ $builder->build({ >+ source => 'UserPermission', >+ value => { >+ borrowernumber => $authorized_patron->borrowernumber, >+ module_bit => 9, >+ code => 'advanced_editor', >+ }, >+ }); >+ >+ my $password = 'thePassword123'; >+ $authorized_patron->set_password({ password => $password, skip_validation => 1 }); >+ my $auth_userid = $authorized_patron->userid; >+ >+ my $unauthorized_patron = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 0 } >+ }); >+ $unauthorized_patron->set_password({ password => $password, skip_validation => 1 }); >+ my $unauth_userid = $unauthorized_patron->userid; >+ >+ my $macro = $builder->build_object({ >+ class => 'Koha::AdvancedEditorMacros', >+ value => { borrowernumber => $authorized_patron->borrowernumber, shared => 0 } >+ }); >+ my $macro_2 = $builder->build_object({ >+ class => 'Koha::AdvancedEditorMacros', >+ value => { borrowernumber => $unauthorized_patron->borrowernumber, shared => 0 } >+ }); >+ my $macro_id = $macro->id; >+ my $macro_2_id = $macro_2->id; >+ my $macro_values = Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro->TO_JSON ); >+ delete $macro_values->{macro_id}; >+ >+ # Unauthorized attempt to update >+ $t->put_ok( "//$unauth_userid:$password@/api/v1/advancededitormacros/$macro_id" >+ => json => { name => 'New unauthorized name change' } ) >+ ->status_is(403); >+ >+ # Attempt partial update on a PUT >+ my $macro_with_missing_field = { >+ name => "Call it macro-roni", >+ }; >+ >+ $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_with_missing_field ) >+ ->status_is(400) >+ ->json_has( "/errors" => >+ [ { message => "Missing property.", path => "/body/macro_text" } ] >+ ); >+ >+ my $macro_update = { >+ name => "Macro-update", >+ macro_text => "delete 100", >+ patron_id => $authorized_patron->borrowernumber, >+ shared => 0, >+ }; >+ >+ my $test = $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_update ) >+ ->status_is(200, 'Authorized user can update a macro') >+ ->json_is( '/macro_id' => $macro_id, 'We get the id back' ) >+ ->json_is( '/name' => $macro_update->{name}, 'We get the name back' ) >+ ->json_is( '/macro_text' => $macro_update->{macro_text}, 'We get the text back' ) >+ ->json_is( '/patron_id' => $macro_update->{patron_id}, 'We get the patron_id back' ) >+ ->json_is( '/shared' => $macro_update->{shared}, 'It should still not be shared' ); >+ >+ # Now try to make the macro shared >+ $macro_update->{shared} = 1; >+ >+ $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_id" => json => $macro_update ) >+ ->status_is(403, 'Cannot make your macro shared on private endpoint'); >+ $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_id" => json => $macro_update ) >+ ->status_is(403, 'Cannot make your macro shared without permission'); >+ >+ $builder->build({ >+ source => 'UserPermission', >+ value => { >+ borrowernumber => $authorized_patron->borrowernumber, >+ module_bit => 9, >+ code => 'create_shared_macros', >+ }, >+ }); >+ >+ $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_update ) >+ ->status_is(403, 'Cannot make your macro shared on the private endpoint'); >+ >+ $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_id" => json => $macro_update ) >+ ->status_is(200, 'Can update macro to shared with permission') >+ ->json_is( '/macro_id' => $macro_id, 'We get back the id' ) >+ ->json_is( '/name' => $macro_update->{name}, 'We get back the name' ) >+ ->json_is( '/macro_text' => $macro_update->{macro_text}, 'We get back the text' ) >+ ->json_is( '/patron_id' => $macro_update->{patron_id}, 'We get back our patron id' ) >+ ->json_is( '/shared' => 1, 'It is shared' ); >+ >+ # Authorized attempt to write invalid data >+ my $macro_with_invalid_field = { %$macro_update }; >+ $macro_with_invalid_field->{'big_mac_ro'} = 'Mac attack'; >+ >+ $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_with_invalid_field ) >+ ->status_is(400) >+ ->json_is( >+ "/errors" => [ >+ { >+ message => "Properties not allowed: big_mac_ro.", >+ path => "/body" >+ } >+ ] >+ ); >+ >+ my $non_existent_macro = $builder->build_object({class => 'Koha::AdvancedEditorMacros'}); >+ my $non_existent_code = $non_existent_macro->id; >+ $non_existent_macro->delete; >+ >+ $t->put_ok("//$auth_userid:$password@/api/v1/advancededitormacros/$non_existent_code" => json => $macro_update) >+ ->status_is(404); >+ >+ $t->put_ok("//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id" => json => $macro_update) >+ ->status_is(403, "Cannot update other borrowers private macro"); >+}; >+ >+subtest 'delete() tests' => sub { >+ plan tests => 12; >+ >+ my $authorized_patron = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 0 } >+ }); >+ $builder->build({ >+ source => 'UserPermission', >+ value => { >+ borrowernumber => $authorized_patron->borrowernumber, >+ module_bit => 9, >+ code => 'advanced_editor', >+ }, >+ }); >+ >+ my $password = 'thePassword123'; >+ $authorized_patron->set_password({ password => $password, skip_validation => 1 }); >+ my $auth_userid = $authorized_patron->userid; >+ >+ my $unauthorized_patron = $builder->build_object({ >+ class => 'Koha::Patrons', >+ value => { flags => 0 } >+ }); >+ $unauthorized_patron->set_password({ password => $password, skip_validation => 1 }); >+ my $unauth_userid = $unauthorized_patron->userid; >+ >+ my $macro = $builder->build_object({ >+ class => 'Koha::AdvancedEditorMacros', >+ value => { borrowernumber => $authorized_patron->borrowernumber, shared => 0 } >+ }); >+ my $macro_2 = $builder->build_object({ >+ class => 'Koha::AdvancedEditorMacros', >+ value => { borrowernumber => $unauthorized_patron->borrowernumber, shared => 0 } >+ }); >+ my $macro_id = $macro->id; >+ my $macro_2_id = $macro_2->id; >+ >+ # Unauthorized attempt to delete >+ $t->delete_ok( "//$unauth_userid:$password@/api/v1/advancededitormacros/$macro_2_id") >+ ->status_is(403, "Cannot delete macro without permission"); >+ >+ $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id") >+ ->status_is(200, 'Can delete macro with permission'); >+ >+ $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id") >+ ->status_is(403, 'Cannot delete other users macro with permission'); >+ >+ $macro_2->shared(1)->store(); >+ >+ $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_2_id") >+ ->status_is(403, 'Cannot delete other users shared macro without permission'); >+ >+ $builder->build({ >+ source => 'UserPermission', >+ value => { >+ borrowernumber => $authorized_patron->borrowernumber, >+ module_bit => 9, >+ code => 'delete_shared_macros', >+ }, >+ }); >+ $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id") >+ ->status_is(403, 'Cannot delete other users shared macro with permission on private endpoint'); >+ $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_2_id") >+ ->status_is(200, 'Can delete other users shared macro with permission'); >+ >+}; >+ >+$schema->storage->txn_rollback; >-- >2.11.0
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 17268
:
93474
|
95948
|
96616
|
96617
|
96618
|
96757
|
96758
|
96759
|
96760
|
100559
|
100560
|
100561
|
100562
|
100563
|
100564
|
100565
|
100569
|
100570
|
100571
|
100572
|
100573
|
100574
|
100575
|
100584
|
100604
|
100758
|
100759
|
100760
|
100761
|
100762
|
100763
|
100766
|
100767
|
100768
|
100769
|
100770
|
100771
|
100772
|
100773
|
100774
|
100775
|
100776
|
100777
|
100780
|
100781
|
100782
|
100783
|
100784
|
100785
|
100983
|
100984
|
100985
|
100986
|
100987
|
100988
|
101980
|
103507
|
103508
|
103509
|
103510
|
103511
|
103512
|
103513
|
103514
|
104144
|
104145
|
104146
|
104147
|
104148
|
104149
|
104150
|
104151
|
104152
|
104153