Improved user management routes

Change-Id: I3310e03a96565f6c02fe48710c1ef4e48e6fe115
diff --git a/.gitignore b/.gitignore
index 43657d5..387feae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+cache
 kalamar.secret
 start-test
 todo.org
diff --git a/dev/demo/all.html b/dev/demo/all.html
index 067acef..0478638 100644
--- a/dev/demo/all.html
+++ b/dev/demo/all.html
@@ -69,13 +69,17 @@
       <div>
 	<fieldset>
 	  <form>
-	    <legend><span>Login</span></legend>
+	    <legend><span>Anmelden</span></legend>
  	    <input type="text" name="handle_or_email" placeholder="Benutzername" />
 	    <div>
 	      <input type="password" name="pwd" placeholder="Passwort" />
 	      <button type="submit"><span>Go</span></button>
 	    </div>
-	</form>
+	  </form>
+	  <ul style="font-size: 80%">
+	    <li><a href="#">Registrieren</a></li>
+	    <li><a href="#">Passwort vergessen?</a></li>
+	  </ul>
 	</fieldset>
       </div>
 
diff --git a/dev/scss/sidebar/sidebar.scss b/dev/scss/sidebar/sidebar.scss
index ddcf811..665f222 100644
--- a/dev/scss/sidebar/sidebar.scss
+++ b/dev/scss/sidebar/sidebar.scss
@@ -53,7 +53,7 @@
     margin: 0;
   }
 
-  ul {
+  ul.nav {
     list-style-type: none;
 /*
     background-color: $light-green;
@@ -135,10 +135,15 @@
   fieldset {
     position: relative;
     border-width: 0;
+    legend {
+      display: none;
+    }
+
     input[type=text], input[type=password] {
       @include input-field;
       width: 100%;
     }
+
     > form > div {
       position: relative;
       width: 100%;
@@ -146,6 +151,20 @@
       padding-right: $button-width
     }
 
+    ul {
+      display: block;
+      font-size: 80%;
+      text-align: right;
+      > li {
+	display: inline;
+	&:first-child::after {
+	  content: ' | ';
+	}
+      }
+      padding: 0;
+      margin-top: 0;
+    }
+
     button {
       position: absolute;
       // height: 100%;
diff --git a/kalamar.conf b/kalamar.conf
index f48fece..83866f9 100644
--- a/kalamar.conf
+++ b/kalamar.conf
@@ -1,11 +1,15 @@
+# api => 'http://10.0.10.51:7070/api/v0.1/'
+# api => 'http://10.0.10.13:7070/api/v0.1/'
+my $api = 'http://localhost:9999/api/v0.1/';
+
 {
   Search => {
     engine => 'Kalamar::API',
     # IDS Kustvakt server:
-    # api => 'http://10.0.10.13:7070/api/v0.1/'
-    # Local Kustvakt server:
-    # api => 'http://10.0.10.51:7070/api/v0.1/'
-    api => 'http://localhost:9999/api/v0.1/'
+    api => $api
+  },
+  Kalamar => {
+    api => $api
   },
   CHI => {
     default => {
diff --git a/kalamar.dict b/kalamar.dict
index 8f9443b..16968ec 100644
--- a/kalamar.dict
+++ b/kalamar.dict
@@ -22,6 +22,8 @@
     },
     about => 'Über KorAP',
     login => 'Anmelden',
+    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") %>',
     searchtitle => 'KorAP: Finde <%== loc("searchjob") %>',
     searchplaceholder => 'Finde ...',
@@ -63,6 +65,8 @@
     },
     about => 'About KorAP',
     login => 'Login',
+    register => 'Register',
+    pwdforgotten => 'Password forgotten?',
     go => 'Go!',
     searchjob => '»<%== $q %>« <% if (param("collection-name")) { %>in »<%== param("collection-name") %>«<% } elsif (param("collection")) { %>in the defined corpus<% } %> with <%== loc("QL_". $ql, "unknown query language") %>',
     searchtitle => 'KorAP: Find <%== loc("searchjob") %>',
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index 9623a81..12b5ded 100644
--- a/lib/Kalamar.pm
+++ b/lib/Kalamar.pm
@@ -87,7 +87,8 @@
     'Search',                    # Abstract Search framework
     'CHI',                       # Global caching mechanism
     'TagHelpers::MailToChiffre', # Obfuscate email addresses
-    'KalamarHelpers'             # Specific Helpers for Kalamar
+    'KalamarHelpers',            # Specific Helpers for Kalamar
+    'KalamarUser'                # Specific Helpers for Kalamar
   ) {
     $self->plugin($_);
   };
@@ -109,6 +110,7 @@
   $r->get('/')->to('search#query')->name('index');
 
   # Collection route
+  # TODO: Probably rename to /corpus
   $r->get('/collection')->to('Search#collections')->name('collections');
   $r->get('/collection/:id')->to('Search#collection')->name('collection');
 
@@ -128,8 +130,12 @@
   my $match  = $text->get('/:match_id');
   $match->to('search#match_info')->name('match');
 
-  $r->post('/login')->to('User#login');
-  $r->post('/logout')->to('User#logout');
+  # User Management
+  $r->any('/user')->to(controller => 'User');
+  $r->post('/login')->to(action => 'login')->name('login');
+  $r->get('/logout')->to(action => 'logout')->name('logout');
+  $r->any('/register')->to(action => 'register')->name('register');
+  $r->any('/forgotten')->to(action => 'pwdforgotten')->name('pwdforgotten');
 
   # Default user is called 'korap'
   # $r->route('/user/:user/:collection')
diff --git a/lib/Kalamar/Controller/User.pm b/lib/Kalamar/Controller/User.pm
index 691d648..f59f932 100644
--- a/lib/Kalamar/Controller/User.pm
+++ b/lib/Kalamar/Controller/User.pm
@@ -3,11 +3,34 @@
 
 sub login {
   my $c = shift;
+  my $v = $c->validator;
+  $v->required('handle_or_email');
+  $v->required('pwd');
+
+  my $handle = $v->param('handle_or_email');
+  my $pwd = $v->param('pwd');
+
+  $c->user->login($handle, $pwd);
+
+  return $c->redirect_to;
+};
+
+sub logout {
+  shift->user->logout;
+};
+
+sub register {
+  my $c = shift;
   $c->render(json => {
-    response => 'logged in'
+    response => 'register'
   });
 };
 
-sub logout {};
+sub pwdforgotten {
+  my $c = shift;
+  $c->render(json => {
+    response => 'pwdforgotten'
+  });
+};
 
 1;
diff --git a/lib/Kalamar/Plugin/KalamarHelpers.pm b/lib/Kalamar/Plugin/KalamarHelpers.pm
index 97e3d55..8ae6c1e 100644
--- a/lib/Kalamar/Plugin/KalamarHelpers.pm
+++ b/lib/Kalamar/Plugin/KalamarHelpers.pm
@@ -106,7 +106,7 @@
       my $scope = shift;
 
       # Create unordered list
-      my $html = "<ul>\n";
+      my $html = '<ul class="nav">'."\n";
 
       # Embed all link tags
       foreach (@$items) {
diff --git a/lib/Kalamar/Plugin/KalamarUser.pm b/lib/Kalamar/Plugin/KalamarUser.pm
index 209b8cb..8d12d30 100644
--- a/lib/Kalamar/Plugin/KalamarUser.pm
+++ b/lib/Kalamar/Plugin/KalamarUser.pm
@@ -54,6 +54,7 @@
 
       # Login successful
       if (my $res = $tx->success) {
+
 	my $jwt = $res->json;
 
 	my $auth = $jwt->{token_type} . ' ' . $jwt->{token};
@@ -92,6 +93,7 @@
       my $c = shift;
       my $param = shift;
 
+      # 'info' is useless!
       return unless $param =~ m/^details|settings$/;
 
       # The user may be logged in
@@ -110,14 +112,16 @@
 
 	my $tx = $plugin->build_authorized_tx($auth, 'GET', 'user/' . $param);
 	$tx = $plugin->ua->start($tx);
+
 	unless ($value = $tx->success) {
-#	  warn $tx->code;
 	  return;
 	}
 #	else {
 #	  warn $c->dumper($value->json);
 #	};
-	$value = $value->json;
+	if ($value) {
+	  $value = $value->json;
+	};
 
 	$chi->set($user . '_' . $param => $value);
       };
@@ -127,6 +131,42 @@
     }
   );
 
+  $mojo->helper(
+    'user.set' => sub {
+      my $c = shift;
+      my $param = shift;
+
+      # 'info' is useless!
+      return unless $param =~ m/^details|settings$/;
+
+      my $json_obj = shift;
+
+      # The user may be logged in
+      my $auth = ($c->stash('auth') || $c->session('auth')) or return;
+
+      # Get namespaced cache
+      my $chi = $c->chi('user');
+
+      # Get user and check, if the user is real
+      my $user = $chi->get($auth);
+
+      # Build a JSON transaction object
+      my $tx = $plugin->build_authorized_tx(
+	$auth, 'POST', 'user/' . $param, json => $json_obj
+      );
+
+      # Start
+      $tx = $plugin->ua->start($tx);
+
+      my $res = $tx->success or return;
+
+      # Kill all caches!!
+      $chi->remove($user . '_' . $param);
+
+      # Return value
+      return $res->json;
+    }
+  );
 
   # Logout
   $mojo->helper(
@@ -162,6 +202,7 @@
 
   my $url = Mojo::URL->new($plugin->api)->path($path);
 
+
   $header->{Authorization} = $auth;
 
   return $ua->build_tx($method, $url => $header => @values);
diff --git a/t/remote_user.t b/t/remote_user.t
new file mode 100644
index 0000000..1c0d1d1
--- /dev/null
+++ b/t/remote_user.t
@@ -0,0 +1,44 @@
+use Mojo::Base -strict;
+use lib '../lib', 'lib';
+use Test::More skip_all => 'No remote tests';
+use Test::Mojo;
+use Data::Dumper;
+
+$ENV{MOJO_USERAGENT_DEBUG} = 1;
+
+my $t = Test::Mojo->new('Kalamar');
+
+my $c = $t->app->build_controller;
+
+
+ok(!$c->user->get('details'), 'User not logged in');
+
+# Login with user credentials
+ok($c->user->login('kustvakt', 'kustvakt2015'), 'Login with demo user');
+is($c->stash('user'), 'kustvakt', 'Kustvakt is logged in');
+like($c->stash('auth'), qr/^api_token /, 'Kustvakt is logged in');
+
+my $details = $c->user->get('details');
+is($details->{email}, 'kustvakt@ids-mannheim.de', 'Email');
+is($details->{firstName}, 'Kustvakt', 'Firstname');
+is($details->{lastName}, 'KorAP', 'Lastname');
+is($details->{country}, 'Germany', 'Country');
+is($details->{address}, 'Mannheim', 'Address');
+is($details->{username}, 'kustvakt', 'Username');
+is($details->{institution}, 'IDS Mannheim', 'Institution');
+
+my $settings = $c->user->get('settings');
+is($settings->{username}, 'kustvakt', 'Username');
+
+# ok($c->user->set(details => { firstName => 'Me' }), 'Set first name');
+#ok($c->user->set(details => {
+#  firstName => 'Akron',
+#  lastName => 'Fuxfell'
+#}), 'Set first name');
+
+# diag Dumper $c->user->get('info');
+
+ok(1,'Fine');
+
+done_testing;
+__END__
diff --git a/templates/layouts/main.html.ep b/templates/layouts/main.html.ep
index af8feb4..f92ab2d 100644
--- a/templates/layouts/main.html.ep
+++ b/templates/layouts/main.html.ep
@@ -26,14 +26,18 @@
 % if (1) { # user not logged in
 % content_for 'sidebar', begin
 <fieldset>
-  <form>
+  %= form_for 'login', begin
     <legend><span><%= loc 'login' %></span></legend>
     <input type="text" name="handle_or_email" placeholder="<%= loc 'email' %>" />
     <div>
       <input type="password" name="pwd" placeholder="<%= loc 'pwd' %>" />
       <button type="submit"><span><%= loc 'go' %></span></button>
     </div>
-  </form>
+  % end
+  <ul>
+    <li><%= link_to loc('register') => 'register' %></li>
+    <li><%= link_to loc('pwdforgotten') => 'pwd_forgotten' %></li>
+  </ul>
 </fieldset>
 % end
 % }