From 1db2d6fc025fffebc35af6ec99b47b626280a317 Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Thu, 25 Apr 2019 02:13:37 -0300 Subject: [PATCH] Bug 22835: Serve plugin static files through API This patch serves static files declared within plugins. To declare static files the plugin must implement the method 'static_routes' which retrieves the spec of static file routes to add to the API. Once those routes are added to the API, the become available through the /api/v1/contrib//static//// endpoint. To test: 1) Install bug-22835-plugin.kpz 2) Point your browser to /api/v1/contrib/kitchensink/static/static_files/mm.gif CHECK => No file is served 3) Apply this patch 4) restart_all 5) Repeat step 2. SUCCESS => File is served! 6) Sign off --- Koha/REST/Plugin/PluginRoutes.pm | 41 ++++++++++++------ Koha/REST/V1/Static.pm | 90 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 Koha/REST/V1/Static.pm diff --git a/Koha/REST/Plugin/PluginRoutes.pm b/Koha/REST/Plugin/PluginRoutes.pm index f51c7bdb46..43ac913332 100644 --- a/Koha/REST/Plugin/PluginRoutes.pm +++ b/Koha/REST/Plugin/PluginRoutes.pm @@ -50,11 +50,11 @@ sub register { { @plugins = Koha::Plugins->new()->GetPlugins( { - method => 'api_routes', + method => 'api_namespace', } ); # plugin needs to define a namespace - @plugins = grep { $_->api_namespace } @plugins; + #@plugins = grep { $_->api_namespace } @plugins; } foreach my $plugin ( @plugins ) { @@ -98,21 +98,38 @@ sub inject_routes { sub merge_spec { my ( $spec, $plugin ) = @_; - my $plugin_spec = $plugin->api_routes; + if($plugin->can('api_routes')) { + my $plugin_spec = $plugin->api_routes; - foreach my $route ( keys %{ $plugin_spec } ) { + foreach my $route ( keys %{ $plugin_spec } ) { + my $THE_route = '/contrib/' . $plugin->api_namespace . $route; + if ( exists $spec->{ $THE_route } ) { + # Route exists, overwriting is forbidden + Koha::Exceptions::Plugin::ForbiddenAction->throw( + "Attempted to overwrite $THE_route" + ); + } - my $THE_route = '/contrib/' . $plugin->api_namespace . $route; - if ( exists $spec->{ $THE_route } ) { - # Route exists, overwriting is forbidden - Koha::Exceptions::Plugin::ForbiddenAction->throw( - "Attempted to overwrite $THE_route" - ); + $spec->{'paths'}->{ $THE_route } = $plugin_spec->{ $route }; } - - $spec->{'paths'}->{ $THE_route } = $plugin_spec->{ $route }; } + if($plugin->can('static_routes')) { + my $plugin_spec = $plugin->static_routes; + + foreach my $route ( keys %{ $plugin_spec } ) { + + my $THE_route = '/contrib/' . $plugin->api_namespace . '/static'.$route; + if ( exists $spec->{ $THE_route } ) { + # Route exists, overwriting is forbidden + Koha::Exceptions::Plugin::ForbiddenAction->throw( + "Attempted to overwrite $THE_route" + ); + } + + $spec->{'paths'}->{ $THE_route } = $plugin_spec->{ $route }; + } + } return $spec; } diff --git a/Koha/REST/V1/Static.pm b/Koha/REST/V1/Static.pm new file mode 100644 index 0000000000..d0f31c9a40 --- /dev/null +++ b/Koha/REST/V1/Static.pm @@ -0,0 +1,90 @@ +package Koha::REST::V1::Static; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Try::Tiny; + +=head1 API + +=head2 Class methods + +=head3 get + +Mehtod that gets file contents + +=cut + +sub get { + my $self = shift; + my $c = $self->openapi->valid_input or return; + + if ( C4::Context->preference('UseKohaPlugins') + && C4::Context->config("enable_plugins") ) + { + my $path = $c->req->url->path->leading_slash(1); + + return $c->render(status => 400, openapi => { error => 'Endpoint inteded for plugin static files' }) unless "$path" =~ /^\/api\/v1\/contrib/; + + my $namespace = $path->[3]; + + my $checkpath = '/api/v1/contrib/'.$namespace.'/static'; + + return $c->render(status => 400, openapi => { error => 'Endpoint inteded for plugin static files' }) unless "$path" =~ /\Q$checkpath/; + + my @plugins = Koha::Plugins->new()->GetPlugins( + { + method => 'api_namespace', + } + ); + + @plugins = grep { $_->api_namespace eq $namespace} @plugins; + warn scalar(@plugins); + return $c->render({ status => 404, openapi => { error => 'File not found' } }) unless scalar(@plugins) > 0; + return $c->render({ status => 500, openapi => { error => 'Namespace not unique' } }) unless scalar(@plugins) == 1; + + my $plugin = $plugins[0]; + + my $basepath = $plugin->bundle_path; + + warn $basepath; + + my $relpath = join ('/', splice (@$path, 5)); + + warn $relpath; + + warn join('/', $basepath, $relpath); + return try { + my $asset = Mojo::Asset::File->new(path => join('/', $basepath, $relpath)); + return $c->render({ status => 404, openapi => { error => 'File not found' } }) unless $asset->is_file; + # $c->res->headers->content_type("image/jpeg"); + return $c->reply->asset($asset); + } + catch { + return $c->render({ status => 404, openapi => { error => 'File not found' } }); + } + + } else { + $c->render({ status => 500, openapi => { error => 'Plugins are not enabled' } }) + } + + +} + +1; \ No newline at end of file -- 2.11.0