From 84f871649696880b7e4578e7526f4889bae76a7d Mon Sep 17 00:00:00 2001
From: Nick Clemens <nick@bywatersolutions.com>
Date: Thu, 2 Jan 2020 14:56:10 +0000
Subject: [PATCH] Bug 17268: Make shared macros use their own path

Bug 17268: Update API to use shared instead of public
---
 Koha/AdvancedEditorMacro.pm                        |  12 +-
 Koha/REST/V1/AdvancedEditorMacro.pm                | 226 ++++++++++++++------
 .../swagger/definitions/advancededitormacro.json   |   6 +-
 api/v1/swagger/paths.json                          |   6 +
 api/v1/swagger/paths/advancededitormacros.json     | 229 ++++++++++++++++++++-
 t/db_dependent/api/v1/advanced_editor_macros.t     | 127 +++++++-----
 6 files changed, 473 insertions(+), 133 deletions(-)

diff --git a/Koha/AdvancedEditorMacro.pm b/Koha/AdvancedEditorMacro.pm
index 1b90af7a55..d30fcc5f16 100644
--- a/Koha/AdvancedEditorMacro.pm
+++ b/Koha/AdvancedEditorMacro.pm
@@ -33,21 +33,17 @@ Koha::AdvancedEditorMacro - Koha Advanced Editor Macro Object class
 
 =head3 to_api_mapping
 
-This method returns the mapping for representing a Koha::AdvancedEditorMacro object
-on the API.
-
 =cut
 
 sub to_api_mapping {
     return {
-        id              => 'macro_id',
-        name            => 'name',
-        macro           => 'macro_text',
-        borrowernumber  => 'patron_id',
-        public          => 'public',
+        id                  => 'macro_id',
+        macro               => 'macro_text',
+        borrowernumber      => 'patron_id',
     };
 }
 
+
 =head2 Internal methods
 
 =head3 _type
diff --git a/Koha/REST/V1/AdvancedEditorMacro.pm b/Koha/REST/V1/AdvancedEditorMacro.pm
index 05faaa58b7..92f6730c2a 100644
--- a/Koha/REST/V1/AdvancedEditorMacro.pm
+++ b/Koha/REST/V1/AdvancedEditorMacro.pm
@@ -38,7 +38,7 @@ 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 => { public => 1, borrowernumber => $patron->borrowernumber } });
+        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 );
     }
@@ -64,16 +64,50 @@ Controller function that handles retrieving a single Koha::AdvancedEditorMacro
 sub get {
     my $c = shift->openapi->valid_input or return;
     my $patron = $c->stash('koha.user');
-    my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('advancededitormacro_id') );
+    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->public || $macro->borrowernumber == $patron->borrowernumber ){
-        return $c->render( status  => 403,
-                           openapi => { error => "You do not have permission to access this macro" } );
+    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 );
 }
 
@@ -86,12 +120,9 @@ Controller function that handles adding a new Koha::AdvancedEditorMacro object
 sub add {
     my $c = shift->openapi->valid_input or return;
 
-    if( defined $c->validation->param('body')->{public} && $c->validation->param('body')->{public} == 1 ){
-        my $patron = $c->stash('koha.user');
-        unless ( $patron->has_permission({ editcatalogue => 'create_public_macros' }) ){
-            return $c->render( status  => 403,
-                               openapi => { error => "You do not have permission to create public macros" } );
-        }
+    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 {
@@ -103,25 +134,38 @@ sub add {
             openapi => $macro->to_api
         );
     }
-    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." }
-            );
-        }
-    };
+    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::Library object
+Controller function that handles updating a Koha::AdvancedEditorMacro object
 
 =cut
 
@@ -134,17 +178,15 @@ sub update {
         return $c->render( status  => 404,
                            openapi => { error => "Object not found" } );
     }
-
     my $patron = $c->stash('koha.user');
-    if( $macro->public == 1 || defined $c->validation->param('body')->{public} && $c->validation->param('body')->{public} == 1 && $macro->borrowernumber == $patron->borrowernumber ){
-        unless ( $patron->has_permission({ editcatalogue => 'create_public_macros' }) ){
-            return $c->render( status  => 403,
-                               openapi => { error => "You do not have permission to create/edit public macros" } );
-        }
+
+    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 or public macros (with permission) " } );
+                               openapi => { error => "You can only edit macros you own" } );
         }
     }
 
@@ -154,21 +196,42 @@ sub update {
         $macro->store();
         return $c->render( status => 200, openapi => $macro->to_api );
     }
-    catch {
-        if ( $_->isa('Koha::Exceptions::Object') ) {
-            return $c->render( status  => 500,
-                               openapi => { error => $_->message } );
-        }
-        else {
-            return $c->render( status => 500,
-                openapi => { error => "Something went wrong, check the logs."} );
-        }
-    };
+    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::AdvancedEditoracro object
+Controller function that handles deleting a Koha::AdvancedEditorMacro object
 
 =cut
 
@@ -182,15 +245,13 @@ sub delete {
     }
 
     my $patron = $c->stash('koha.user');
-    if( $macro->public == 1 && $macro->borrowernumber != $patron->borrowernumber ){
-        unless ( $patron->has_permission({ editcatalogue => 'delete_public_macros' }) ){
-            return $c->render( status  => 403,
-                               openapi => { error => "You do not have permission to create public macros" } );
-        }
+    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 or public macros (with permission) " } );
+                               openapi => { error => "You can only delete macros you own" } );
         }
     }
 
@@ -198,18 +259,55 @@ sub delete {
         $macro->delete;
         return $c->render( status => 200, openapi => "" );
     }
-    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. line 159"} );
-        }
-    };
+    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
@@ -266,8 +364,8 @@ sub _to_model {
         }
     }
 
-    if ( exists $macro->{public} ) {
-        $macro->{public} = ($macro->{public}) ? 1 : 0;
+    if ( exists $macro->{shared} ) {
+        $macro->{shared} = ($macro->{shared}) ? 1 : 0;
     }
 
 
@@ -282,10 +380,8 @@ sub _to_model {
 
 our $to_api_mapping = {
     id                  => 'macro_id',
-    name                => 'name',
     macro               => 'macro_text',
     borrowernumber      => 'patron_id',
-    public              => 'public',
 };
 
 =head3 $to_model_mapping
@@ -294,10 +390,8 @@ our $to_api_mapping = {
 
 our $to_model_mapping = {
     macro_id         => 'id',
-    name             => 'name',
     macro_text       => 'macro',
     patron_id        => 'borrowernumber',
-    public           => 'public',
 };
 
 1;
diff --git a/api/v1/swagger/definitions/advancededitormacro.json b/api/v1/swagger/definitions/advancededitormacro.json
index 0f46754704..b5f7403292 100644
--- a/api/v1/swagger/definitions/advancededitormacro.json
+++ b/api/v1/swagger/definitions/advancededitormacro.json
@@ -16,11 +16,11 @@
       "description": "borrower number",
       "type": ["integer", "null"]
     },
-    "public": {
-        "description": "is macro public",
+    "shared": {
+        "description": "is macro shared",
         "type": ["string", "null"]
     }
   },
   "additionalProperties": false,
-  "required": ["name", "macro_text", "patron_id", "public"]
+  "required": ["name", "macro_text", "patron_id", "shared"]
 }
diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json
index c8c7217f5a..7491f84d7a 100644
--- a/api/v1/swagger/paths.json
+++ b/api/v1/swagger/paths.json
@@ -74,6 +74,12 @@
   "/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
index 23e63bcb24..7c7eb93aaa 100644
--- a/api/v1/swagger/paths/advancededitormacros.json
+++ b/api/v1/swagger/paths/advancededitormacros.json
@@ -30,9 +30,9 @@
           "type": "string"
         },
         {
-          "name": "public",
+          "name": "shared",
           "in": "query",
-          "description": "Search on public macros",
+          "description": "Search on shared macros",
           "required": false,
           "type": "string"
         }
@@ -127,6 +127,63 @@
       }
     }
   },
+  "/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",
@@ -292,5 +349,173 @@
         }
       }
     }
+  },
+  "/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/t/db_dependent/api/v1/advanced_editor_macros.t b/t/db_dependent/api/v1/advanced_editor_macros.t
index 924de8fef2..025c73fa2d 100644
--- a/t/db_dependent/api/v1/advanced_editor_macros.t
+++ b/t/db_dependent/api/v1/advanced_editor_macros.t
@@ -64,7 +64,7 @@ subtest 'list() tests' => sub {
             name => 'Test2',
             macro => 'delete 100',
             borrowernumber => $patron_1->borrowernumber,
-            public => 1,
+            shared=> 1,
         }
     });
     my $macro_3 = $builder->build_object({ class => 'Koha::AdvancedEditorMacros', value =>
@@ -79,11 +79,11 @@ subtest 'list() tests' => sub {
             name => 'Test4',
             macro => 'delete 100',
             borrowernumber => $patron_2->borrowernumber,
-            public => 1,
+            shared => 1,
         }
     });
 
-    my $macros_index = Koha::AdvancedEditorMacros->search({ -or => { public => 1, borrowernumber => $patron_1->borrowernumber } })->count-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" )
@@ -106,7 +106,7 @@ subtest 'list() tests' => sub {
         $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?public=1")
+        $t->get_ok("//$userid:$password@/api/v1/advancededitormacros?shared=1")
           ->status_is(200)
           ->json_has( [ $macro_2, $macro_4 ] );
     };
@@ -120,7 +120,7 @@ subtest 'list() tests' => sub {
 
 subtest 'get() tests' => sub {
 
-    plan tests => 12;
+    plan tests => 15;
 
     my $patron = $builder->build_object({
         class => 'Koha::Patrons',
@@ -131,29 +131,34 @@ subtest 'get() tests' => sub {
     my $userid = $patron->userid;
 
     my $macro_1 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => {
-            public => 1,
+            shared => 1,
         }
     });
     my $macro_2 = $builder->build_object( { class => 'Koha::AdvancedEditorMacros', value => {
-            public => 0,
+            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( 200, 'SWAGGER3.2.2' )
-      ->json_is( '' => Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro_1->TO_JSON ), 'SWAGGER3.3.2' );
+      ->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, 'SWAGGER3.2.2' )
+      ->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, 'SWAGGER3.2.2' )
-      ->json_is( '' => Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro_3->TO_JSON ), 'SWAGGER3.3.2' );
+      ->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;
@@ -166,7 +171,7 @@ subtest 'get() tests' => sub {
 
 subtest 'add() tests' => sub {
 
-    plan tests => 20;
+    plan tests => 24;
 
     my $authorized_patron = $builder->build_object({
         class => 'Koha::Patrons',
@@ -194,7 +199,7 @@ subtest 'add() tests' => sub {
 
     my $macro = $builder->build_object({
         class => 'Koha::AdvancedEditorMacros',
-        value => { public => 0 }
+        value => { shared => 0 }
     });
     my $macro_values     = Koha::REST::V1::AdvancedEditorMacro::_to_api( $macro->TO_JSON );
     delete $macro_values->{macro_id};
@@ -222,12 +227,12 @@ subtest 'add() tests' => sub {
     # 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', 'SWAGGER3.3.1' )
-      ->json_is( '/name' => $macro_values->{name}, 'SWAGGER3.3.1' )
-      ->json_is( '/macro_text' => $macro_values->{macro_text}, 'SWAGGER3.3.1' )
-      ->json_is( '/patron_id' => $macro_values->{patron_id}, 'SWAGGER3.3.1' )
-      ->json_is( '/public' => $macro_values->{public}, 'SWAGGER3.3.1' )
-      ->header_like( Location => qr|^\/api\/v1\/advancededitormacros\/d*|, 'SWAGGER3.4.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;
@@ -245,30 +250,37 @@ subtest 'add() tests' => sub {
         ]
     );
 
-    $macro_values->{public} = 1;
+    $macro_values->{shared} = 1;
     delete $macro_values->{macro_id};
 
-    # Unauthorized attempt to write a public macro
+    # 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_public_macros',
+            code           => 'create_shared_macros',
         },
     });
 
-    # Authorized attempt to write a public macro
+    # 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 => 28;
+    plan tests => 32;
 
     my $authorized_patron = $builder->build_object({
         class => 'Koha::Patrons',
@@ -296,11 +308,11 @@ subtest 'update() tests' => sub {
 
     my $macro = $builder->build_object({
         class => 'Koha::AdvancedEditorMacros',
-        value => { borrowernumber => $authorized_patron->borrowernumber, public => 0 }
+        value => { borrowernumber => $authorized_patron->borrowernumber, shared => 0 }
     });
     my $macro_2 = $builder->build_object({
         class => 'Koha::AdvancedEditorMacros',
-        value => { borrowernumber => $unauthorized_patron->borrowernumber, public => 0 }
+        value => { borrowernumber => $unauthorized_patron->borrowernumber, shared => 0 }
     });
     my $macro_id = $macro->id;
     my $macro_2_id = $macro_2->id;
@@ -327,39 +339,44 @@ subtest 'update() tests' => sub {
         name => "Macro-update",
         macro_text => "delete 100",
         patron_id => $authorized_patron->borrowernumber,
-        public => 0,
+        shared => 0,
     };
 
     my $test = $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_update )
-      ->status_is(200, 'SWAGGER3.2.1')
-      ->json_has( '/macro_id', 'SWAGGER3.3.1' )
-      ->json_is( '/name' => $macro_update->{name}, 'SWAGGER3.3.1' )
-      ->json_is( '/macro_text' => $macro_update->{macro_text}, 'SWAGGER3.3.1' )
-      ->json_is( '/patron_id' => $macro_update->{patron_id}, 'SWAGGER3.3.1' )
-      ->json_is( '/public' => $macro_update->{public}, 'SWAGGER3.3.1' );
+      ->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 public
-    $macro_update->{public} = 1;
+    # Now try to make the macro shared
+    $macro_update->{shared} = 1;
 
-    $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_update )
-      ->status_is(403, 'Cannot make your macro public without permission');
+    $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_public_macros',
+            code           => 'create_shared_macros',
         },
     });
 
     $t->put_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_id" => json => $macro_update )
-      ->status_is(200, 'Can update macro to public with permission')
-      ->json_has( '/macro_id', 'SWAGGER3.3.1' )
-      ->json_is( '/name' => $macro_update->{name}, 'SWAGGER3.3.1' )
-      ->json_is( '/macro_text' => $macro_update->{macro_text}, 'SWAGGER3.3.1' )
-      ->json_is( '/patron_id' => $macro_update->{patron_id}, 'SWAGGER3.3.1' )
-      ->json_is( '/public' => $macro_update->{public}, 'SWAGGER3.3.1' );
+      ->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 };
@@ -384,11 +401,11 @@ subtest 'update() tests' => sub {
       ->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 non public macro");
+      ->status_is(403, "Cannot update other borrowers private macro");
 };
 
 subtest 'delete() tests' => sub {
-    plan tests => 10;
+    plan tests => 12;
 
     my $authorized_patron = $builder->build_object({
         class => 'Koha::Patrons',
@@ -416,11 +433,11 @@ subtest 'delete() tests' => sub {
 
     my $macro = $builder->build_object({
         class => 'Koha::AdvancedEditorMacros',
-        value => { borrowernumber => $authorized_patron->borrowernumber, public => 0 }
+        value => { borrowernumber => $authorized_patron->borrowernumber, shared => 0 }
     });
     my $macro_2 = $builder->build_object({
         class => 'Koha::AdvancedEditorMacros',
-        value => { borrowernumber => $unauthorized_patron->borrowernumber, public => 0 }
+        value => { borrowernumber => $unauthorized_patron->borrowernumber, shared => 0 }
     });
     my $macro_id = $macro->id;
     my $macro_2_id = $macro_2->id;
@@ -435,21 +452,23 @@ subtest 'delete() tests' => sub {
     $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id")
       ->status_is(403, 'Cannot delete other users macro with permission');
 
-    $macro_2->public(1)->store();
+    $macro_2->shared(1)->store();
 
-    $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id")
-      ->status_is(403, 'Cannot delete other users public macro without permission');
+    $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_public_macros',
+            code           => 'delete_shared_macros',
         },
     });
     $t->delete_ok( "//$auth_userid:$password@/api/v1/advancededitormacros/$macro_2_id")
-      ->status_is(200, 'Can delete other users public macro with permission');
+      ->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');
 
 };
 
-- 
2.11.0