Bug 17268: Advanced cataloging editor macros - add endpoint
[koha.git] / Koha / REST / V1 / AdvancedEditorMacro.pm
1 package Koha::REST::V1::AdvancedEditorMacro;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with Koha; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 use Modern::Perl;
19
20 use Mojo::Base 'Mojolicious::Controller';
21 use Koha::AdvancedEditorMacros;
22
23 use Try::Tiny;
24
25 =head1 API
26
27 =head2 Class Methods
28
29 =cut
30
31 =head3 list
32
33 Controller function that handles listing Koha::AdvancedEditorMacro objects
34
35 =cut
36
37 sub list {
38     my $c = shift->openapi->valid_input or return;
39     my $patron = $c->stash('koha.user');
40     return try {
41         my $macros_set = Koha::AdvancedEditorMacros->search({ -or => { shared => 1, borrowernumber => $patron->borrowernumber } });
42         my $macros = $c->objects->search( $macros_set, \&_to_model, \&_to_api );
43         return $c->render( status => 200, openapi => $macros );
44     }
45     catch {
46         if ( $_->isa('DBIx::Class::Exception') ) {
47             return $c->render( status  => 500,
48                                openapi => { error => $_->{msg} } );
49         }
50         else {
51             return $c->render( status => 500,
52                 openapi => { error => "Something went wrong, check the logs. $_"} );
53         }
54     };
55
56 }
57
58 =head3 get
59
60 Controller function that handles retrieving a single Koha::AdvancedEditorMacro
61
62 =cut
63
64 sub get {
65     my $c = shift->openapi->valid_input or return;
66     my $patron = $c->stash('koha.user');
67     my $macro = Koha::AdvancedEditorMacros->find({
68         id => $c->validation->param('advancededitormacro_id'),
69     });
70     unless ($macro) {
71         return $c->render( status  => 404,
72                            openapi => { error => "Macro not found" } );
73     }
74     if( $macro->shared ){
75         return $c->render( status => 403, openapi => {
76             error => "This macro is shared, you must access it via advancededitormacros/shared"
77         });
78     }
79     warn $macro->borrowernumber;
80     warn $patron->borrowernumber;
81     if( $macro->borrowernumber != $patron->borrowernumber ){
82         return $c->render( status => 403, openapi => {
83             error => "You do not have permission to access this macro"
84         });
85     }
86
87     return $c->render( status => 200, openapi => $macro->to_api );
88 }
89
90 =head3 get_shared
91
92 Controller function that handles retrieving a single Koha::AdvancedEditorMacro
93
94 =cut
95
96 sub get_shared {
97     my $c = shift->openapi->valid_input or return;
98     my $patron = $c->stash('koha.user');
99     my $macro = Koha::AdvancedEditorMacros->find({
100         id => $c->validation->param('advancededitormacro_id'),
101     });
102     unless ($macro) {
103         return $c->render( status  => 404,
104                            openapi => { error => "Macro not found" } );
105     }
106     unless( $macro->shared ){
107         return $c->render( status => 403, openapi => {
108             error => "This macro is not shared, you must access it via advancededitormacros"
109         });
110     }
111     return $c->render( status => 200, openapi => $macro->to_api );
112 }
113
114 =head3 add
115
116 Controller function that handles adding a new Koha::AdvancedEditorMacro object
117
118 =cut
119
120 sub add {
121     my $c = shift->openapi->valid_input or return;
122
123     if( defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){
124         return $c->render( status  => 403,
125                            openapi => { error => "To create shared macros you must use advancededitor/shared" } );
126     }
127
128     return try {
129         my $macro = Koha::AdvancedEditorMacro->new( _to_model( $c->validation->param('body') ) );
130         $macro->store;
131         $c->res->headers->location( $c->req->url->to_string . '/' . $macro->id );
132         return $c->render(
133             status  => 201,
134             openapi => $macro->to_api
135         );
136     }
137     catch { handle_error($_) };
138 }
139
140 =head3 add_shared
141
142 Controller function that handles adding a new shared Koha::AdvancedEditorMacro object
143
144 =cut
145
146 sub add_shared {
147     my $c = shift->openapi->valid_input or return;
148
149     unless( defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){
150         return $c->render( status  => 403,
151                            openapi => { error => "To create private macros you must use advancededitor" } );
152     }
153
154     return try {
155         my $macro = Koha::AdvancedEditorMacro->new( _to_model( $c->validation->param('body') ) );
156         $macro->store;
157         $c->res->headers->location( $c->req->url->to_string . '/' . $macro->id );
158         return $c->render(
159             status  => 201,
160             openapi => $macro->to_api
161         );
162     }
163     catch { handle_error($_) };
164 }
165
166 =head3 update
167
168 Controller function that handles updating a Koha::AdvancedEditorMacro object
169
170 =cut
171
172 sub update {
173     my $c = shift->openapi->valid_input or return;
174
175     my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') );
176
177     if ( not defined $macro ) {
178         return $c->render( status  => 404,
179                            openapi => { error => "Object not found" } );
180     }
181     my $patron = $c->stash('koha.user');
182
183     if( $macro->shared == 1 || defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){
184         return $c->render( status  => 403,
185                            openapi => { error => "To update a macro as shared you must use the advancededitormacros/shared endpoint" } );
186     } else {
187         unless ( $macro->borrowernumber == $patron->borrowernumber ){
188             return $c->render( status  => 403,
189                                openapi => { error => "You can only edit macros you own" } );
190         }
191     }
192
193     return try {
194         my $params = $c->req->json;
195         $macro->set( _to_model($params) );
196         $macro->store();
197         return $c->render( status => 200, openapi => $macro->to_api );
198     }
199     catch { handle_error($_) };
200 }
201
202 =head3 update_shared
203
204 Controller function that handles updating a shared Koha::AdvancedEditorMacro object
205
206 =cut
207
208 sub update_shared {
209     my $c = shift->openapi->valid_input or return;
210
211     my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') );
212
213     if ( not defined $macro ) {
214         return $c->render( status  => 404,
215                            openapi => { error => "Object not found" } );
216     }
217
218     unless( $macro->shared == 1 || defined $c->validation->param('body')->{shared} && $c->validation->param('body')->{shared} == 1 ){
219         return $c->render( status  => 403,
220                            openapi => { error => "You can only update shared macros using this endpoint" } );
221     }
222
223     return try {
224         my $params = $c->req->json;
225         $macro->set( _to_model($params) );
226         $macro->store();
227         return $c->render( status => 200, openapi => $macro->to_api );
228     }
229     catch { handle_error($_) };
230 }
231
232 =head3 delete
233
234 Controller function that handles deleting a Koha::AdvancedEditorMacro object
235
236 =cut
237
238 sub delete {
239     my $c = shift->openapi->valid_input or return;
240
241     my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') );
242     if ( not defined $macro ) {
243         return $c->render( status  => 404,
244                            openapi => { error => "Object not found" } );
245     }
246
247     my $patron = $c->stash('koha.user');
248     if( $macro->shared == 1 ){
249         return $c->render( status  => 403,
250                            openapi => { error => "You cannot delete shared macros using this endpoint" } );
251     } else {
252         unless ( $macro->borrowernumber == $patron->borrowernumber ){
253             return $c->render( status  => 403,
254                                openapi => { error => "You can only delete macros you own" } );
255         }
256     }
257
258     return try {
259         $macro->delete;
260         return $c->render( status => 200, openapi => "" );
261     }
262     catch { handle_error($_) };
263 }
264
265 =head3 delete_shared
266
267 Controller function that handles deleting a shared Koha::AdvancedEditorMacro object
268
269 =cut
270
271 sub delete_shared {
272     my $c = shift->openapi->valid_input or return;
273
274     my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') );
275     if ( not defined $macro ) {
276         return $c->render( status  => 404,
277                            openapi => { error => "Object not found" } );
278     }
279
280     unless( $macro->shared == 1 ){
281         return $c->render( status  => 403,
282                            openapi => { error => "You can only delete shared macros using this endpoint" } );
283     }
284
285     return try {
286         $macro->delete;
287         return $c->render( status => 200, openapi => "" );
288     }
289     catch { handle_error($_,$c) };
290 }
291
292 =head3 _handle_error
293
294 Helper function that passes exception or error
295
296 =cut
297
298 sub _handle_error {
299     my ($err,$c) = @_;
300     if ( $err->isa('DBIx::Class::Exception') ) {
301         return $c->render( status  => 500,
302                            openapi => { error => $err->{msg} } );
303     }
304     else {
305         return $c->render( status => 500,
306             openapi => { error => "Something went wrong, check the logs."} );
307     }
308 };
309
310
311 =head3 _to_api
312
313 Helper function that maps a hashref of Koha::AdvancedEditorMacro attributes into REST api
314 attribute names.
315
316 =cut
317
318 sub _to_api {
319     my $macro = shift;
320
321     # Rename attributes
322     foreach my $column ( keys %{ $Koha::REST::V1::AdvancedEditorMacro::to_api_mapping } ) {
323         my $mapped_column = $Koha::REST::V1::AdvancedEditorMacro::to_api_mapping->{$column};
324         if (    exists $macro->{ $column }
325              && defined $mapped_column )
326         {
327             # key /= undef
328             $macro->{ $mapped_column } = delete $macro->{ $column };
329         }
330         elsif (    exists $macro->{ $column }
331                 && !defined $mapped_column )
332         {
333             # key == undef => to be deleted
334             delete $macro->{ $column };
335         }
336     }
337
338     return $macro;
339 }
340
341 =head3 _to_model
342
343 Helper function that maps REST api objects into Koha::AdvancedEditorMacros
344 attribute names.
345
346 =cut
347
348 sub _to_model {
349     my $macro = shift;
350
351     foreach my $attribute ( keys %{ $Koha::REST::V1::AdvancedEditorMacro::to_model_mapping } ) {
352         my $mapped_attribute = $Koha::REST::V1::AdvancedEditorMacro::to_model_mapping->{$attribute};
353         if (    exists $macro->{ $attribute }
354              && defined $mapped_attribute )
355         {
356             # key /= undef
357             $macro->{ $mapped_attribute } = delete $macro->{ $attribute };
358         }
359         elsif (    exists $macro->{ $attribute }
360                 && !defined $mapped_attribute )
361         {
362             # key == undef => to be deleted
363             delete $macro->{ $attribute };
364         }
365     }
366
367     if ( exists $macro->{shared} ) {
368         $macro->{shared} = ($macro->{shared}) ? 1 : 0;
369     }
370
371
372     return $macro;
373 }
374
375 =head2 Global variables
376
377 =head3 $to_api_mapping
378
379 =cut
380
381 our $to_api_mapping = {
382     id                  => 'macro_id',
383     macro               => 'macro_text',
384     borrowernumber      => 'patron_id',
385 };
386
387 =head3 $to_model_mapping
388
389 =cut
390
391 our $to_model_mapping = {
392     macro_id         => 'id',
393     macro_text       => 'macro',
394     patron_id        => 'borrowernumber',
395 };
396
397 1;