Added authorized search and fixed logout
Change-Id: Ia18d1bf14286c658a9aef9ca29508145f07309ca
diff --git a/kalamar.conf b/kalamar.conf
index c748169..441f2da 100644
--- a/kalamar.conf
+++ b/kalamar.conf
@@ -1,7 +1,7 @@
-# api => 'http://10.0.10.51:7070/api/v0.1/'
-my $api = 'http://10.0.10.13:7070/api/v0.1/';
-#my $api = 'http://localhost:9998/api/v0.1/';
-
+# my api => 'http://10.0.10.51:7070/api/v0.1/'
+# my $api = 'http://10.0.10.13:7070/api/v0.1/';
+# my $api = 'http://localhost:9998/api/v0.1/';
+my $api = 'http://10.0.2.40:8089/api/v0.1/';
{
Search => {
engine => 'Kalamar::API',
diff --git a/kalamar.dict b/kalamar.dict
index 0dafc51..985e769 100644
--- a/kalamar.dict
+++ b/kalamar.dict
@@ -25,7 +25,7 @@
logout => 'Abmelden',
register => 'Registrieren',
pwdforgotten => 'Password vergessen?',
- searchjob => '»<%== $q %>« <% if (param("collection-name")) { %>in »<%== param("collection-name") %>«<% } elsif (param("collection")) { %>im definierten Korpus<% } %> mit <%== loc("QL_" . $ql, "unbekannter Anfragesprache") %>',
+ searchjob => '»<%== $q %>«<% if (param("collection-name")) { %> in »<%== param("collection-name") %>«<% } elsif (param("collection")) { %>im definierten Korpus<% } %> mit <%== loc("QL_" . $ql, "unbekannter Anfragesprache") %>',
searchtitle => 'KorAP: Finde <%== loc("searchjob") %>',
searchplaceholder => 'Finde ...',
go => 'Los!',
@@ -57,7 +57,8 @@
Auth => {
loginSuccess => 'Anmeldung erfolgreich',
loginFail => 'Anmeldung fehlgeschlagen',
- logoutSuccess => 'Abmeldung erfolgreich'
+ logoutSuccess => 'Abmeldung erfolgreich',
+ logoutFail => 'Abmeldung fehlgeschlagen'
}
},
-en => {
@@ -108,7 +109,8 @@
Auth => {
loginSuccess => 'Login successful',
loginFail => 'Access denied',
- logoutSuccess => 'Logout successful'
+ logoutSuccess => 'Logout successful',
+ logoutFail => 'Logout failed'
}
}
};
diff --git a/lib/Kalamar/API.pm b/lib/Kalamar/API.pm
index 9f9c2b7..e5af2c8 100644
--- a/lib/Kalamar/API.pm
+++ b/lib/Kalamar/API.pm
@@ -24,6 +24,7 @@
query_language
time_exceeded
api_request
+ authorized
_api_cache
api_response
benchmark
@@ -88,18 +89,20 @@
$index->api_request($url->to_string);
# Create new user agent and set timeout to 2 minutes
- my $ua = $c->user->ua;
- $ua->inactivity_timeout(120);
+ #my $ua = $c->user->ua;
+ #$tx = $plugin->ua->start($tx);
+
+ #$ua->inactivity_timeout(120);
# Debugging
$c->app->log->debug('Search for ' . $index->api_request);
# Search non-blocking
if ($cb) {
-
- $ua->get(
- $url => sub {
+ $c->user->auth_request(
+ get => $url => sub {
my $tx = pop;
+
$self->_process_response('matches', $index, $tx);
weaken $index;
return $cb->($index);
@@ -108,7 +111,7 @@
# Search blocking
else {
- my $tx = $ua->get($url);
+ my $tx = $c->user->auth_request->get($url);
$self->_process_response('matches', $index, $tx);
return $index;
};
@@ -361,11 +364,13 @@
# Set result values
$index->items_per_page($meta->{itemsPerPage});
+ # Set authorization
+ $index->authorized($meta->{authorized}) if $meta->{authorized};
# Bouncing query
-# if ($json->{query}) {
-# $index->query_jsonld($json->{query});
-# };
+ # if ($json->{query}) {
+ # $index->query_jsonld($json->{query});
+ # };
# Legacy
# elsif ($json->{request}->{query}) {
@@ -465,11 +470,11 @@
my $errors = $json->{errors};
# TODO: Check for ref!
foreach (@$errors) {
- $c->notify(
- error =>
- ($_->[0] ? $_->[0] . ': ' : '') .
- $_->[1]
- );
+ $c->notify(
+ error =>
+ ($_->[0] ? $_->[0] . ': ' : '') .
+ $_->[1]
+ );
};
}
diff --git a/lib/Kalamar/Apps/test_backend.pl b/lib/Kalamar/Apps/test_backend.pl
index a887b59..d8af676 100644
--- a/lib/Kalamar/Apps/test_backend.pl
+++ b/lib/Kalamar/Apps/test_backend.pl
@@ -11,16 +11,24 @@
# TODO: Test the fake server
-helper jwt => sub {
+my $secret = 's3cr3t';
+
+helper jwt_encode => sub {
shift;
return Mojo::JWT->new(
- secret => 's3cr3t',
+ secret => $secret,
token_type => 'api_token',
- expires => Mojo::Date->new(time + (3 * 34 * 60 * 60)),
+ expires => time + (3 * 34 * 60 * 60),
claims => { @_ }
);
};
+helper jwt_decode => sub {
+ my ($c, $auth) = @_;
+ $auth =~ s/\s*api_token\s+//;
+ return Mojo::JWT->new(secret => $secret)->decode($auth);
+};
+
# Base page
get '/' => sub {
@@ -44,6 +52,7 @@
"meta" => {
"count" => 25,
"startIndex" => 0,
+ "authorized" => undef,
"timeout" => 120000,
"context" => {
"left" => ["token",40],
@@ -113,6 +122,12 @@
};
+ if (my $auth = $c->req->headers->header('Authorization')) {
+ if (my $jwt = $c->jwt_decode($auth)) {
+ $response->{meta}->{authorized} = $jwt->{username} if $jwt->{username};
+ };
+ };
+
if ($v->param('page')) {
$response->{meta}->{startIndex} = $v->param("startIndex");
};
@@ -131,6 +146,23 @@
############
# Request API token
+get '/auth/logout' => sub {
+ my $c = shift;
+
+ if (my $auth = $c->req->headers->header('Authorization')) {
+ if (my $jwt = $c->jwt_decode($auth)) {
+ my $user = $jwt->{username} if $jwt->{username};
+
+ $c->app->log->debug('Server-Logout: ' . $user);
+ return $c->render(json => { msg => [[0, 'Fine!']]});
+ };
+ };
+
+ return $c->render(status => 400, json => { error => [[0, 'No!']]});
+};
+
+
+# Request API token
get '/auth/apiToken' => sub {
my $c = shift;
@@ -156,7 +188,7 @@
if ($pwd eq 'pass') {
# Render info with token
- my $jwt = $c->jwt(username => $username);
+ my $jwt = $c->jwt_encode(username => $username);
# Render in the Kustvakt fashion:
return $c->render(
@@ -172,14 +204,14 @@
return $c->render(
json => {
- error => [[3, 'x']]
+ error => [[2004, undef]]
}
);
};
return $c->render(
json => {
- error => [[4, 'x']]
+ error => [[2004, undef]]
}
);
};
diff --git a/lib/Kalamar/Controller/User.pm b/lib/Kalamar/Controller/User.pm
index 636f4c3..a1fab18 100644
--- a/lib/Kalamar/Controller/User.pm
+++ b/lib/Kalamar/Controller/User.pm
@@ -40,13 +40,14 @@
# Log out of the system
if ($c->user->logout) {
- $c->notify('success', $c->loc('Auth_logoutSuccess'));
+ $c->notify(success => $c->loc('Auth_logoutSuccess'));
}
# Something went wrong
else {
$c->notify('error', $c->loc('Auth_logoutFail'));
};
+
return $c->redirect_to('index');
};
diff --git a/lib/Kalamar/Plugin/KalamarUser.pm b/lib/Kalamar/Plugin/KalamarUser.pm
index f951f0f..561720a 100644
--- a/lib/Kalamar/Plugin/KalamarUser.pm
+++ b/lib/Kalamar/Plugin/KalamarUser.pm
@@ -26,7 +26,7 @@
$plugin->api($param->{api}) or return;
$plugin->ua(Mojo::UserAgent->new(
connect_timeout => 15,
- inactivity_timeout => 60
+ inactivity_timeout => 120
));
# Set app to server
@@ -53,29 +53,65 @@
$mojo->helper(
'user.ua' => sub {
my $c = shift;
+
my $auth = $c->user_auth;
return $plugin->ua unless $auth;
my $client = $c->req->headers->header('X-Forwarded-For');
- my $ua = Mojo::UserAgent->new;
+ my $ua = Mojo::UserAgent->new(
+ connect_timeout => 15,
+ inactivity_timeout => 120
+ );
# Set app to server
- $ua->server->app($mojo);
+ $ua->server->app($c->app);
$ua->on(
start => sub {
my ($ua, $tx) = @_;
my $headers = $tx->req->headers;
$headers->header('Authorization' => $auth);
- $headers->header('X-Forwarded-For' => $client);
+ $headers->header('X-Forwarded-For' => $client) if $client;
}
);
return $ua;
}
);
+ # Request with authorization header
+ $mojo->helper(
+ 'user.auth_request' => sub {
+ my $c = shift;
+ my $method = shift;
+ my $path = shift;
+
+ # Check for callback
+ my $cb;
+ if ($_[-1] && ref $_[-1] eq 'CODE') {
+ $cb = pop;
+ };
+
+ my $ua = $plugin->ua;
+
+ my $tx;
+ if ($c->user_auth) {
+ $tx = $plugin->build_authorized_tx(
+ $c->user_auth, uc($method), $path, @_
+ );
+ }
+ else {
+ $tx = $ua->build_tx(
+ uc($method), $path, @_
+ );
+ };
+ return $ua->start($tx, $cb) if $cb;
+ return $ua->start($tx);
+ }
+ );
+
+
# Login
$mojo->helper(
'user.login' => sub {
@@ -107,14 +143,7 @@
# Dealing with errors here
if (my $error = $jwt->{error}) {
if (ref $error eq 'ARRAY') {
- foreach (@$error) {
- if (ref($_) eq 'ARRAY') {
- $c->notify(error => join(', ', @{$_}));
- }
- else {
- $c->notify(error => 'There is an unknown JWT error');
- };
- };
+ $c->notify(error => $c->dumper($_));
}
else {
$c->notify(error => 'There is an unknown JWT error');
@@ -187,7 +216,7 @@
unless ($value) {
- my $tx = $plugin->build_authorized_tx($auth, 'GET', 'user/' . $param);
+ my $tx = $plugin->build_authorized_tx($auth, 'GET', Mojo::URL->new($plugin->api)->path('user/' . $param));
$tx = $plugin->ua->start($tx);
unless ($value = $tx->success) {
@@ -252,21 +281,22 @@
# TODO: csrf-protection!
- my $url = Mojo::URL->new($plugin->api);
- $url->query('/auth/logout');
+ my $url = Mojo::URL->new($plugin->api)->path('auth/logout');
- # Receive value from server
- my $return_value = $c->user->ua->get($url);
+ my $tx = $c->user->auth_request(
+ 'get', $url
+ );
- # TODO:
- # Do something with value
+ if ($tx->success) {
+ # Clear cache
+ $c->chi('user')->remove($c->user_auth);
- # Clear cache
- $c->chi('user')->remove($c->user_auth);
-
- # Expire session
- $c->session(expires => 1);
- return 1;
+ # Expire session
+ $c->session(user => undef);
+ $c->session(auth => undef);
+ return 1;
+ };
+ return 0;
}
);
};
@@ -286,7 +316,7 @@
$header = {};
};
- my $url = Mojo::URL->new($plugin->api)->path($path);
+ my $url = Mojo::URL->new($path);
$header->{Authorization} = $auth;
diff --git a/t/remote_user.t b/t/remote_user.t
index d904fb7..a484d1d 100644
--- a/t/remote_user.t
+++ b/t/remote_user.t
@@ -8,6 +8,13 @@
my $t = Test::Mojo->new('Kalamar');
+$t->get_ok('/?q=Baum')
+ ->status_is(200)
+ ->text_like('h1 span', qr/KorAP: Find .Baum./i)
+ ->text_like('#total-results', qr/\d+$/)
+ ->content_like(qr/\"authorized\"\:null/)
+ ;
+
$t->get_ok('/')
->element_exists('form[action=/user/login] input[name=handle_or_email]');
@@ -29,17 +36,45 @@
->status_is(200)
->element_exists_not('div.notify-error')
->element_exists('div.notify-success')
- ->text_is('div.notify-success', 'Login successful!')
+ ->text_is('div.notify-success', 'Login successful')
+ ;
+
+# Now the user is logged in and should be able to
+# search with authorization
+$t->get_ok('/?q=Baum')
+ ->status_is(200)
+ ->text_like('h1 span', qr/KorAP: Find .Baum./i)
+ ->text_like('#total-results', qr/\d+$/)
+ ->element_exists_not('div.notify-error')
+ ->content_like(qr/\"authorized\"\:\"test\"/)
;
+# Logout
+$t->get_ok('/user/logout')
+ ->status_is(302)
+ ->header_is('Location' => '/');
+
+$t->get_ok('/')
+ ->status_is(200)
+ ->element_exists_not('div.notify-error')
+ ->element_exists('div.notify-success')
+ ->text_is('div.notify-success', 'Logout successful')
+ ;
+
+$t->get_ok('/?q=Baum')
+ ->status_is(200)
+ ->text_like('h1 span', qr/KorAP: Find .Baum./i)
+ ->text_like('#total-results', qr/\d+$/)
+ ->content_like(qr/\"authorized\"\:null/)
+ ;
+
done_testing;
__END__
-
ok(!$c->user->get('details'), 'User not logged in');
# Login with user credentials