View | Details | Raw Unified | Return to bug 17268
Collapse All | Expand All

(-)a/Koha/AdvancedEditorMacro.pm (+57 lines)
Line 0 Link Here
1
package Koha::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 Carp;
21
22
use Koha::Database;
23
24
use base qw(Koha::Object);
25
26
=head1 NAME
27
28
Koha::AdvancedEditorMacro - Koha Advanced Editor Macro Object class
29
30
=head1 API
31
32
=head2 Class methods
33
34
=head3 to_api_mapping
35
36
=cut
37
38
sub to_api_mapping {
39
    return {
40
        id                  => 'macro_id',
41
        macro               => 'macro_text',
42
        borrowernumber      => 'patron_id',
43
    };
44
}
45
46
47
=head2 Internal methods
48
49
=head3 _type
50
51
=cut
52
53
sub _type {
54
    return 'AdvancedEditorMacro';
55
}
56
57
1;
(-)a/Koha/AdvancedEditorMacros.pm (+50 lines)
Line 0 Link Here
1
package Koha::AdvancedEditorMacros;
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 Carp;
21
22
use Koha::Database;
23
24
use Koha::AdvancedEditorMacro;
25
26
use base qw(Koha::Objects);
27
28
=head1 NAME
29
30
Koha::AdvancedEditorMacros - Koha Advanced Editor Macro Object set class
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3 type
39
40
=cut
41
42
sub _type {
43
    return 'AdvancedEditorMacro';
44
}
45
46
sub object_class {
47
    return 'Koha::AdvancedEditorMacro';
48
}
49
50
1;
(-)a/Koha/REST/V1/AdvancedEditorMacro.pm (+397 lines)
Line 0 Link Here
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;
(-)a/api/v1/swagger/definitions.json (+3 lines)
Lines 47-52 Link Here
47
  "order": {
47
  "order": {
48
    "$ref": "definitions/order.json"
48
    "$ref": "definitions/order.json"
49
  },
49
  },
50
  "advancededitormacro": {
51
    "$ref": "definitions/advancededitormacro.json"
52
  },
50
  "patron": {
53
  "patron": {
51
    "$ref": "definitions/patron.json"
54
    "$ref": "definitions/patron.json"
52
  },
55
  },
(-)a/api/v1/swagger/definitions/advancededitormacro.json (+26 lines)
Line 0 Link Here
1
{
2
  "type": "object",
3
  "properties": {
4
    "macro_id": {
5
      "$ref": "../x-primitives.json#/advancededitormacro_id"
6
    },
7
    "name": {
8
      "description": "macro name",
9
      "type": "string"
10
    },
11
    "macro_text": {
12
      "description": "macro text",
13
      "type": ["string", "null"]
14
    },
15
    "patron_id": {
16
      "description": "borrower number",
17
      "type": ["integer", "null"]
18
    },
19
    "shared": {
20
        "description": "is macro shared",
21
        "type": ["boolean", "null"]
22
    }
23
  },
24
  "additionalProperties": false,
25
  "required": ["name", "macro_text", "patron_id", "shared"]
26
}
(-)a/api/v1/swagger/parameters.json (+3 lines)
Lines 2-7 Link Here
2
  "biblio_id_pp": {
2
  "biblio_id_pp": {
3
    "$ref": "parameters/biblio.json#/biblio_id_pp"
3
    "$ref": "parameters/biblio.json#/biblio_id_pp"
4
  },
4
  },
5
  "advancededitormacro_id_pp": {
6
    "$ref": "parameters/advancededitormacro.json#/advancededitormacro_id_pp"
7
  },
5
  "patron_id_pp": {
8
  "patron_id_pp": {
6
    "$ref": "parameters/patron.json#/patron_id_pp"
9
    "$ref": "parameters/patron.json#/patron_id_pp"
7
  },
10
  },
(-)a/api/v1/swagger/parameters/advancededitormacro.json (+9 lines)
Line 0 Link Here
1
{
2
    "advancededitormacro_id_pp": {
3
      "name": "advancededitormacro_id",
4
      "in": "path",
5
      "description": "Advanced Editor Macro internal identifier",
6
      "required": true,
7
      "type": "integer"
8
    }
9
}
(-)a/api/v1/swagger/paths.json (+12 lines)
Lines 68-73 Link Here
68
  "/checkouts/{checkout_id}/allows_renewal": {
68
  "/checkouts/{checkout_id}/allows_renewal": {
69
    "$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}~1allows_renewal"
69
    "$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}~1allows_renewal"
70
  },
70
  },
71
  "/advancededitormacros": {
72
    "$ref": "paths/advancededitormacros.json#/~1advancededitormacros"
73
  },
74
  "/advancededitormacros/{advancededitormacro_id}": {
75
    "$ref": "paths/advancededitormacros.json#/~1advancededitormacros~1{advancededitormacro_id}"
76
  },
77
  "/advancededitormacros/shared": {
78
    "$ref": "paths/advancededitormacros.json#/~1advancededitormacros~1shared"
79
  },
80
  "/advancededitormacros/shared/{advancededitormacro_id}": {
81
    "$ref": "paths/advancededitormacros.json#/~1advancededitormacros~1shared~1{advancededitormacro_id}"
82
  },
71
  "/patrons": {
83
  "/patrons": {
72
    "$ref": "paths/patrons.json#/~1patrons"
84
    "$ref": "paths/patrons.json#/~1patrons"
73
  },
85
  },
(-)a/api/v1/swagger/paths/advancededitormacros.json (+521 lines)
Line 0 Link Here
1
{
2
  "/advancededitormacros": {
3
    "get": {
4
      "x-mojo-to": "AdvancedEditorMacro#list",
5
      "operationId": "listMacro",
6
      "tags": ["advancededitormacro"],
7
      "produces": [
8
        "application/json"
9
      ],
10
      "parameters": [
11
        {
12
          "name": "name",
13
          "in": "query",
14
          "description": "Case insensative search on macro name",
15
          "required": false,
16
          "type": "string"
17
        },
18
        {
19
          "name": "macro_text",
20
          "in": "query",
21
          "description": "Case insensative search on macro text",
22
          "required": false,
23
          "type": "string"
24
        },
25
        {
26
          "name": "patron_id",
27
          "in": "query",
28
          "description": "Search on internal patron_id",
29
          "required": false,
30
          "type": "string"
31
        },
32
        {
33
          "name": "shared",
34
          "in": "query",
35
          "description": "Search on shared macros",
36
          "required": false,
37
          "type": "string"
38
        }
39
      ],
40
      "responses": {
41
        "200": {
42
          "description": "A list of macros",
43
          "schema": {
44
            "type": "array",
45
            "items": {
46
              "$ref": "../definitions.json#/advancededitormacro"
47
            }
48
          }
49
        },
50
        "403": {
51
          "description": "Access forbidden",
52
          "schema": {
53
            "$ref": "../definitions.json#/error"
54
          }
55
        },
56
        "500": {
57
          "description": "Internal error",
58
          "schema": {
59
            "$ref": "../definitions.json#/error"
60
          }
61
        },
62
        "503": {
63
          "description": "Under maintenance",
64
          "schema": {
65
            "$ref": "../definitions.json#/error"
66
          }
67
        }
68
      },
69
      "x-koha-authorization": {
70
        "permissions": {
71
            "editcatalogue": "advanced_editor"
72
        }
73
      }
74
    },
75
    "post": {
76
      "x-mojo-to": "AdvancedEditorMacro#add",
77
      "operationId": "addAdvancedEditorMacro",
78
      "tags": ["advancededitormacro"],
79
      "parameters": [{
80
        "name": "body",
81
        "in": "body",
82
        "description": "A JSON object containing informations about the new macro",
83
        "required": true,
84
        "schema": {
85
          "$ref": "../definitions.json#/advancededitormacro"
86
        }
87
      }],
88
      "produces": [
89
        "application/json"
90
      ],
91
      "responses": {
92
        "201": {
93
          "description": "Macro added",
94
          "schema": {
95
            "$ref": "../definitions.json#/advancededitormacro"
96
          }
97
        },
98
        "401": {
99
          "description": "Authentication required",
100
          "schema": {
101
            "$ref": "../definitions.json#/error"
102
          }
103
        },
104
        "403": {
105
          "description": "Access forbidden",
106
          "schema": {
107
            "$ref": "../definitions.json#/error"
108
          }
109
        },
110
        "500": {
111
          "description": "Internal error",
112
          "schema": {
113
            "$ref": "../definitions.json#/error"
114
          }
115
        },
116
        "503": {
117
          "description": "Under maintenance",
118
          "schema": {
119
            "$ref": "../definitions.json#/error"
120
          }
121
        }
122
      },
123
      "x-koha-authorization": {
124
        "permissions": {
125
          "editcatalogue": "advanced_editor"
126
        }
127
      }
128
    }
129
  },
130
  "/advancededitormacros/shared": {
131
    "post": {
132
      "x-mojo-to": "AdvancedEditorMacro#add_shared",
133
      "operationId": "addsharedAdvancedEditorMacro",
134
      "tags": ["advancededitormacro"],
135
      "parameters": [{
136
        "name": "body",
137
        "in": "body",
138
        "description": "A JSON object containing informations about the new macro",
139
        "required": true,
140
        "schema": {
141
          "$ref": "../definitions.json#/advancededitormacro"
142
        }
143
      }],
144
      "produces": [
145
        "application/json"
146
      ],
147
      "responses": {
148
        "201": {
149
          "description": "Macro added",
150
          "schema": {
151
            "$ref": "../definitions.json#/advancededitormacro"
152
          }
153
        },
154
        "401": {
155
          "description": "Authentication required",
156
          "schema": {
157
            "$ref": "../definitions.json#/error"
158
          }
159
        },
160
        "403": {
161
          "description": "Access forbidden",
162
          "schema": {
163
            "$ref": "../definitions.json#/error"
164
          }
165
        },
166
        "500": {
167
          "description": "Internal error",
168
          "schema": {
169
            "$ref": "../definitions.json#/error"
170
          }
171
        },
172
        "503": {
173
          "description": "Under maintenance",
174
          "schema": {
175
            "$ref": "../definitions.json#/error"
176
          }
177
        }
178
      },
179
      "x-koha-authorization": {
180
        "permissions": {
181
          "editcatalogue": "advanced_editor",
182
          "editcatalogue": "create_shared_macros"
183
        }
184
      }
185
    }
186
  },
187
  "/advancededitormacros/{advancededitormacro_id}": {
188
    "get": {
189
      "x-mojo-to": "AdvancedEditorMacro#get",
190
      "operationId": "getAdvancedEditorMacro",
191
      "tags": ["advancededitormacros"],
192
      "parameters": [{
193
        "$ref": "../parameters.json#/advancededitormacro_id_pp"
194
      }],
195
      "produces": [
196
        "application/json"
197
      ],
198
      "responses": {
199
        "200": {
200
          "description": "A macro",
201
          "schema": {
202
            "$ref": "../definitions.json#/advancededitormacro"
203
          }
204
        },
205
        "403": {
206
          "description": "Access forbidden",
207
          "schema": {
208
            "$ref": "../definitions.json#/error"
209
          }
210
        },
211
        "404": {
212
          "description": "AdvancedEditorMacro not found",
213
          "schema": {
214
            "$ref": "../definitions.json#/error"
215
          }
216
        },
217
        "500": {
218
          "description": "Internal error",
219
          "schema": {
220
            "$ref": "../definitions.json#/error"
221
          }
222
        },
223
        "503": {
224
          "description": "Under maintenance",
225
          "schema": {
226
            "$ref": "../definitions.json#/error"
227
          }
228
        }
229
      },
230
      "x-koha-authorization": {
231
        "permissions": {
232
            "editcatalogue": "advanced_editor"
233
        }
234
      }
235
    },
236
    "put": {
237
      "x-mojo-to": "AdvancedEditorMacro#update",
238
      "operationId": "updateAdvancedEditorMacro",
239
      "tags": ["advancededitormacros"],
240
      "parameters": [{
241
        "$ref": "../parameters.json#/advancededitormacro_id_pp"
242
      }, {
243
        "name": "body",
244
        "in": "body",
245
        "description": "An advanced editor macro object",
246
        "required": true,
247
        "schema": {
248
          "$ref": "../definitions.json#/advancededitormacro"
249
        }
250
      }],
251
      "produces": [
252
        "application/json"
253
      ],
254
      "responses": {
255
        "200": {
256
          "description": "An advanced editor macro",
257
          "schema": {
258
            "$ref": "../definitions.json#/advancededitormacro"
259
          }
260
        },
261
        "401": {
262
          "description": "Authentication required",
263
          "schema": {
264
            "$ref": "../definitions.json#/error"
265
          }
266
        },
267
        "403": {
268
          "description": "Access forbidden",
269
          "schema": {
270
            "$ref": "../definitions.json#/error"
271
          }
272
        },
273
        "404": {
274
          "description": "Macro not found",
275
          "schema": {
276
            "$ref": "../definitions.json#/error"
277
          }
278
        },
279
        "500": {
280
          "description": "Internal error",
281
          "schema": {
282
            "$ref": "../definitions.json#/error"
283
          }
284
        },
285
        "503": {
286
          "description": "Under maintenance",
287
          "schema": {
288
            "$ref": "../definitions.json#/error"
289
          }
290
        }
291
      },
292
      "x-koha-authorization": {
293
        "permissions": {
294
          "editcatalogue": "advanced_editor"
295
        }
296
      }
297
    },
298
    "delete": {
299
      "x-mojo-to": "AdvancedEditorMacro#delete",
300
      "operationId": "deleteAdvancedEditorMacro",
301
      "tags": ["advancededitormacros"],
302
      "parameters": [{
303
        "$ref": "../parameters.json#/advancededitormacro_id_pp"
304
      }],
305
      "produces": [
306
        "application/json"
307
      ],
308
      "responses": {
309
        "200": {
310
          "description": "Advanced editor macro deleted",
311
          "schema": {
312
            "type": "string"
313
          }
314
        },
315
        "401": {
316
          "description": "Authentication required",
317
          "schema": {
318
            "$ref": "../definitions.json#/error"
319
          }
320
        },
321
        "403": {
322
          "description": "Access forbidden",
323
          "schema": {
324
            "$ref": "../definitions.json#/error"
325
          }
326
        },
327
        "404": {
328
          "description": "Macro not found",
329
          "schema": {
330
            "$ref": "../definitions.json#/error"
331
          }
332
        },
333
        "500": {
334
          "description": "Internal error",
335
          "schema": {
336
            "$ref": "../definitions.json#/error"
337
          }
338
        },
339
        "503": {
340
          "description": "Under maintenance",
341
          "schema": {
342
            "$ref": "../definitions.json#/error"
343
          }
344
        }
345
      },
346
      "x-koha-authorization": {
347
        "permissions": {
348
          "editcatalogue": "advanced_editor"
349
        }
350
      }
351
    }
352
  },
353
  "/advancededitormacros/shared/{advancededitormacro_id}": {
354
    "get": {
355
      "x-mojo-to": "AdvancedEditorMacro#get_shared",
356
      "operationId": "getsharedAdvancedEditorMacro",
357
      "tags": ["advancededitormacros"],
358
      "parameters": [{
359
        "$ref": "../parameters.json#/advancededitormacro_id_pp"
360
      }],
361
      "produces": [
362
        "application/json"
363
      ],
364
      "responses": {
365
        "200": {
366
          "description": "A macro",
367
          "schema": {
368
            "$ref": "../definitions.json#/advancededitormacro"
369
          }
370
        },
371
        "403": {
372
          "description": "Access forbidden",
373
          "schema": {
374
            "$ref": "../definitions.json#/error"
375
          }
376
        },
377
        "404": {
378
          "description": "AdvancedEditorMacro not found",
379
          "schema": {
380
            "$ref": "../definitions.json#/error"
381
          }
382
        },
383
        "500": {
384
          "description": "Internal error",
385
          "schema": {
386
            "$ref": "../definitions.json#/error"
387
          }
388
        },
389
        "503": {
390
          "description": "Under maintenance",
391
          "schema": {
392
            "$ref": "../definitions.json#/error"
393
          }
394
        }
395
      },
396
      "x-koha-authorization": {
397
        "permissions": {
398
            "editcatalogue": "advanced_editor"
399
        }
400
      }
401
    },
402
    "put": {
403
      "x-mojo-to": "AdvancedEditorMacro#update_shared",
404
      "operationId": "updatesharedAdvancedEditorMacro",
405
      "tags": ["advancededitormacros"],
406
      "parameters": [{
407
        "$ref": "../parameters.json#/advancededitormacro_id_pp"
408
      }, {
409
        "name": "body",
410
        "in": "body",
411
        "description": "An advanced editor macro object",
412
        "required": true,
413
        "schema": {
414
          "$ref": "../definitions.json#/advancededitormacro"
415
        }
416
      }],
417
      "produces": [
418
        "application/json"
419
      ],
420
      "responses": {
421
        "200": {
422
          "description": "An advanced editor macro",
423
          "schema": {
424
            "$ref": "../definitions.json#/advancededitormacro"
425
          }
426
        },
427
        "401": {
428
          "description": "Authentication required",
429
          "schema": {
430
            "$ref": "../definitions.json#/error"
431
          }
432
        },
433
        "403": {
434
          "description": "Access forbidden",
435
          "schema": {
436
            "$ref": "../definitions.json#/error"
437
          }
438
        },
439
        "404": {
440
          "description": "Macro not found",
441
          "schema": {
442
            "$ref": "../definitions.json#/error"
443
          }
444
        },
445
        "500": {
446
          "description": "Internal error",
447
          "schema": {
448
            "$ref": "../definitions.json#/error"
449
          }
450
        },
451
        "503": {
452
          "description": "Under maintenance",
453
          "schema": {
454
            "$ref": "../definitions.json#/error"
455
          }
456
        }
457
      },
458
      "x-koha-authorization": {
459
        "permissions": {
460
          "editcatalogue": "advanced_editor",
461
          "editcatalogue": "create_shared_macros"
462
        }
463
      }
464
    },
465
    "delete": {
466
      "x-mojo-to": "AdvancedEditorMacro#delete_shared",
467
      "operationId": "deletesharedAdvancedEditorMacro",
468
      "tags": ["advancededitormacros"],
469
      "parameters": [{
470
        "$ref": "../parameters.json#/advancededitormacro_id_pp"
471
      }],
472
      "produces": [
473
        "application/json"
474
      ],
475
      "responses": {
476
        "200": {
477
          "description": "Advanced editor macro deleted",
478
          "schema": {
479
            "type": "string"
480
          }
481
        },
482
        "401": {
483
          "description": "Authentication required",
484
          "schema": {
485
            "$ref": "../definitions.json#/error"
486
          }
487
        },
488
        "403": {
489
          "description": "Access forbidden",
490
          "schema": {
491
            "$ref": "../definitions.json#/error"
492
          }
493
        },
494
        "404": {
495
          "description": "Macro not found",
496
          "schema": {
497
            "$ref": "../definitions.json#/error"
498
          }
499
        },
500
        "500": {
501
          "description": "Internal error",
502
          "schema": {
503
            "$ref": "../definitions.json#/error"
504
          }
505
        },
506
        "503": {
507
          "description": "Under maintenance",
508
          "schema": {
509
            "$ref": "../definitions.json#/error"
510
          }
511
        }
512
      },
513
      "x-koha-authorization": {
514
        "permissions": {
515
          "editcatalogue": "advanced_editor",
516
          "editcatalogue": "delete_shared_macros"
517
        }
518
      }
519
    }
520
  }
521
}
(-)a/api/v1/swagger/x-primitives.json (+5 lines)
Lines 3-8 Link Here
3
    "type": "integer",
3
    "type": "integer",
4
    "description": "Internal biblio identifier"
4
    "description": "Internal biblio identifier"
5
  },
5
  },
6
  "advancededitormacro_id": {
7
    "type": "integer",
8
    "description": "Internal advanced editor macro identifier",
9
    "readOnly": true
10
  },
6
  "patron_id": {
11
  "patron_id": {
7
    "type": "integer",
12
    "type": "integer",
8
    "description": "Internal patron identifier"
13
    "description": "Internal patron identifier"
(-)a/t/db_dependent/api/v1/advanced_editor_macros.t (-1 / +475 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
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 Test::More tests => 5;
21
use Test::Mojo;
22
use Test::Warn;
23
24
use t::lib::TestBuilder;
25
use t::lib::Mocks;
26
27
use Koha::AdvancedEditorMacros;
28
use Koha::Database;
29
30
my $schema  = Koha::Database->new->schema;
31
my $builder = t::lib::TestBuilder->new;
32
33
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
34
35
my $t = Test::Mojo->new('Koha::REST::V1');
36
37
$schema->storage->txn_begin;
38
39
subtest 'list() tests' => sub {
40
    plan tests => 8;
41
42
43
    my $patron_1 = $builder->build_object({
44
        class => 'Koha::Patrons',
45
        value => { flags => 9 }
46
    });
47
    my $patron_2 = $builder->build_object({
48
        class => 'Koha::Patrons',
49
    });
50
    my $password = 'thePassword123';
51
    $patron_1->set_password({ password => $password, skip_validation => 1 });
52
    my $userid = $patron_1->userid;
53
54
    # Create test context
55
    my $macro_1 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value =>
56
        {
57
            name => 'Test1',
58
            macro => 'delete 100',
59
            borrowernumber => $patron_1->borrowernumber,
60
        }
61
    });
62
    my $macro_2 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value =>
63
        {
64
            name => 'Test2',
65
            macro => 'delete 100',
66
            borrowernumber => $patron_1->borrowernumber,
67
            shared=> 1,
68
        }
69
    });
70
    my $macro_3 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value =>
71
        {
72
            name => 'Test3',
73
            macro => 'delete 100',
74
            borrowernumber => $patron_2->borrowernumber,
75
        }
76
    });
77
    my $macro_4 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value =>
78
        {
79
            name => 'Test4',
80
            macro => 'delete 100',
81
            borrowernumber => $patron_2->borrowernumber,
82
            shared => 1,
83
        }
84
    });
85
86
    my $macros_index = Koha::AdvancedEditorMacros->search({ -or => { shared => 1, borrowernumber => $patron_1->borrowernumber } })->count-1;
87
    ## Authorized user tests
88
    # Make sure we are returned with the correct amount of macros
89
    $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros" )
90
      ->status_is( 200, 'SWAGGER3.2.2' )
91
      ->json_has('/' . $macros_index . '/macro_id')
92
      ->json_hasnt('/' . ($macros_index + 1) . '/macro_id');
93
94
    subtest 'query parameters' => sub {
95
96
        plan tests => 15;
97
        $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?name=" . $macro_2->name)
98
          ->status_is(200)
99
          ->json_has( [ $macro_2 ] );
100
        $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?name=" . $macro_3->name)
101
          ->status_is(200)
102
          ->json_has( [ ] );
103
        $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?macro_text=delete 100")
104
          ->status_is(200)
105
          ->json_has( [ $macro_1, $macro_2, $macro_4 ] );
106
        $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?patron_id=" . $patron_1->borrowernumber)
107
          ->status_is(200)
108
          ->json_has( [ $macro_1, $macro_2 ] );
109
        $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?shared=1")
110
          ->status_is(200)
111
          ->json_has( [ $macro_2, $macro_4 ] );
112
    };
113
114
    # Warn on unsupported query parameter
115
    $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros?macro_blah=blah" )
116
      ->status_is(400)
117
      ->json_is( [{ path => '/query/macro_blah', message => 'Malformed query string'}] );
118
119
};
120
121
subtest 'get() tests' => sub {
122
123
    plan tests => 15;
124
125
    my $patron = $builder->build_object({
126
        class => 'Koha::Patrons',
127
        value => { flags => 1 }
128
    });
129
    my $password = 'thePassword123';
130
    $patron->set_password({ password => $password, skip_validation => 1 });
131
    my $userid = $patron->userid;
132
133
    my $macro_1 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => {
134
            shared => 1,
135
        }
136
    });
137
    my $macro_2 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => {
138
            shared => 0,
139
        }
140
    });
141
    my $macro_3 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => {
142
            borrowernumber => $patron->borrowernumber,
143
            shared => 0,
144
        }
145
    });
146
147
    $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $macro_1->id )
148
      ->status_is( 403, 'Cannot get a shared macro via regular endpoint' )
149
      ->json_is( '/error' => 'This macro is shared, you must access it via advancededitormacros/shared' );
150
151
    $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/shared/" . $macro_1->id )
152
      ->status_is( 200, 'Can get a shared macro via shared endpoint' )
153
      ->json_is( '' => Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro_1->TO_JSON ), 'Macro correctly retrieved' );
154
155
    $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $macro_2->id )
156
      ->status_is( 403, 'Cannot access another users macro' )
157
      ->json_is( '/error' => 'You do not have permission to access this macro' );
158
159
    $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $macro_3->id )
160
      ->status_is( 200, 'Can get your own private macro' )
161
      ->json_is( '' => Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro_3->TO_JSON ), 'Macro correctly retrieved' );
162
163
    my $non_existent_code = $macro_1->id;
164
    $macro_1->delete;
165
166
    $t->get_ok( "//$userid:$password@/api/v1/advancededitormacros/" . $non_existent_code )
167
      ->status_is(404)
168
      ->json_is( '/error' => 'Macro not found' );
169
170
};
171
172
subtest 'add() tests' => sub {
173
174
    plan tests => 24;
175
176
    my $authorized_patron = $builder->build_object({
177
        class => 'Koha::Patrons',
178
        value => { flags => 0 }
179
    });
180
    $builder->build({
181
        source => 'UserPermission',
182
        value  => {
183
            borrowernumber => $authorized_patron->borrowernumber,
184
            module_bit     => 9,
185
            code           => 'advanced_editor',
186
        },
187
    });
188
189
    my $password = 'thePassword123';
190
    $authorized_patron->set_password({ password => $password, skip_validation => 1 });
191
    my $auth_userid = $authorized_patron->userid;
192
193
    my $unauthorized_patron = $builder->build_object({
194
        class => 'Koha::Patrons',
195
        value => { flags => 0 }
196
    });
197
    $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
198
    my $unauth_userid = $unauthorized_patron->userid;
199
200
    my $macro = $builder->build_object({
201
        class => 'Koha::AdvancedEditorMacros',
202
        value => { shared => 0 }
203
    });
204
    my $macro_values     = Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro->TO_JSON );
205
    delete $macro_values->{macro_id};
206
    $macro->delete;
207
208
    # Unauthorized attempt to write
209
    $t->post_ok( "//$unauth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values )
210
      ->status_is(403);
211
212
    # Authorized attempt to write invalid data
213
    my $macro_with_invalid_field = { %$macro_values };
214
    $macro_with_invalid_field->{'big_mac_ro'} = 'Mac attack';
215
216
    $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_with_invalid_field )
217
      ->status_is(400)
218
      ->json_is(
219
        "/errors" => [
220
            {
221
                message => "Properties not allowed: big_mac_ro.",
222
                path    => "/body"
223
            }
224
        ]
225
    );
226
227
    # Authorized attempt to write
228
    $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values )
229
      ->status_is( 201, 'SWAGGER3.2.1' )
230
      ->json_has( '/macro_id', 'We generated a new id' )
231
      ->json_is( '/name' => $macro_values->{name}, 'The name matches what we supplied' )
232
      ->json_is( '/macro_text' => $macro_values->{macro_text}, 'The text matches what we supplied' )
233
      ->json_is( '/patron_id' => $macro_values->{patron_id}, 'The borrower matches the borrower who submitted' )
234
      ->json_is( '/shared' => 0, 'The macro is not shared' )
235
      ->header_like( Location => qr|^\/api\/v1\/advancededitormacros\/d*|, 'Correct location' );
236
237
    # save the library_id
238
    my $macro_id = 999;
239
240
    # Authorized attempt to create with existing id
241
    $macro_values->{macro_id} = $macro_id;
242
243
    $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values )
244
      ->status_is(400)
245
      ->json_is( '/errors' => [
246
            {
247
                message => "Read-only.",
248
                path   => "/body/macro_id"
249
            }
250
        ]
251
    );
252
253
    $macro_values->{shared} = 1;
254
    delete $macro_values->{macro_id};
255
256
    # Unauthorized attempt to write a shared macro on private endpoint
257
    $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values )
258
      ->status_is(403);
259
    # Unauthorized attempt to write a private macro on shared endpoint
260
    $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared" => json => $macro_values )
261
      ->status_is(403);
262
263
    $builder->build({
264
        source => 'UserPermission',
265
        value  => {
266
            borrowernumber => $authorized_patron->borrowernumber,
267
            module_bit     => 9,
268
            code           => 'create_shared_macros',
269
        },
270
    });
271
272
    # Authorized attempt to write a shared macro on private endpoint
273
    $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros" => json => $macro_values )
274
      ->status_is(403);
275
276
    # Authorized attempt to write a shared macro on shared endpoint
277
    $t->post_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared" => json => $macro_values )
278
      ->status_is(201);
279
280
};
281
282
subtest 'update() tests' => sub {
283
    plan tests => 32;
284
285
    my $authorized_patron = $builder->build_object({
286
        class => 'Koha::Patrons',
287
        value => { flags => 0 }
288
    });
289
    $builder->build({
290
        source => 'UserPermission',
291
        value  => {
292
            borrowernumber => $authorized_patron->borrowernumber,
293
            module_bit     => 9,
294
            code           => 'advanced_editor',
295
        },
296
    });
297
298
    my $password = 'thePassword123';
299
    $authorized_patron->set_password({ password => $password, skip_validation => 1 });
300
    my $auth_userid = $authorized_patron->userid;
301
302
    my $unauthorized_patron = $builder->build_object({
303
        class => 'Koha::Patrons',
304
        value => { flags => 0 }
305
    });
306
    $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
307
    my $unauth_userid = $unauthorized_patron->userid;
308
309
    my $macro = $builder->build_object({
310
        class => 'Koha::AdvancedEditorMacros',
311
        value => { borrowernumber => $authorized_patron->borrowernumber, shared => 0 }
312
    });
313
    my $macro_2 = $builder->build_object({
314
        class => 'Koha::AdvancedEditorMacros',
315
        value => { borrowernumber => $unauthorized_patron->borrowernumber, shared => 0 }
316
    });
317
    my $macro_id = $macro->id;
318
    my $macro_2_id = $macro_2->id;
319
    my $macro_values     = Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro->TO_JSON );
320
    delete $macro_values->{macro_id};
321
322
    # Unauthorized attempt to update
323
    $t->put_ok( "//$unauth_userid:$password@/api/v1/advancededitormacros/$macro_id"
324
                    => json => { name => 'New unauthorized name change' } )
325
      ->status_is(403);
326
327
    # Attempt partial update on a PUT
328
    my $macro_with_missing_field = {
329
        name => "Call it macro-roni",
330
    };
331
332
    $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_with_missing_field )
333
      ->status_is(400)
334
      ->json_has( "/errors" =>
335
          [ { message => "Missing property.", path => "/body/macro_text" } ]
336
      );
337
338
    my $macro_update = {
339
        name => "Macro-update",
340
        macro_text => "delete 100",
341
        patron_id => $authorized_patron->borrowernumber,
342
        shared => 0,
343
    };
344
345
    my $test = $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_update )
346
      ->status_is(200, 'Authorized user can update a macro')
347
      ->json_is( '/macro_id' => $macro_id, 'We get the id back' )
348
      ->json_is( '/name' => $macro_update->{name}, 'We get the name back' )
349
      ->json_is( '/macro_text' => $macro_update->{macro_text}, 'We get the text back' )
350
      ->json_is( '/patron_id' => $macro_update->{patron_id}, 'We get the patron_id back' )
351
      ->json_is( '/shared' => $macro_update->{shared}, 'It should still not be shared' );
352
353
    # Now try to make the macro shared
354
    $macro_update->{shared} = 1;
355
356
    $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_id" => json => $macro_update )
357
      ->status_is(403, 'Cannot make your macro shared on private endpoint');
358
    $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_id" => json => $macro_update )
359
      ->status_is(403, 'Cannot make your macro shared without permission');
360
361
    $builder->build({
362
        source => 'UserPermission',
363
        value  => {
364
            borrowernumber => $authorized_patron->borrowernumber,
365
            module_bit     => 9,
366
            code           => 'create_shared_macros',
367
        },
368
    });
369
370
    $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_update )
371
      ->status_is(403, 'Cannot make your macro shared on the private endpoint');
372
373
    $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_id" => json => $macro_update )
374
      ->status_is(200, 'Can update macro to shared with permission')
375
      ->json_is( '/macro_id' => $macro_id, 'We get back the id' )
376
      ->json_is( '/name' => $macro_update->{name}, 'We get back the name' )
377
      ->json_is( '/macro_text' => $macro_update->{macro_text}, 'We get back the text' )
378
      ->json_is( '/patron_id' => $macro_update->{patron_id}, 'We get back our patron id' )
379
      ->json_is( '/shared' => 1, 'It is shared' );
380
381
    # Authorized attempt to write invalid data
382
    my $macro_with_invalid_field = { %$macro_update };
383
    $macro_with_invalid_field->{'big_mac_ro'} = 'Mac attack';
384
385
    $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_with_invalid_field )
386
      ->status_is(400)
387
      ->json_is(
388
        "/errors" => [
389
            {
390
                message => "Properties not allowed: big_mac_ro.",
391
                path    => "/body"
392
            }
393
        ]
394
    );
395
396
    my $non_existent_macro = $builder->build_object({class => 'Koha::AdvancedEditorMacros'});
397
    my $non_existent_code = $non_existent_macro->id;
398
    $non_existent_macro->delete;
399
400
    $t->put_ok("//$auth_userid:$password@/api/v1/advancededitormacros/$non_existent_code" => json => $macro_update)
401
      ->status_is(404);
402
403
    $t->put_ok("//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id" => json => $macro_update)
404
      ->status_is(403, "Cannot update other borrowers private macro");
405
};
406
407
subtest 'delete() tests' => sub {
408
    plan tests => 12;
409
410
    my $authorized_patron = $builder->build_object({
411
        class => 'Koha::Patrons',
412
        value => { flags => 0 }
413
    });
414
    $builder->build({
415
        source => 'UserPermission',
416
        value  => {
417
            borrowernumber => $authorized_patron->borrowernumber,
418
            module_bit     => 9,
419
            code           => 'advanced_editor',
420
        },
421
    });
422
423
    my $password = 'thePassword123';
424
    $authorized_patron->set_password({ password => $password, skip_validation => 1 });
425
    my $auth_userid = $authorized_patron->userid;
426
427
    my $unauthorized_patron = $builder->build_object({
428
        class => 'Koha::Patrons',
429
        value => { flags => 0 }
430
    });
431
    $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
432
    my $unauth_userid = $unauthorized_patron->userid;
433
434
    my $macro = $builder->build_object({
435
        class => 'Koha::AdvancedEditorMacros',
436
        value => { borrowernumber => $authorized_patron->borrowernumber, shared => 0 }
437
    });
438
    my $macro_2 = $builder->build_object({
439
        class => 'Koha::AdvancedEditorMacros',
440
        value => { borrowernumber => $unauthorized_patron->borrowernumber, shared => 0 }
441
    });
442
    my $macro_id = $macro->id;
443
    my $macro_2_id = $macro_2->id;
444
445
    # Unauthorized attempt to delete
446
    $t->delete_ok( "//$unauth_userid:$password@/api/v1/advancededitormacros/$macro_2_id")
447
      ->status_is(403, "Cannot delete macro without permission");
448
449
    $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id")
450
      ->status_is(200, 'Can delete macro with permission');
451
452
    $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id")
453
      ->status_is(403, 'Cannot delete other users macro with permission');
454
455
    $macro_2->shared(1)->store();
456
457
    $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_2_id")
458
      ->status_is(403, 'Cannot delete other users shared macro without permission');
459
460
    $builder->build({
461
        source => 'UserPermission',
462
        value  => {
463
            borrowernumber => $authorized_patron->borrowernumber,
464
            module_bit     => 9,
465
            code           => 'delete_shared_macros',
466
        },
467
    });
468
    $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id")
469
      ->status_is(403, 'Cannot delete other users shared macro with permission on private endpoint');
470
    $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/shared/$macro_2_id")
471
      ->status_is(200, 'Can delete other users shared macro with permission');
472
473
};
474
475
$schema->storage->txn_rollback;

Return to bug 17268