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/<api_namespace>/static/<path>/<to>/<file>/<filename> 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

Sponsored-by: Theke Solutions
Signed-off-by: Arthur Suzuki <arthur.suzuki@biblibre.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
This commit is contained in:
Agustin Moyano 2019-04-25 02:13:37 -03:00 committed by Martin Renvoize
parent 0cca2795cd
commit 688967e6ea
No known key found for this signature in database
GPG Key ID: 422B469130441A0F
2 changed files with 119 additions and 12 deletions

View File

@ -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;
}

90
Koha/REST/V1/Static.pm Normal file
View File

@ -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;