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