Bug 14868: Swagger2-driven Permission checking
Define 'x-koha-permission' for the Swagger2 Operation Object, to automatically authorize against the required permissions. This way we immediately tell the API consumer in the Swagger2-definition, which permissions are needed to access defined resources. Also we don't need to maintain permissions in multiple locations and we can build a smart testing framework to help a lot in creating tests for the new REST API. Signed-off-by: Benjamin Rokseth <benjamin.rokseth@kul.oslo.kommune.no> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io> Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
This commit is contained in:
parent
49df1cc10f
commit
ac1286dacd
2 changed files with 58 additions and 22 deletions
|
@ -18,33 +18,13 @@ package Koha::REST::V1;
|
|||
use Modern::Perl;
|
||||
use Mojo::Base 'Mojolicious';
|
||||
|
||||
use C4::Auth qw( check_cookie_auth get_session );
|
||||
use C4::Auth qw( check_cookie_auth get_session haspermission );
|
||||
use C4::Context;
|
||||
use Koha::Patrons;
|
||||
|
||||
sub startup {
|
||||
my $self = shift;
|
||||
|
||||
my $route = $self->routes->under->to(
|
||||
cb => sub {
|
||||
my $c = shift;
|
||||
# Mojo doesn't use %ENV the way CGI apps do
|
||||
# Manually pass the remote_address to check_auth_cookie
|
||||
my $remote_addr = $c->tx->remote_address;
|
||||
my ($status, $sessionID) = check_cookie_auth(
|
||||
$c->cookie('CGISESSID'), undef,
|
||||
{ remote_addr => $remote_addr });
|
||||
|
||||
if ($status eq "ok") {
|
||||
my $session = get_session($sessionID);
|
||||
my $user = Koha::Patrons->find($session->param('number'));
|
||||
$c->stash('koha.user' => $user);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
);
|
||||
|
||||
# Force charset=utf8 in Content-Type header for JSON responses
|
||||
$self->types->type(json => 'application/json; charset=utf8');
|
||||
|
||||
|
@ -54,9 +34,64 @@ sub startup {
|
|||
}
|
||||
|
||||
$self->plugin(Swagger2 => {
|
||||
route => $route,
|
||||
url => $self->home->rel_file("api/v1/swagger/swagger.min.json"),
|
||||
});
|
||||
}
|
||||
|
||||
=head3 authenticate_api_request
|
||||
|
||||
Validates authentication and allows access if authorization is not required or
|
||||
if authorization is required and user has required permissions to access.
|
||||
|
||||
This subroutine is called before every request to API.
|
||||
|
||||
=cut
|
||||
|
||||
sub authenticate_api_request {
|
||||
my ($next, $c, $action_spec) = @_;
|
||||
|
||||
my ($session, $user);
|
||||
my $cookie = $c->cookie('CGISESSID');
|
||||
# Mojo doesn't use %ENV the way CGI apps do
|
||||
# Manually pass the remote_address to check_auth_cookie
|
||||
my $remote_addr = $c->tx->remote_address;
|
||||
my ($status, $sessionID) = check_cookie_auth(
|
||||
$cookie, undef,
|
||||
{ remote_addr => $remote_addr });
|
||||
if ($status eq "ok") {
|
||||
$session = get_session($sessionID);
|
||||
$user = Koha::Patrons->find($session->param('number'));
|
||||
$c->stash('koha.user' => $user);
|
||||
}
|
||||
else {
|
||||
return $c->render_swagger(
|
||||
{ error => "Authentication failure." },
|
||||
{},
|
||||
401
|
||||
) if $cookie and $action_spec->{'x-koha-permission'};
|
||||
}
|
||||
|
||||
if ($action_spec->{'x-koha-permission'}) {
|
||||
return $c->render_swagger(
|
||||
{ error => "Authentication required." },
|
||||
{},
|
||||
401
|
||||
) unless $user;
|
||||
|
||||
if (C4::Auth::haspermission($user->userid, $action_spec->{'x-koha-permission'})) {
|
||||
return $next->($c);
|
||||
}
|
||||
else {
|
||||
return $c->render_swagger(
|
||||
{ error => "Authorization failure. Missing required permission(s)." },
|
||||
{},
|
||||
403
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $next->($c);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
}
|
||||
},
|
||||
"basePath": "/api/v1",
|
||||
"x-mojo-around-action": "Koha::REST::V1::authenticate_api_request",
|
||||
"paths": {
|
||||
"$ref": "paths.json"
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue